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)


Reply via email to