[PATCH v2 10/47] dma/dpaa2: validate IOVA in pre-populate helpers

Prashant Gupta prashant.gupta_3 at nxp.com
Thu Sep 10 15:51:21 CEST 2026


From: Gagandeep Singh <g.singh at nxp.com>

fle_sdd_pre_populate() and fle_sdd_sg_pre_populate() converted the SDD
and SG entry virtual addresses to IOVA with DPAA2_VADDR_TO_IOVA(), which
does not verify that the range is actually mapped in the IOMMU/SMMU. An
unmapped buffer was silently programmed into the hardware descriptor,
leading to an SMMU translation fault at transfer time that is hard to
trace back to the missing mapping.

Use DPAA2_VADDR_TO_IOVA_AND_CHECK() for the SDD, source SG and
destination SG buffers and rte_panic() with the offending address and
size when the translation is missing, so the misconfiguration is caught
early and clearly.

Signed-off-by: Gagandeep Singh <g.singh at nxp.com>
---
 drivers/dma/dpaa2/dpaa2_qdma.c | 42 ++++++++++++++++++++++++++++------
 1 file changed, 35 insertions(+), 7 deletions(-)

diff --git a/drivers/dma/dpaa2/dpaa2_qdma.c b/drivers/dma/dpaa2/dpaa2_qdma.c
index 6fd3530f0d..8a180ab400 100644
--- a/drivers/dma/dpaa2/dpaa2_qdma.c
+++ b/drivers/dma/dpaa2/dpaa2_qdma.c
@@ -187,7 +187,15 @@ fle_sdd_pre_populate(struct qdma_cntx_fle_sdd *fle_sdd,
 {
 	struct qbman_fle *fle = fle_sdd->fle;
 	struct qdma_sdd *sdd = fle_sdd->sdd;
-	uint64_t sdd_iova = DPAA2_VADDR_TO_IOVA(sdd);
+	uint64_t sdd_iova, iova_size;
+
+	iova_size = sizeof(struct qdma_sdd) * DPAA2_QDMA_MAX_SDD;
+	sdd_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(sdd, iova_size);
+	if (sdd_iova == RTE_BAD_IOVA) {
+		DPAA2_QDMA_ERR("No IOMMU map for sdd(%p)(size=%" PRIu64 ")",
+			sdd, iova_size);
+		return -ENOMEM;
+	}
 
 	/* first frame list to source descriptor */
 	DPAA2_SET_FLE_ADDR(&fle[DPAA2_QDMA_SDD_FLE], sdd_iova);
@@ -285,22 +293,36 @@ sg_entry_pre_populate(struct qdma_cntx_sg *sg_cntx)
 	}
 }
 
-static void
+static int
 fle_sdd_sg_pre_populate(struct qdma_cntx_sg *sg_cntx,
 	struct qdma_virt_queue *qdma_vq)
 {
 	struct qdma_sg_entry *src_sge = sg_cntx->sg_src_entry;
 	struct qdma_sg_entry *dst_sge = sg_cntx->sg_dst_entry;
-	rte_iova_t src_sge_iova, dst_sge_iova;
+	rte_iova_t src_sge_iova, dst_sge_iova, iova_size;
 	struct dpaa2_qdma_rbp *rbp = &qdma_vq->rbp;
 
 	memset(sg_cntx, 0, sizeof(struct qdma_cntx_sg));
 
-	src_sge_iova = DPAA2_VADDR_TO_IOVA(src_sge);
-	dst_sge_iova = DPAA2_VADDR_TO_IOVA(dst_sge);
+	iova_size = RTE_DPAAX_QDMA_JOB_SUBMIT_MAX *
+		sizeof(struct qdma_sg_entry);
+
+	src_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(src_sge, iova_size);
+	if (src_sge_iova == RTE_BAD_IOVA) {
+		DPAA2_QDMA_ERR("No IOMMU map for src_sge(%p)(size=%" PRIu64 ")",
+			src_sge, (uint64_t)iova_size);
+		return -ENOMEM;
+	}
+
+	dst_sge_iova = DPAA2_VADDR_TO_IOVA_AND_CHECK(dst_sge, iova_size);
+	if (dst_sge_iova == RTE_BAD_IOVA) {
+		DPAA2_QDMA_ERR("No IOMMU map for dst_sge(%p)(size=%" PRIu64 ")",
+			dst_sge, (uint64_t)iova_size);
+		return -ENOMEM;
+	}
 
 	sg_entry_pre_populate(sg_cntx);
-	fle_sdd_pre_populate(&sg_cntx->fle_sdd,
+	return fle_sdd_pre_populate(&sg_cntx->fle_sdd,
 		rbp, src_sge_iova, dst_sge_iova,
 		QBMAN_FLE_WORD4_FMT_SGE);
 }
@@ -671,7 +693,13 @@ dpaa2_qdma_copy_sg(void *dev_private,
 
 	if (qdma_vq->fle_pre_populate) {
 		if (unlikely(!fle[DPAA2_QDMA_SRC_FLE].length)) {
-			fle_sdd_sg_pre_populate(cntx_sg, qdma_vq);
+			ret = fle_sdd_sg_pre_populate(cntx_sg, qdma_vq);
+			if (unlikely(ret)) {
+				if (!qdma_dev->is_silent)
+					rte_mempool_put(qdma_vq->fle_pool,
+						cntx_sg);
+				return ret;
+			}
 			if (!qdma_dev->is_silent && cntx_sg && idx_addr) {
 				for (i = 0; i < nb_src; i++)
 					cntx_sg->cntx_idx[i] = idx_addr[i];
-- 
2.43.0



More information about the dev mailing list