ACPI / video: Dummy acpi_video_register should return error code
[cascardo/linux.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/tlb.h>
17 #include <asm/tlbflush.h>
18
19 static DEFINE_RAW_SPINLOCK(native_tlbie_lock);
20
21 static inline void __tlbiel_pid(unsigned long pid, int set)
22 {
23         unsigned long rb,rs,ric,prs,r;
24
25         rb = PPC_BIT(53); /* IS = 1 */
26         rb |= set << PPC_BITLSHIFT(51);
27         rs = ((unsigned long)pid) << PPC_BITLSHIFT(31);
28         prs = 1; /* process scoped */
29         r = 1;   /* raidx format */
30         ric = 2;  /* invalidate all the caches */
31
32         asm volatile("ptesync": : :"memory");
33         asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
34                      "(%2 << 17) | (%3 << 18) | (%4 << 21)"
35                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
36         asm volatile("ptesync": : :"memory");
37 }
38
39 /*
40  * We use 128 set in radix mode and 256 set in hpt mode.
41  */
42 static inline void _tlbiel_pid(unsigned long pid)
43 {
44         int set;
45
46         for (set = 0; set < POWER9_TLB_SETS_RADIX ; set++) {
47                 __tlbiel_pid(pid, set);
48         }
49         return;
50 }
51
52 static inline void _tlbie_pid(unsigned long pid)
53 {
54         unsigned long rb,rs,ric,prs,r;
55
56         rb = PPC_BIT(53); /* IS = 1 */
57         rs = pid << PPC_BITLSHIFT(31);
58         prs = 1; /* process scoped */
59         r = 1;   /* raidx format */
60         ric = 2;  /* invalidate all the caches */
61
62         asm volatile("ptesync": : :"memory");
63         asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
64                      "(%2 << 17) | (%3 << 18) | (%4 << 21)"
65                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
66         asm volatile("eieio; tlbsync; ptesync": : :"memory");
67 }
68
69 static inline void _tlbiel_va(unsigned long va, unsigned long pid,
70                               unsigned long ap)
71 {
72         unsigned long rb,rs,ric,prs,r;
73
74         rb = va & ~(PPC_BITMASK(52, 63));
75         rb |= ap << PPC_BITLSHIFT(58);
76         rs = pid << PPC_BITLSHIFT(31);
77         prs = 1; /* process scoped */
78         r = 1;   /* raidx format */
79         ric = 0;  /* no cluster flush yet */
80
81         asm volatile("ptesync": : :"memory");
82         asm volatile(".long 0x7c000224 | (%0 << 11) | (%1 << 16) |"
83                      "(%2 << 17) | (%3 << 18) | (%4 << 21)"
84                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
85         asm volatile("ptesync": : :"memory");
86 }
87
88 static inline void _tlbie_va(unsigned long va, unsigned long pid,
89                              unsigned long ap)
90 {
91         unsigned long rb,rs,ric,prs,r;
92
93         rb = va & ~(PPC_BITMASK(52, 63));
94         rb |= ap << PPC_BITLSHIFT(58);
95         rs = pid << PPC_BITLSHIFT(31);
96         prs = 1; /* process scoped */
97         r = 1;   /* raidx format */
98         ric = 0;  /* no cluster flush yet */
99
100         asm volatile("ptesync": : :"memory");
101         asm volatile(".long 0x7c000264 | (%0 << 11) | (%1 << 16) |"
102                      "(%2 << 17) | (%3 << 18) | (%4 << 21)"
103                      : : "r"(rb), "i"(r), "i"(prs), "i"(ric), "r"(rs) : "memory");
104         asm volatile("eieio; tlbsync; ptesync": : :"memory");
105 }
106
107 /*
108  * Base TLB flushing operations:
109  *
110  *  - flush_tlb_mm(mm) flushes the specified mm context TLB's
111  *  - flush_tlb_page(vma, vmaddr) flushes one page
112  *  - flush_tlb_range(vma, start, end) flushes a range of pages
113  *  - flush_tlb_kernel_range(start, end) flushes kernel pages
114  *
115  *  - local_* variants of page and mm only apply to the current
116  *    processor
117  */
118 void radix__local_flush_tlb_mm(struct mm_struct *mm)
119 {
120         unsigned long pid;
121
122         preempt_disable();
123         pid = mm->context.id;
124         if (pid != MMU_NO_CONTEXT)
125                 _tlbiel_pid(pid);
126         preempt_enable();
127 }
128 EXPORT_SYMBOL(radix__local_flush_tlb_mm);
129
130 void radix___local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
131                             unsigned long ap, int nid)
132 {
133         unsigned long pid;
134
135         preempt_disable();
136         pid = mm ? mm->context.id : 0;
137         if (pid != MMU_NO_CONTEXT)
138                 _tlbiel_va(vmaddr, pid, ap);
139         preempt_enable();
140 }
141
142 void radix__local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
143 {
144 #ifdef CONFIG_HUGETLB_PAGE
145         /* need the return fix for nohash.c */
146         if (vma && is_vm_hugetlb_page(vma))
147                 return __local_flush_hugetlb_page(vma, vmaddr);
148 #endif
149         radix___local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
150                                mmu_get_ap(mmu_virtual_psize), 0);
151 }
152 EXPORT_SYMBOL(radix__local_flush_tlb_page);
153
154 #ifdef CONFIG_SMP
155 static int mm_is_core_local(struct mm_struct *mm)
156 {
157         return cpumask_subset(mm_cpumask(mm),
158                               topology_sibling_cpumask(smp_processor_id()));
159 }
160
161 void radix__flush_tlb_mm(struct mm_struct *mm)
162 {
163         unsigned long pid;
164
165         preempt_disable();
166         pid = mm->context.id;
167         if (unlikely(pid == MMU_NO_CONTEXT))
168                 goto no_context;
169
170         if (!mm_is_core_local(mm)) {
171                 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
172
173                 if (lock_tlbie)
174                         raw_spin_lock(&native_tlbie_lock);
175                 _tlbie_pid(pid);
176                 if (lock_tlbie)
177                         raw_spin_unlock(&native_tlbie_lock);
178         } else
179                 _tlbiel_pid(pid);
180 no_context:
181         preempt_enable();
182 }
183 EXPORT_SYMBOL(radix__flush_tlb_mm);
184
185 void radix___flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
186                        unsigned long ap, int nid)
187 {
188         unsigned long pid;
189
190         preempt_disable();
191         pid = mm ? mm->context.id : 0;
192         if (unlikely(pid == MMU_NO_CONTEXT))
193                 goto bail;
194         if (!mm_is_core_local(mm)) {
195                 int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
196
197                 if (lock_tlbie)
198                         raw_spin_lock(&native_tlbie_lock);
199                 _tlbie_va(vmaddr, pid, ap);
200                 if (lock_tlbie)
201                         raw_spin_unlock(&native_tlbie_lock);
202         } else
203                 _tlbiel_va(vmaddr, pid, ap);
204 bail:
205         preempt_enable();
206 }
207
208 void radix__flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
209 {
210 #ifdef CONFIG_HUGETLB_PAGE
211         if (vma && is_vm_hugetlb_page(vma))
212                 return flush_hugetlb_page(vma, vmaddr);
213 #endif
214         radix___flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
215                          mmu_get_ap(mmu_virtual_psize), 0);
216 }
217 EXPORT_SYMBOL(radix__flush_tlb_page);
218
219 #endif /* CONFIG_SMP */
220
221 void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end)
222 {
223         int lock_tlbie = !mmu_has_feature(MMU_FTR_LOCKLESS_TLBIE);
224
225         if (lock_tlbie)
226                 raw_spin_lock(&native_tlbie_lock);
227         _tlbie_pid(0);
228         if (lock_tlbie)
229                 raw_spin_unlock(&native_tlbie_lock);
230 }
231 EXPORT_SYMBOL(radix__flush_tlb_kernel_range);
232
233 /*
234  * Currently, for range flushing, we just do a full mm flush. Because
235  * we use this in code path where we don' track the page size.
236  */
237 void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
238                      unsigned long end)
239
240 {
241         struct mm_struct *mm = vma->vm_mm;
242         radix__flush_tlb_mm(mm);
243 }
244 EXPORT_SYMBOL(radix__flush_tlb_range);
245
246
247 void radix__tlb_flush(struct mmu_gather *tlb)
248 {
249         struct mm_struct *mm = tlb->mm;
250         radix__flush_tlb_mm(mm);
251 }