On 10/15/26 11:40, Clément MATHIEU--DRIF wrote:
> 
> On Wed, 2026-10-14 at 10:21 +0200, Ruslan Ruslichenko wrote:
>> Caution: External email. Do not open attachments or click links, unless this 
>> email comes from a known sender and you know the content is safe.
>>
>>
>> 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.
>>
> 
> Ok, I see,
> 
> The issue I see here is that we are basically re-implemeting what IOMMUs 
> already do through the PCI API.  
> It looks like there is a risk here as some IOMMUs might want to update their 
> state when being called on ATS/PRI, which won't be done here.
> 
> I'm not super familiar with RemotePort but I have a high level overview of 
> what some companies do to bridge rtl simulators with a PCI bus in Qemu.  
> IIUC, the bus type of the simulator is known, and their bridge allocates an 
> emulated device of the matching type in Qemu so they can call the official 
> APIs as if there was a "real" emulated device.
> 
> In your use case, what kind of devices are you running in the external 
> simulator? PCI I guess?
> 


The most common usage of ATS and remote-port-ats is indeed bound to PCI 
subsystem.
For reference, in Remote Port subsystem it is used by remote-port-pci-device 
and remote-port-pcie-root-port in Xilinx tree:
https://github.com/Xilinx/qemu/blob/master/hw/core/remote-port-pci-device.c
https://github.com/Xilinx/qemu/blob/master/hw/core/remote-port-pcie-root-port.c

And since there is already existing 'pci_ats_request_translation' API, I agree 
it is a cleaner and more correct approach.
I think, ATS device can use PCIDevice created by those models and call 
pci_ats_request_translation(), which removes the need for physmem-level helper.
Although, the 'ats_request_translation' is currently implemented only by the 
Intel IOMMU, ARM SMMU don't implement it, so this needs to be done too.

In our case we have a use case where a device on the platform bus, behind SMMU 
also wants to use ATS requests.
But those likely require separate approach and it belongs to SMMU for platform 
bus series, such as:
https://lists.nongnu.org/archive/html/qemu-devel/2025-12/msg02637.html

So will drop 'ats_do_translate' for the next revision. 

Thanks for the feedback!

--
Best Regards,
Ruslan

>>
>>> On Tue, 2026-09-15 at 18:00 +0200, Ruslan Ruslichenko wrote:
>>>
>>>> From: Ruslan Ruslichenko 
>>>> <[[[email protected]](mailto:[email protected])](mailto:[[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])](mailto:[[email protected]](mailto:[email protected]))>
>>>> Signed-off-by: Takahiro Nakata 
>>>> <[[[email protected]](mailto:[email protected])](mailto:[[email protected]](mailto:[email protected]))>
>>>> Signed-off-by: Ruslan Ruslichenko 
>>>> <[[[email protected]](mailto:[email protected])](mailto:[[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)
>>>
>>


Reply via email to