This source file includes following definitions.
- local_flush_tlb_all
- flush_tlb_all
- flush_tlb_mm
- flush_tlb_page_nosync
- flush_tlb_page
- __flush_tlb_range
- flush_tlb_range
- flush_tlb_kernel_range
- __flush_tlb_kernel_pgtable
1
2
3
4
5
6
7
8 #ifndef __ASM_TLBFLUSH_H
9 #define __ASM_TLBFLUSH_H
10
11 #ifndef __ASSEMBLY__
12
13 #include <linux/mm_types.h>
14 #include <linux/sched.h>
15 #include <asm/cputype.h>
16 #include <asm/mmu.h>
17
18
19
20
21
22
23
24
25
26
27
28
29
30 #define __TLBI_0(op, arg) asm ("tlbi " #op "\n" \
31 ALTERNATIVE("nop\n nop", \
32 "dsb ish\n tlbi " #op, \
33 ARM64_WORKAROUND_REPEAT_TLBI, \
34 CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
35 : : )
36
37 #define __TLBI_1(op, arg) asm ("tlbi " #op ", %0\n" \
38 ALTERNATIVE("nop\n nop", \
39 "dsb ish\n tlbi " #op ", %0", \
40 ARM64_WORKAROUND_REPEAT_TLBI, \
41 CONFIG_ARM64_WORKAROUND_REPEAT_TLBI) \
42 : : "r" (arg))
43
44 #define __TLBI_N(op, arg, n, ...) __TLBI_##n(op, arg)
45
46 #define __tlbi(op, ...) __TLBI_N(op, ##__VA_ARGS__, 1, 0)
47
48 #define __tlbi_user(op, arg) do { \
49 if (arm64_kernel_unmapped_at_el0()) \
50 __tlbi(op, (arg) | USER_ASID_FLAG); \
51 } while (0)
52
53
54 #define __TLBI_VADDR(addr, asid) \
55 ({ \
56 unsigned long __ta = (addr) >> 12; \
57 __ta &= GENMASK_ULL(43, 0); \
58 __ta |= (unsigned long)(asid) << 48; \
59 __ta; \
60 })
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131 static inline void local_flush_tlb_all(void)
132 {
133 dsb(nshst);
134 __tlbi(vmalle1);
135 dsb(nsh);
136 isb();
137 }
138
139 static inline void flush_tlb_all(void)
140 {
141 dsb(ishst);
142 __tlbi(vmalle1is);
143 dsb(ish);
144 isb();
145 }
146
147 static inline void flush_tlb_mm(struct mm_struct *mm)
148 {
149 unsigned long asid = __TLBI_VADDR(0, ASID(mm));
150
151 dsb(ishst);
152 __tlbi(aside1is, asid);
153 __tlbi_user(aside1is, asid);
154 dsb(ish);
155 }
156
157 static inline void flush_tlb_page_nosync(struct vm_area_struct *vma,
158 unsigned long uaddr)
159 {
160 unsigned long addr = __TLBI_VADDR(uaddr, ASID(vma->vm_mm));
161
162 dsb(ishst);
163 __tlbi(vale1is, addr);
164 __tlbi_user(vale1is, addr);
165 }
166
167 static inline void flush_tlb_page(struct vm_area_struct *vma,
168 unsigned long uaddr)
169 {
170 flush_tlb_page_nosync(vma, uaddr);
171 dsb(ish);
172 }
173
174
175
176
177
178 #define MAX_TLBI_OPS PTRS_PER_PTE
179
180 static inline void __flush_tlb_range(struct vm_area_struct *vma,
181 unsigned long start, unsigned long end,
182 unsigned long stride, bool last_level)
183 {
184 unsigned long asid = ASID(vma->vm_mm);
185 unsigned long addr;
186
187 start = round_down(start, stride);
188 end = round_up(end, stride);
189
190 if ((end - start) >= (MAX_TLBI_OPS * stride)) {
191 flush_tlb_mm(vma->vm_mm);
192 return;
193 }
194
195
196 stride >>= 12;
197
198 start = __TLBI_VADDR(start, asid);
199 end = __TLBI_VADDR(end, asid);
200
201 dsb(ishst);
202 for (addr = start; addr < end; addr += stride) {
203 if (last_level) {
204 __tlbi(vale1is, addr);
205 __tlbi_user(vale1is, addr);
206 } else {
207 __tlbi(vae1is, addr);
208 __tlbi_user(vae1is, addr);
209 }
210 }
211 dsb(ish);
212 }
213
214 static inline void flush_tlb_range(struct vm_area_struct *vma,
215 unsigned long start, unsigned long end)
216 {
217
218
219
220
221 __flush_tlb_range(vma, start, end, PAGE_SIZE, false);
222 }
223
224 static inline void flush_tlb_kernel_range(unsigned long start, unsigned long end)
225 {
226 unsigned long addr;
227
228 if ((end - start) > (MAX_TLBI_OPS * PAGE_SIZE)) {
229 flush_tlb_all();
230 return;
231 }
232
233 start = __TLBI_VADDR(start, 0);
234 end = __TLBI_VADDR(end, 0);
235
236 dsb(ishst);
237 for (addr = start; addr < end; addr += 1 << (PAGE_SHIFT - 12))
238 __tlbi(vaale1is, addr);
239 dsb(ish);
240 isb();
241 }
242
243
244
245
246
247 static inline void __flush_tlb_kernel_pgtable(unsigned long kaddr)
248 {
249 unsigned long addr = __TLBI_VADDR(kaddr, 0);
250
251 dsb(ishst);
252 __tlbi(vaae1is, addr);
253 dsb(ish);
254 isb();
255 }
256 #endif
257
258 #endif