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
|