[sorry if you get this twice, I had an email hiccup sending this]
Hi folks,
In our SVVP testing, we noticed that the Microsoft HCT requires that PCI
subsystem IDs are set for all PCI devices. Meaning that for Xen to be a
compliant virtualization platform, qemu-dm must have these set for all
devices.
A comment in tools/ioemu/hw/xen_platform.c notes that this is a known
issue, and other source files show that the intent is to use the
XenSource ID (0x5853) for the subsystem vendor ID, and 0x0001 for the
subsystem id throughout.
But, this isn't done across the board (e.g. the PIIX bridge devices
don't have these IDs). This makes the Microsoft HCT fail.
Attached is a patch that makes pci_register_device initialize these
values with the 0x5853/0x0001 defaults, and removes the explicit inits
of these values in the various devices.
A few issues that are worthy of discussion: since Windows use the
subsystem IDs in its device tree, Windows systems will come up with
'found new hardware' after this patch. But, they will just reload the
same driver, of course, and live happily ever after. Also, we considered
using Sun PCI subsystem IDs (as we do on our actual hardware), but
figured that it would be better to use the XenSource ids, so that all
Xen-based products out there can use eachothers virtual machines with
minimal hassle.
- Frank
Init PCI subsystem IDs consistently.
Store default values for the PCI subsystem IDs (offset 0x2c in config space)
in the PCIBus structure, and propagate them to all devices when they
are registered. Remove all explicit initialization of these values
in the various qemu devices.
Signed-off-by: Frank van der Linden <Frank.Vanderlinden@xxxxxxx>
diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c
--- a/tools/ioemu/hw/cirrus_vga.c
+++ b/tools/ioemu/hw/cirrus_vga.c
@@ -3360,10 +3360,6 @@ void pci_cirrus_vga_init(PCIBus *bus, Di
pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
- pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
- pci_conf[0x2d] = 0x58;
- pci_conf[0x2e] = 0x01; /* subsystem device */
- pci_conf[0x2f] = 0x00;
/* setup VGA */
s = &d->cirrus_vga;
diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c
--- a/tools/ioemu/hw/ide.c
+++ b/tools/ioemu/hw/ide.c
@@ -2779,10 +2779,6 @@ void pci_piix_ide_init(PCIBus *bus, Bloc
pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
- pci_conf[0x2d] = 0x58;
- pci_conf[0x2e] = 0x01; /* subsystem device */
- pci_conf[0x2f] = 0x00;
piix3_reset(d);
diff --git a/tools/ioemu/hw/ne2000.c b/tools/ioemu/hw/ne2000.c
--- a/tools/ioemu/hw/ne2000.c
+++ b/tools/ioemu/hw/ne2000.c
@@ -834,10 +834,6 @@ void pci_ne2000_init(PCIBus *bus, NICInf
pci_conf[0x0a] = 0x00; // ethernet network controller
pci_conf[0x0b] = 0x02;
pci_conf[0x0e] = 0x00; // header_type
- pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
- pci_conf[0x2d] = 0x58;
- pci_conf[0x2e] = 0x01; /* subsystem device */
- pci_conf[0x2f] = 0x00;
pci_conf[0x3d] = 1; // interrupt pin 0
pci_register_io_region(&d->dev, 0, 0x100,
diff --git a/tools/ioemu/hw/pci.c b/tools/ioemu/hw/pci.c
--- a/tools/ioemu/hw/pci.c
+++ b/tools/ioemu/hw/pci.c
@@ -37,6 +37,7 @@ struct PCIBus {
PCIDevice *devices[256];
PCIDevice *parent_dev;
PCIBus *next;
+ uint8_t subsys_config[4]; /* Defaults for devices on this bus */
/* The bus IRQ state is the logical OR of the connected devices.
Keep a count of the number of devices with raised IRQs. */
int irq_count[];
@@ -47,6 +48,29 @@ target_phys_addr_t pci_mem_base;
target_phys_addr_t pci_mem_base;
static int pci_irq_index;
static PCIBus *first_bus;
+
+void pci_init_bus_subsysid(PCIBus *bus, uint16_t vendor_id, uint16_t device_id)
+{
+ PCIDevice *bd;
+ int i;
+
+ bus->subsys_config[0] = vendor_id & 0xff;
+ bus->subsys_config[1] = vendor_id >> 8;
+ bus->subsys_config[2] = device_id & 0xff;
+ bus->subsys_config[3] = device_id >> 8;
+
+ for (i = bus->devfn_min; i < 256; i++) {
+ bd = bus->devices[i];
+ if (bd == NULL)
+ continue;
+ pci_init_device_subsysid(bus, bd);
+ }
+}
+
+void pci_init_device_subsysid(PCIBus *bus, PCIDevice *d)
+{
+ memcpy(&d->config[0x2c], bus->subsys_config, 4);
+}
PCIBus *pci_register_bus(pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
void *pic, int devfn_min, int nirq)
@@ -69,6 +93,7 @@ PCIBus *pci_register_secondary_bus(PCIDe
bus->parent_dev = dev;
bus->next = dev->bus->next;
dev->bus->next = bus;
+ memcpy(bus->subsys_config, &dev->config[0x2c], 4);
return bus;
}
@@ -129,6 +154,7 @@ PCIDevice *pci_register_device(PCIBus *b
pci_dev->config_write = config_write;
pci_dev->irq_index = pci_irq_index++;
bus->devices[devfn] = pci_dev;
+ pci_init_device_subsysid(bus, pci_dev);
return pci_dev;
}
diff --git a/tools/ioemu/hw/rtl8139.c b/tools/ioemu/hw/rtl8139.c
--- a/tools/ioemu/hw/rtl8139.c
+++ b/tools/ioemu/hw/rtl8139.c
@@ -3449,10 +3449,6 @@ void pci_rtl8139_init(PCIBus *bus, NICIn
pci_conf[0x0e] = 0x00; /* header_type */
pci_conf[0x3d] = 1; /* interrupt pin 0 */
pci_conf[0x34] = 0xdc;
- pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */
- pci_conf[0x2d] = 0x58;
- pci_conf[0x2e] = 0x01; /* subsystem device */
- pci_conf[0x2f] = 0x00;
s = &d->rtl8139;
diff --git a/tools/ioemu/hw/xen_platform.c b/tools/ioemu/hw/xen_platform.c
--- a/tools/ioemu/hw/xen_platform.c
+++ b/tools/ioemu/hw/xen_platform.c
@@ -116,8 +116,9 @@ int xen_pci_load(QEMUFile *f, void *opaq
void pci_xen_platform_init(PCIBus *bus)
{
- PCIDevice *d;
+ PCIDevice *d, *bd;
struct pci_config_header *pch;
+ int i;
printf("Register xen platform.\n");
d = pci_register_device(bus, "xen-platform", sizeof(PCIDevice), -1, NULL,
@@ -133,10 +134,17 @@ void pci_xen_platform_init(PCIBus *bus)
pch->header_type = 0;
pch->interrupt_pin = 1;
- /* Microsoft WHQL requires non-zero subsystem IDs. */
- /* http://www.pcisig.com/reflector/msg02205.html. */
- pch->subsystem_vendor_id = pch->vendor_id; /* Duplicate vendor id. */
- pch->subsystem_id = 0x0001; /* Hardcode sub-id as 1. */
+ /*
+ * Microsoft WHQL requires non-zero subsystem IDs.
+ * http://www.pcisig.com/reflector/msg02205.html.
+ *
+ * Duplicate the XenSource 0x5853,0x0001 ids for all devices
+ * as the default.
+ *
+ * The init function for a device can override this.
+ */
+
+ pci_init_bus_subsysid(bus, pch->vendor_id, pch->device_id);
pci_register_io_region(d, 0, 0x100, PCI_ADDRESS_SPACE_IO,
platform_ioport_map);
diff --git a/tools/ioemu/vl.h b/tools/ioemu/vl.h
--- a/tools/ioemu/vl.h
+++ b/tools/ioemu/vl.h
@@ -831,6 +831,9 @@ void pci_register_io_region(PCIDevice *p
uint32_t size, int type,
PCIMapIORegionFunc *map_func);
+void pci_init_bus_subsysid(PCIBus *, uint16_t, uint16_t);
+void pci_init_device_subsysid(PCIBus *, PCIDevice *);
+
void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level);
uint32_t pci_default_read_config(PCIDevice *d,
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|