[PATCH 1/9] iommu: introduce iova_to_phys_length in iommu_domain_ops
guanghuifeng at linux.alibaba.com
guanghuifeng at linux.alibaba.com
Mon Jun 1 01:41:48 PDT 2026
在 2026/6/1 7:51, Jason Gunthorpe 写道:
> On Sun, May 31, 2026 at 05:36:29PM +0800, Guanghui Feng wrote:
>> Add iova_to_phys_length callback to struct iommu_domain_ops alongside
>> the existing iova_to_phys. The new callback returns both the physical
>> address and the PTE mapping page size in a single page table walk.
>>
>> Add iommu_iova_to_phys_length() core function that:
>> - Checks ops->iova_to_phys_length first (preferred path)
>> - Falls back to ops->iova_to_phys for unmigrated drivers
>>
>> This enables callers like VFIO to efficiently traverse IOVA space
>> by actual mapping granularity instead of fixed PAGE_SIZE steps.
>>
>> Signed-off-by: Guanghui Feng <guanghuifeng at linux.alibaba.com>
>> Acked-by: Shiqiang Zhang <shiyu.zsq at linux.alibaba.com>
>> Acked-by: Simon Guo <wei.guo.simon at linux.alibaba.com>
>> ---
>> drivers/iommu/iommu.c | 34 ++++++++++++++++++++++++++++++++--
>> include/linux/iommu.h | 9 +++++++++
>> 2 files changed, 41 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>> index d1a9e713d3a0..43323229a1df 100644
>> --- a/drivers/iommu/iommu.c
>> +++ b/drivers/iommu/iommu.c
>> @@ -2545,15 +2545,45 @@ void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
>> }
>> EXPORT_SYMBOL_GPL(iommu_detach_group);
>>
>> -phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
>> +/**
>> + * iommu_iova_to_phys_length - Translate IOVA and return mapping page size
>> + * @domain: IOMMU domain to query
>> + * @iova: IO virtual address to translate
>> + * @mapped_length: Output parameter for the PTE page size (e.g. 4KB/2MB/1GB)
>> + *
>> + * Like iommu_iova_to_phys() but additionally returns the page size of the
>> + * PTE mapping at @iova through @mapped_length.
>> + *
>> + * Return: The physical address for the given IOVA, or 0 if no translation.
>> + */
> When introducing the new function I would like to fix this 0 error as
> well, it should return PHYS_MAX for error
Implementations such as arm_smmu_iova_to_phys/DOMAIN_NS(iova_to_phys)
all use a return value of 0 as an invalid state, so 0 is used as the
representation
of an invalid state to maintain compatibility.
>
>> +phys_addr_t iommu_iova_to_phys_length(struct iommu_domain *domain,
>> + dma_addr_t iova,
>> + size_t *mapped_length)
>> {
>> + if (mapped_length)
>> + *mapped_length = 0;
>> +
>> if (domain->type == IOMMU_DOMAIN_IDENTITY)
>> return iova;
>>
>> if (domain->type == IOMMU_DOMAIN_BLOCKED)
>> return 0;
> Any domain that doesn't have an op should fail, blocked is one example
In accordance with the implementation of iommu_iova_to_phys, it returns
a phy value of 0 in invalid states.
>
>>
>> - return domain->ops->iova_to_phys(domain, iova);
>> + if (domain->ops->iova_to_phys_length)
>> + return domain->ops->iova_to_phys_length(domain, iova,
>> + mapped_length);
>> +
>> + /* Fallback to legacy iova_to_phys without length info */
>> + if (domain->ops->iova_to_phys)
>> + return domain->ops->iova_to_phys(domain, iova);
> If it falls back it should return something sensible for the length.
>
> I suggest you approach the patch plan a little differently, the first
> patches should implement the new function and an iommput
> implementation
>
> Arrange things so the normal iova_to_phys calls the new function if it
> is available and discards the length.
>
> Then convert callers that can take advantage of it. Have the fallback
> path also compute the length by iterating internally.
>
> Finally one patch per driver implementing the new op, this could even
> be a second series.
>
> Don't remove iova_to_phys(), it is fine for things that don't need the
> length.
Does this mean retaining the iommu_iova_to_phys implementation but
implementing it through domain->ops->iova_to_phys_length (mapped_length
is NULL)?
>
> Jason
More information about the linux-arm-kernel
mailing list