On 10/13/26 16:27, Clément MATHIEU--DRIF wrote:
> Do you need to operate at physmem level?
> We have an API for PCI device for ATS and PRI (see
> pci_ats_request_translation and pci_pri_unregister_notifier)
>
This helper is used by Remote-Port-ATS device, which is used for resolving ATS
requests from remote masters via RemotePort link and it is TYPE_DEVICE itself.
As it is not a PCI device itself, we cannot use PCI API unfortunately.
> On Tue, 2026-09-15 at 18:00 +0200, Ruslan Ruslichenko wrote:
>> From: Ruslan Ruslichenko
>> <[[email protected]](mailto:[email protected])>
>>
>> Add 'ats_do_translate' method to enable manual IOMMU address
>> translation.
>>
>> This allows the Remote Port subsystem to resolve guest virtual
>> addresses to physical addresses by querying the QEMU IOMMU
>> translation pipeline. This is required for the Remote Port
>> subsystem to support translation requests from external masters
>> in a co-simulation environment.
>>
>> Signed-off-by: Edgar E. Iglesias
>> <[[email protected]](mailto:[email protected])>
>> Signed-off-by: Takahiro Nakata
>> <[[email protected]](mailto:[email protected])>
>> Signed-off-by: Ruslan Ruslichenko
>> <[[email protected]](mailto:[email protected])>
>> ---
>> include/system/memory.h | 8 +++++++
>> system/physmem.c | 53 +++++++++++++++++++++++++++++++++++++++++
>> 2 files changed, 61 insertions(+)
>>
>> diff --git a/include/system/memory.h b/include/system/memory.h
>> index a7e03fc3e7..2032d3028d 100644
>> --- a/include/system/memory.h
>> +++ b/include/system/memory.h
>> @@ -2583,6 +2583,14 @@ static inline MemoryRegion
>> *address_space_translate(AddressSpace *as,
>> addr, xlat, len, is_write, attrs);
>> }
>>
>> +MemoryRegion *ats_do_translate(AddressSpace *as,
>> + hwaddr addr,
>> + hwaddr *xlat,
>> + hwaddr *plen_out,
>> + AddressSpace **target_as,
>> + int *prot,
>> + MemTxAttrs attrs);
>> +
>> /* address_space_access_valid: check for validity of accessing an address
>> * space range
>> *
>> diff --git a/system/physmem.c b/system/physmem.c
>> index a4a6a4710c..1acda22ede 100644
>> --- a/system/physmem.c
>> +++ b/system/physmem.c
>> @@ -525,6 +525,59 @@ static MemoryRegionSection
>> flatview_do_translate(FlatView *fv,
>> return *section;
>> }
>>
>> +/* This function is called from RCU critical section */
>> +MemoryRegion *ats_do_translate(AddressSpace *as,
>> + hwaddr addr,
>> + hwaddr *xlat,
>> + hwaddr *plen_out,
>> + AddressSpace **target_as,
>> + int *prot,
>> + MemTxAttrs attrs)
>> +{
>> + MemoryRegionSection *section;
>> + IOMMUMemoryRegion *iommu_mr;
>> + hwaddr plen = (hwaddr)(-1);
>> + FlatView *fv = address_space_to_flatview(as);
>> + IOMMUMemoryRegionClass *imrc;
>> + IOMMUTLBEntry iotlb;
>> + int iommu_idx = 0;
>> +
>> + if (!plen_out) {
>> + plen_out = &plen;
>> + }
>> +
>> + /* This can be MMIO, so setup MMIO bit. */
>> + section = address_space_translate_internal(
>> + flatview_to_dispatch(fv), addr, xlat,
>> + plen_out, true);
>> +
>> + /* Illegal translation */
>> + if (section->mr == &io_mem_unassigned) {
>> + return NULL;
>> + }
>> +
>> + iommu_mr = memory_region_get_iommu(section->mr);
>> + if (!iommu_mr) {
>> + return NULL;
>> + }
>> +
>> + imrc = memory_region_get_iommu_class_nocheck(iommu_mr);
>> +
>> + if (imrc->attrs_to_index) {
>> + iommu_idx = imrc->attrs_to_index(iommu_mr, attrs);
>> + }
>> +
>> + iotlb = imrc->translate(iommu_mr, addr, IOMMU_RO, iommu_idx);
>> +
>> + *xlat = ((iotlb.translated_addr & ~iotlb.addr_mask)
>> + | (addr & iotlb.addr_mask));
>> + *plen_out = MIN(*plen_out, (addr | iotlb.addr_mask) - addr + 1);
>> + *prot = iotlb.perm;
>> + *target_as = iotlb.target_as;
>> +
>> + return section->mr;
>> +}
>> +
>> /* Called from RCU critical section */
>> IOMMUTLBEntry address_space_get_iotlb_entry(AddressSpace *as, hwaddr addr,
>> bool is_write, MemTxAttrs attrs)