[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [qemu-xen-unstable] passthrough: pt_bar_mapping etc.: use correct CMD for PCI BAR mapping etc.
commit 5d767b7b3fac52336f59e5b40d8befa6b1909937 Author: Ian Jackson <ian.jackson@xxxxxxxxxxxxx> Date: Tue May 5 15:22:17 2009 +0100 passthrough: pt_bar_mapping etc.: use correct CMD for PCI BAR mapping etc. dbb8aafa702b8b4f5568e08641d98471fd04e0f8 has a bug: The virtual CMD value we get from reg_entry->data is not the proper value because reg_entry->data only holds the emulated bits and the PCI_COMMAND_IO/PCI_COMMAND_MEMORY bits are not in it. Instead, we can use pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2) to get the proper value. We should only update the mapping of the related BAR, NOT the mappings of ALL BARs. In pt_exp_rom_bar_reg_write(), we should also update the mapping. And for PCI_ROM_SLOT, when the PCI_ROM_ADDRESS_ENABLE bit is 0, we should not have the mapping. Signed-off-by: Dexuan Cui <dexuan.cui@xxxxxxxxx> --- hw/pass-through.c | 113 +++++++++++++++++++++++++++++----------------------- 1 files changed, 63 insertions(+), 50 deletions(-) diff --git a/hw/pass-through.c b/hw/pass-through.c index 6a53137..d2bed51 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -1791,64 +1791,74 @@ out: } /* mapping BAR */ -static void pt_bar_mapping(struct pt_dev *ptdev, int io_enable, int mem_enable) +static void pt_bar_mapping_one(struct pt_dev *ptdev, int bar, int io_enable, + int mem_enable) { PCIDevice *dev = (PCIDevice *)&ptdev->dev; PCIIORegion *r; struct pt_region *base = NULL; uint32_t r_size = 0, r_addr = -1; int ret = 0; - int i; - for (i=0; i<PCI_NUM_REGIONS; i++) - { - r = &dev->io_regions[i]; + r = &dev->io_regions[bar]; - /* check valid region */ - if (!r->size) - continue; + /* check valid region */ + if (!r->size) + return; - base = &ptdev->bases[i]; - /* skip unused BAR or upper 64bit BAR */ - if ((base->bar_flag == PT_BAR_FLAG_UNUSED) || - (base->bar_flag == PT_BAR_FLAG_UPPER)) - continue; + base = &ptdev->bases[bar]; + /* skip unused BAR or upper 64bit BAR */ + if ((base->bar_flag == PT_BAR_FLAG_UNUSED) || + (base->bar_flag == PT_BAR_FLAG_UPPER)) + return; - /* copy region address to temporary */ - r_addr = r->addr; + /* copy region address to temporary */ + r_addr = r->addr; - /* need unmapping in case I/O Space or Memory Space disable */ - if (((base->bar_flag == PT_BAR_FLAG_IO) && !io_enable ) || - ((base->bar_flag == PT_BAR_FLAG_MEM) && !mem_enable )) + /* need unmapping in case I/O Space or Memory Space disable */ + if (((base->bar_flag == PT_BAR_FLAG_IO) && !io_enable ) || + ((base->bar_flag == PT_BAR_FLAG_MEM) && !mem_enable )) + r_addr = -1; + if ( (bar == PCI_ROM_SLOT) && (r_addr != -1) ) + { + uint32_t rom_reg; + rom_reg = pt_pci_read_config(&ptdev->dev, PCI_ROM_ADDRESS, 4); + if ( !(rom_reg & PCI_ROM_ADDRESS_ENABLE) ) r_addr = -1; + } - /* prevent guest software mapping memory resource to 00000000h */ - if ((base->bar_flag == PT_BAR_FLAG_MEM) && (r_addr == 0)) - r_addr = -1; + /* prevent guest software mapping memory resource to 00000000h */ + if ((base->bar_flag == PT_BAR_FLAG_MEM) && (r_addr == 0)) + r_addr = -1; - /* align resource size (memory type only) */ - r_size = r->size; - PT_GET_EMUL_SIZE(base->bar_flag, r_size); - - /* check overlapped address */ - ret = pt_chk_bar_overlap(dev->bus, dev->devfn, - r_addr, r_size, r->type); - if (ret > 0) - PT_LOG("Warning: ptdev[%02x:%02x.%x][Region:%d][Address:%08xh]" - "[Size:%08xh] is overlapped.\n", pci_bus_num(dev->bus), - (dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7), - i, r_addr, r_size); - - /* check whether we need to update the mapping or not */ - if (r_addr != ptdev->bases[i].e_physbase) - { - /* mapping BAR */ - r->map_func((PCIDevice *)ptdev, i, r_addr, - r_size, r->type); - } + /* align resource size (memory type only) */ + r_size = r->size; + PT_GET_EMUL_SIZE(base->bar_flag, r_size); + + /* check overlapped address */ + ret = pt_chk_bar_overlap(dev->bus, dev->devfn, + r_addr, r_size, r->type); + if (ret > 0) + PT_LOG("Warning: ptdev[%02x:%02x.%x][Region:%d][Address:%08xh]" + "[Size:%08xh] is overlapped.\n", pci_bus_num(dev->bus), + (dev->devfn >> 3) & 0x1F, (dev->devfn & 0x7), + bar, r_addr, r_size); + + /* check whether we need to update the mapping or not */ + if (r_addr != ptdev->bases[bar].e_physbase) + { + /* mapping BAR */ + r->map_func((PCIDevice *)ptdev, bar, r_addr, + r_size, r->type); } +} - return; +static void pt_bar_mapping(struct pt_dev *ptdev, int io_enable, int mem_enable) +{ + int i; + + for (i=0; i<PCI_NUM_REGIONS; i++) + pt_bar_mapping_one(ptdev, i, io_enable, mem_enable); } /* check power state transition */ @@ -3051,6 +3061,7 @@ static int pt_bar_reg_write(struct pt_dev *ptdev, uint32_t prev_offset; uint32_t r_size = 0; int index = 0; + uint16_t cmd; /* get BAR index */ index = pt_bar_offset_to_index(reg->offset); @@ -3170,14 +3181,10 @@ exit: *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); /* After BAR reg update, we need to remap BAR*/ - reg_grp_entry = pt_find_reg_grp(ptdev, PCI_COMMAND); - if (reg_grp_entry) - { - reg_entry = pt_find_reg(reg_grp_entry, PCI_COMMAND); - if (reg_entry) - pt_bar_mapping(ptdev, reg_entry->data & PCI_COMMAND_IO, - reg_entry->data & PCI_COMMAND_MEMORY); - } + cmd = pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2); + pt_bar_mapping_one(ptdev, index, cmd & PCI_COMMAND_IO, + cmd & PCI_COMMAND_MEMORY); + return 0; } @@ -3195,6 +3202,7 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev, uint32_t r_size = 0; uint32_t bar_emu_mask = 0; uint32_t bar_ro_mask = 0; + uint16_t cmd; r = &d->io_regions[PCI_ROM_SLOT]; r_size = r->size; @@ -3217,6 +3225,11 @@ static int pt_exp_rom_bar_reg_write(struct pt_dev *ptdev, throughable_mask = ~bar_emu_mask & valid_mask; *value = PT_MERGE_VALUE(*value, dev_value, throughable_mask); + /* After BAR reg update, we need to remap BAR*/ + cmd = pt_pci_read_config(&ptdev->dev, PCI_COMMAND, 2); + pt_bar_mapping_one(ptdev, PCI_ROM_SLOT, cmd & PCI_COMMAND_IO, + cmd & PCI_COMMAND_MEMORY); + return 0; } -- generated by git-patchbot for /home/xen/git/qemu-xen-unstable.git _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |