diff options
Diffstat (limited to 'arch/arm64/include/asm/tlbflush.h')
-rw-r--r-- | arch/arm64/include/asm/tlbflush.h | 49 |
1 files changed, 42 insertions, 7 deletions
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h index bc3949064725..e3660cce3e96 100644 --- a/arch/arm64/include/asm/tlbflush.h +++ b/arch/arm64/include/asm/tlbflush.h @@ -15,6 +15,12 @@ #include <asm/cputype.h> #include <asm/mmu.h> +#ifdef CONFIG_IMX_SCU_SOC +extern bool TKT340553_SW_WORKAROUND; +#else +#define TKT340553_SW_WORKAROUND 0 +#endif + /* * Raw TLBI operations. * @@ -149,9 +155,16 @@ static inline void flush_tlb_mm(struct mm_struct *mm) unsigned long asid = __TLBI_VADDR(0, ASID(mm)); dsb(ishst); - __tlbi(aside1is, asid); - __tlbi_user(aside1is, asid); - dsb(ish); + if (TKT340553_SW_WORKAROUND) { + /* Flush the entire TLB */ + __tlbi(vmalle1is); + dsb(ish); + isb(); + } else { + __tlbi(aside1is, asid); + __tlbi_user(aside1is, asid); + dsb(ish); + } } static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, @@ -160,8 +173,15 @@ static inline void flush_tlb_page_nosync(struct vm_area_struct *vma, unsigned long addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm)); dsb(ishst); - __tlbi(vale1is, addr); - __tlbi_user(vale1is, addr); + if (TKT340553_SW_WORKAROUND) { + /* Flush the entire TLB */ + __tlbi(vmalle1is); + dsb(ish); + isb(); + } else { + __tlbi(vale1is, addr); + __tlbi_user(vale1is, addr); + } } static inline void flush_tlb_page(struct vm_area_struct *vma, @@ -199,6 +219,15 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, end = __TLBI_VADDR(end, asid); dsb(ishst); + + if (TKT340553_SW_WORKAROUND) { + /* Flush the entire TLB and exit */ + __tlbi(vmalle1is); + dsb(ish); + isb(); + return; + } + for (addr = start; addr < end; addr += stride) { if (last_level) { __tlbi(vale1is, addr); @@ -208,6 +237,7 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma, __tlbi_user(vae1is, addr); } } + dsb(ish); } @@ -225,7 +255,8 @@ static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end { unsigned long addr; - if ((end - start) > (MAX_TLBI_OPS * PAGE_SIZE)) { + if (((end - start) > (MAX_TLBI_OPS * PAGE_SIZE)) + || (TKT340553_SW_WORKAROUND)) { flush_tlb_all(); return; } @@ -249,7 +280,11 @@ static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr) unsigned long addr = __TLBI_VADDR(kaddr, 0); dsb(ishst); - __tlbi(vaae1is, addr); + if (TKT340553_SW_WORKAROUND) + /* Flush the entire TLB */ + __tlbi(vmalle1is); + else + __tlbi(vaae1is, addr); dsb(ish); isb(); } |