From 3f3cbbb2369ebba67cccf8c60d6a0043b315e17c Mon Sep 17 00:00:00 2001 From: Julia Suvorova Date: Tue, 13 Jul 2021 02:42:02 +0200 Subject: hw/pci/pcie: Do not set HPC flag if acpihp is used Instead of changing the hot-plug type in _OSC register, do not set the 'Hot-Plug Capable' flag. This way guest will choose ACPI hot-plug if it is preferred and leave the option to use SHPC with pcie-pci-bridge. The ability to control hot-plug for each downstream port is retained, while 'hotplug=off' on the port means all hot-plug types are disabled. Signed-off-by: Julia Suvorova Reviewed-by: Igor Mammedov Reviewed-by: Marcel Apfelbaum Reviewed-by: David Gibson Message-Id: <20210713004205.775386-4-jusual@redhat.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/pci/pcie_port.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'include/hw/pci') diff --git a/include/hw/pci/pcie_port.h b/include/hw/pci/pcie_port.h index bea8ecad0f..e25b289ce8 100644 --- a/include/hw/pci/pcie_port.h +++ b/include/hw/pci/pcie_port.h @@ -57,8 +57,11 @@ struct PCIESlot { /* Disable ACS (really for a pcie_root_port) */ bool disable_acs; - /* Indicates whether hot-plug is enabled on the slot */ + /* Indicates whether any type of hot-plug is allowed on the slot */ bool hotplug; + + bool native_hotplug; + QLIST_ENTRY(PCIESlot) next; }; -- cgit 1.4.1 From 2d64b7bbb2a2e945635633486ef9a060cb2c89bc Mon Sep 17 00:00:00 2001 From: Xingang Wang Date: Thu, 8 Jul 2021 12:55:11 +0000 Subject: hw/pci/pci_host: Allow PCI host to bypass iommu Add a new bypass_iommu property for PCI host and use it to check whether devices attached to the PCI root bus will bypass iommu. In pci_device_iommu_address_space(), check the property and avoid getting iommu address space for devices bypass iommu. Signed-off-by: Xingang Wang Reviewed-by: Eric Auger Message-Id: <1625748919-52456-2-git-send-email-wangxingang5@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 18 +++++++++++++++++- hw/pci/pci_host.c | 1 + include/hw/pci/pci.h | 1 + include/hw/pci/pci_host.h | 1 + 4 files changed, 20 insertions(+), 1 deletion(-) (limited to 'include/hw/pci') diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 377084f1a8..27d588e268 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -416,6 +416,22 @@ const char *pci_root_bus_path(PCIDevice *dev) return rootbus->qbus.name; } +bool pci_bus_bypass_iommu(PCIBus *bus) +{ + PCIBus *rootbus = bus; + PCIHostState *host_bridge; + + if (!pci_bus_is_root(bus)) { + rootbus = pci_device_root_bus(bus->parent_dev); + } + + host_bridge = PCI_HOST_BRIDGE(rootbus->qbus.parent); + + assert(host_bridge->bus == rootbus); + + return host_bridge->bypass_iommu; +} + static void pci_root_bus_init(PCIBus *bus, DeviceState *parent, MemoryRegion *address_space_mem, MemoryRegion *address_space_io, @@ -2718,7 +2734,7 @@ AddressSpace *pci_device_iommu_address_space(PCIDevice *dev) iommu_bus = parent_bus; } - if (iommu_bus && iommu_bus->iommu_fn) { + if (!pci_bus_bypass_iommu(bus) && iommu_bus && iommu_bus->iommu_fn) { return iommu_bus->iommu_fn(bus, iommu_bus->iommu_opaque, devfn); } return &address_space_memory; diff --git a/hw/pci/pci_host.c b/hw/pci/pci_host.c index 8ca5fadcbd..cf02f0d6a5 100644 --- a/hw/pci/pci_host.c +++ b/hw/pci/pci_host.c @@ -222,6 +222,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_END_OF_LIST(), }; diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index 6be4e0c460..f4d51b672b 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -480,6 +480,7 @@ void pci_for_each_bus(PCIBus *bus, PCIBus *pci_device_root_bus(const PCIDevice *d); const char *pci_root_bus_path(PCIDevice *dev); +bool pci_bus_bypass_iommu(PCIBus *bus); PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn); int pci_qdev_find_device(const char *id, PCIDevice **pdev); void pci_bus_get_w64_range(PCIBus *bus, Range *range); diff --git a/include/hw/pci/pci_host.h b/include/hw/pci/pci_host.h index 52e038c019..c6f4eb4585 100644 --- a/include/hw/pci/pci_host.h +++ b/include/hw/pci/pci_host.h @@ -43,6 +43,7 @@ struct PCIHostState { uint32_t config_reg; bool mig_enabled; PCIBus *bus; + bool bypass_iommu; QLIST_ENTRY(PCIHostState) next; }; -- cgit 1.4.1 From 500db1daf3079c3d0222bd3963cf4e5bf6175175 Mon Sep 17 00:00:00 2001 From: Xingang Wang Date: Thu, 8 Jul 2021 12:55:15 +0000 Subject: hw/pci: Add pci_bus_range() to get PCI bus number range This helps to get the min and max bus number of a PCI bus hierarchy. Signed-off-by: Xingang Wang Reviewed-by: Eric Auger Message-Id: <1625748919-52456-6-git-send-email-wangxingang5@huawei.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- hw/pci/pci.c | 16 ++++++++++++++++ include/hw/pci/pci.h | 1 + 2 files changed, 17 insertions(+) (limited to 'include/hw/pci') diff --git a/hw/pci/pci.c b/hw/pci/pci.c index 27d588e268..23d2ae2ab2 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -537,6 +537,22 @@ int pci_bus_num(PCIBus *s) return PCI_BUS_GET_CLASS(s)->bus_num(s); } +/* Returns the min and max bus numbers of a PCI bus hierarchy */ +void pci_bus_range(PCIBus *bus, int *min_bus, int *max_bus) +{ + int i; + *min_bus = *max_bus = pci_bus_num(bus); + + for (i = 0; i < ARRAY_SIZE(bus->devices); ++i) { + PCIDevice *dev = bus->devices[i]; + + if (dev && PCI_DEVICE_GET_CLASS(dev)->is_bridge) { + *min_bus = MIN(*min_bus, dev->config[PCI_SECONDARY_BUS]); + *max_bus = MAX(*max_bus, dev->config[PCI_SUBORDINATE_BUS]); + } + } +} + int pci_bus_numa_node(PCIBus *bus) { return PCI_BUS_GET_CLASS(bus)->numa_node(bus); diff --git a/include/hw/pci/pci.h b/include/hw/pci/pci.h index f4d51b672b..d0f4266e37 100644 --- a/include/hw/pci/pci.h +++ b/include/hw/pci/pci.h @@ -450,6 +450,7 @@ static inline PCIBus *pci_get_bus(const PCIDevice *dev) return PCI_BUS(qdev_get_parent_bus(DEVICE(dev))); } int pci_bus_num(PCIBus *s); +void pci_bus_range(PCIBus *bus, int *min_bus, int *max_bus); static inline int pci_dev_bus_num(const PCIDevice *dev) { return pci_bus_num(pci_get_bus(dev)); -- cgit 1.4.1