aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZhenyu Ye <[email protected]>2020-06-25 16:03:11 +0800
committerCatalin Marinas <[email protected]>2020-07-07 11:23:46 +0100
commite735b98a5fe08c0f50f9fdc3e3a844e3638e6649 (patch)
tree15acf246fe406eae95a9b79b2704a5f16bcbca09
parentc10bc62ae4d2135c9db40e96a8e994164faee531 (diff)
arm64: Add tlbi_user_level TLB invalidation helper
Add a level-hinted parameter to __tlbi_user, which only gets used if ARMv8.4-TTL gets detected. ARMv8.4-TTL provides the TTL field in tlbi instruction to indicate the level of translation table walk holding the leaf entry for the address that is being invalidated. This patch set the default level value of flush_tlb_range() to 0, which will be updated in future patches. And set the ttl value of flush_tlb_page_nosync() to 3 because it is only called to flush a single pte page. Signed-off-by: Zhenyu Ye <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
-rw-r--r--arch/arm64/include/asm/tlbflush.h18
1 files changed, 12 insertions, 6 deletions
diff --git a/arch/arm64/include/asm/tlbflush.h b/arch/arm64/include/asm/tlbflush.h
index 3353f26302de..e1d07612e147 100644
--- a/arch/arm64/include/asm/tlbflush.h
+++ b/arch/arm64/include/asm/tlbflush.h
@@ -104,6 +104,11 @@
__tlbi(op, arg); \
} while(0)
+#define __tlbi_user_level(op, arg, level) do { \
+ if (arm64_kernel_unmapped_at_el0()) \
+ __tlbi_level(op, (arg | USER_ASID_FLAG), level); \
+} while (0)
+
/*
* TLB Invalidation
* ================
@@ -205,8 +210,9 @@ 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);
+ /* This function is only called on a small page */
+ __tlbi_level(vale1is, addr, 3);
+ __tlbi_user_level(vale1is, addr, 3);
}
static inline void flush_tlb_page(struct vm_area_struct *vma,
@@ -246,11 +252,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
dsb(ishst);
for (addr = start; addr < end; addr += stride) {
if (last_level) {
- __tlbi(vale1is, addr);
- __tlbi_user(vale1is, addr);
+ __tlbi_level(vale1is, addr, 0);
+ __tlbi_user_level(vale1is, addr, 0);
} else {
- __tlbi(vae1is, addr);
- __tlbi_user(vae1is, addr);
+ __tlbi_level(vae1is, addr, 0);
+ __tlbi_user_level(vae1is, addr, 0);
}
}
dsb(ish);