powerpc/mm/radix: Remove unused code
[linux-2.6-block.git] / arch / powerpc / mm / tlb-radix.c
1 /*
2  * TLB flush routines for radix kernels.
3  *
4  * Copyright 2015-2016, Aneesh Kumar K.V, IBM Corporation.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version
9  * 2 of the License, or (at your option) any later version.
10  */
11
12 #include <linux/mm.h>
13 #include <linux/hugetlb.h>
14 #include <linux/memblock.h>
15
16 #include <asm/ppc-opcode.h>
17 #include <asm/tlb.h>
18 #include <asm/tlbflush.h>
19 #include <asm/trace.h>
20 #include <asm/cputhreads.h>
21
22 #define RIC_FLUSH_TLB 0
23 #define RIC_FLUSH_PWC 1
24 #define RIC_FLUSH_ALL 2
25
26 /*
27  * tlbiel instruction for radix, set invalidation
28  * i.e., r=1 and is=01 or is=10 or is=11
29  */
30 static inline void tlbiel_radix_set_isa300(unsigned int set, unsigned int is,
31                                         unsigned int pid,
32                                         unsigned int ric, unsigned int prs)
33 {
34         unsigned long rb;
35         unsigned long rs;
36         unsigned int r = 1; /* radix format */
37
38         rb = (set << PPC_BITLSHIFT(51)) | (is << PPC_BITLSHIFT(53));
39         rs = ((unsigned long)pid << PPC_BITLSHIFT(31));
40
41         asm volatile(PPC_TLBIEL(%0, %1, %2, %3, %4)
42                      : : "r"(rb), "r"(rs), "i"(ric), "i"(prs), "r"(r)
43                      : "memory");
44 }
45
46 static void tlbiel_all_isa300(unsigned int num_sets, unsigned int is)
47 {
48         unsigned int set;
49
50         asm volatile("ptesync": : :"memory");
51
52         /*
53          * Flush the first set of the TLB, and the entire Page Walk Cache
54          * and partition table entries. Then flush the remaining sets of the
55          * TLB.
56          */
57         tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 0);
58         for (set = 1; set < num_sets; set++)
59                 tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 0);
60
61         /* Do the same for process scoped entries. */
62         tlbiel_radix_set_isa300(0, is, 0, RIC_FLUSH_ALL, 1);
63         for (set = 1; set < num_sets; set++)
64                 tlbiel_radix_set_isa300(set, is, 0, RIC_FLUSH_TLB, 1);
65
66         asm volatile("ptesync": : :"memory");
67 }
68
69 void radix__tlbiel_all(unsigned int action)
70 {
71         unsigned int is;
72
73         switch (action) {
74         case TLB_INVAL_SCOPE_GLOBAL:
75                 is = 3;
76                 break;
77         case TLB_INVAL_SCOPE_LPID:
78                 is = 2;
79                 break;
80         default:
81                 BUG();
82         }
83
84         if (early_cpu_has_feature(CPU_FTR_ARCH_300))
85                 tlbiel_all_isa300(POWER9_TLB_SETS_RADIX, is);
86         else
87                 WARN(1, "%s called on pre-POWER9 CPU\n", __func__);
88
89         asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
90 }
91
92 static inline void __tlbiel_pid(unsigned long pid, int set,
93                                 unsigned long ric)
94 {
95         unsigned long rb,rs,prs,r;
96
97         rb = PPC_BIT(53); /* IS = 1 */
98         rb |= set << PPC_BITLSHIFT(51);
99         rs = ((unsigned long)pid) << PPC_BITLSHIFT(31);
100         prs = 1; /* process scoped */
101         r = 1;   /* raidx format */
102
103         asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
104                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
105         trace_tlbie(0, 1, rb, rs, ric, prs, r);
106 }
107
108 static inline void __tlbie_pid(unsigned long pid, unsigned long ric)
109 {
110         unsigned long rb,rs,prs,r;
111
112         rb = PPC_BIT(53); /* IS = 1 */
113         rs = pid << PPC_BITLSHIFT(31);
114         prs = 1; /* process scoped */
115         r = 1;   /* raidx format */
116
117         asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
118                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
119         trace_tlbie(0, 0, rb, rs, ric, prs, r);
120 }
121
122 /*
123  * We use 128 set in radix mode and 256 set in hpt mode.
124  */
125 static inline void _tlbiel_pid(unsigned long pid, unsigned long ric)
126 {
127         int set;
128
129         asm volatile("ptesync": : :"memory");
130
131         /*
132          * Flush the first set of the TLB, and if we're doing a RIC_FLUSH_ALL,
133          * also flush the entire Page Walk Cache.
134          */
135         __tlbiel_pid(pid, 0, ric);
136
137         /* For PWC, only one flush is needed */
138         if (ric == RIC_FLUSH_PWC) {
139                 asm volatile("ptesync": : :"memory");
140                 return;
141         }
142
143         /* For the remaining sets, just flush the TLB */
144         for (set = 1; set < POWER9_TLB_SETS_RADIX ; set++)
145                 __tlbiel_pid(pid, set, RIC_FLUSH_TLB);
146
147         asm volatile("ptesync": : :"memory");
148         asm volatile(PPC_INVALIDATE_ERAT "; isync" : : :"memory");
149 }
150
151 static inline void _tlbie_pid(unsigned long pid, unsigned long ric)
152 {
153         asm volatile("ptesync": : :"memory");
154
155         /*
156          * Workaround the fact that the "ric" argument to __tlbie_pid
157          * must be a compile-time contraint to match the "i" constraint
158          * in the asm statement.
159          */
160         switch (ric) {
161         case RIC_FLUSH_TLB:
162                 __tlbie_pid(pid, RIC_FLUSH_TLB);
163                 break;
164         case RIC_FLUSH_PWC:
165                 __tlbie_pid(pid, RIC_FLUSH_PWC);
166                 break;
167         case RIC_FLUSH_ALL:
168         default:
169                 __tlbie_pid(pid, RIC_FLUSH_ALL);
170         }
171         asm volatile("eieio; tlbsync; ptesync": : :"memory");
172 }
173
174 static inline void __tlbiel_va(unsigned long va, unsigned long pid,
175                                unsigned long ap, unsigned long ric)
176 {
177         unsigned long rb,rs,prs,r;
178
179         rb = va & ~(PPC_BITMASK(52, 63));
180         rb |= ap << PPC_BITLSHIFT(58);
181         rs = pid << PPC_BITLSHIFT(31);
182         prs = 1; /* process scoped */
183         r = 1;   /* raidx format */
184
185         asm volatile(PPC_TLBIEL(%0, %4, %3, %2, %1)
186                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
187         trace_tlbie(0, 1, rb, rs, ric, prs, r);
188 }
189
190 static inline void __tlbiel_va_range(unsigned long start, unsigned long end,
191                                     unsigned long pid, unsigned long page_size,
192                                     unsigned long psize)
193 {
194         unsigned long addr;
195         unsigned long ap = mmu_get_ap(psize);
196
197         for (addr = start; addr < end; addr += page_size)
198                 __tlbiel_va(addr, pid, ap, RIC_FLUSH_TLB);
199 }
200
201 static inline void _tlbiel_va(unsigned long va, unsigned long pid,
202                               unsigned long psize, unsigned long ric)
203 {
204         unsigned long ap = mmu_get_ap(psize);
205
206         asm volatile("ptesync": : :"memory");
207         __tlbiel_va(va, pid, ap, ric);
208         asm volatile("ptesync": : :"memory");
209 }
210
211 static inline void _tlbiel_va_range(unsigned long start, unsigned long end,
212                                     unsigned long pid, unsigned long page_size,
213                                     unsigned long psize, bool also_pwc)
214 {
215         asm volatile("ptesync": : :"memory");
216         if (also_pwc)
217                 __tlbiel_pid(pid, 0, RIC_FLUSH_PWC);
218         __tlbiel_va_range(start, end, pid, page_size, psize);
219         asm volatile("ptesync": : :"memory");
220 }
221
222 static inline void __tlbie_va(unsigned long va, unsigned long pid,
223                              unsigned long ap, unsigned long ric)
224 {
225         unsigned long rb,rs,prs,r;
226
227         rb = va & ~(PPC_BITMASK(52, 63));
228         rb |= ap << PPC_BITLSHIFT(58);
229         rs = pid << PPC_BITLSHIFT(31);
230         prs = 1; /* process scoped */
231         r = 1;   /* raidx format */
232
233         asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
234                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
235         trace_tlbie(0, 0, rb, rs, ric, prs, r);
236 }
237
238 static inline void __tlbie_va_range(unsigned long start, unsigned long end,
239                                     unsigned long pid, unsigned long page_size,
240                                     unsigned long psize)
241 {
242         unsigned long addr;
243         unsigned long ap = mmu_get_ap(psize);
244
245         for (addr = start; addr < end; addr += page_size)
246                 __tlbie_va(addr, pid, ap, RIC_FLUSH_TLB);
247 }
248
249 static inline void _tlbie_va(unsigned long va, unsigned long pid,
250                               unsigned long psize, unsigned long ric)
251 {
252         unsigned long ap = mmu_get_ap(psize);
253
254         asm volatile("ptesync": : :"memory");
255         __tlbie_va(va, pid, ap, ric);
256         asm volatile("eieio; tlbsync; ptesync": : :"memory");
257 }
258
259 static inline void _tlbie_va_range(unsigned long start, unsigned long end,
260                                     unsigned long pid, unsigned long page_size,
261                                     unsigned long psize, bool also_pwc)
262 {
263         asm volatile("ptesync": : :"memory");
264         if (also_pwc)
265                 __tlbie_pid(pid, RIC_FLUSH_PWC);
266         __tlbie_va_range(start, end, pid, page_size, psize);
267         asm volatile("eieio; tlbsync; ptesync": : :"memory");
268 }
269
270 /*
271  * Base TLB flushing operations:
272  *
273  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
274  *  - flush_tlb_page(vma, vmaddr) flushes one page
275  *  - flush_tlb_range(vma, start, end) flushes a range of pages
276  *  - flush_tlb_kernel_range(start, end) flushes kernel pages
277  *
278  *  - local_* variants of page and mm only apply to the current
279  *    processor
280  */
281 void radix__local_flush_tlb_mm(struct mm_struct *mm)
282 {
283         unsigned long pid;
284
285         preempt_disable();
286         pid = mm->context.id;
287         if (pid != MMU_NO_CONTEXT)
288                 _tlbiel_pid(pid, RIC_FLUSH_TLB);
289         preempt_enable();
290 }
291 EXPORT_SYMBOL(radix__local_flush_tlb_mm);
292
293 #ifndef CONFIG_SMP
294 void radix__local_flush_all_mm(struct mm_struct *mm)
295 {
296         unsigned long pid;
297
298         preempt_disable();
299         pid = mm->context.id;
300         if (pid != MMU_NO_CONTEXT)
301                 _tlbiel_pid(pid, RIC_FLUSH_ALL);
302         preempt_enable();
303 }
304 EXPORT_SYMBOL(radix__local_flush_all_mm);
305 #endif /* CONFIG_SMP */
306
307 void radix__local_flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
308                                        int psize)
309 {
310         unsigned long pid;
311
312         preempt_disable();
313         pid = mm->context.id;
314         if (pid != MMU_NO_CONTEXT)
315                 _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
316         preempt_enable();
317 }
318
319 void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
320 {
321 #ifdef CONFIG_HUGETLB_PAGE
322         /* need the return fix for nohash.c */
323         if (is_vm_hugetlb_page(vma))
324                 return radix__local_flush_hugetlb_page(vma, vmaddr);
325 #endif
326         radix__local_flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
327 }
328 EXPORT_SYMBOL(radix__local_flush_tlb_page);
329
330 static bool mm_needs_flush_escalation(struct mm_struct *mm)
331 {
332         /*
333          * P9 nest MMU has issues with the page walk cache
334          * caching PTEs and not flushing them properly when
335          * RIC = 0 for a PID/LPID invalidate
336          */
337         return atomic_read(&mm->context.copros) != 0;
338 }
339
340 #ifdef CONFIG_SMP
341 void radix__flush_tlb_mm(struct mm_struct *mm)
342 {
343         unsigned long pid;
344
345         pid = mm->context.id;
346         if (unlikely(pid == MMU_NO_CONTEXT))
347                 return;
348
349         preempt_disable();
350         if (!mm_is_thread_local(mm)) {
351                 if (mm_needs_flush_escalation(mm))
352                         _tlbie_pid(pid, RIC_FLUSH_ALL);
353                 else
354                         _tlbie_pid(pid, RIC_FLUSH_TLB);
355         } else
356                 _tlbiel_pid(pid, RIC_FLUSH_TLB);
357         preempt_enable();
358 }
359 EXPORT_SYMBOL(radix__flush_tlb_mm);
360
361 void radix__flush_all_mm(struct mm_struct *mm)
362 {
363         unsigned long pid;
364
365         pid = mm->context.id;
366         if (unlikely(pid == MMU_NO_CONTEXT))
367                 return;
368
369         preempt_disable();
370         if (!mm_is_thread_local(mm))
371                 _tlbie_pid(pid, RIC_FLUSH_ALL);
372         else
373                 _tlbiel_pid(pid, RIC_FLUSH_ALL);
374         preempt_enable();
375 }
376 EXPORT_SYMBOL(radix__flush_all_mm);
377
378 void radix__flush_tlb_pwc(struct mmu_gather *tlb, unsigned long addr)
379 {
380         tlb->need_flush_all = 1;
381 }
382 EXPORT_SYMBOL(radix__flush_tlb_pwc);
383
384 void radix__flush_tlb_page_psize(struct mm_struct *mm, unsigned long vmaddr,
385                                  int psize)
386 {
387         unsigned long pid;
388
389         pid = mm->context.id;
390         if (unlikely(pid == MMU_NO_CONTEXT))
391                 return;
392
393         preempt_disable();
394         if (!mm_is_thread_local(mm))
395                 _tlbie_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
396         else
397                 _tlbiel_va(vmaddr, pid, psize, RIC_FLUSH_TLB);
398         preempt_enable();
399 }
400
401 void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
402 {
403 #ifdef CONFIG_HUGETLB_PAGE
404         if (is_vm_hugetlb_page(vma))
405                 return radix__flush_hugetlb_page(vma, vmaddr);
406 #endif
407         radix__flush_tlb_page_psize(vma->vm_mm, vmaddr, mmu_virtual_psize);
408 }
409 EXPORT_SYMBOL(radix__flush_tlb_page);
410
411 #else /* CONFIG_SMP */
412 #define radix__flush_all_mm radix__local_flush_all_mm
413 #endif /* CONFIG_SMP */
414
415 void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
416 {
417         _tlbie_pid(0, RIC_FLUSH_ALL);
418 }
419 EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
420
421 #define TLB_FLUSH_ALL -1UL
422
423 /*
424  * Number of pages above which we invalidate the entire PID rather than
425  * flush individual pages, for local and global flushes respectively.
426  *
427  * tlbie goes out to the interconnect and individual ops are more costly.
428  * It also does not iterate over sets like the local tlbiel variant when
429  * invalidating a full PID, so it has a far lower threshold to change from
430  * individual page flushes to full-pid flushes.
431  */
432 static unsigned long tlb_single_page_flush_ceiling __read_mostly = 33;
433 static unsigned long tlb_local_single_page_flush_ceiling __read_mostly = POWER9_TLB_SETS_RADIX * 2;
434
435 void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
436                      unsigned long end)
437
438 {
439         struct mm_struct *mm = vma->vm_mm;
440         unsigned long pid;
441         unsigned int page_shift = mmu_psize_defs[mmu_virtual_psize].shift;
442         unsigned long page_size = 1UL << page_shift;
443         unsigned long nr_pages = (end - start) >> page_shift;
444         bool local, full;
445
446 #ifdef CONFIG_HUGETLB_PAGE
447         if (is_vm_hugetlb_page(vma))
448                 return radix__flush_hugetlb_tlb_range(vma, start, end);
449 #endif
450
451         pid = mm->context.id;
452         if (unlikely(pid == MMU_NO_CONTEXT))
453                 return;
454
455         preempt_disable();
456         if (mm_is_thread_local(mm)) {
457                 local = true;
458                 full = (end == TLB_FLUSH_ALL ||
459                                 nr_pages > tlb_local_single_page_flush_ceiling);
460         } else {
461                 local = false;
462                 full = (end == TLB_FLUSH_ALL ||
463                                 nr_pages > tlb_single_page_flush_ceiling);
464         }
465
466         if (full) {
467                 if (local) {
468                         _tlbiel_pid(pid, RIC_FLUSH_TLB);
469                 } else {
470                         if (mm_needs_flush_escalation(mm))
471                                 _tlbie_pid(pid, RIC_FLUSH_ALL);
472                         else
473                                 _tlbie_pid(pid, RIC_FLUSH_TLB);
474                 }
475         } else {
476                 bool hflush = false;
477                 unsigned long hstart, hend;
478
479 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
480                 hstart = (start + HPAGE_PMD_SIZE - 1) >> HPAGE_PMD_SHIFT;
481                 hend = end >> HPAGE_PMD_SHIFT;
482                 if (hstart < hend) {
483                         hstart <<= HPAGE_PMD_SHIFT;
484                         hend <<= HPAGE_PMD_SHIFT;
485                         hflush = true;
486                 }
487 #endif
488
489                 asm volatile("ptesync": : :"memory");
490                 if (local) {
491                         __tlbiel_va_range(start, end, pid, page_size, mmu_virtual_psize);
492                         if (hflush)
493                                 __tlbiel_va_range(hstart, hend, pid,
494                                                 HPAGE_PMD_SIZE, MMU_PAGE_2M);
495                         asm volatile("ptesync": : :"memory");
496                 } else {
497                         __tlbie_va_range(start, end, pid, page_size, mmu_virtual_psize);
498                         if (hflush)
499                                 __tlbie_va_range(hstart, hend, pid,
500                                                 HPAGE_PMD_SIZE, MMU_PAGE_2M);
501                         asm volatile("eieio; tlbsync; ptesync": : :"memory");
502                 }
503         }
504         preempt_enable();
505 }
506 EXPORT_SYMBOL(radix__flush_tlb_range);
507
508 static int radix_get_mmu_psize(int page_size)
509 {
510         int psize;
511
512         if (page_size == (1UL << mmu_psize_defs[mmu_virtual_psize].shift))
513                 psize = mmu_virtual_psize;
514         else if (page_size == (1UL << mmu_psize_defs[MMU_PAGE_2M].shift))
515                 psize = MMU_PAGE_2M;
516         else if (page_size == (1UL << mmu_psize_defs[MMU_PAGE_1G].shift))
517                 psize = MMU_PAGE_1G;
518         else
519                 return -1;
520         return psize;
521 }
522
523 static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
524                                   unsigned long end, int psize);
525
526 void radix__tlb_flush(struct mmu_gather *tlb)
527 {
528         int psize = 0;
529         struct mm_struct *mm = tlb->mm;
530         int page_size = tlb->page_size;
531
532         /*
533          * if page size is not something we understand, do a full mm flush
534          *
535          * A "fullmm" flush must always do a flush_all_mm (RIC=2) flush
536          * that flushes the process table entry cache upon process teardown.
537          * See the comment for radix in arch_exit_mmap().
538          */
539         if (tlb->fullmm) {
540                 radix__flush_all_mm(mm);
541         } else if ( (psize = radix_get_mmu_psize(page_size)) == -1) {
542                 if (!tlb->need_flush_all)
543                         radix__flush_tlb_mm(mm);
544                 else
545                         radix__flush_all_mm(mm);
546         } else {
547                 unsigned long start = tlb->start;
548                 unsigned long end = tlb->end;
549
550                 if (!tlb->need_flush_all)
551                         radix__flush_tlb_range_psize(mm, start, end, psize);
552                 else
553                         radix__flush_tlb_pwc_range_psize(mm, start, end, psize);
554         }
555         tlb->need_flush_all = 0;
556 }
557
558 static inline void __radix__flush_tlb_range_psize(struct mm_struct *mm,
559                                 unsigned long start, unsigned long end,
560                                 int psize, bool also_pwc)
561 {
562         unsigned long pid;
563         unsigned int page_shift = mmu_psize_defs[psize].shift;
564         unsigned long page_size = 1UL << page_shift;
565         unsigned long nr_pages = (end - start) >> page_shift;
566         bool local, full;
567
568         pid = mm->context.id;
569         if (unlikely(pid == MMU_NO_CONTEXT))
570                 return;
571
572         preempt_disable();
573         if (mm_is_thread_local(mm)) {
574                 local = true;
575                 full = (end == TLB_FLUSH_ALL ||
576                                 nr_pages > tlb_local_single_page_flush_ceiling);
577         } else {
578                 local = false;
579                 full = (end == TLB_FLUSH_ALL ||
580                                 nr_pages > tlb_single_page_flush_ceiling);
581         }
582
583         if (full) {
584                 if (!local && mm_needs_flush_escalation(mm))
585                         also_pwc = true;
586
587                 if (local)
588                         _tlbiel_pid(pid, also_pwc ? RIC_FLUSH_ALL : RIC_FLUSH_TLB);
589                 else
590                         _tlbie_pid(pid, also_pwc ? RIC_FLUSH_ALL: RIC_FLUSH_TLB);
591         } else {
592                 if (local)
593                         _tlbiel_va_range(start, end, pid, page_size, psize, also_pwc);
594                 else
595                         _tlbie_va_range(start, end, pid, page_size, psize, also_pwc);
596         }
597         preempt_enable();
598 }
599
600 void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
601                                   unsigned long end, int psize)
602 {
603         return __radix__flush_tlb_range_psize(mm, start, end, psize, false);
604 }
605
606 static void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
607                                   unsigned long end, int psize)
608 {
609         __radix__flush_tlb_range_psize(mm, start, end, psize, true);
610 }
611
612 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
613 void radix__flush_tlb_collapsed_pmd(struct mm_struct *mm, unsigned long addr)
614 {
615         unsigned long pid, end;
616
617         pid = mm->context.id;
618         if (unlikely(pid == MMU_NO_CONTEXT))
619                 return;
620
621         /* 4k page size, just blow the world */
622         if (PAGE_SIZE == 0x1000) {
623                 radix__flush_all_mm(mm);
624                 return;
625         }
626
627         end = addr + HPAGE_PMD_SIZE;
628
629         /* Otherwise first do the PWC, then iterate the pages. */
630         preempt_disable();
631
632         if (mm_is_thread_local(mm)) {
633                 _tlbiel_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
634         } else {
635                 _tlbie_va_range(addr, end, pid, PAGE_SIZE, mmu_virtual_psize, true);
636         }
637
638         preempt_enable();
639 }
640 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
641
642 void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
643                                 unsigned long start, unsigned long end)
644 {
645         radix__flush_tlb_range_psize(vma->vm_mm, start, end, MMU_PAGE_2M);
646 }
647 EXPORT_SYMBOL(radix__flush_pmd_tlb_range);
648
649 void radix__flush_tlb_all(void)
650 {
651         unsigned long rb,prs,r,rs;
652         unsigned long ric = RIC_FLUSH_ALL;
653
654         rb = 0x3 << PPC_BITLSHIFT(53); /* IS = 3 */
655         prs = 0; /* partition scoped */
656         r = 1;   /* raidx format */
657         rs = 1 & ((1UL << 32) - 1); /* any LPID value to flush guest mappings */
658
659         asm volatile("ptesync": : :"memory");
660         /*
661          * now flush guest entries by passing PRS = 1 and LPID != 0
662          */
663         asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
664                      : : "r"(rb), "i"(r), "i"(1), "i"(ric), "r"(rs) : "memory");
665         /*
666          * now flush host entires by passing PRS = 0 and LPID == 0
667          */
668         asm volatile(PPC_TLBIE_5(%0, %4, %3, %2, %1)
669                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(0) : "memory");
670         asm volatile("eieio; tlbsync; ptesync": : :"memory");
671 }
672
673 void radix__flush_tlb_pte_p9_dd1(unsigned long old_pte, struct mm_struct *mm,
674                                  unsigned long address)
675 {
676         /*
677          * We track page size in pte only for DD1, So we can
678          * call this only on DD1.
679          */
680         if (!cpu_has_feature(CPU_FTR_POWER9_DD1)) {
681                 VM_WARN_ON(1);
682                 return;
683         }
684
685         if (old_pte & R_PAGE_LARGE)
686                 radix__flush_tlb_page_psize(mm, address, MMU_PAGE_2M);
687         else
688                 radix__flush_tlb_page_psize(mm, address, mmu_virtual_psize);
689 }
690
691 #ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
692 extern void radix_kvm_prefetch_workaround(struct mm_struct *mm)
693 {
694         unsigned int pid = mm->context.id;
695
696         if (unlikely(pid == MMU_NO_CONTEXT))
697                 return;
698
699         /*
700          * If this context hasn't run on that CPU before and KVM is
701          * around, there's a slim chance that the guest on another
702          * CPU just brought in obsolete translation into the TLB of
703          * this CPU due to a bad prefetch using the guest PID on
704          * the way into the hypervisor.
705          *
706          * We work around this here. If KVM is possible, we check if
707          * any sibling thread is in KVM. If it is, the window may exist
708          * and thus we flush that PID from the core.
709          *
710          * A potential future improvement would be to mark which PIDs
711          * have never been used on the system and avoid it if the PID
712          * is new and the process has no other cpumask bit set.
713          */
714         if (cpu_has_feature(CPU_FTR_HVMODE) && radix_enabled()) {
715                 int cpu = smp_processor_id();
716                 int sib = cpu_first_thread_sibling(cpu);
717                 bool flush = false;
718
719                 for (; sib <= cpu_last_thread_sibling(cpu) && !flush; sib++) {
720                         if (sib == cpu)
721                                 continue;
722                         if (paca[sib].kvm_hstate.kvm_vcpu)
723                                 flush = true;
724                 }
725                 if (flush)
726                         _tlbiel_pid(pid, RIC_FLUSH_ALL);
727         }
728 }
729 EXPORT_SYMBOL_GPL(radix_kvm_prefetch_workaround);
730 #endif /* CONFIG_KVM_BOOK3S_HV_POSSIBLE */