[PATCH 4/6] alpha: only use a targeted tbi() when the target mm is really current (UP)

From: Magnus Lindholm

Date: Sun Aug 09 2026 - 04:57:46 EST


The uniprocessor flush_tlb_page() has the same defect the previous patch
fixed for SMP:

if (mm == current->active_mm)
flush_tlb_current_page(mm, vma, addr);
else
flush_tlb_other(mm);

For a non-executable vma flush_tlb_current_page() issues tbi(2, addr),
which acts on the address space context currently loaded, so it reaches
the mm's translations only when that context belongs to it. Under lazy
TLB an idle or kernel task keeps the mm as its active_mm while a different
ASN is loaded, so the tbi() invalidates the wrong context and the stale
translation survives.

Use current->mm instead, as for SMP.

This is not theoretical on a uniprocessor. folio_mkclean() runs in the
writeback flusher kworker, which borrows the mm, and with one CPU that
kworker necessarily shares it with the thread holding the translation. A
test that writes a small MAP_SHARED file while background writeback cleans
it loses data on every round: the mapping holds one value and the file
another.

flush_tlb_mm() and flush_icache_user_page() need no equivalent change
here. Both use __load_new_mm_context(), which allocates and loads a fresh
context rather than relying on a targeted tbi() against whatever ASN
happened to be loaded.

Signed-off-by: Magnus Lindholm <linmag7@xxxxxxxxx>
---
arch/alpha/include/asm/tlbflush.h | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/arch/alpha/include/asm/tlbflush.h b/arch/alpha/include/asm/tlbflush.h
index 0c8529997f54..6593a64090f1 100644
--- a/arch/alpha/include/asm/tlbflush.h
+++ b/arch/alpha/include/asm/tlbflush.h
@@ -87,7 +87,14 @@ flush_tlb_page(struct vm_area_struct *vma, unsigned long addr)
{
struct mm_struct *mm = vma->vm_mm;

- if (mm == current->active_mm)
+ /*
+ * tbi() acts on the address space context currently loaded, so it
+ * reaches MM's translations only when a thread of MM is current.
+ * Under lazy TLB an idle or kernel task keeps MM as its active_mm
+ * with a different ASN loaded, and a targeted tbi() would then
+ * invalidate the wrong context.
+ */
+ if (mm == current->mm)
flush_tlb_current_page(mm, vma, addr);
else
flush_tlb_other(mm);
--
2.53.0