Current Designware PCIe host cannot connect to an IOMMU, since it has
registered PCIIOMMUOps.get_address_space() and an IOMMU cannot overwrite
PCIIOMMUOps.get_address_space() without breaking the PCIe translation
rules.
This commit implements designware_pcie_host_set_mem(), which is used to
register PCIIOMMUOps.set_memory_region(), so an IOMMU can designate the
downstream memory region for the PCIe devices.
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 --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
index c3fc37b904..8afe447562 100644
--- a/hw/pci-host/designware.c
+++ b/hw/pci-host/designware.c
@@ -395,7 +395,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;
@@ -436,7 +435,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";
/*
@@ -461,7 +460,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
@@ -666,8 +665,16 @@ static AddressSpace *designware_pcie_host_set_iommu(PCIBus *bus, void *opaque,
return &s->pci.address_space;
}
+void designware_pcie_host_set_mem(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_memory_region = designware_pcie_host_set_mem,
};
static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
@@ -703,6 +710,11 @@ static void designware_pcie_host_realize(DeviceState *dev, Error **errp)
TYPE_PCIE_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 c484e377a8..9562a4ff96 100644
--- a/include/hw/pci-host/designware.h
+++ b/include/hw/pci-host/designware.h
@@ -89,6 +89,8 @@ struct DesignwarePCIEHost {
} pci;
MemoryRegion mmio;
+ AddressSpace bridge_as;
+ MemoryRegion bridge_mr;
};
#endif /* DESIGNWARE_H */
--
2.43.2