aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBernhard Beschow <shentey@gmail.com>2025-02-23 12:46:52 +0100
committerPeter Maydell <peter.maydell@linaro.org>2025-02-25 15:32:58 +0000
commitfaa2150a527b1919646316dba268b71ced8762a6 (patch)
tree87fb257b28cb2b39b6f8418ae89bd5b5d4ad484e
parentb513766ee968dbfca31034b185f0a0fcf99f4269 (diff)
downloadqemu-faa2150a527b1919646316dba268b71ced8762a6.zip
qemu-faa2150a527b1919646316dba268b71ced8762a6.tar.gz
qemu-faa2150a527b1919646316dba268b71ced8762a6.tar.bz2
hw/pci-host/designware: Prevent device attachment on internal PCIe root bus
On the real device, the PCIe root bus is only connected to a PCIe bridge and does not allow for direct attachment of devices. Doing so in QEMU results in no PCI devices being detected by Linux. Instead, PCI devices should plug into the secondary PCIe bus spawned by the internal PCIe bridge. Unfortunately, QEMU defaults to plugging devices into the PCIe root bus. To work around this, every PCI device created on the command line needs an extra `bus=dw-pcie` option which is error prone. Fix that by marking the PCIe root bus as full which makes QEMU decend into the child PCIe bus. Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Bernhard Beschow <shentey@gmail.com> Message-id: 20250223114708.1780-3-shentey@gmail.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--hw/pci-host/designware.c18
-rw-r--r--include/hw/pci-host/designware.h7
2 files changed, 24 insertions, 1 deletions
diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index 3e8c36e..c07740b 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -55,6 +55,17 @@
#define DESIGNWARE_PCIE_ATU_DEVFN(x) (((x) >> 16) & 0xff)
#define DESIGNWARE_PCIE_ATU_UPPER_TARGET 0x91C
+static void designware_pcie_root_bus_class_init(ObjectClass *klass, void *data)
+{
+ BusClass *k = BUS_CLASS(klass);
+
+ /*
+ * Designware has only a single root complex. Enforce the limit on the
+ * parent bus
+ */
+ k->max_dev = 1;
+}
+
static DesignwarePCIEHost *
designware_pcie_root_to_host(DesignwarePCIERoot *root)
{
@@ -699,7 +710,7 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
&s->pci.memory,
&s->pci.io,
0, 4,
- TYPE_PCIE_BUS);
+ TYPE_DESIGNWARE_PCIE_ROOT_BUS);
pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
memory_region_init(&s->pci.address_space_root,
@@ -754,6 +765,11 @@ static void designware_pcie_host_init(Object *obj)
static const TypeInfo designware_pcie_types[] = {
{
+ .name = TYPE_DESIGNWARE_PCIE_ROOT_BUS,
+ .parent = TYPE_PCIE_BUS,
+ .instance_size = sizeof(DesignwarePCIERootBus),
+ .class_init = designware_pcie_root_bus_class_init,
+ }, {
.name = TYPE_DESIGNWARE_PCIE_HOST,
.parent = TYPE_PCI_HOST_BRIDGE,
.instance_size = sizeof(DesignwarePCIEHost),
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index bf8b278..a35a3bd 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -25,12 +25,19 @@
#include "hw/pci/pci_bridge.h"
#include "qom/object.h"
+#define TYPE_DESIGNWARE_PCIE_ROOT_BUS "designware-pcie-root-BUS"
+OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERootBus, DESIGNWARE_PCIE_ROOT_BUS)
+
#define TYPE_DESIGNWARE_PCIE_HOST "designware-pcie-host"
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIEHost, DESIGNWARE_PCIE_HOST)
#define TYPE_DESIGNWARE_PCIE_ROOT "designware-pcie-root"
OBJECT_DECLARE_SIMPLE_TYPE(DesignwarePCIERoot, DESIGNWARE_PCIE_ROOT)
+struct DesignwarePCIERootBus {
+ PCIBus parent;
+};
+
typedef struct DesignwarePCIEViewport {
DesignwarePCIERoot *root;