diff options
Diffstat (limited to 'hw/pci')
| -rw-r--r-- | hw/pci/pci.c | 40 | ||||
| -rw-r--r-- | hw/pci/pci_host.c | 2 | ||||
| -rw-r--r-- | hw/pci/pcie.c | 8 | ||||
| -rw-r--r-- | hw/pci/pcie_sriov.c | 1 |
4 files changed, 43 insertions, 8 deletions
diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e2eb4c3b4a..784c02a182 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -65,6 +65,7 @@ bool pci_available = true; static char *pcibus_get_dev_path(DeviceState *dev); static char *pcibus_get_fw_dev_path(DeviceState *dev); static void pcibus_reset(BusState *qbus); +static bool pcie_has_upstream_port(PCIDevice *dev); static Property pci_props[] = { DEFINE_PROP_PCI_DEVFN("addr", PCIDevice, devfn, -1), @@ -82,6 +83,8 @@ static Property pci_props[] = { DEFINE_PROP_UINT32("acpi-index", PCIDevice, acpi_index, 0), DEFINE_PROP_BIT("x-pcie-err-unc-mask", PCIDevice, cap_present, QEMU_PCIE_ERR_UNC_MASK_BITNR, true), + DEFINE_PROP_BIT("x-pcie-ari-nextfn-1", PCIDevice, cap_present, + QEMU_PCIE_ARI_NEXTFN_1_BITNR, false), DEFINE_PROP_END_OF_LIST() }; @@ -2121,6 +2124,25 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) } } + /* + * A PCIe Downstream Port that do not have ARI Forwarding enabled must + * associate only Device 0 with the device attached to the bus + * representing the Link from the Port (PCIe base spec rev 4.0 ver 0.3, + * sec 7.3.1). + * With ARI, PCI_SLOT() can return non-zero value as the traditional + * 5-bit Device Number and 3-bit Function Number fields in its associated + * Routing IDs, Requester IDs and Completer IDs are interpreted as a + * single 8-bit Function Number. Hence, ignore ARI capable devices. + */ + if (pci_is_express(pci_dev) && + !pcie_find_capability(pci_dev, PCI_EXT_CAP_ID_ARI) && + pcie_has_upstream_port(pci_dev) && + PCI_SLOT(pci_dev->devfn)) { + warn_report("PCI: slot %d is not valid for %s," + " parent device only allows plugging into slot 0.", + PCI_SLOT(pci_dev->devfn), pci_dev->name); + } + if (pci_dev->failover_pair_id) { if (!pci_bus_is_express(pci_get_bus(pci_dev))) { error_setg(errp, "failover primary device must be on " @@ -2164,8 +2186,8 @@ static void pci_qdev_realize(DeviceState *qdev, Error **errp) pci_dev->msi_trigger = pci_msi_trigger; } -PCIDevice *pci_new_multifunction(int devfn, bool multifunction, - const char *name) +static PCIDevice *pci_new_internal(int devfn, bool multifunction, + const char *name) { DeviceState *dev; @@ -2175,9 +2197,14 @@ PCIDevice *pci_new_multifunction(int devfn, bool multifunction, return PCI_DEVICE(dev); } +PCIDevice *pci_new_multifunction(int devfn, const char *name) +{ + return pci_new_internal(devfn, true, name); +} + PCIDevice *pci_new(int devfn, const char *name) { - return pci_new_multifunction(devfn, false, name); + return pci_new_internal(devfn, false, name); } bool pci_realize_and_unref(PCIDevice *dev, PCIBus *bus, Error **errp) @@ -2186,17 +2213,18 @@ bool pci_realize_and_unref(PCIDevice *dev, PCIBus *bus, Error **errp) } PCIDevice *pci_create_simple_multifunction(PCIBus *bus, int devfn, - bool multifunction, const char *name) { - PCIDevice *dev = pci_new_multifunction(devfn, multifunction, name); + PCIDevice *dev = pci_new_multifunction(devfn, name); pci_realize_and_unref(dev, bus, &error_fatal); return dev; } PCIDevice *pci_create_simple(PCIBus *bus, int devfn, const char *name) { - return pci_create_simple_multifunction(bus, devfn, false, name); + PCIDevice *dev = pci_new(devfn, name); + pci_realize_and_unref(dev, bus, &error_fatal); + return dev; } static uint8_t pci_find_space(PCIDevice *pdev, uint8_t size) diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index dfd185bbb4..7af8afdcbe 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -232,7 +232,7 @@ const VMStateDescription vmstate_pcihost = { static Property pci_host_properties_common[] = { DEFINE_PROP_BOOL("x-config-reg-migration-enabled", PCIHostState, mig_enabled, true), - DEFINE_PROP_BOOL("bypass-iommu", PCIHostState, bypass_iommu, false), + DEFINE_PROP_BOOL(PCI_HOST_BYPASS_IOMMU, PCIHostState, bypass_iommu, false), DEFINE_PROP_END_OF_LIST(), }; diff --git a/hw/pci/pcie.c b/hw/pci/pcie.c index b7f107ed8d..6db0cf69cd 100644 --- a/hw/pci/pcie.c +++ b/hw/pci/pcie.c @@ -666,6 +666,10 @@ void pcie_cap_slot_init(PCIDevice *dev, PCIESlot *s) pci_word_test_and_set_mask(dev->w1cmask + pos + PCI_EXP_SLTSTA, PCI_EXP_HP_EV_SUPPORTED); + /* Avoid migration abortion when this device hot-removed by guest */ + pci_word_test_and_clear_mask(dev->cmask + pos + PCI_EXP_SLTSTA, + PCI_EXP_SLTSTA_PDS); + dev->exp.hpev_notified = false; qbus_set_hotplug_handler(BUS(pci_bridge_get_sec_bus(PCI_BRIDGE(dev))), @@ -1035,8 +1039,10 @@ void pcie_sync_bridge_lnk(PCIDevice *bridge_dev) */ /* ARI */ -void pcie_ari_init(PCIDevice *dev, uint16_t offset, uint16_t nextfn) +void pcie_ari_init(PCIDevice *dev, uint16_t offset) { + uint16_t nextfn = dev->cap_present & QEMU_PCIE_ARI_NEXTFN_1 ? 1 : 0; + pcie_add_capability(dev, PCI_EXT_CAP_ID_ARI, PCI_ARI_VER, offset, PCI_ARI_SIZEOF); pci_set_long(dev->config + offset + PCI_ARI_CAP, (nextfn & 0xff) << 8); diff --git a/hw/pci/pcie_sriov.c b/hw/pci/pcie_sriov.c index aa5a757b11..76a3b6917e 100644 --- a/hw/pci/pcie_sriov.c +++ b/hw/pci/pcie_sriov.c @@ -211,6 +211,7 @@ static void unregister_vfs(PCIDevice *dev) error_free(local_err); } object_unparent(OBJECT(vf)); + object_unref(OBJECT(vf)); } g_free(dev->exp.sriov_pf.vf); dev->exp.sriov_pf.vf = NULL; |