public inbox for linux-arm-kernel@lists.infradead.org 
 help / color / mirror / Atom feed
From: Guanghui Feng <guanghuifeng@linux•alibaba.com>
To: boris.brezillon@collabora•com, robh@kernel•org,
	steven.price@arm•com, adrian.larumbe@collabora•com,
	maarten.lankhorst@linux•intel.com, mripard@kernel•org,
	tzimmermann@suse•de, airlied@gmail•com, liviu.dudau@arm•com,
	joro@8bytes•org, will@kernel•org, robin.murphy@arm•com,
	alex@shazbot•org, dri-devel@lists•freedesktop.org,
	linux-kernel@vger•kernel.org, iommu@lists•linux.dev,
	kvm@vger•kernel.org, linux-arm-kernel@lists•infradead.org,
	jgg@ziepe•ca, kevin.tian@intel•com, baolu.lu@linux•intel.com,
	suravee.suthikulpanit@amd•com, dwmw2@infradead•org
Cc: xlpang@linux•alibaba.com, oliver.yang@linux•alibaba.com,
	shiyu.zsq@linux•alibaba.com, wei.guo.simon@linux•alibaba.com
Subject: [PATCH 6/9] iommu: direct page-table drivers implement iova_to_phys_length
Date: Sun, 31 May 2026 17:36:34 +0800	[thread overview]
Message-ID: <20260531093637.3893199-7-guanghuifeng@linux.alibaba.com> (raw)
In-Reply-To: <20260531093637.3893199-1-guanghuifeng@linux.alibaba.com>

Implement iova_to_phys_length for all IOMMU drivers with direct page
tables. Each returns the actual PTE mapping size.

Also fix mtk_iommu_v1 pre-existing bug: add page offset to PA.

Signed-off-by: Guanghui Feng <guanghuifeng@linux•alibaba.com>
Acked-by: Shiqiang Zhang <shiyu.zsq@linux•alibaba.com>
Acked-by: Simon Guo <wei.guo.simon@linux•alibaba.com>
---
 drivers/iommu/exynos-iommu.c    | 21 ++++++++++++++++-----
 drivers/iommu/fsl_pamu_domain.c | 26 +++++++++++++++++++++++---
 drivers/iommu/msm_iommu.c       | 25 +++++++++++++++++++------
 drivers/iommu/mtk_iommu_v1.c    | 15 +++++++++++++--
 drivers/iommu/omap-iommu.c      | 32 +++++++++++++++++++++++---------
 drivers/iommu/rockchip-iommu.c  | 11 ++++++++---
 drivers/iommu/s390-iommu.c      | 15 +++++++++++----
 drivers/iommu/sprd-iommu.c      | 13 ++++++++++---
 drivers/iommu/sun50i-iommu.c    | 13 ++++++++++---
 drivers/iommu/tegra-smmu.c      | 12 +++++++++---
 drivers/iommu/virtio-iommu.c    | 13 ++++++++++---
 11 files changed, 152 insertions(+), 44 deletions(-)

diff --git a/drivers/iommu/exynos-iommu.c b/drivers/iommu/exynos-iommu.c
index 874d05f4b396..00ab813ed436 100644
--- a/drivers/iommu/exynos-iommu.c
+++ b/drivers/iommu/exynos-iommu.c
@@ -1372,27 +1372,38 @@ static size_t exynos_iommu_unmap(struct iommu_domain *iommu_domain,
 	return 0;
 }
 
-static phys_addr_t exynos_iommu_iova_to_phys(struct iommu_domain *iommu_domain,
-					  dma_addr_t iova)
+static phys_addr_t exynos_iommu_iova_to_phys_length(struct iommu_domain *iommu_domain,
+						 dma_addr_t iova,
+						 size_t *mapped_length)
 {
 	struct exynos_iommu_domain *domain = to_exynos_domain(iommu_domain);
 	sysmmu_pte_t *entry;
 	unsigned long flags;
 	phys_addr_t phys = 0;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	spin_lock_irqsave(&domain->pgtablelock, flags);
 
 	entry = section_entry(domain->pgtable, iova);
 
 	if (lv1ent_section(entry)) {
 		phys = section_phys(entry) + section_offs(iova);
+		if (mapped_length)
+			*mapped_length = SECT_SIZE;
 	} else if (lv1ent_page(entry)) {
 		entry = page_entry(entry, iova);
 
-		if (lv2ent_large(entry))
+		if (lv2ent_large(entry)) {
 			phys = lpage_phys(entry) + lpage_offs(iova);
-		else if (lv2ent_small(entry))
+			if (mapped_length)
+				*mapped_length = LPAGE_SIZE;
+		} else if (lv2ent_small(entry)) {
 			phys = spage_phys(entry) + spage_offs(iova);
+			if (mapped_length)
+				*mapped_length = SPAGE_SIZE;
+		}
 	}
 
 	spin_unlock_irqrestore(&domain->pgtablelock, flags);
@@ -1484,7 +1495,7 @@ static const struct iommu_ops exynos_iommu_ops = {
 		.attach_dev	= exynos_iommu_attach_device,
 		.map_pages	= exynos_iommu_map,
 		.unmap_pages	= exynos_iommu_unmap,
-		.iova_to_phys	= exynos_iommu_iova_to_phys,
+		.iova_to_phys_length	= exynos_iommu_iova_to_phys_length,
 		.free		= exynos_iommu_domain_free,
 	}
 };
diff --git a/drivers/iommu/fsl_pamu_domain.c b/drivers/iommu/fsl_pamu_domain.c
index 9664ef9840d2..48a072074b56 100644
--- a/drivers/iommu/fsl_pamu_domain.c
+++ b/drivers/iommu/fsl_pamu_domain.c
@@ -169,12 +169,32 @@ static void attach_device(struct fsl_dma_domain *dma_domain, int liodn, struct d
 	spin_unlock_irqrestore(&device_domain_lock, flags);
 }
 
-static phys_addr_t fsl_pamu_iova_to_phys(struct iommu_domain *domain,
-					 dma_addr_t iova)
+static phys_addr_t fsl_pamu_iova_to_phys_length(struct iommu_domain *domain,
+						dma_addr_t iova,
+						size_t *mapped_length)
 {
+	if (mapped_length)
+		*mapped_length = 0;
+
 	if (iova < domain->geometry.aperture_start ||
 	    iova > domain->geometry.aperture_end)
 		return 0;
+
+	/*
+	 * PAMU configures exactly one Primary PAACE entry per LIODN with the
+	 * Multi-Window (MW) bit cleared and ATM = PAACE_ATM_WINDOW_XLATE,
+	 * WBAL/TWBAL = 0. That is, every LIODN is backed by a single hardware
+	 * mapping window of fixed size (1ULL << 36, i.e. 64GB, see
+	 * pamu_config_ppaace()) performing an identity translation. The driver
+	 * does not split this window into SPAACE sub-windows, so the entire
+	 * aperture is one PAACE "PTE" entry. Return that single entry's size
+	 * as mapped_length, matching the iova_to_phys_length contract that
+	 * mapped_length reports the full size of the mapping entry which
+	 * covers iova (not the remaining bytes from iova to its end).
+	 */
+	if (mapped_length)
+		*mapped_length = 1ULL << 36;
+
 	return iova;
 }
 
@@ -435,7 +455,7 @@ static const struct iommu_ops fsl_pamu_ops = {
 	.device_group   = fsl_pamu_device_group,
 	.default_domain_ops = &(const struct iommu_domain_ops) {
 		.attach_dev	= fsl_pamu_attach_device,
-		.iova_to_phys	= fsl_pamu_iova_to_phys,
+		.iova_to_phys_length	= fsl_pamu_iova_to_phys_length,
 		.free		= fsl_pamu_domain_free,
 	}
 };
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 0ad5ff431d5b..f36fdbf8076f 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -523,8 +523,9 @@ static size_t msm_iommu_unmap(struct iommu_domain *domain, unsigned long iova,
 	return ret;
 }
 
-static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
-					  dma_addr_t va)
+static phys_addr_t msm_iommu_iova_to_phys_length(struct iommu_domain *domain,
+						 dma_addr_t va,
+						 size_t *mapped_length)
 {
 	struct msm_priv *priv;
 	struct msm_iommu_dev *iommu;
@@ -533,6 +534,9 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	unsigned long flags;
 	phys_addr_t ret = 0;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	spin_lock_irqsave(&msm_iommu_lock, flags);
 
 	priv = to_msm_priv(domain);
@@ -558,13 +562,22 @@ static phys_addr_t msm_iommu_iova_to_phys(struct iommu_domain *domain,
 	par = GET_PAR(iommu->base, master->num);
 
 	/* We are dealing with a supersection */
-	if (GET_NOFAULT_SS(iommu->base, master->num))
+	if (GET_NOFAULT_SS(iommu->base, master->num)) {
 		ret = (par & 0xFF000000) | (va & 0x00FFFFFF);
-	else	/* Upper 20 bits from PAR, lower 12 from VA */
+		if (mapped_length)
+			*mapped_length = SZ_16M;
+	} else {
+		/* Upper 20 bits from PAR, lower 12 from VA */
 		ret = (par & 0xFFFFF000) | (va & 0x00000FFF);
+		if (mapped_length)
+			*mapped_length = SZ_4K;
+	}
 
-	if (GET_FAULT(iommu->base, master->num))
+	if (GET_FAULT(iommu->base, master->num)) {
 		ret = 0;
+		if (mapped_length)
+			*mapped_length = 0;
+	}
 
 	__disable_clocks(iommu);
 fail:
@@ -706,7 +719,7 @@ static struct iommu_ops msm_iommu_ops = {
 		 */
 		.iotlb_sync	= NULL,
 		.iotlb_sync_map	= msm_iommu_sync_map,
-		.iova_to_phys	= msm_iommu_iova_to_phys,
+		.iova_to_phys_length	= msm_iommu_iova_to_phys_length,
 		.free		= msm_iommu_domain_free,
 	}
 };
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index ac97dd2868d4..a451de7d669e 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -393,17 +393,28 @@ static size_t mtk_iommu_v1_unmap(struct iommu_domain *domain, unsigned long iova
 	return size;
 }
 
-static phys_addr_t mtk_iommu_v1_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova)
+static phys_addr_t mtk_iommu_v1_iova_to_phys_length(struct iommu_domain *domain,
+						    dma_addr_t iova,
+						    size_t *mapped_length)
 {
 	struct mtk_iommu_v1_domain *dom = to_mtk_domain(domain);
 	unsigned long flags;
 	phys_addr_t pa;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	spin_lock_irqsave(&dom->pgtlock, flags);
 	pa = *(dom->pgt_va + (iova >> MT2701_IOMMU_PAGE_SHIFT));
 	pa = pa & (~(MT2701_IOMMU_PAGE_SIZE - 1));
 	spin_unlock_irqrestore(&dom->pgtlock, flags);
 
+	if (pa) {
+		pa |= (iova & (MT2701_IOMMU_PAGE_SIZE - 1));
+		if (mapped_length)
+			*mapped_length = MT2701_IOMMU_PAGE_SIZE;
+	}
+
 	return pa;
 }
 
@@ -590,7 +601,7 @@ static const struct iommu_ops mtk_iommu_v1_ops = {
 		.attach_dev	= mtk_iommu_v1_attach_device,
 		.map_pages	= mtk_iommu_v1_map,
 		.unmap_pages	= mtk_iommu_v1_unmap,
-		.iova_to_phys	= mtk_iommu_v1_iova_to_phys,
+		.iova_to_phys_length = mtk_iommu_v1_iova_to_phys_length,
 		.free		= mtk_iommu_v1_domain_free,
 	}
 };
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 8231d7d6bb6a..91daa69decc9 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1592,8 +1592,9 @@ static void omap_iommu_domain_free(struct iommu_domain *domain)
 	kfree(omap_domain);
 }
 
-static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
-					   dma_addr_t da)
+static phys_addr_t omap_iommu_iova_to_phys_length(struct iommu_domain *domain,
+						  dma_addr_t da,
+						  size_t *mapped_length)
 {
 	struct omap_iommu_domain *omap_domain = to_omap_domain(domain);
 	struct omap_iommu_device *iommu = omap_domain->iommus;
@@ -1602,6 +1603,9 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
 	u32 *pgd, *pte;
 	phys_addr_t ret = 0;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	/*
 	 * all the iommus within the domain will have identical programming,
 	 * so perform the lookup using just the first iommu
@@ -1609,21 +1613,31 @@ static phys_addr_t omap_iommu_iova_to_phys(struct iommu_domain *domain,
 	iopgtable_lookup_entry(oiommu, da, &pgd, &pte);
 
 	if (pte) {
-		if (iopte_is_small(*pte))
+		if (iopte_is_small(*pte)) {
 			ret = omap_iommu_translate(*pte, da, IOPTE_MASK);
-		else if (iopte_is_large(*pte))
+			if (ret && mapped_length)
+				*mapped_length = IOPTE_SIZE;
+		} else if (iopte_is_large(*pte)) {
 			ret = omap_iommu_translate(*pte, da, IOLARGE_MASK);
-		else
+			if (ret && mapped_length)
+				*mapped_length = IOLARGE_SIZE;
+		} else {
 			dev_err(dev, "bogus pte 0x%x, da 0x%llx", *pte,
 				(unsigned long long)da);
+		}
 	} else {
-		if (iopgd_is_section(*pgd))
+		if (iopgd_is_section(*pgd)) {
 			ret = omap_iommu_translate(*pgd, da, IOSECTION_MASK);
-		else if (iopgd_is_super(*pgd))
+			if (ret && mapped_length)
+				*mapped_length = IOSECTION_SIZE;
+		} else if (iopgd_is_super(*pgd)) {
 			ret = omap_iommu_translate(*pgd, da, IOSUPER_MASK);
-		else
+			if (ret && mapped_length)
+				*mapped_length = IOSUPER_SIZE;
+		} else {
 			dev_err(dev, "bogus pgd 0x%x, da 0x%llx", *pgd,
 				(unsigned long long)da);
+		}
 	}
 
 	return ret;
@@ -1723,7 +1737,7 @@ static const struct iommu_ops omap_iommu_ops = {
 		.attach_dev	= omap_iommu_attach_dev,
 		.map_pages	= omap_iommu_map,
 		.unmap_pages	= omap_iommu_unmap,
-		.iova_to_phys	= omap_iommu_iova_to_phys,
+		.iova_to_phys_length	= omap_iommu_iova_to_phys_length,
 		.free		= omap_iommu_domain_free,
 	}
 };
diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 0013cf196c57..dad3ff38fe2c 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -648,8 +648,8 @@ static irqreturn_t rk_iommu_irq(int irq, void *dev_id)
 	return ret;
 }
 
-static phys_addr_t rk_iommu_iova_to_phys(struct iommu_domain *domain,
-					 dma_addr_t iova)
+static phys_addr_t rk_iommu_iova_to_phys_length(struct iommu_domain *domain,
+					 dma_addr_t iova, size_t *mapped_length)
 {
 	struct rk_iommu_domain *rk_domain = to_rk_domain(domain);
 	unsigned long flags;
@@ -657,6 +657,9 @@ static phys_addr_t rk_iommu_iova_to_phys(struct iommu_domain *domain,
 	u32 dte, pte;
 	u32 *page_table;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	spin_lock_irqsave(&rk_domain->dt_lock, flags);
 
 	dte = rk_domain->dt[rk_iova_dte_index(iova)];
@@ -670,6 +673,8 @@ static phys_addr_t rk_iommu_iova_to_phys(struct iommu_domain *domain,
 		goto out;
 
 	phys = rk_ops->pt_address(pte) + rk_iova_page_offset(iova);
+	if (mapped_length)
+		*mapped_length = SPAGE_SIZE;
 out:
 	spin_unlock_irqrestore(&rk_domain->dt_lock, flags);
 
@@ -1187,7 +1192,7 @@ static const struct iommu_ops rk_iommu_ops = {
 		.attach_dev	= rk_iommu_attach_device,
 		.map_pages	= rk_iommu_map,
 		.unmap_pages	= rk_iommu_unmap,
-		.iova_to_phys	= rk_iommu_iova_to_phys,
+		.iova_to_phys_length = rk_iommu_iova_to_phys_length,
 		.free		= rk_iommu_domain_free,
 	}
 };
diff --git a/drivers/iommu/s390-iommu.c b/drivers/iommu/s390-iommu.c
index f148f559ac56..8df98aceb5f7 100644
--- a/drivers/iommu/s390-iommu.c
+++ b/drivers/iommu/s390-iommu.c
@@ -986,8 +986,9 @@ static unsigned long *get_rto_from_iova(struct s390_domain *domain,
 	}
 }
 
-static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
-					   dma_addr_t iova)
+static phys_addr_t s390_iommu_iova_to_phys_length(struct iommu_domain *domain,
+						  dma_addr_t iova,
+						  size_t *mapped_length)
 {
 	struct s390_domain *s390_domain = to_s390_domain(domain);
 	unsigned long *rto, *sto, *pto;
@@ -995,6 +996,9 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
 	unsigned int rtx, sx, px;
 	phys_addr_t phys = 0;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	if (iova < domain->geometry.aperture_start ||
 	    iova > domain->geometry.aperture_end)
 		return 0;
@@ -1014,8 +1018,11 @@ static phys_addr_t s390_iommu_iova_to_phys(struct iommu_domain *domain,
 		if (reg_entry_isvalid(ste)) {
 			pto = get_st_pto(ste);
 			pte = READ_ONCE(pto[px]);
-			if (pt_entry_isvalid(pte))
+			if (pt_entry_isvalid(pte)) {
 				phys = pte & ZPCI_PTE_ADDR_MASK;
+				if (mapped_length)
+					*mapped_length = SZ_4K;
+			}
 		}
 	}
 
@@ -1183,7 +1190,7 @@ static struct iommu_domain blocking_domain = {
 		.flush_iotlb_all = s390_iommu_flush_iotlb_all, \
 		.iotlb_sync      = s390_iommu_iotlb_sync, \
 		.iotlb_sync_map  = s390_iommu_iotlb_sync_map, \
-		.iova_to_phys	= s390_iommu_iova_to_phys, \
+		.iova_to_phys_length	= s390_iommu_iova_to_phys_length, \
 		.free		= s390_domain_free, \
 	}
 
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index c1a34445d244..da14574a6430 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -366,8 +366,9 @@ static void sprd_iommu_sync(struct iommu_domain *domain,
 	sprd_iommu_sync_map(domain, 0, 0);
 }
 
-static phys_addr_t sprd_iommu_iova_to_phys(struct iommu_domain *domain,
-					   dma_addr_t iova)
+static phys_addr_t sprd_iommu_iova_to_phys_length(struct iommu_domain *domain,
+						  dma_addr_t iova,
+						  size_t *mapped_length)
 {
 	struct sprd_iommu_domain *dom = to_sprd_domain(domain);
 	unsigned long flags;
@@ -375,6 +376,9 @@ static phys_addr_t sprd_iommu_iova_to_phys(struct iommu_domain *domain,
 	unsigned long start = domain->geometry.aperture_start;
 	unsigned long end = domain->geometry.aperture_end;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	if (WARN_ON(iova < start || iova > end))
 		return 0;
 
@@ -383,6 +387,9 @@ static phys_addr_t sprd_iommu_iova_to_phys(struct iommu_domain *domain,
 	pa = (pa << SPRD_IOMMU_PAGE_SHIFT) + ((iova - start) & (SPRD_IOMMU_PAGE_SIZE - 1));
 	spin_unlock_irqrestore(&dom->pgtlock, flags);
 
+	if (pa && mapped_length)
+		*mapped_length = SPRD_IOMMU_PAGE_SIZE;
+
 	return pa;
 }
 
@@ -420,7 +427,7 @@ static const struct iommu_ops sprd_iommu_ops = {
 		.unmap_pages	= sprd_iommu_unmap,
 		.iotlb_sync_map	= sprd_iommu_sync_map,
 		.iotlb_sync	= sprd_iommu_sync,
-		.iova_to_phys	= sprd_iommu_iova_to_phys,
+		.iova_to_phys_length	= sprd_iommu_iova_to_phys_length,
 		.free		= sprd_iommu_domain_free,
 	}
 };
diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index be3f1ce696ba..66c354baaca1 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -659,14 +659,18 @@ static size_t sun50i_iommu_unmap(struct iommu_domain *domain, unsigned long iova
 	return SZ_4K;
 }
 
-static phys_addr_t sun50i_iommu_iova_to_phys(struct iommu_domain *domain,
-					     dma_addr_t iova)
+static phys_addr_t sun50i_iommu_iova_to_phys_length(struct iommu_domain *domain,
+						    dma_addr_t iova,
+						    size_t *mapped_length)
 {
 	struct sun50i_iommu_domain *sun50i_domain = to_sun50i_domain(domain);
 	phys_addr_t pt_phys;
 	u32 *page_table;
 	u32 dte, pte;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	dte = sun50i_domain->dt[sun50i_iova_get_dte_index(iova)];
 	if (!sun50i_dte_is_pt_valid(dte))
 		return 0;
@@ -677,6 +681,9 @@ static phys_addr_t sun50i_iommu_iova_to_phys(struct iommu_domain *domain,
 	if (!sun50i_pte_is_page_valid(pte))
 		return 0;
 
+	if (mapped_length)
+		*mapped_length = SZ_4K;
+
 	return sun50i_pte_get_page_address(pte) +
 		sun50i_iova_get_page_offset(iova);
 }
@@ -857,7 +864,7 @@ static const struct iommu_ops sun50i_iommu_ops = {
 		.flush_iotlb_all = sun50i_iommu_flush_iotlb_all,
 		.iotlb_sync_map = sun50i_iommu_iotlb_sync_map,
 		.iotlb_sync	= sun50i_iommu_iotlb_sync,
-		.iova_to_phys	= sun50i_iommu_iova_to_phys,
+		.iova_to_phys_length	= sun50i_iommu_iova_to_phys_length,
 		.map_pages	= sun50i_iommu_map,
 		.unmap_pages	= sun50i_iommu_unmap,
 		.free		= sun50i_iommu_domain_free,
diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 67e7a7b925f0..c2545d577fdc 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -803,20 +803,26 @@ static size_t tegra_smmu_unmap(struct iommu_domain *domain, unsigned long iova,
 	return size;
 }
 
-static phys_addr_t tegra_smmu_iova_to_phys(struct iommu_domain *domain,
-					   dma_addr_t iova)
+static phys_addr_t tegra_smmu_iova_to_phys_length(struct iommu_domain *domain,
+					   dma_addr_t iova, size_t *mapped_length)
 {
 	struct tegra_smmu_as *as = to_smmu_as(domain);
 	unsigned long pfn;
 	dma_addr_t pte_dma;
 	u32 *pte;
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	pte = tegra_smmu_pte_lookup(as, iova, &pte_dma);
 	if (!pte || !*pte)
 		return 0;
 
 	pfn = *pte & as->smmu->pfn_mask;
 
+	if (mapped_length)
+		*mapped_length = SZ_4K;
+
 	return SMMU_PFN_PHYS(pfn) + SMMU_OFFSET_IN_PAGE(iova);
 }
 
@@ -1007,7 +1013,7 @@ static const struct iommu_ops tegra_smmu_ops = {
 		.attach_dev	= tegra_smmu_attach_dev,
 		.map_pages	= tegra_smmu_map,
 		.unmap_pages	= tegra_smmu_unmap,
-		.iova_to_phys	= tegra_smmu_iova_to_phys,
+		.iova_to_phys_length = tegra_smmu_iova_to_phys_length,
 		.free		= tegra_smmu_domain_free,
 	}
 };
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 587fc13197f1..80c9c06a1380 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -912,8 +912,9 @@ static size_t viommu_unmap_pages(struct iommu_domain *domain, unsigned long iova
 	return ret ? 0 : unmapped;
 }
 
-static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
-				       dma_addr_t iova)
+static phys_addr_t viommu_iova_to_phys_length(struct iommu_domain *domain,
+					      dma_addr_t iova,
+					      size_t *mapped_length)
 {
 	u64 paddr = 0;
 	unsigned long flags;
@@ -921,11 +922,17 @@ static phys_addr_t viommu_iova_to_phys(struct iommu_domain *domain,
 	struct interval_tree_node *node;
 	struct viommu_domain *vdomain = to_viommu_domain(domain);
 
+	if (mapped_length)
+		*mapped_length = 0;
+
 	spin_lock_irqsave(&vdomain->mappings_lock, flags);
 	node = interval_tree_iter_first(&vdomain->mappings, iova, iova);
 	if (node) {
 		mapping = container_of(node, struct viommu_mapping, iova);
 		paddr = mapping->paddr + (iova - mapping->iova.start);
+		if (mapped_length)
+			*mapped_length = mapping->iova.last -
+					 mapping->iova.start + 1;
 	}
 	spin_unlock_irqrestore(&vdomain->mappings_lock, flags);
 
@@ -1102,7 +1109,7 @@ static const struct iommu_ops viommu_ops = {
 		.attach_dev		= viommu_attach_dev,
 		.map_pages		= viommu_map_pages,
 		.unmap_pages		= viommu_unmap_pages,
-		.iova_to_phys		= viommu_iova_to_phys,
+		.iova_to_phys_length	= viommu_iova_to_phys_length,
 		.flush_iotlb_all	= viommu_flush_iotlb_all,
 		.iotlb_sync		= viommu_iotlb_sync,
 		.iotlb_sync_map		= viommu_iotlb_sync_map,
-- 
2.43.7



  parent reply	other threads:[~2026-05-31  9:37 UTC|newest]

Thread overview: 95+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20260529115116.GR2487554@ziepe.ca>
2026-05-31  9:36 ` [PATCH 0/9] iommu: introduce iova_to_phys_length for efficient IOVA-to-physical translation Guanghui Feng
2026-05-31  9:36   ` [PATCH 1/9] iommu: introduce iova_to_phys_length in iommu_domain_ops Guanghui Feng
2026-05-31 23:51     ` Jason Gunthorpe
2026-06-01  8:41       ` guanghuifeng
2026-06-01 13:43         ` Jason Gunthorpe
2026-06-01 14:14           ` guanghuifeng
2026-06-01 14:31             ` Jason Gunthorpe
2026-05-31  9:36   ` [PATCH 2/9] iommu/io-pgtable: introduce iova_to_phys_length in io_pgtable_ops Guanghui Feng
2026-05-31  9:36   ` [PATCH 3/9] iommu/generic_pt: implement iova_to_phys_length Guanghui Feng
2026-05-31 23:54     ` Jason Gunthorpe
2026-06-01  9:23       ` guanghuifeng
     [not found]       ` <fa924b86-1ca9-4819-8330-0d5f6ede8923@linux.alibaba.com>
2026-06-01 14:32         ` Jason Gunthorpe
2026-06-02  7:20       ` guanghuifeng
2026-06-02 12:32         ` Jason Gunthorpe
2026-05-31  9:36   ` [PATCH 4/9] iommu/arm-smmu: " Guanghui Feng
2026-05-31  9:36   ` [PATCH 5/9] iommu: apple-dart/ipmmu/mtk_iommu " Guanghui Feng
2026-05-31  9:36   ` Guanghui Feng [this message]
2026-05-31  9:36   ` [PATCH 7/9] vfio/iommufd: use iova_to_phys_length for efficient unmap Guanghui Feng
2026-05-31 23:58     ` Jason Gunthorpe
2026-05-31  9:36   ` [PATCH 8/9] drm/gpu, iommu/io-pgtable: switch to iova_to_phys_length Guanghui Feng
2026-05-31  9:36   ` [PATCH 9/9] iommu: remove deprecated iova_to_phys from domain_ops and io_pgtable_ops Guanghui Feng
2026-06-02 10:46   ` [PATCH v2 00/30] iommu: introduce iova_to_phys_length for efficient IOVA-to-physical translation Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 01/30] iommu: introduce iova_to_phys_length in iommu_domain_ops Guanghui Feng
2026-06-03  1:08       ` Jason Gunthorpe
2026-06-02 10:46     ` [PATCH v2 02/30] iommu/io-pgtable-arm: introduce iova_to_phys_length in io_pgtable_ops Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 03/30] iommu/io-pgtable-arm-v7s: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 04/30] iommu/io-pgtable-dart: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 05/30] iommu/generic_pt: implement iova_to_phys_length Guanghui Feng
2026-06-03  1:11       ` Jason Gunthorpe
2026-06-02 10:46     ` [PATCH v2 06/30] iommu/arm-smmu-v3: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 07/30] iommu/arm-smmu: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 08/30] iommu/qcom_iommu: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 09/30] iommu/apple-dart: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 10/30] iommu/ipmmu-vmsa: " Guanghui Feng
2026-06-03  1:13       ` Jason Gunthorpe
2026-06-02 10:46     ` [PATCH v2 11/30] iommu/mtk_iommu: " Guanghui Feng
2026-06-03  1:17       ` Jason Gunthorpe
2026-06-02 10:46     ` [PATCH v2 12/30] iommu/exynos: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 13/30] iommu/fsl_pamu: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 14/30] iommu/msm: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 15/30] iommu/mtk_v1: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 16/30] iommu/omap: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 17/30] iommu/rockchip: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 18/30] iommu/s390: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 19/30] iommu/sprd: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 20/30] iommu/sun50i: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 21/30] iommu/tegra-smmu: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 22/30] iommu/virtio: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 23/30] vfio/iommufd: use iova_to_phys_length for efficient unmap Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 24/30] drm/panfrost: switch to iova_to_phys_length Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 25/30] drm/panthor: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 26/30] iommu/io-pgtable: selftests " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 27/30] iommu/io-pgtable-arm: remove deprecated iova_to_phys wrapper Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 28/30] iommu/io-pgtable-arm-v7s: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 29/30] iommu/io-pgtable-dart: " Guanghui Feng
2026-06-02 10:46     ` [PATCH v2 30/30] iommu: remove iova_to_phys from domain_ops and io_pgtable_ops Guanghui Feng
2026-06-03 15:17     ` [PATCH v3 00/32] iommu: introduce iova_to_phys_length and remove iova_to_phys Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 01/32] iommu: introduce iova_to_phys_length in iommu_domain_ops Guanghui Feng
2026-06-04  2:44         ` Baolu Lu
2026-06-04 14:16         ` Jason Gunthorpe
2026-06-03 15:17       ` [PATCH v3 02/32] iommu/io-pgtable-arm: introduce iova_to_phys_length in io_pgtable_ops Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 03/32] iommu/io-pgtable-arm-v7s: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 04/32] iommu/io-pgtable-dart: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 05/32] iommu/generic_pt: implement iova_to_phys_length Guanghui Feng
2026-06-04  3:30         ` Baolu Lu
2026-06-04 14:12           ` Jason Gunthorpe
2026-06-03 15:17       ` [PATCH v3 06/32] iommu/arm-smmu-v3: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 07/32] iommu/arm-smmu: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 08/32] iommu/qcom_iommu: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 09/32] iommu/apple-dart: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 10/32] iommu/ipmmu-vmsa: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 11/32] iommu/mtk_iommu: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 12/32] iommu/exynos: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 13/32] iommu/fsl_pamu: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 14/32] iommu/msm: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 15/32] iommu/mtk_v1: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 16/32] iommu/omap: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 17/32] iommu/rockchip: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 18/32] iommu/s390: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 19/32] iommu/sprd: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 20/32] iommu/sun50i: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 21/32] iommu/tegra-smmu: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 22/32] iommu/virtio: " Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 23/32] vfio: use iova_to_phys_length for efficient unmap Guanghui Feng
2026-06-04 14:27         ` Jason Gunthorpe
2026-06-03 15:17       ` [PATCH v3 24/32] iommufd: " Guanghui Feng
2026-06-04 14:26         ` Jason Gunthorpe
2026-06-03 15:17       ` [PATCH v3 25/32] iommufd/selftest: switch to iommu_iova_to_phys_length Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 26/32] drm/panfrost: switch to iova_to_phys_length Guanghui Feng
2026-06-03 15:17       ` [PATCH v3 27/32] drm/panthor: " Guanghui Feng
2026-06-03 15:18       ` [PATCH v3 28/32] iommu/io-pgtable: selftests " Guanghui Feng
2026-06-03 15:18       ` [PATCH v3 29/32] iommu/io-pgtable-arm: remove deprecated iova_to_phys wrapper Guanghui Feng
2026-06-03 15:18       ` [PATCH v3 30/32] iommu/io-pgtable-arm-v7s: " Guanghui Feng
2026-06-03 15:18       ` [PATCH v3 31/32] iommu/io-pgtable-dart: " Guanghui Feng
2026-06-03 15:18       ` [PATCH v3 32/32] iommu: remove iova_to_phys from domain_ops and io_pgtable_ops Guanghui Feng

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260531093637.3893199-7-guanghuifeng@linux.alibaba.com \
    --to=guanghuifeng@linux$(echo .)alibaba.com \
    --cc=adrian.larumbe@collabora$(echo .)com \
    --cc=airlied@gmail$(echo .)com \
    --cc=alex@shazbot$(echo .)org \
    --cc=baolu.lu@linux$(echo .)intel.com \
    --cc=boris.brezillon@collabora$(echo .)com \
    --cc=dri-devel@lists$(echo .)freedesktop.org \
    --cc=dwmw2@infradead$(echo .)org \
    --cc=iommu@lists$(echo .)linux.dev \
    --cc=jgg@ziepe$(echo .)ca \
    --cc=joro@8bytes$(echo .)org \
    --cc=kevin.tian@intel$(echo .)com \
    --cc=kvm@vger$(echo .)kernel.org \
    --cc=linux-arm-kernel@lists$(echo .)infradead.org \
    --cc=linux-kernel@vger$(echo .)kernel.org \
    --cc=liviu.dudau@arm$(echo .)com \
    --cc=maarten.lankhorst@linux$(echo .)intel.com \
    --cc=mripard@kernel$(echo .)org \
    --cc=oliver.yang@linux$(echo .)alibaba.com \
    --cc=robh@kernel$(echo .)org \
    --cc=robin.murphy@arm$(echo .)com \
    --cc=shiyu.zsq@linux$(echo .)alibaba.com \
    --cc=steven.price@arm$(echo .)com \
    --cc=suravee.suthikulpanit@amd$(echo .)com \
    --cc=tzimmermann@suse$(echo .)de \
    --cc=wei.guo.simon@linux$(echo .)alibaba.com \
    --cc=will@kernel$(echo .)org \
    --cc=xlpang@linux$(echo .)alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox