summaryrefslogtreecommitdiff
path: root/arch/arm64/include/asm/tlbflush.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/include/asm/tlbflush.h')
-rw-r--r--arch/arm64/include/asm/tlbflush.h41
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);
}