Skip to content

Commit c4ab2cb

Browse files
Zhenyu Yectmarinas
authored andcommitted
arm64: tlb: Set the TTL field in flush_tlb_range
This patch uses the cleared_* in struct mmu_gather to set the TTL field in flush_tlb_range(). Signed-off-by: Zhenyu Ye <[email protected]> Reviewed-by: Catalin Marinas <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Catalin Marinas <[email protected]>
1 parent 2631ed0 commit c4ab2cb

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

arch/arm64/include/asm/tlb.h

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,37 @@ static void tlb_flush(struct mmu_gather *tlb);
2121

2222
#include <asm-generic/tlb.h>
2323

24+
/*
25+
* get the tlbi levels in arm64. Default value is 0 if more than one
26+
* of cleared_* is set or neither is set.
27+
* Arm64 doesn't support p4ds now.
28+
*/
29+
static inline int tlb_get_level(struct mmu_gather *tlb)
30+
{
31+
if (tlb->cleared_ptes && !(tlb->cleared_pmds ||
32+
tlb->cleared_puds ||
33+
tlb->cleared_p4ds))
34+
return 3;
35+
36+
if (tlb->cleared_pmds && !(tlb->cleared_ptes ||
37+
tlb->cleared_puds ||
38+
tlb->cleared_p4ds))
39+
return 2;
40+
41+
if (tlb->cleared_puds && !(tlb->cleared_ptes ||
42+
tlb->cleared_pmds ||
43+
tlb->cleared_p4ds))
44+
return 1;
45+
46+
return 0;
47+
}
48+
2449
static inline void tlb_flush(struct mmu_gather *tlb)
2550
{
2651
struct vm_area_struct vma = TLB_FLUSH_VMA(tlb->mm, 0);
2752
bool last_level = !tlb->freed_tables;
2853
unsigned long stride = tlb_get_unmap_size(tlb);
54+
int tlb_level = tlb_get_level(tlb);
2955

3056
/*
3157
* If we're tearing down the address space then we only care about
@@ -38,7 +64,8 @@ static inline void tlb_flush(struct mmu_gather *tlb)
3864
return;
3965
}
4066

41-
__flush_tlb_range(&vma, tlb->start, tlb->end, stride, last_level);
67+
__flush_tlb_range(&vma, tlb->start, tlb->end, stride,
68+
last_level, tlb_level);
4269
}
4370

4471
static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,

arch/arm64/include/asm/tlbflush.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -230,7 +230,8 @@ static inline void flush_tlb_page(struct vm_area_struct *vma,
230230

231231
static inline void __flush_tlb_range(struct vm_area_struct *vma,
232232
unsigned long start, unsigned long end,
233-
unsigned long stride, bool last_level)
233+
unsigned long stride, bool last_level,
234+
int tlb_level)
234235
{
235236
unsigned long asid = ASID(vma->vm_mm);
236237
unsigned long addr;
@@ -252,11 +253,11 @@ static inline void __flush_tlb_range(struct vm_area_struct *vma,
252253
dsb(ishst);
253254
for (addr = start; addr < end; addr += stride) {
254255
if (last_level) {
255-
__tlbi_level(vale1is, addr, 0);
256-
__tlbi_user_level(vale1is, addr, 0);
256+
__tlbi_level(vale1is, addr, tlb_level);
257+
__tlbi_user_level(vale1is, addr, tlb_level);
257258
} else {
258-
__tlbi_level(vae1is, addr, 0);
259-
__tlbi_user_level(vae1is, addr, 0);
259+
__tlbi_level(vae1is, addr, tlb_level);
260+
__tlbi_user_level(vae1is, addr, tlb_level);
260261
}
261262
}
262263
dsb(ish);
@@ -268,8 +269,9 @@ static inline void flush_tlb_range(struct vm_area_struct *vma,
268269
/*
269270
* We cannot use leaf-only invalidation here, since we may be invalidating
270271
* table entries as part of collapsing hugepages or moving page tables.
272+
* Set the tlb_level to 0 because we can not get enough information here.
271273
*/
272-
__flush_tlb_range(vma, start, end, PAGE_SIZE, false);
274+
__flush_tlb_range(vma, start, end, PAGE_SIZE, false, 0);
273275
}
274276

275277
static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)

0 commit comments

Comments
 (0)