@@ -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",
@@ -97,6 +97,8 @@ struct DesignwarePCIEHost {
} pci;
MemoryRegion mmio;
+ AddressSpace bridge_as;
+ MemoryRegion bridge_mr;
};
#endif /* DESIGNWARE_H */
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(-)