Patchwork pci: Rework handling of multiple host bridges (pci domains)

login
register
mail settings
Submitter David Gibson
Date Dec. 17, 2012, 5:07 a.m.
Message ID <1355720844-15032-1-git-send-email-david@gibson.dropbear.id.au>
Download mbox | patch
Permalink /patch/206771/
State New
Headers show

Comments

David Gibson - Dec. 17, 2012, 5:07 a.m.
Currently the qemu core PCI code doesn't support a machine having
multiple independent PCI host bridges (aka PCI domains).  It does have
some incomplete stubs for such support, but unfortunately what's there
is based on a bogus premise.

PCI domains are often referenced by a PCI domain number, and the
current code stores a domain number for each root-level PCI bus
(although it's always set to 0 so far).  But by definition, the domain
number never appears on the PCI bus itself, so domain numbers are
assigned purely by convention.  Some platforms have a well defined
convention, for example on PC the domain numbers are assigned by
ACPI.  However other platforms have no strong convention, and so
domain numbering is performed entirely by the guest and we have no
reasonable way of knowing what it will pick.

Fixing this is complicated by the fact that the domain numbers are
exposed in migration streams via pcibus_get_dev_path().  We also can't
easily switch to using the qbus name as our identifier, because
libvirt and other tools often expect a bus named simply "pci" to exist
- including on platforms that would need the identifier "0000" to
match existing device paths.

This patch replaces the domain number in the PCIHostBus structure with
a string "root bus id".  The idea is that platforms which do have a
strong domain convention can derive this from the domain number, other
platforms can use whatever technique is appropriate to generate a
stable, clear id for each PCI host bridge.  The functions for creating
new PCI buses / host bridges now take an id.  If this is NULL, it is
treated as "0000" which makes the device paths backwards compatible
with existing migration streams.

Platforms are updated to supply root bus ids as follows:
 * Machines I believe support migration (x86, ARM), use NULL so that
the device paths don't change.

 * Machines that appear only to support a single PCI host bridge, but
which as far as I know don't (yet) support migration (i.e. most
things), use "pci" as the root bus ID.

 * PPC4xx can in theory support multiple host bridges in real
hardware, although our current models never construct that.  In this
case we use "pci@XXXX" for the root bus ID, where XXXX is the host
bridge's base IO address (on the system bus).  This changes device
paths, but migration is so broken on PPC at present it doesn't matter.

 * pseries (aka sPAPR) has more extensive existing support for
multiple host bridges, since multiple (indeed, numerous) PCI host
bridges are routine on "real" hardware (pseries is emulating an
existing defined para-virtualized environment).  Here we use
"pci@XXXX" as the root bus id, where XXXX is the BUID
(firmware supplied ID for the host bridge, which is used in hypervisor
calls).

This patch leaves pci_parse_devaddr() (and therefore its callers)
broken for machines that don't use the backwards compat "0000" id.
I'm looking at fixing that in a later version of this patch.

Cc: Michael S. Tsirkin <mst@redhat.com>

Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 hw/alpha_typhoon.c |    2 +-
 hw/apb_pci.c       |    2 +-
 hw/bonito.c        |    2 +-
 hw/grackle_pci.c   |    2 +-
 hw/gt64xxx.c       |    2 +-
 hw/pci-hotplug.c   |   22 +++--------
 hw/pci.c           |  104 ++++++++++++++++++++++++++++++++++++----------------
 hw/pci.h           |    9 +++--
 hw/pcie_aer.c      |    4 +-
 hw/piix_pci.c      |    2 +-
 hw/ppc4xx_pci.c    |    5 ++-
 hw/ppce500_pci.c   |    2 +-
 hw/prep_pci.c      |    2 +-
 hw/q35.c           |    2 +-
 hw/sh_pci.c        |    2 +-
 hw/spapr_pci.c     |    2 +-
 hw/unin_pci.c      |    4 +-
 hw/versatile_pci.c |    2 +-
 18 files changed, 103 insertions(+), 69 deletions(-)

Michael,

I know this is pretty ugly, but I haven't spotted any better way of
doing things, given th constraint of maintaining migration stream
compatibility.  Does something along these lines seem reasonable, or
is there another approach you'd prefer for fixing the domain problem.

Patch

diff --git a/hw/alpha_typhoon.c b/hw/alpha_typhoon.c
index 9b16d96..0736c8c 100644
--- a/hw/alpha_typhoon.c
+++ b/hw/alpha_typhoon.c
@@ -769,7 +769,7 @@  PCIBus *typhoon_init(ram_addr_t ram_size, ISABus **isa_bus,
     memory_region_add_subregion(addr_space, 0x801fc000000ULL,
                                 &s->pchip.reg_io);
 
-    b = pci_register_bus(dev, "pci",
+    b = pci_register_bus(dev, "pci", "pci",
                          typhoon_set_irq, sys_map_irq, s,
                          &s->pchip.reg_mem, addr_space_io, 0, 64);
     phb->bus = b;
diff --git a/hw/apb_pci.c b/hw/apb_pci.c
index 054814f..893864f 100644
--- a/hw/apb_pci.c
+++ b/hw/apb_pci.c
@@ -377,7 +377,7 @@  PCIBus *pci_apb_init(hwaddr special_base,
     memory_region_init(&d->pci_mmio, "pci-mmio", 0x100000000ULL);
     memory_region_add_subregion(get_system_memory(), mem_base, &d->pci_mmio);
 
-    d->bus = pci_register_bus(&d->busdev.qdev, "pci",
+    d->bus = pci_register_bus(&d->busdev.qdev, "pci", "pci",
                               pci_apb_set_irq, pci_pbm_map_irq, d,
                               &d->pci_mmio,
                               get_system_io(),
diff --git a/hw/bonito.c b/hw/bonito.c
index 0bf6d4a..1063133 100644
--- a/hw/bonito.c
+++ b/hw/bonito.c
@@ -704,7 +704,7 @@  static int bonito_pcihost_initfn(SysBusDevice *dev)
 {
     PCIHostState *phb = PCI_HOST_BRIDGE(dev);
 
-    phb->bus = pci_register_bus(DEVICE(dev), "pci",
+    phb->bus = pci_register_bus(DEVICE(dev), "pci", "pci",
                                 pci_bonito_set_irq, pci_bonito_map_irq, dev,
                                 get_system_memory(), get_system_io(),
                                 0x28, 32);
diff --git a/hw/grackle_pci.c b/hw/grackle_pci.c
index 67da307..2fe9148 100644
--- a/hw/grackle_pci.c
+++ b/hw/grackle_pci.c
@@ -82,7 +82,7 @@  PCIBus *pci_grackle_init(uint32_t base, qemu_irq *pic,
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    phb->bus = pci_register_bus(dev, "pci",
+    phb->bus = pci_register_bus(dev, "pci", "pci",
                                 pci_grackle_set_irq,
                                 pci_grackle_map_irq,
                                 pic,
diff --git a/hw/gt64xxx.c b/hw/gt64xxx.c
index 95d491d..6a127e7 100644
--- a/hw/gt64xxx.c
+++ b/hw/gt64xxx.c
@@ -1102,7 +1102,7 @@  PCIBus *gt64120_register(qemu_irq *pic)
     qdev_init_nofail(dev);
     d = GT64120_PCI_HOST_BRIDGE(dev);
     phb = PCI_HOST_BRIDGE(dev);
-    phb->bus = pci_register_bus(dev, "pci",
+    phb->bus = pci_register_bus(dev, "pci", "pci",
                                 gt64120_pci_set_irq, gt64120_pci_map_irq,
                                 pic,
                                 get_system_memory(),
diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 3bcfdcc..8fdcd08 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -113,18 +113,12 @@  static int scsi_hot_add(Monitor *mon, DeviceState *adapter,
 
 int pci_drive_hot_add(Monitor *mon, const QDict *qdict, DriveInfo *dinfo)
 {
-    int dom, pci_bus;
-    unsigned slot;
     PCIDevice *dev;
     const char *pci_addr = qdict_get_str(qdict, "pci_addr");
 
     switch (dinfo->type) {
     case IF_SCSI:
-        if (pci_read_devaddr(mon, pci_addr, &dom, &pci_bus, &slot)) {
-            goto err;
-        }
-        dev = pci_find_device(pci_find_root_bus(dom), pci_bus,
-                              PCI_DEVFN(slot, 0));
+        dev = pci_read_and_find_devaddr(mon, pci_addr);
         if (!dev) {
             monitor_printf(mon, "no pci device with address %s\n", pci_addr);
             goto err;
@@ -250,8 +244,8 @@  void pci_device_hot_add(Monitor *mon, const QDict *qdict)
     }
 
     if (dev) {
-        monitor_printf(mon, "OK domain %d, bus %d, slot %d, function %d\n",
-                       pci_find_domain(dev->bus),
+        monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n",
+                       pci_root_bus_id(dev->bus),
                        pci_bus_num(dev->bus), PCI_SLOT(dev->devfn),
                        PCI_FUNC(dev->devfn));
     } else
@@ -262,17 +256,11 @@  void pci_device_hot_add(Monitor *mon, const QDict *qdict)
 static int pci_device_hot_remove(Monitor *mon, const char *pci_addr)
 {
     PCIDevice *d;
-    int dom, bus;
-    unsigned slot;
     Error *local_err = NULL;
 
-    if (pci_read_devaddr(mon, pci_addr, &dom, &bus, &slot)) {
-        return -1;
-    }
-
-    d = pci_find_device(pci_find_root_bus(dom), bus, PCI_DEVFN(slot, 0));
+    d = pci_read_and_find_devaddr(mon, pci_addr);
     if (!d) {
-        monitor_printf(mon, "slot %d empty\n", slot);
+        monitor_printf(mon, "slot %s empty\n", pci_addr);
         return -1;
     }
 
diff --git a/hw/pci.c b/hw/pci.c
index 97a0cd7..27c3e1a 100644
--- a/hw/pci.c
+++ b/hw/pci.c
@@ -85,7 +85,7 @@  static uint16_t pci_default_sub_vendor_id = PCI_SUBVENDOR_ID_REDHAT_QUMRANET;
 static uint16_t pci_default_sub_device_id = PCI_SUBDEVICE_ID_QEMU;
 
 struct PCIHostBus {
-    int domain;
+    const char *root_bus_id;
     struct PCIBus *bus;
     QLIST_ENTRY(PCIHostBus) next;
 };
@@ -232,29 +232,29 @@  static int pcibus_reset(BusState *qbus)
     return 1;
 }
 
-static void pci_host_bus_register(int domain, PCIBus *bus)
+static void pci_host_bus_register(PCIBus *bus, const char *id)
 {
     struct PCIHostBus *host;
+
     host = g_malloc0(sizeof(*host));
-    host->domain = domain;
+    if (id) {
+        host->root_bus_id = g_strdup(id);
+    } else {
+        host->root_bus_id = "0000";
+    }
     host->bus = bus;
-    QLIST_INSERT_HEAD(&host_buses, host, next);
-}
-
-PCIBus *pci_find_root_bus(int domain)
-{
-    struct PCIHostBus *host;
 
     QLIST_FOREACH(host, &host_buses, next) {
-        if (host->domain == domain) {
-            return host->bus;
+        if (strcmp(id, host->root_bus_id) == 0) {
+            fprintf(stderr, "Duplicate id \"%s\" for PCI host bridges\n", id);
+            exit(1);
         }
     }
 
-    return NULL;
+    QLIST_INSERT_HEAD(&host_buses, host, next);
 }
 
-int pci_find_domain(const PCIBus *bus)
+const char *pci_root_bus_id(const PCIBus *bus)
 {
     PCIDevice *d;
     struct PCIHostBus *host;
@@ -266,16 +266,48 @@  int pci_find_domain(const PCIBus *bus)
 
     QLIST_FOREACH(host, &host_buses, next) {
         if (host->bus == bus) {
-            return host->domain;
+            return host->root_bus_id;
         }
     }
-
     abort();    /* should not be reached */
-    return -1;
+    return NULL;
+}
+
+#if 0
+static PCIBus *pci_find_root_bus_by_id(const char *id)
+{
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        if (strcmp(host->root_bus_id, id) == 0) {
+            return host->bus;
+        }
+    }
+
+    return NULL;
+}
+#endif
+
+static PCIBus *pci_find_root_bus_by_domain(int domain)
+{
+    struct PCIHostBus *host;
+
+    QLIST_FOREACH(host, &host_buses, next) {
+        int id_domain;
+        char *e;
+
+        id_domain = strtol(host->root_bus_id, &e, 16);
+        if ((*e == '\0') && (domain == id_domain)) {
+            return host->bus;
+        }
+    }
+
+    return NULL;
 }
 
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
+                         const char *root_bus_id,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min)
@@ -288,12 +320,13 @@  void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
 
     /* host bridge */
     QLIST_INIT(&bus->child);
-    pci_host_bus_register(0, bus); /* for now only pci domain 0 is supported */
+    pci_host_bus_register(bus, root_bus_id);
 
     vmstate_register(NULL, -1, &vmstate_pcibus, bus);
 }
 
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    const char *root_bus_id,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     uint8_t devfn_min)
@@ -301,8 +334,8 @@  PCIBus *pci_bus_new(DeviceState *parent, const char *name,
     PCIBus *bus;
 
     bus = g_malloc0(sizeof(*bus));
-    pci_bus_new_inplace(bus, parent, name, address_space_mem,
-                        address_space_io, devfn_min);
+    pci_bus_new_inplace(bus, parent, name, root_bus_id,
+                        address_space_mem, address_space_io, devfn_min);
     OBJECT(bus)->free = g_free;
     return bus;
 }
@@ -325,6 +358,7 @@  void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *qdev)
 }
 
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
+                         const char *root_bus_id,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
@@ -333,8 +367,8 @@  PCIBus *pci_register_bus(DeviceState *parent, const char *name,
 {
     PCIBus *bus;
 
-    bus = pci_bus_new(parent, name, address_space_mem,
-                      address_space_io, devfn_min);
+    bus = pci_bus_new(parent, name, root_bus_id,
+                      address_space_mem, address_space_io, devfn_min);
     pci_bus_irqs(bus, set_irq, map_irq, irq_opaque, nirq);
     return bus;
 }
@@ -557,36 +591,44 @@  static int pci_parse_devaddr(const char *addr, int *domp, int *busp,
     return 0;
 }
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp)
+PCIDevice *pci_read_and_find_devaddr(Monitor *mon, const char *addr)
 {
+    int domnum, busnum;
+    unsigned slotnum;
+    PCIBus *root_bus;
+
     /* strip legacy tag */
     if (!strncmp(addr, "pci_addr=", 9)) {
         addr += 9;
     }
-    if (pci_parse_devaddr(addr, domp, busp, slotp, NULL)) {
+    if (pci_parse_devaddr(addr, &domnum, &busnum, &slotnum, NULL)) {
         monitor_printf(mon, "Invalid pci address\n");
-        return -1;
+        return NULL;
     }
-    return 0;
+
+    root_bus = pci_find_root_bus_by_domain(domnum);
+    return pci_find_device(root_bus, busnum, PCI_DEVFN(slotnum, 0));
 }
 
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr)
 {
+    PCIBus *root_bus;
     int dom, bus;
     unsigned slot;
 
     if (!devaddr) {
+        root_bus = pci_find_root_bus_by_domain(0);
         *devfnp = -1;
-        return pci_find_bus_nr(pci_find_root_bus(0), 0);
+        return pci_find_bus_nr(root_bus, 0);
     }
 
     if (pci_parse_devaddr(devaddr, &dom, &bus, &slot, NULL) < 0) {
         return NULL;
     }
 
+    root_bus = pci_find_root_bus_by_domain(dom);
     *devfnp = PCI_DEVFN(slot, 0);
-    return pci_find_bus_nr(pci_find_root_bus(dom), bus);
+    return pci_find_bus_nr(root_bus, bus);
 }
 
 static void pci_init_cmask(PCIDevice *dev)
@@ -1913,10 +1955,10 @@  int pci_add_capability(PCIDevice *pdev, uint8_t cap_id,
         for (i = offset; i < offset + size; i++) {
             overlapping_cap = pci_find_capability_at_offset(pdev, i);
             if (overlapping_cap) {
-                fprintf(stderr, "ERROR: %04x:%02x:%02x.%x "
+                fprintf(stderr, "ERROR: %s:%02x:%02x.%x "
                         "Attempt to add PCI capability %x at offset "
                         "%x overlaps existing capability %x at offset %x\n",
-                        pci_find_domain(pdev->bus), pci_bus_num(pdev->bus),
+                        pci_root_bus_id(pdev->bus), pci_bus_num(pdev->bus),
                         PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
                         cap_id, offset, overlapping_cap, i);
                 return -EINVAL;
@@ -2071,7 +2113,7 @@  static char *pcibus_get_dev_path(DeviceState *dev)
     path[path_len] = '\0';
 
     /* First field is the domain. */
-    s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d->bus));
+    s = snprintf(domain, sizeof domain, "%s:00", pci_root_bus_id(d->bus));
     assert(s == domain_len);
     memcpy(path, domain, domain_len);
 
diff --git a/hw/pci.h b/hw/pci.h
index 4da0c2a..9c76178 100644
--- a/hw/pci.h
+++ b/hw/pci.h
@@ -308,10 +308,12 @@  typedef int (*pci_hotplug_fn)(DeviceState *qdev, PCIDevice *pci_dev,
                               PCIHotplugState state);
 void pci_bus_new_inplace(PCIBus *bus, DeviceState *parent,
                          const char *name,
+                         const char *root_bus_id,
                          MemoryRegion *address_space_mem,
                          MemoryRegion *address_space_io,
                          uint8_t devfn_min);
 PCIBus *pci_bus_new(DeviceState *parent, const char *name,
+                    const char *root_bus_id,
                     MemoryRegion *address_space_mem,
                     MemoryRegion *address_space_io,
                     uint8_t devfn_min);
@@ -322,6 +324,7 @@  void pci_bus_hotplug(PCIBus *bus, pci_hotplug_fn hotplug, DeviceState *dev);
 /* 0 <= pin <= 3 0 = INTA, 1 = INTB, 2 = INTC, 3 = INTD */
 int pci_swizzle_map_irq_fn(PCIDevice *pci_dev, int pin);
 PCIBus *pci_register_bus(DeviceState *parent, const char *name,
+                         const char *root_bus_id,
                          pci_set_irq_fn set_irq, pci_map_irq_fn map_irq,
                          void *irq_opaque,
                          MemoryRegion *address_space_mem,
@@ -347,14 +350,12 @@  int pci_bus_num(PCIBus *s);
 void pci_for_each_device(PCIBus *bus, int bus_num,
                          void (*fn)(PCIBus *bus, PCIDevice *d, void *opaque),
                          void *opaque);
-PCIBus *pci_find_root_bus(int domain);
-int pci_find_domain(const PCIBus *bus);
+const char *pci_root_bus_id(const PCIBus *bus);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, const char *devaddr);
 
-int pci_read_devaddr(Monitor *mon, const char *addr, int *domp, int *busp,
-                     unsigned *slotp);
+PCIDevice *pci_read_and_find_devaddr(Monitor *mon, const char *addr);
 
 void pci_device_deassert_intx(PCIDevice *dev);
 
diff --git a/hw/pcie_aer.c b/hw/pcie_aer.c
index b04c164..9c79b3f 100644
--- a/hw/pcie_aer.c
+++ b/hw/pcie_aer.c
@@ -1022,8 +1022,8 @@  int do_pcie_aer_inject_error(Monitor *mon,
     *ret_data = qobject_from_jsonf("{'id': %s, "
                                    "'domain': %d, 'bus': %d, 'devfn': %d, "
                                    "'ret': %d}",
-                                   id,
-                                   pci_find_domain(dev->bus),
+                                   /* FIXME: how do we encode host bridge ID */
+                                   id, 0,
                                    pci_bus_num(dev->bus), dev->devfn,
                                    ret);
     assert(*ret_data);
diff --git a/hw/piix_pci.c b/hw/piix_pci.c
index ba1b3de..0e15094 100644
--- a/hw/piix_pci.c
+++ b/hw/piix_pci.c
@@ -232,7 +232,7 @@  static PCIBus *i440fx_common_init(const char *device_name,
     dev = qdev_create(NULL, "i440FX-pcihost");
     s = PCI_HOST_BRIDGE(dev);
     s->address_space = address_space_mem;
-    b = pci_bus_new(dev, NULL, pci_address_space,
+    b = pci_bus_new(dev, NULL, NULL, pci_address_space,
                     address_space_io, 0);
     s->bus = b;
     object_property_add_child(qdev_get_machine(), "i440fx", OBJECT(dev), NULL);
diff --git a/hw/ppc4xx_pci.c b/hw/ppc4xx_pci.c
index d3ad6a0..0a1f072 100644
--- a/hw/ppc4xx_pci.c
+++ b/hw/ppc4xx_pci.c
@@ -335,6 +335,7 @@  static const VMStateDescription vmstate_ppc4xx_pci = {
 /* XXX Interrupt acknowledge cycles not supported. */
 static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
 {
+    char id[20];
     PPC4xxPCIState *s;
     PCIHostState *h;
     PCIBus *b;
@@ -343,11 +344,13 @@  static int ppc4xx_pcihost_initfn(SysBusDevice *dev)
     h = PCI_HOST_BRIDGE(dev);
     s = PPC4xx_PCI_HOST_BRIDGE(dev);
 
+    sprintf(id, "pci@%" HWADDR_PRIx, dev->mmio[0].addr);
+
     for (i = 0; i < ARRAY_SIZE(s->irq); i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    b = pci_register_bus(DEVICE(dev), NULL, ppc4xx_pci_set_irq,
+    b = pci_register_bus(DEVICE(dev), NULL, id, ppc4xx_pci_set_irq,
                          ppc4xx_pci_map_irq, s->irq, get_system_memory(),
                          get_system_io(), 0, 4);
     h->bus = b;
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 09e3507..4b579a0 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -354,7 +354,7 @@  static int e500_pcihost_initfn(SysBusDevice *dev)
 
     memory_region_init(&s->pio, "pci-pio", PCIE500_PCI_IOLEN);
 
-    b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
+    b = pci_register_bus(DEVICE(dev), "pci", "pci", mpc85xx_pci_set_irq,
                          mpc85xx_pci_map_irq, s->irq, address_space_mem,
                          &s->pio, PCI_DEVFN(s->first_slot, 0), 4);
     h->bus = b;
diff --git a/hw/prep_pci.c b/hw/prep_pci.c
index 0bc479c..ac71bd2 100644
--- a/hw/prep_pci.c
+++ b/hw/prep_pci.c
@@ -116,7 +116,7 @@  static int raven_pcihost_init(SysBusDevice *dev)
         sysbus_init_irq(dev, &s->irq[i]);
     }
 
-    bus = pci_register_bus(DEVICE(dev), NULL,
+    bus = pci_register_bus(DEVICE(dev), "pci", "pci",
                            prep_set_irq, prep_map_irq, s->irq,
                            address_space_mem, address_space_io, 0, 4);
     h->bus = bus;
diff --git a/hw/q35.c b/hw/q35.c
index efebc27..de5ba55 100644
--- a/hw/q35.c
+++ b/hw/q35.c
@@ -53,7 +53,7 @@  static int q35_host_init(SysBusDevice *dev)
     if (pcie_host_init(&s->host) < 0) {
         return -1;
     }
-    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0",
+    b = pci_bus_new(&s->host.pci.busdev.qdev, "pcie.0", NULL,
                     s->mch.pci_address_space, s->mch.address_space_io, 0);
     s->host.pci.bus = b;
     qdev_set_parent_bus(DEVICE(&s->mch), BUS(b));
diff --git a/hw/sh_pci.c b/hw/sh_pci.c
index fdec71b..f1ae2bc 100644
--- a/hw/sh_pci.c
+++ b/hw/sh_pci.c
@@ -119,7 +119,7 @@  static int sh_pci_device_init(SysBusDevice *dev)
     for (i = 0; i < 4; i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
-    s->bus = pci_register_bus(&s->busdev.qdev, "pci",
+    s->bus = pci_register_bus(&s->busdev.qdev, "pci", "pci",
                               sh_pci_set_irq, sh_pci_map_irq,
                               s->irq,
                               get_system_memory(),
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index a6885c4..103dab3 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -621,7 +621,7 @@  static int spapr_phb_init(SysBusDevice *s)
                                     &sphb->msiwindow);
     }
 
-    bus = pci_register_bus(DEVICE(s), sphb->busname,
+    bus = pci_register_bus(DEVICE(s), sphb->busname, sphb->dtbusname,
                            pci_spapr_set_irq, pci_spapr_map_irq, sphb,
                            &sphb->memspace, &sphb->iospace,
                            PCI_DEVFN(0, 0), PCI_NUM_PINS);
diff --git a/hw/unin_pci.c b/hw/unin_pci.c
index 9981d94..5f4cebd 100644
--- a/hw/unin_pci.c
+++ b/hw/unin_pci.c
@@ -234,7 +234,7 @@  PCIBus *pci_pmac_init(qemu_irq *pic,
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    h->bus = pci_register_bus(dev, "pci",
+    h->bus = pci_register_bus(dev, "pci", "pci",
                               pci_unin_set_irq, pci_unin_map_irq,
                               pic,
                               &d->pci_mmio,
@@ -300,7 +300,7 @@  PCIBus *pci_pmac_u3_init(qemu_irq *pic,
     memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                 &d->pci_hole);
 
-    h->bus = pci_register_bus(dev, "pci",
+    h->bus = pci_register_bus(dev, "pci", "pci",
                               pci_unin_set_irq, pci_unin_map_irq,
                               pic,
                               &d->pci_mmio,
diff --git a/hw/versatile_pci.c b/hw/versatile_pci.c
index e0c3ee3..6395a08 100644
--- a/hw/versatile_pci.c
+++ b/hw/versatile_pci.c
@@ -67,7 +67,7 @@  static int pci_vpb_init(SysBusDevice *dev)
     for (i = 0; i < 4; i++) {
         sysbus_init_irq(dev, &s->irq[i]);
     }
-    bus = pci_register_bus(&dev->qdev, "pci",
+    bus = pci_register_bus(&dev->qdev, "pci", NULL,
                            pci_vpb_set_irq, pci_vpb_map_irq, s->irq,
                            get_system_memory(), get_system_io(),
                            PCI_DEVFN(11, 0), 4);