From: Mirsad Ostrakovic <[email protected]> Update the Remote Port memory slave to support transactions targeting an AddressSpace managed by an IOMMU.
This patch: - Adds 'iommu-id' and 'rp-chan0' properties to configure the connection. - Implements logic to retrieve the specific AddressSpace for a given stream ID from the default system bus IOMMU registry. This enables external simulators (connected via Remote Port) to perform DMA operations that are correctly translated by the guest's IOMMU/SMMU logic. Signed-off-by: Mirsad Ostrakovic <[email protected]> Signed-off-by: Ruslan Ruslichenko <[email protected]> --- hw/core/remote-port-memory-slave.c | 35 +++++++++++++++++++++- include/hw/core/remote-port-memory-slave.h | 3 ++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/hw/core/remote-port-memory-slave.c b/hw/core/remote-port-memory-slave.c index bb23325469..0419e75bfa 100644 --- a/hw/core/remote-port-memory-slave.c +++ b/hw/core/remote-port-memory-slave.c @@ -182,12 +182,38 @@ static void rp_cmd_rw(RemotePortMemorySlave *s, struct rp_pkt *pkt, rp_write(s->rp, (void *)s->rsp.pkt, enclen); } +static AddressSpace *bus_iommu_address_space(BusState *iommu_bus, + uint32_t iommu_id, uint16_t devid) +{ + if (iommu_bus && iommu_bus->iommu[iommu_id].iommu_ops) { + return iommu_bus->iommu[iommu_id].iommu_ops->get_address_space( + iommu_bus, iommu_bus->iommu[iommu_id].iommu_opaque, devid); + } + return &address_space_memory; +} + +static void rp_memory_slave_init_done(Notifier *notifier, void *data) +{ + RemotePortMemorySlave *s = container_of(notifier, RemotePortMemorySlave, + machine_done); + AddressSpace *as; + + if (s->channel_id) { + as = bus_iommu_address_space(sysbus_get_default(), s->iommu_id, + s->rp_stream_id); + address_space_init(&s->as, as->root, "dma"); + } else { + address_space_init(&s->as, s->mr ? s->mr : get_system_memory(), "dma"); + } +} + static void rp_memory_slave_realize(DeviceState *dev, Error **errp) { RemotePortMemorySlave *s = REMOTE_PORT_MEMORY_SLAVE(dev); s->peer = rp_get_peer(s->rp); - address_space_init(&s->as, s->mr ? s->mr : get_system_memory(), "dma"); + s->machine_done.notify = rp_memory_slave_init_done; + qemu_add_machine_init_done_notifier(&s->machine_done); } static void rp_memory_slave_write(RemotePortDevice *s, struct rp_pkt *pkt) @@ -232,10 +258,17 @@ static void rp_memory_slave_unrealize(DeviceState *dev) address_space_destroy(&s->as); } +static Property rp_properties[] = { + DEFINE_PROP_UINT32("iommu-id", RemotePortMemorySlave, iommu_id, 0), + DEFINE_PROP_UINT32("rp-chan0", RemotePortMemorySlave, channel_id, 0), + DEFINE_PROP_END_OF_LIST() +}; + static void rp_memory_slave_class_init(ObjectClass *oc, const void *data) { RemotePortDeviceClass *rpdc = REMOTE_PORT_DEVICE_CLASS(oc); DeviceClass *dc = DEVICE_CLASS(oc); + device_class_set_props_n(dc, rp_properties, ARRAY_SIZE(rp_properties)); rpdc->ops[RP_CMD_write] = rp_memory_slave_write; rpdc->ops[RP_CMD_read] = rp_memory_slave_read; diff --git a/include/hw/core/remote-port-memory-slave.h b/include/hw/core/remote-port-memory-slave.h index d88e806ed6..3161073a3f 100644 --- a/include/hw/core/remote-port-memory-slave.h +++ b/include/hw/core/remote-port-memory-slave.h @@ -23,6 +23,7 @@ typedef struct RemotePortMemorySlave { /* private */ SysBusDevice parent; /* public */ + uint32_t channel_id; struct RemotePort *rp; struct rp_peer_state *peer; MemoryRegion *mr; @@ -30,5 +31,7 @@ typedef struct RemotePortMemorySlave { MemTxAttrs attr; RemotePortDynPkt rsp; RemotePortATSCache *ats_cache; + Notifier machine_done; + uint32_t iommu_id; } RemotePortMemorySlave; #endif -- 2.43.0
