mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults
@ 2026-11-10  6:05 Arun Iyengar via B4 Relay
  2026-11-10  6:05 ` [PATCH 1/2] iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults Arun Iyengar via B4 Relay
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-10  6:05 UTC (permalink / raw)
  To: Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, Maxime Ripard
  Cc: iommu, linux-arm-kernel, linux-sunxi, linux-kernel

On an H616 with a display scanning out, the IOMMU reports page faults
with master -1 at the IOVA right after the end of the framebuffer: once
at the first fbcon frame, and then once per frame for a while after
each TLB flush, e.g. while a video decoder frees its buffers. They are
failed walks of the TLB prefetcher, which the hardware flags with bit 31
of the page table interrupt registers and no master bit. Patch 1 stops
reporting them. Patch 2 makes the remaining fault messages say which
walk failed and what the interrupt register held.

Tested on an Orange Pi Zero2 (H616) with HDMI forced on at 1024x768 and
three 4K H.264 decodes through cedrus, on 7.3 kernels with and without
the patches:
- without: 214 "Page fault ... (master -1, dir rd)" lines;
- with: none, no "Page fault" line at all, and no decode errors or
  timeouts.
Since the patched kernel prints every fault that is not a masterless
prefetch walk, this also shows that the hardware sets bit 31 for these
walks.

These patches were developed with Claude (Anthropic) as a coding
assistant. It investigated the problem and wrote the code and the commit
messages; I reviewed them, and they were tested on an Orange Pi Zero2
(H616) as described above.

---
Arun Iyengar (2):
      iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults
      iommu/sun50i: Print the page table level and status of a fault

 drivers/iommu/sun50i-iommu.c | 50 ++++++++++++++++++++++++++++++++++----------
 1 file changed, 39 insertions(+), 11 deletions(-)
---
base-commit: 2cf4be57b301ed2d7af82e70cff5dfd96894d8de
change-id: 20261110-sun50i-iommu-prefetch-85cc9ecff559

Best regards,
--  
Arun Iyengar <aiyengar1990@gmail.com>



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults
  2026-11-10  6:05 [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Arun Iyengar via B4 Relay
@ 2026-11-10  6:05 ` Arun Iyengar via B4 Relay
  2026-11-10  6:05 ` [PATCH 2/2] iommu/sun50i: Print the page table level and status of a fault Arun Iyengar via B4 Relay
  2026-11-10 16:04 ` [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Jernej Škrabec
  2 siblings, 0 replies; 4+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-10  6:05 UTC (permalink / raw)
  To: Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, Maxime Ripard
  Cc: iommu, linux-arm-kernel, linux-sunxi, linux-kernel

From: Arun Iyengar <aiyengar1990@gmail.com>

With a display scanning out, the driver reports

  sun50i-iommu 30f0000.iommu: Page fault for 0x00000000fff00000 (master -1, dir rd)

on an H616 once when fbcon takes over the framebuffer (the first
scanout frame), and again, vsync-spaced, after TLB flushes while a video
decoder frees its buffers (every unmap flushes the whole TLB and PTW
cache in this driver). No device accesses that address: with the IOVA
allocator handing out addresses from the top down and size-aligned, the
3 MiB fbcon framebuffer of a 1024x768 mode is the first allocation and
lands at 0xffc00000-0xffefffff, and the top 1 MiB of the IOVA space
above it is never mapped. 0xfff00000 is the page after the end of the
framebuffer.

The walk that fails is the TLB prefetcher's, for the page after the one
the master is reading. The H616 user manual (3.12.6.50, 3.12.6.51) gives
the L1/L2 page table interrupt registers a bit 31 next to the per-master
bits for walks that no master started, and Allwinner's sunxi-iommu
driver treats a page table interrupt with bit 31 set as a prefetch of an
unmapped page ("It's OK to prefetch an invalid pagetable") and does not
report it. This driver masks the register to the master bits, gets no
bit, and reports ilog2(0) = -1 as the master.

Return early for a page table interrupt with the prefetch bit set and no
master bit: no master read anything and nothing is stalled, so there is
nothing to report, reset or zap. Print such walks with dev_dbg so they
can still be counted.

Fixes: 4100b8c229b3 ("iommu: Add Allwinner H6 IOMMU driver")
Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
 drivers/iommu/sun50i-iommu.c | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index be3f1ce696ba..1b7a7f0d9b62 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -73,6 +73,15 @@
 #define IOMMU_INT_ERR_DATA_REG(i)	(0x150 + (i) * 4)
 #define IOMMU_L1PG_INT_REG		0x0180
 #define IOMMU_L2PG_INT_REG		0x0184
+/*
+ * Besides one bit per master, the L1/L2 page table interrupt registers
+ * have a bit for a page table walk that no master started: the TLB
+ * prefetcher's walk for the page after the one being accessed (H616 user
+ * manual 3.12.6.50 and 3.12.6.51, bit 31, "debug mode"; the vendor's
+ * sunxi-iommu treats a page table fault with this bit as a prefetch of an
+ * unmapped page and does not report it).
+ */
+#define IOMMU_PG_INT_PREFETCH			BIT(31)
 
 #define IOMMU_INT_INVALID_L2PG			BIT(17)
 #define IOMMU_INT_INVALID_L1PG			BIT(16)
@@ -891,6 +900,20 @@ static phys_addr_t sun50i_iommu_handle_pt_irq(struct sun50i_iommu *iommu,
 
 	iova = iommu_read(iommu, addr_reg);
 	blame = iommu_read(iommu, blame_reg);
+
+	/*
+	 * A walk the TLB prefetcher started for the page after the one a
+	 * master is reading fails whenever that next page is not mapped,
+	 * e.g. for the display engine scanning out a framebuffer that ends
+	 * at an unmapped IOVA. No master accessed the page and nothing is
+	 * stalled or cached, so there is nothing to report, reset or zap.
+	 */
+	if ((blame & IOMMU_PG_INT_PREFETCH) && !(blame & IOMMU_INT_MASTER_MASK)) {
+		dev_dbg_ratelimited(iommu->dev, "page table prefetch of unmapped %pad\n",
+				    &iova);
+		return iova;
+	}
+
 	master = ilog2(blame & IOMMU_INT_MASTER_MASK);
 
 	/*

-- 
2.55.0



^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] iommu/sun50i: Print the page table level and status of a fault
  2026-11-10  6:05 [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Arun Iyengar via B4 Relay
  2026-11-10  6:05 ` [PATCH 1/2] iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults Arun Iyengar via B4 Relay
@ 2026-11-10  6:05 ` Arun Iyengar via B4 Relay
  2026-11-10 16:04 ` [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Jernej Škrabec
  2 siblings, 0 replies; 4+ messages in thread
From: Arun Iyengar via B4 Relay @ 2026-11-10  6:05 UTC (permalink / raw)
  To: Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Chen-Yu Tsai, Jernej Skrabec,
	Samuel Holland, Maxime Ripard
  Cc: iommu, linux-arm-kernel, linux-sunxi, linux-kernel

From: Arun Iyengar <aiyengar1990@gmail.com>

A page table fault that the hardware does not attribute to a master is
currently printed with master ilog2(0) = -1 and nothing else, which says
neither which walk failed nor what the interrupt register held. Name the
level (L1 or L2 page table, or permission) and print the raw blame
register next to the master, and print -1 explicitly when no master bit
is set, so such a fault is still diagnosable.

Signed-off-by: Arun Iyengar <aiyengar1990@gmail.com>
---
 drivers/iommu/sun50i-iommu.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/sun50i-iommu.c b/drivers/iommu/sun50i-iommu.c
index 1b7a7f0d9b62..47e398e25a51 100644
--- a/drivers/iommu/sun50i-iommu.c
+++ b/drivers/iommu/sun50i-iommu.c
@@ -874,11 +874,13 @@ static const struct iommu_ops sun50i_iommu_ops = {
 };
 
 static void sun50i_iommu_report_fault(struct sun50i_iommu *iommu,
-				      unsigned master, phys_addr_t iova,
-				      unsigned prot)
+				      int master, phys_addr_t iova,
+				      unsigned int prot, const char *type,
+				      u32 status)
 {
-	dev_err(iommu->dev, "Page fault for %pad (master %d, dir %s)\n",
-		&iova, master, (prot == IOMMU_FAULT_WRITE) ? "wr" : "rd");
+	dev_err(iommu->dev, "Page fault for %pad (master %d, dir %s, %s, status %#x)\n",
+		&iova, master, (prot == IOMMU_FAULT_WRITE) ? "wr" : "rd",
+		type, status);
 
 	if (iommu->domain)
 		report_iommu_fault(iommu->domain, iommu->dev, iova, prot);
@@ -890,10 +892,11 @@ static void sun50i_iommu_report_fault(struct sun50i_iommu *iommu,
 
 static phys_addr_t sun50i_iommu_handle_pt_irq(struct sun50i_iommu *iommu,
 					      unsigned addr_reg,
-					      unsigned blame_reg)
+					      unsigned int blame_reg,
+					      const char *level)
 {
 	phys_addr_t iova;
-	unsigned master;
+	int master = -1;
 	u32 blame;
 
 	assert_spin_locked(&iommu->iommu_lock);
@@ -909,19 +912,21 @@ static phys_addr_t sun50i_iommu_handle_pt_irq(struct sun50i_iommu *iommu,
 	 * stalled or cached, so there is nothing to report, reset or zap.
 	 */
 	if ((blame & IOMMU_PG_INT_PREFETCH) && !(blame & IOMMU_INT_MASTER_MASK)) {
-		dev_dbg_ratelimited(iommu->dev, "page table prefetch of unmapped %pad\n",
-				    &iova);
+		dev_dbg_ratelimited(iommu->dev, "%s prefetch of unmapped %pad\n",
+				    level, &iova);
 		return iova;
 	}
 
-	master = ilog2(blame & IOMMU_INT_MASTER_MASK);
+	if (blame & IOMMU_INT_MASTER_MASK)
+		master = ilog2(blame & IOMMU_INT_MASTER_MASK);
 
 	/*
 	 * If the address is not in the page table, we can't get what
 	 * operation triggered the fault. Assume it's a read
 	 * operation.
 	 */
-	sun50i_iommu_report_fault(iommu, master, iova, IOMMU_FAULT_READ);
+	sun50i_iommu_report_fault(iommu, master, iova, IOMMU_FAULT_READ, level,
+				  blame);
 
 	return iova;
 }
@@ -976,7 +981,7 @@ static phys_addr_t sun50i_iommu_handle_perm_irq(struct sun50i_iommu *iommu)
 	 * operation triggered the fault. Assume it's a read
 	 * operation.
 	 */
-	sun50i_iommu_report_fault(iommu, master, iova, dir);
+	sun50i_iommu_report_fault(iommu, master, iova, dir, "permission", blame);
 
 	return iova;
 }
@@ -1000,11 +1005,11 @@ static irqreturn_t sun50i_iommu_irq(int irq, void *dev_id)
 	if (status & IOMMU_INT_INVALID_L2PG)
 		sun50i_iommu_handle_pt_irq(iommu,
 					    IOMMU_INT_ERR_ADDR_L2_REG,
-					    IOMMU_L2PG_INT_REG);
+					    IOMMU_L2PG_INT_REG, "L2 page table");
 	else if (status & IOMMU_INT_INVALID_L1PG)
 		sun50i_iommu_handle_pt_irq(iommu,
 					   IOMMU_INT_ERR_ADDR_L1_REG,
-					   IOMMU_L1PG_INT_REG);
+					   IOMMU_L1PG_INT_REG, "L1 page table");
 	else
 		sun50i_iommu_handle_perm_irq(iommu);
 

-- 
2.55.0



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults
  2026-11-10  6:05 [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Arun Iyengar via B4 Relay
  2026-11-10  6:05 ` [PATCH 1/2] iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults Arun Iyengar via B4 Relay
  2026-11-10  6:05 ` [PATCH 2/2] iommu/sun50i: Print the page table level and status of a fault Arun Iyengar via B4 Relay
@ 2026-11-10 16:04 ` Jernej Škrabec
  2 siblings, 0 replies; 4+ messages in thread
From: Jernej Škrabec @ 2026-11-10 16:04 UTC (permalink / raw)
  To: Joerg Roedel (AMD),
	Will Deacon, Robin Murphy, Chen-Yu Tsai, Samuel Holland,
	Maxime Ripard, aiyengar1990
  Cc: iommu, linux-arm-kernel, linux-sunxi, linux-kernel

Dne torek, 10. november 2026 ob 07:05:16 Srednjeevropski standardni čas je Arun Iyengar via B4 Relay napisal(a):
> On an H616 with a display scanning out, the IOMMU reports page faults
> with master -1 at the IOVA right after the end of the framebuffer: once
> at the first fbcon frame, and then once per frame for a while after
> each TLB flush, e.g. while a video decoder frees its buffers. They are
> failed walks of the TLB prefetcher, which the hardware flags with bit 31
> of the page table interrupt registers and no master bit. Patch 1 stops
> reporting them. Patch 2 makes the remaining fault messages say which
> walk failed and what the interrupt register held.
> 
> Tested on an Orange Pi Zero2 (H616) with HDMI forced on at 1024x768 and
> three 4K H.264 decodes through cedrus, on 7.3 kernels with and without
> the patches:
> - without: 214 "Page fault ... (master -1, dir rd)" lines;
> - with: none, no "Page fault" line at all, and no decode errors or
>   timeouts.
> Since the patched kernel prints every fault that is not a masterless
> prefetch walk, this also shows that the hardware sets bit 31 for these
> walks.

First off, display engine isn't in merged yet. Second, I don't observe any
such issues with my wip H616 code.

I think it's best to wait until driver is merged and can be retested and
merged then, if needed.

Best regards,
Jernej

> 
> These patches were developed with Claude (Anthropic) as a coding
> assistant. It investigated the problem and wrote the code and the commit
> messages; I reviewed them, and they were tested on an Orange Pi Zero2
> (H616) as described above.
> 
> ---
> Arun Iyengar (2):
>       iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults
>       iommu/sun50i: Print the page table level and status of a fault
> 
>  drivers/iommu/sun50i-iommu.c | 50 ++++++++++++++++++++++++++++++++++----------
>  1 file changed, 39 insertions(+), 11 deletions(-)
> ---
> base-commit: 2cf4be57b301ed2d7af82e70cff5dfd96894d8de
> change-id: 20261110-sun50i-iommu-prefetch-85cc9ecff559
> 
> Best regards,
> --  
> Arun Iyengar <aiyengar1990@gmail.com>
> 
> 
> 





^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2026-11-10 16:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-10  6:05 [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Arun Iyengar via B4 Relay
2026-11-10  6:05 ` [PATCH 1/2] iommu/sun50i: Don't report TLB prefetches of unmapped pages as faults Arun Iyengar via B4 Relay
2026-11-10  6:05 ` [PATCH 2/2] iommu/sun50i: Print the page table level and status of a fault Arun Iyengar via B4 Relay
2026-11-10 16:04 ` [PATCH 0/2] iommu/sun50i: Don't report TLB prefetch walks as page faults Jernej Škrabec

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®