diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c index f9e68c30999c9cea119be103fbcd5872bc2348ef..c36e725ba1c1f044b321a7799cff79eee40efe9b 100644 --- a/hw/pci-host/piix.c +++ b/hw/pci-host/piix.c @@ -629,11 +629,20 @@ static const TypeInfo i440fx_info = { .class_init = i440fx_class_init, }; +static const char *i440fx_pcihost_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + /* For backwards compat with old device paths */ + return "0000"; +} + static void i440fx_pcihost_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + hc->root_bus_path = i440fx_pcihost_root_bus_path; k->init = i440fx_pcihost_initfn; dc->fw_name = "pci"; dc->no_user = 1; diff --git a/hw/pci-host/q35.c b/hw/pci-host/q35.c index 3a5cff989e475c60801d9553753e9d6f11ed183d..13148ed533513bcb4b3a2787bcae23c124ab74f3 100644 --- a/hw/pci-host/q35.c +++ b/hw/pci-host/q35.c @@ -63,6 +63,13 @@ static int q35_host_init(SysBusDevice *dev) return 0; } +static const char *q35_host_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + /* For backwards compat with old device paths */ + return "0000"; +} + static Property mch_props[] = { DEFINE_PROP_UINT64("MCFG", Q35PCIHost, host.base_addr, MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT), @@ -73,7 +80,9 @@ static void q35_host_class_init(ObjectClass *klass, void *data) { DeviceClass *dc = DEVICE_CLASS(klass); SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); + hc->root_bus_path = q35_host_root_bus_path; k->init = q35_host_init; dc->props = mch_props; dc->fw_name = "pci"; diff --git a/hw/pci/pci-hotplug-old.c b/hw/pci/pci-hotplug-old.c index 37e0720513431ce7905fba0f6825d95d9643300f..e2518108f40ea2c8c5a3e0521728d3ddccac2651 100644 --- a/hw/pci/pci-hotplug-old.c +++ b/hw/pci/pci-hotplug-old.c @@ -275,8 +275,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), + monitor_printf(mon, "OK root bus %s, bus %d, slot %d, function %d\n", + pci_root_bus_path(dev), pci_bus_num(dev->bus), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn)); } else diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 69a699574e978124f8146e09cf17b4ff5bdf7334..350b87229487ea2a0a635820390390cd4334190c 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -25,6 +25,7 @@ #include "hw/pci/pci.h" #include "hw/pci/pci_bridge.h" #include "hw/pci/pci_bus.h" +#include "hw/pci/pci_host.h" #include "monitor/monitor.h" #include "net/net.h" #include "sysemu/sysemu.h" @@ -270,19 +271,20 @@ PCIBus *pci_device_root_bus(const PCIDevice *d) return bus; } -int pci_find_domain(const PCIDevice *dev) +const char *pci_root_bus_path(PCIDevice *dev) { - const PCIBus *rootbus = pci_device_root_bus(dev); - struct PCIHostBus *host; + PCIBus *rootbus = pci_device_root_bus(dev); + PCIHostState *host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent); + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_GET_CLASS(host_bridge); - QLIST_FOREACH(host, &host_buses, next) { - if (host->bus == rootbus) { - return host->domain; - } + assert(!rootbus->parent_dev); + assert(host_bridge->bus == rootbus); + + if (hc->root_bus_path) { + return (*hc->root_bus_path)(host_bridge, rootbus); } - abort(); /* should not be reached */ - return -1; + return rootbus->qbus.name; } static void pci_bus_init(PCIBus *bus, DeviceState *parent, @@ -2000,10 +2002,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), pci_bus_num(pdev->bus), + pci_root_bus_path(pdev), pci_bus_num(pdev->bus), PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), cap_id, offset, overlapping_cap, i); return -EINVAL; @@ -2137,30 +2139,30 @@ static char *pcibus_get_dev_path(DeviceState *dev) * domain:Bus:Slot.Func for systems without nested PCI bridges. * Slot.Function list specifies the slot and function numbers for all * devices on the path from root to the specific device. */ - char domain[] = "DDDD:00"; + const char *root_bus_path; + int root_bus_len; char slot[] = ":SS.F"; - int domain_len = sizeof domain - 1 /* For '\0' */; int slot_len = sizeof slot - 1 /* For '\0' */; int path_len; char *path, *p; int s; + root_bus_path = pci_root_bus_path(d); + root_bus_len = strlen(root_bus_path); + /* Calculate # of slots on path between device and root. */; slot_depth = 0; for (t = d; t; t = t->bus->parent_dev) { ++slot_depth; } - path_len = domain_len + slot_len * slot_depth; + path_len = root_bus_len + slot_len * slot_depth; /* Allocate memory, fill in the terminating null byte. */ path = g_malloc(path_len + 1 /* For '\0' */); path[path_len] = '\0'; - /* First field is the domain. */ - s = snprintf(domain, sizeof domain, "%04x:00", pci_find_domain(d)); - assert(s == domain_len); - memcpy(path, domain, domain_len); + memcpy(path, root_bus_path, root_bus_len); /* Fill in slot numbers. We walk up from device to root, so need to print * them in the reverse order, last to first. */ diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 12254b18a925d68a9c169d9bb7c4c66bab17c8d9..7dd9b25609d7778bc4def15ea34904bb9eabc88b 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -169,6 +169,7 @@ static const TypeInfo pci_host_type_info = { .name = TYPE_PCI_HOST_BRIDGE, .parent = TYPE_SYS_BUS_DEVICE, .abstract = true, + .class_size = sizeof(PCIHostBridgeClass), .instance_size = sizeof(PCIHostState), }; diff --git a/hw/pci/pcie_aer.c b/hw/pci/pcie_aer.c index 06f77acc21bee8b4e88af81dff5098ab93ad5d73..ca762ab09a211a0c1a24667ba2efc665031f8326 100644 --- a/hw/pci/pcie_aer.c +++ b/hw/pci/pcie_aer.c @@ -817,9 +817,9 @@ void pcie_aer_inject_error_print(Monitor *mon, const QObject *data) qdict = qobject_to_qdict(data); devfn = (int)qdict_get_int(qdict, "devfn"); - monitor_printf(mon, "OK id: %s domain: %x, bus: %x devfn: %x.%x\n", + monitor_printf(mon, "OK id: %s root bus: %s, bus: %x devfn: %x.%x\n", qdict_get_str(qdict, "id"), - (int) qdict_get_int(qdict, "domain"), + qdict_get_str(qdict, "root_bus"), (int) qdict_get_int(qdict, "bus"), PCI_SLOT(devfn), PCI_FUNC(devfn)); } @@ -1020,9 +1020,9 @@ int do_pcie_aer_inject_error(Monitor *mon, ret = pcie_aer_inject_error(dev, &err); *ret_data = qobject_from_jsonf("{'id': %s, " - "'domain': %d, 'bus': %d, 'devfn': %d, " + "'root_bus': %s, 'bus': %d, 'devfn': %d, " "'ret': %d}", - id, pci_find_domain(dev), + id, pci_root_bus_path(dev), pci_bus_num(dev->bus), dev->devfn, ret); assert(*ret_data); diff --git a/hw/ppc/spapr_pci.c b/hw/ppc/spapr_pci.c index c8c12c8241b2a7cd24d3ac99d3f16b31efa14954..f7be24c755f16fde4a49f8c9d8895c073df8a772 100644 --- a/hw/ppc/spapr_pci.c +++ b/hw/ppc/spapr_pci.c @@ -696,11 +696,21 @@ static Property spapr_phb_properties[] = { DEFINE_PROP_END_OF_LIST(), }; +static const char *spapr_phb_root_bus_path(PCIHostState *host_bridge, + PCIBus *rootbus) +{ + sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(host_bridge); + + return sphb->dtbusname; +} + static void spapr_phb_class_init(ObjectClass *klass, void *data) { + PCIHostBridgeClass *hc = PCI_HOST_BRIDGE_CLASS(klass); SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass); DeviceClass *dc = DEVICE_CLASS(klass); + hc->root_bus_path = spapr_phb_root_bus_path; sdc->init = spapr_phb_init; dc->props = spapr_phb_properties; dc->reset = spapr_phb_reset; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index f2bf1edbd9d0ba88651c4a51b7b965df2982d626..e0597b7e9e838de2a44850260e4b2f1545e3efbe 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -391,7 +391,7 @@ void pci_for_each_device(PCIBus *bus, int bus_num, void *opaque); PCIBus *pci_find_primary_bus(void); PCIBus *pci_device_root_bus(const PCIDevice *d); -int pci_find_domain(const PCIDevice *dev); +const char *pci_root_bus_path(PCIDevice *dev); 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); diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h index 236cd0f75cb946e49fb845727c5137720b7b799b..44052f2b4d7eaabeead2dbfba2a83ad6f5e132bd 100644 --- a/include/hw/pci/pci_host.h +++ b/include/hw/pci/pci_host.h @@ -33,6 +33,10 @@ #define TYPE_PCI_HOST_BRIDGE "pci-host-bridge" #define PCI_HOST_BRIDGE(obj) \ OBJECT_CHECK(PCIHostState, (obj), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_CLASS(klass) \ + OBJECT_CLASS_CHECK(PCIHostBridgeClass, (klass), TYPE_PCI_HOST_BRIDGE) +#define PCI_HOST_BRIDGE_GET_CLASS(obj) \ + OBJECT_GET_CLASS(PCIHostBridgeClass, (obj), TYPE_PCI_HOST_BRIDGE) struct PCIHostState { SysBusDevice busdev; @@ -44,6 +48,12 @@ struct PCIHostState { PCIBus *bus; }; +typedef struct PCIHostBridgeClass { + SysBusDeviceClass parent_class; + + const char *(*root_bus_path)(PCIHostState *, PCIBus *); +} PCIHostBridgeClass; + /* common internal helpers for PCI/PCIe hosts, cut off overflows */ void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr, uint32_t limit, uint32_t val, uint32_t len);