1
2
3
4
5
6
7
8
9
10#ifndef _ASMARM_TLBFLUSH_H
11#define _ASMARM_TLBFLUSH_H
12
13
14#ifndef CONFIG_MMU
15
16#define tlb_flush(tlb) ((void) tlb)
17
18#else
19
20#include <asm/glue.h>
21
22#define TLB_V3_PAGE (1 << 0)
23#define TLB_V4_U_PAGE (1 << 1)
24#define TLB_V4_D_PAGE (1 << 2)
25#define TLB_V4_I_PAGE (1 << 3)
26#define TLB_V6_U_PAGE (1 << 4)
27#define TLB_V6_D_PAGE (1 << 5)
28#define TLB_V6_I_PAGE (1 << 6)
29
30#define TLB_V3_FULL (1 << 8)
31#define TLB_V4_U_FULL (1 << 9)
32#define TLB_V4_D_FULL (1 << 10)
33#define TLB_V4_I_FULL (1 << 11)
34#define TLB_V6_U_FULL (1 << 12)
35#define TLB_V6_D_FULL (1 << 13)
36#define TLB_V6_I_FULL (1 << 14)
37
38#define TLB_V6_U_ASID (1 << 16)
39#define TLB_V6_D_ASID (1 << 17)
40#define TLB_V6_I_ASID (1 << 18)
41
42#define TLB_DCLEAN (1 << 30)
43#define TLB_WB (1 << 31)
44
45
46
47
48
49
50
51
52
53
54
55
56#undef _TLB
57#undef MULTI_TLB
58
59#define v3_tlb_flags (TLB_V3_FULL | TLB_V3_PAGE)
60
61#ifdef CONFIG_CPU_TLB_V3
62# define v3_possible_flags v3_tlb_flags
63# define v3_always_flags v3_tlb_flags
64# ifdef _TLB
65# define MULTI_TLB 1
66# else
67# define _TLB v3
68# endif
69#else
70# define v3_possible_flags 0
71# define v3_always_flags (-1UL)
72#endif
73
74#define v4_tlb_flags (TLB_V4_U_FULL | TLB_V4_U_PAGE)
75
76#ifdef CONFIG_CPU_TLB_V4WT
77# define v4_possible_flags v4_tlb_flags
78# define v4_always_flags v4_tlb_flags
79# ifdef _TLB
80# define MULTI_TLB 1
81# else
82# define _TLB v4
83# endif
84#else
85# define v4_possible_flags 0
86# define v4_always_flags (-1UL)
87#endif
88
89#define v4wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \
90 TLB_V4_I_FULL | TLB_V4_D_FULL | \
91 TLB_V4_I_PAGE | TLB_V4_D_PAGE)
92
93#ifdef CONFIG_CPU_TLB_V4WBI
94# define v4wbi_possible_flags v4wbi_tlb_flags
95# define v4wbi_always_flags v4wbi_tlb_flags
96# ifdef _TLB
97# define MULTI_TLB 1
98# else
99# define _TLB v4wbi
100# endif
101#else
102# define v4wbi_possible_flags 0
103# define v4wbi_always_flags (-1UL)
104#endif
105
106#define v4wb_tlb_flags (TLB_WB | TLB_DCLEAN | \
107 TLB_V4_I_FULL | TLB_V4_D_FULL | \
108 TLB_V4_D_PAGE)
109
110#ifdef CONFIG_CPU_TLB_V4WB
111# define v4wb_possible_flags v4wb_tlb_flags
112# define v4wb_always_flags v4wb_tlb_flags
113# ifdef _TLB
114# define MULTI_TLB 1
115# else
116# define _TLB v4wb
117# endif
118#else
119# define v4wb_possible_flags 0
120# define v4wb_always_flags (-1UL)
121#endif
122
123#define v6wbi_tlb_flags (TLB_WB | TLB_DCLEAN | \
124 TLB_V6_I_FULL | TLB_V6_D_FULL | \
125 TLB_V6_I_PAGE | TLB_V6_D_PAGE | \
126 TLB_V6_I_ASID | TLB_V6_D_ASID)
127
128#ifdef CONFIG_CPU_TLB_V6
129# define v6wbi_possible_flags v6wbi_tlb_flags
130# define v6wbi_always_flags v6wbi_tlb_flags
131# ifdef _TLB
132# define MULTI_TLB 1
133# else
134# define _TLB v6wbi
135# endif
136#else
137# define v6wbi_possible_flags 0
138# define v6wbi_always_flags (-1UL)
139#endif
140
141#ifdef CONFIG_CPU_TLB_V7
142# define v7wbi_possible_flags v6wbi_tlb_flags
143# define v7wbi_always_flags v6wbi_tlb_flags
144# ifdef _TLB
145# define MULTI_TLB 1
146# else
147# define _TLB v7wbi
148# endif
149#else
150# define v7wbi_possible_flags 0
151# define v7wbi_always_flags (-1UL)
152#endif
153
154#ifndef _TLB
155#error Unknown TLB model
156#endif
157
158#ifndef __ASSEMBLY__
159
160#include <linux/sched.h>
161
162struct cpu_tlb_fns {
163 void (*flush_user_range)(unsigned long, unsigned long, struct vm_area_struct *);
164 void (*flush_kern_range)(unsigned long, unsigned long);
165 unsigned long tlb_flags;
166};
167
168
169
170
171#ifdef MULTI_TLB
172
173#define __cpu_flush_user_tlb_range cpu_tlb.flush_user_range
174#define __cpu_flush_kern_tlb_range cpu_tlb.flush_kern_range
175
176#else
177
178#define __cpu_flush_user_tlb_range __glue(_TLB,_flush_user_tlb_range)
179#define __cpu_flush_kern_tlb_range __glue(_TLB,_flush_kern_tlb_range)
180
181extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long, struct vm_area_struct *);
182extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
183
184#endif
185
186extern struct cpu_tlb_fns cpu_tlb;
187
188#define __cpu_tlb_flags cpu_tlb.tlb_flags
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245#define possible_tlb_flags (v3_possible_flags | \
246 v4_possible_flags | \
247 v4wbi_possible_flags | \
248 v4wb_possible_flags | \
249 v6wbi_possible_flags)
250
251#define always_tlb_flags (v3_always_flags & \
252 v4_always_flags & \
253 v4wbi_always_flags & \
254 v4wb_always_flags & \
255 v6wbi_always_flags)
256
257#define tlb_flag(f) ((always_tlb_flags & (f)) || (__tlb_flag & possible_tlb_flags & (f)))
258
259static inline void local_flush_tlb_all(void)
260{
261 const int zero = 0;
262 const unsigned int __tlb_flag = __cpu_tlb_flags;
263
264 if (tlb_flag(TLB_WB))
265 dsb();
266
267 if (tlb_flag(TLB_V3_FULL))
268 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
269 if (tlb_flag(TLB_V4_U_FULL | TLB_V6_U_FULL))
270 asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
271 if (tlb_flag(TLB_V4_D_FULL | TLB_V6_D_FULL))
272 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
273 if (tlb_flag(TLB_V4_I_FULL | TLB_V6_I_FULL))
274 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
275
276 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
277 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
278 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
279
280 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
281 dsb();
282 isb();
283 }
284}
285
286static inline void local_flush_tlb_mm(struct mm_struct *mm)
287{
288 const int zero = 0;
289 const int asid = ASID(mm);
290 const unsigned int __tlb_flag = __cpu_tlb_flags;
291
292 if (tlb_flag(TLB_WB))
293 dsb();
294
295 if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) {
296 if (tlb_flag(TLB_V3_FULL))
297 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (zero) : "cc");
298 if (tlb_flag(TLB_V4_U_FULL))
299 asm("mcr p15, 0, %0, c8, c7, 0" : : "r" (zero) : "cc");
300 if (tlb_flag(TLB_V4_D_FULL))
301 asm("mcr p15, 0, %0, c8, c6, 0" : : "r" (zero) : "cc");
302 if (tlb_flag(TLB_V4_I_FULL))
303 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
304 }
305
306 if (tlb_flag(TLB_V6_U_ASID))
307 asm("mcr p15, 0, %0, c8, c7, 2" : : "r" (asid) : "cc");
308 if (tlb_flag(TLB_V6_D_ASID))
309 asm("mcr p15, 0, %0, c8, c6, 2" : : "r" (asid) : "cc");
310 if (tlb_flag(TLB_V6_I_ASID))
311 asm("mcr p15, 0, %0, c8, c5, 2" : : "r" (asid) : "cc");
312
313 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
314 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
315 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
316
317 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
318 dsb();
319 }
320}
321
322static inline void
323local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
324{
325 const int zero = 0;
326 const unsigned int __tlb_flag = __cpu_tlb_flags;
327
328 uaddr = (uaddr & PAGE_MASK) | ASID(vma->vm_mm);
329
330 if (tlb_flag(TLB_WB))
331 dsb();
332
333 if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) {
334 if (tlb_flag(TLB_V3_PAGE))
335 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (uaddr) : "cc");
336 if (tlb_flag(TLB_V4_U_PAGE))
337 asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
338 if (tlb_flag(TLB_V4_D_PAGE))
339 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
340 if (tlb_flag(TLB_V4_I_PAGE))
341 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
342 if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
343 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
344 }
345
346 if (tlb_flag(TLB_V6_U_PAGE))
347 asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (uaddr) : "cc");
348 if (tlb_flag(TLB_V6_D_PAGE))
349 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (uaddr) : "cc");
350 if (tlb_flag(TLB_V6_I_PAGE))
351 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (uaddr) : "cc");
352
353 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
354 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
355 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
356
357 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
358 dsb();
359 }
360}
361
362static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
363{
364 const int zero = 0;
365 const unsigned int __tlb_flag = __cpu_tlb_flags;
366
367 kaddr &= PAGE_MASK;
368
369 if (tlb_flag(TLB_WB))
370 dsb();
371
372 if (tlb_flag(TLB_V3_PAGE))
373 asm("mcr p15, 0, %0, c6, c0, 0" : : "r" (kaddr) : "cc");
374 if (tlb_flag(TLB_V4_U_PAGE))
375 asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
376 if (tlb_flag(TLB_V4_D_PAGE))
377 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
378 if (tlb_flag(TLB_V4_I_PAGE))
379 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
380 if (!tlb_flag(TLB_V4_I_PAGE) && tlb_flag(TLB_V4_I_FULL))
381 asm("mcr p15, 0, %0, c8, c5, 0" : : "r" (zero) : "cc");
382
383 if (tlb_flag(TLB_V6_U_PAGE))
384 asm("mcr p15, 0, %0, c8, c7, 1" : : "r" (kaddr) : "cc");
385 if (tlb_flag(TLB_V6_D_PAGE))
386 asm("mcr p15, 0, %0, c8, c6, 1" : : "r" (kaddr) : "cc");
387 if (tlb_flag(TLB_V6_I_PAGE))
388 asm("mcr p15, 0, %0, c8, c5, 1" : : "r" (kaddr) : "cc");
389
390 if (tlb_flag(TLB_V6_I_FULL | TLB_V6_D_FULL |
391 TLB_V6_I_PAGE | TLB_V6_D_PAGE |
392 TLB_V6_I_ASID | TLB_V6_D_ASID)) {
393
394 asm("mcr p15, 0, %0, c7, c5, 6" : : "r" (zero) : "cc");
395 dsb();
396 isb();
397 }
398}
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413static inline void flush_pmd_entry(pmd_t *pmd)
414{
415 const unsigned int __tlb_flag = __cpu_tlb_flags;
416
417 if (tlb_flag(TLB_DCLEAN))
418 asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
419 : : "r" (pmd) : "cc");
420 if (tlb_flag(TLB_WB))
421 dsb();
422}
423
424static inline void clean_pmd_entry(pmd_t *pmd)
425{
426 const unsigned int __tlb_flag = __cpu_tlb_flags;
427
428 if (tlb_flag(TLB_DCLEAN))
429 asm("mcr p15, 0, %0, c7, c10, 1 @ flush_pmd"
430 : : "r" (pmd) : "cc");
431}
432
433#undef tlb_flag
434#undef always_tlb_flags
435#undef possible_tlb_flags
436
437
438
439
440#define local_flush_tlb_range(vma,start,end) __cpu_flush_user_tlb_range(start,end,vma)
441#define local_flush_tlb_kernel_range(s,e) __cpu_flush_kern_tlb_range(s,e)
442
443#ifndef CONFIG_SMP
444#define flush_tlb_all local_flush_tlb_all
445#define flush_tlb_mm local_flush_tlb_mm
446#define flush_tlb_page local_flush_tlb_page
447#define flush_tlb_kernel_page local_flush_tlb_kernel_page
448#define flush_tlb_range local_flush_tlb_range
449#define flush_tlb_kernel_range local_flush_tlb_kernel_range
450#else
451extern void flush_tlb_all(void);
452extern void flush_tlb_mm(struct mm_struct *mm);
453extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr);
454extern void flush_tlb_kernel_page(unsigned long kaddr);
455extern void flush_tlb_range(struct vm_area_struct *vma, unsigned long start, unsigned long end);
456extern void flush_tlb_kernel_range(unsigned long start, unsigned long end);
457#endif
458
459
460
461
462
463
464extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr, pte_t pte);
465
466#endif
467
468#endif
469
470#endif
471