diff options
Diffstat (limited to 'arch/arm64/include')
-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 9e82dd79c7db..8c72efcb638e 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. @@ -120,8 +121,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); } @@ -131,8 +136,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); } @@ -148,6 +157,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); @@ -156,10 +166,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 { @@ -189,8 +203,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(); } @@ -204,8 +222,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); } |