[PATCH 1/5] iommu/rockchip: Don't walk a page table that a reset took away

Arun Iyengar via B4 Relay devnull+aiyengar1990.gmail.com at kernel.org
Mon Nov 9 23:11:02 PST 2026


From: Arun Iyengar <aiyengar1990 at gmail.com>

When a page fault is reported, log_iova() reads the directory address
back from the MMU_DTE_ADDR register of the IOMMU and dereferences it
through phys_to_virt() to log the page table entries of the faulting
IOVA. The IOMMU of an RK3588 video decoder core is reset with the core:
by the core's own soft reset, which the hardware also does by itself
when a job times out, and by the core's AXI reset line. A fault taken
just before such a reset is handled with MMU_DTE_ADDR reading 0, and
log_iova() dereferences the physical address 4 * dte_index:

rk_iommu fdc38700.iommu: Page fault at 0x0000000013400200 of type read
Unable to handle kernel paging request at virtual address ffff600000000026
KASAN: probably wild-memory-access in range [...0130-...0137]
...
rk_iommu_irq+0x490/0x758

Only walk the directory if the register holds the address of memory, and
say that the page table was lost to a reset otherwise. The fault is
still acknowledged (zap, PAGE_FAULT_DONE, INT_CLEAR) as before.

Signed-off-by: Arun Iyengar <aiyengar1990 at gmail.com>
---
 drivers/iommu/rockchip-iommu.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/drivers/iommu/rockchip-iommu.c b/drivers/iommu/rockchip-iommu.c
index 21af2f621c76..d40e2a26b7be 100644
--- a/drivers/iommu/rockchip-iommu.c
+++ b/drivers/iommu/rockchip-iommu.c
@@ -564,6 +564,17 @@ static void log_iova(struct rk_iommu *iommu, int index, dma_addr_t iova)
 	mmu_dte_addr = rk_iommu_read(base, RK_MMU_DTE_ADDR);
 	mmu_dte_addr_phys = iommu->rk_ops->pt_address(mmu_dte_addr);
 
+	/*
+	 * A reset of the master can reset its IOMMU too, between the fault and
+	 * this handler: DTE_ADDR then reads 0. Don't walk a directory that
+	 * isn't in memory; the caller still acknowledges the fault.
+	 */
+	if (!mmu_dte_addr || !pfn_valid(PHYS_PFN(mmu_dte_addr_phys))) {
+		dev_err(iommu->dev, "iova = %pad: fault while page table lost to reset (MMU_DTE_ADDR %#08x)\n",
+			&iova, mmu_dte_addr);
+		return;
+	}
+
 	dte_addr_phys = mmu_dte_addr_phys + (4 * dte_index);
 	dte_addr = phys_to_virt(dte_addr_phys);
 	dte = *dte_addr;

-- 
2.55.0





More information about the Linux-rockchip mailing list