diff options
Diffstat (limited to 'arch/arm64/include/asm/tlbflush.h')
-rw-r--r-- | arch/arm64/include/asm/tlbflush.h | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index ad6bd8b26ada..6d2349df0048 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -24,6 +24,7 @@ #include <linux/sched.h> #include <asm/cputype.h> #include <asm/mmu.h> +#include <soc/imx8/soc.h> /* * Raw TLBI operations. @@ -108,8 +109,12 @@ static inline void flush_tlb_mm(struct mm_struct *mm) unsigned long asid = ASID(mm) << 48; dsb(ishst); - __tlbi(aside1is, asid); - __tlbi_user(aside1is, asid); + if (TKT340553_SW_WORKAROUND && ASID(mm) >> 11) { + __tlbi(vmalle1is); + } else { + __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); + } dsb(ish); } @@ -119,8 +124,12 @@ static inline void flush_tlb_page(struct vm_area_struct *vma, unsigned long addr = uaddr >> 12 | (ASID(vma->vm_mm) << 48); dsb(ishst); - __tlbi(vale1is, addr); - __tlbi_user(vale1is, addr); + if (TKT340553_SW_WORKAROUND && (uaddr >> 36 || (ASID(vma->vm_mm) >> 12))) { + __tlbi(vmalle1is); + } else { + __tlbi(vale1is, addr); + __tlbi_user(vale1is, addr); + } dsb(ish); } @@ -136,6 +145,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, { unsigned long asid = ASID(vma->vm_mm) << 48; unsigned long addr; + unsigned long mask = (1 << 20) - 1; if ((end - start) > MAX_TLB_RANGE) { flush_tlb_mm(vma->vm_mm); @@ -144,10 +154,14 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, start = asid | (start >> 12); end = asid | (end >> 12); + mask <<= 24; + dsb(ishst); for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { - if (last_level) { + if (TKT340553_SW_WORKAROUND && (addr & mask || (ASID(vma->vm_mm) >> 12))) { + __tlbi(vmalle1is); + } else if (last_level) { __tlbi(vale1is, addr); __tlbi_user(vale1is, addr); } else { @@ -177,8 +191,12 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end end >>= 12; dsb(ishst); - for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) - __tlbi(vaae1is, addr); + for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12)) { + if (TKT340553_SW_WORKAROUND && addr >> 24) + __tlbi(vmalle1is); + else + __tlbi(vaae1is, addr); + } dsb(ish); isb(); } @@ -192,8 +210,13 @@ static inline void __flush_tlb_pgtable(struct mm_struct *mm, { unsigned long addr = uaddr >> 12 | (ASID(mm) << 48); - __tlbi(vae1is, addr); - __tlbi_user(vae1is, addr); + if (TKT340553_SW_WORKAROUND && (uaddr >> 36 || (ASID(mm) >> 12))) { + __tlbi(vmalle1is); + } else { + __tlbi(vae1is, addr); + __tlbi_user(vae1is, addr); + } + dsb(ish); } |