diff mbox series

[3/4] hw/pci-host/designware: Implement PCIIOMMUOps.set_downstream_mr()

Message ID 20250307203952.13871-4-jason.chien@sifive.com (mailing list archive)
State New
Headers show
Series Integrate IOMMUs with PCI hosts that have ATUs | expand

Commit Message

Jason Chien March 7, 2025, 8:39 p.m. UTC
The original DesignWare PCIe host implementation could not connect with
an IOMMU, as both attempted to register PCIIOMMUOps.

This commit resolves the conflict by hooking PCIIOMMUOps.set_downstream_mr()
through designware_pcie_host_set_mr(), allowing the IOMMU to designate the
PCIe host's downstream memory region via pci_setup_iommu_downstream_mr()
without competing for PCIIOMMUOps.

Signed-off-by: Jason Chien <jason.chien@sifive.com>
---
 hw/pci-host/designware.c         | 18 +++++++++++++++---
 include/hw/pci-host/designware.h |  2 ++
 2 files changed, 17 insertions(+), 3 deletions(-)
diff mbox series

Patch

diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index c07740bfaa..fafbf90259 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -404,7 +404,6 @@  static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
 {
     DesignwarePCIERoot *root = DESIGNWARE_PCIE_ROOT(dev);
     DesignwarePCIEHost *host = designware_pcie_root_to_host(root);
-    MemoryRegion *host_mem = get_system_memory();
     MemoryRegion *address_space = &host->pci.memory;
     PCIBridge *br = PCI_BRIDGE(dev);
     DesignwarePCIEViewport *viewport;
@@ -445,7 +444,7 @@  static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
         viewport->cr[0]   = DESIGNWARE_PCIE_ATU_TYPE_MEM;
 
         source      = &host->pci.address_space_root;
-        destination = host_mem;
+        destination = &host->bridge_mr;
         direction   = "Inbound";
 
         /*
@@ -470,7 +469,7 @@  static void designware_pcie_root_realize(PCIDevice *dev, Error **errp)
 
         destination = &host->pci.memory;
         direction   = "Outbound";
-        source      = host_mem;
+        source      = get_system_memory();
 
         /*
          * Configure MemoryRegion implementing CPU -> PCI memory
@@ -675,8 +674,16 @@  static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
     return &s->pci.address_space;
 }
 
+static void designware_pcie_host_set_mr(void *opaque, MemoryRegion *mr)
+{
+    DesignwarePCIEHost *s = DESIGNWARE_PCIE_HOST(opaque);
+
+    memory_region_add_subregion_overlap(&s->bridge_mr, 0, mr, INT32_MAX);
+}
+
 static const PCIIOMMUOps designware_iommu_ops = {
     .get_address_space = designware_pcie_host_set_iommu,
+    .set_downstream_mr = designware_pcie_host_set_mr,
 };
 
 static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
@@ -713,6 +720,11 @@  static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
                                      TYPE_DESIGNWARE_PCIE_ROOT_BUS);
     pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
 
+    memory_region_init(&s->bridge_mr, OBJECT(s),
+                       "pcie-bus-bridge-memory", UINT64_MAX);
+    memory_region_add_subregion(&s->bridge_mr, 0x0, get_system_memory());
+    address_space_init(&s->bridge_as, &s->bridge_mr, "pcie-bus-bridge-space");
+
     memory_region_init(&s->pci.address_space_root,
                        OBJECT(s),
                        "pcie-bus-address-space-root",
diff --git a/include/hw/pci-host/designware.h b/include/hw/pci-host/designware.h
index a35a3bd06c..30f1598dbe 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -97,6 +97,8 @@  struct DesignwarePCIEHost {
     } pci;
 
     MemoryRegion mmio;
+    AddressSpace bridge_as;
+    MemoryRegion bridge_mr;
 };
 
 #endif /* DESIGNWARE_H */