From 17dd577a6ad517fb099eb5bb39ee399d99649012 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Thu, 10 Aug 2017 14:13:33 +0100 Subject: [PATCH] arm64: mm: Invalidate both kernel and user ASIDs when performing TLBI commit 9b0de864b5bc upstream. Since an mm has both a kernel and a user ASID, we need to ensure that broadcast TLB maintenance targets both address spaces so that things like CoW continue to work with the uaccess primitives in the kernel. Reviewed-by: Mark Rutland Tested-by: Laura Abbott Tested-by: Shanker Donthineni Signed-off-by: Will Deacon Signed-off-by: Alex Shi --- arch/arm64/include/asm/tlbflush.h | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index 2855f83b44c0..8c4f1b245033 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -24,6 +24,7 @@ #include #include #include +#include /* * Raw TLBI operations. @@ -43,6 +44,11 @@ #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0) +#define __tlbi_user(op, arg) do { \ + if (arm64_kernel_unmapped_at_el0()) \ + __tlbi(op, (arg) | USER_ASID_FLAG); \ +} while (0) + /* * TLB Management * ============== @@ -105,8 +111,10 @@ static inline void flush_tlb_mm(struct mm_struct *mm) dsb(ishst); if (TKT340553_SW_WORKAROUND && ASID(mm) >> 11) __tlbi(vmalle1is); - else + else { __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); + } dsb(ish); } @@ -118,8 +126,10 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, dsb(ishst); if (TKT340553_SW_WORKAROUND && (uaddr >> 36 || (ASID(vma->vm_mm) >> 12))) __tlbi(vmalle1is); - else + else { __tlbi(vale1is, addr); + __tlbi_user(vale1is, addr); + } dsb(ish); } @@ -151,10 +161,14 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { if (TKT340553_SW_WORKAROUND && (addr & mask || (ASID(vma->vm_mm) >> 12))) __tlbi(vmalle1is); - else if (last_level) + else if (last_level) { __tlbi(vale1is, addr); - else + __tlbi_user(vale1is, addr); + } + else { __tlbi(vae1is, addr); + __tlbi_user(vae1is, addr); + } } dsb(ish); } @@ -199,8 +213,10 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, if (TKT340553_SW_WORKAROUND && (uaddr >> 36 || (ASID(mm) >> 12))) __tlbi(vmalle1is); - else + else { __tlbi(vae1is, addr); + __tlbi_user(vae1is, addr); + } dsb(ish); } -- 2.17.1