[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 2/3] ioemu: add libpci fixup to handle recent change in PCIUtils
The following commit of PCIUtils changes what 'base_addr' contains. Add a fixup to make sure the pass-through works when building against different versions of PCIUtils. commit 6d143c3283855c474445a3cf27c65280ed7ab1b7 Author: Yu Zhao <yu.zhao@xxxxxxxxx> Date: Fri Dec 26 09:59:28 2008 +0800 Fix base address flags when using sysfs method The base address flags are ignored when using sysfs method, while the proc and generic methods combined the flags into 'base_addr'. This inconsistency may fail some applications using libpci. Signed-off-by: Yu Zhao <yu.zhao@xxxxxxxxx> --- hw/pass-through.c | 117 ++++++++++++++++++++++++++++++++++++++++++---------- hw/pass-through.h | 8 ++++ hw/pt-msi.c | 2 +- 3 files changed, 103 insertions(+), 24 deletions(-) diff --git a/hw/pass-through.c b/hw/pass-through.c index 71dff1f..207bdf0 100644 --- a/hw/pass-through.c +++ b/hw/pass-through.c @@ -48,6 +48,10 @@ struct dpci_infos { /* prototype */ static uint32_t pt_common_reg_init(struct pt_dev *ptdev, struct pt_reg_info_tbl *reg, uint32_t real_offset); +static uint32_t pt_vendor_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset); +static uint32_t pt_device_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset); static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev, struct pt_reg_info_tbl *reg, uint32_t real_offset); static uint32_t pt_status_reg_init(struct pt_dev *ptdev, @@ -152,6 +156,28 @@ static int pt_msixctrl_reg_write(struct pt_dev *ptdev, /* Header Type0 reg static infomation table */ static struct pt_reg_info_tbl pt_emu_reg_header0_tbl[] = { + /* Vendor ID reg */ + { + .offset = PCI_VENDOR_ID, + .size = 2, + .init_val = 0x0000, + .ro_mask = 0xFFFF, + .emu_mask = 0xFFFF, + .init = pt_vendor_reg_init, + .u.w.read = pt_word_reg_read, + .u.w.write = pt_word_reg_write, + }, + /* Device ID reg */ + { + .offset = PCI_DEVICE_ID, + .size = 2, + .init_val = 0x0000, + .ro_mask = 0xFFFF, + .emu_mask = 0xFFFF, + .init = pt_device_reg_init, + .u.w.read = pt_word_reg_read, + .u.w.write = pt_word_reg_write, + }, /* Command reg */ { .offset = PCI_COMMAND, @@ -1421,28 +1447,65 @@ exit: return val; } +static void pt_libpci_fixup(struct pci_dev *dev) +{ +#if PCI_LIB_VERSION < 0x030100 + int i; + FILE *fp; + char path[PATH_MAX], buf[256]; + unsigned long long start, end, flags; + + sprintf(path, "/sys/bus/pci/devices/%04x:%02x:%02x.%x/resource", + dev->domain, dev->bus, dev->dev, dev->func); + fp = fopen(path, "r"); + if ( !fp ) + { + PT_LOG("Can't open %s: %s\n", path, strerror(errno)); + return; + } + + for ( i = 0; i < PCI_NUM_REGIONS; i++ ) + { + if ( fscanf(fp, "%llx %llx %llx", &start, &end, &flags) != 3 ) + { + PT_LOG("Syntax error in %s\n", path); + break; + } + + flags &= 0xf; + + if ( i < PCI_ROM_SLOT ) + dev->base_addr[i] |= flags; + else + dev->rom_base_addr |= flags; + } + + fclose(fp); +#endif /* PCI_LIB_VERSION < 0x030100 */ +} + static int pt_register_regions(struct pt_dev *assigned_device) { int i = 0; - uint32_t bar_data = 0; struct pci_dev *pci_dev = assigned_device->pci_dev; PCIDevice *d = &assigned_device->dev; /* Register PIO/MMIO BARs */ for ( i = 0; i < PCI_BAR_ENTRIES; i++ ) { - if ( pci_dev->base_addr[i] ) + if ( pt_pci_base_addr(pci_dev->base_addr[i]) ) { - assigned_device->bases[i].e_physbase = pci_dev->base_addr[i]; - assigned_device->bases[i].access.u = pci_dev->base_addr[i]; + assigned_device->bases[i].e_physbase = + pt_pci_base_addr(pci_dev->base_addr[i]); + assigned_device->bases[i].access.u = + pt_pci_base_addr(pci_dev->base_addr[i]); /* Register current region */ - bar_data = *((uint32_t*)(d->config + PCI_BASE_ADDRESS_0) + i); - if ( bar_data & PCI_ADDRESS_SPACE_IO ) + if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_IO ) pci_register_io_region((PCIDevice *)assigned_device, i, (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_IO, pt_ioport_map); - else if ( bar_data & PCI_ADDRESS_SPACE_MEM_PREFETCH ) + else if ( pci_dev->base_addr[i] & PCI_ADDRESS_SPACE_MEM_PREFETCH ) pci_register_io_region((PCIDevice *)assigned_device, i, (uint32_t)pci_dev->size[i], PCI_ADDRESS_SPACE_MEM_PREFETCH, pt_iomem_map); @@ -1458,16 +1521,13 @@ static int pt_register_regions(struct pt_dev *assigned_device) } /* Register expansion ROM address */ - if ( pci_dev->rom_base_addr && pci_dev->rom_size ) + if ( pt_pci_base_addr(pci_dev->rom_base_addr) && pci_dev->rom_size ) { /* Re-set BAR reported by OS, otherwise ROM can't be read. */ - bar_data = pci_read_long(pci_dev, PCI_ROM_ADDRESS); - if ( (bar_data & PCI_ROM_ADDRESS_MASK) == 0 ) - { - bar_data |= (pci_dev->rom_base_addr & PCI_ROM_ADDRESS_MASK); - pci_write_long(pci_dev, PCI_ROM_ADDRESS, bar_data); - } + if ( (pci_dev->rom_base_addr & PCI_ROM_ADDRESS_MASK) == 0 ) + pci_write_long(pci_dev, PCI_ROM_ADDRESS, + (pci_dev->rom_base_addr | PCI_ROM_ADDRESS_MASK)); assigned_device->bases[PCI_ROM_SLOT].e_physbase = pci_dev->rom_base_addr; @@ -1569,21 +1629,14 @@ static int pt_bar_reg_parse( PCIDevice *d = &ptdev->dev; struct pt_region *region = NULL; PCIIORegion *r; - uint32_t bar_64 = (reg->offset - 4); int bar_flag = PT_BAR_FLAG_UNUSED; int index = 0; int i; - /* set again the BAR config because it has been overwritten - * by pci_register_io_region() - */ - for (i=reg->offset; i<(reg->offset + 4); i++) - d->config[i] = pci_read_byte(ptdev->pci_dev, i); - /* check 64bit BAR */ index = pt_bar_offset_to_index(reg->offset); if ((index > 0) && (index < PCI_ROM_SLOT) && - ((d->config[bar_64] & (PCI_BASE_ADDRESS_SPACE | + ((ptdev->pci_dev->base_addr[index-1] & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK)) == (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64))) { @@ -1608,7 +1661,7 @@ static int pt_bar_reg_parse( } /* check BAR I/O indicator */ - if (d->config[reg->offset] & PCI_BASE_ADDRESS_SPACE_IO) + if ( ptdev->pci_dev->base_addr[index] & PCI_BASE_ADDRESS_SPACE_IO ) bar_flag = PT_BAR_FLAG_IO; else bar_flag = PT_BAR_FLAG_MEM; @@ -1826,6 +1879,20 @@ static uint32_t pt_common_reg_init(struct pt_dev *ptdev, return reg->init_val; } +/* initialize Vendor ID register value */ +static uint32_t pt_vendor_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset) +{ + return ptdev->pci_dev->vendor_id; +} + +/* initialize Device ID register value */ +static uint32_t pt_device_reg_init(struct pt_dev *ptdev, + struct pt_reg_info_tbl *reg, uint32_t real_offset) +{ + return ptdev->pci_dev->device_id; +} + /* initialize Capabilities Pointer or Next Pointer register */ static uint32_t pt_ptr_reg_init(struct pt_dev *ptdev, struct pt_reg_info_tbl *reg, uint32_t real_offset) @@ -2310,6 +2377,9 @@ static int pt_bar_reg_read(struct pt_dev *ptdev, exit(1); } + /* use fixed-up value from kernel sysfs */ + *value = ptdev->pci_dev->base_addr[index]; + /* set emulate mask depend on BAR flag */ switch (ptdev->bases[index].bar_flag) { @@ -3025,6 +3095,7 @@ struct pt_dev * register_real_device(PCIBus *e_bus, return NULL; } pci_fill_info(pci_dev, PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES); + pt_libpci_fixup(pci_dev); if ( e_devfn == PT_VIRT_DEVFN_AUTO ) { /*indicate a static assignment(not hotplug), so find a free PCI hot plug slot */ diff --git a/hw/pass-through.h b/hw/pass-through.h index a7d2727..7a623be 100644 --- a/hw/pass-through.h +++ b/hw/pass-through.h @@ -297,5 +297,13 @@ struct pt_reg_info_tbl { } u; }; +static inline pciaddr_t pt_pci_base_addr(pciaddr_t base) +{ + if ( base & PCI_ADDRESS_SPACE_IO ) + return base & PCI_ADDR_IO_MASK; + + return base & PCI_ADDR_MEM_MASK; +} + #endif /* __PASSTHROUGH_H__ */ diff --git a/hw/pt-msi.c b/hw/pt-msi.c index 4f25186..9898763 100644 --- a/hw/pt-msi.c +++ b/hw/pt-msi.c @@ -314,7 +314,7 @@ int pt_msix_init(struct pt_dev *dev, int pos) table_off = pci_read_long(pd, pos + PCI_MSIX_TABLE); bar_index = dev->msix->bar_index = table_off & PCI_MSIX_BIR; table_off = dev->msix->table_off = table_off & ~PCI_MSIX_BIR; - dev->msix->table_base = dev->pci_dev->base_addr[bar_index]; + dev->msix->table_base = pt_pci_base_addr(dev->pci_dev->base_addr[bar_index]); PT_LOG("get MSI-X table bar base %llx\n", (unsigned long long)dev->msix->table_base); -- 1.5.6.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |