[PATCH 4/6] alpha: only use a targeted tbi() when the target mm is really current (UP)
Magnus Lindholm <[email protected]>
| Newsgroups | org.kernel.vger.linux-alpha,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- 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