]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
17ed9e31 AK |
2 | #ifndef _ASM_POWERPC_NOHASH_PGTABLE_H |
3 | #define _ASM_POWERPC_NOHASH_PGTABLE_H | |
ee4889c7 AK |
4 | |
5 | #if defined(CONFIG_PPC64) | |
17ed9e31 | 6 | #include <asm/nohash/64/pgtable.h> |
ee4889c7 | 7 | #else |
17ed9e31 | 8 | #include <asm/nohash/32/pgtable.h> |
ee4889c7 AK |
9 | #endif |
10 | ||
6c5d2d3f CL |
11 | /* Permission masks used for kernel mappings */ |
12 | #define PAGE_KERNEL __pgprot(_PAGE_BASE | _PAGE_KERNEL_RW) | |
13 | #define PAGE_KERNEL_NC __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE) | |
6cc07821 | 14 | #define PAGE_KERNEL_NCG __pgprot(_PAGE_BASE_NC | _PAGE_KERNEL_RW | _PAGE_NO_CACHE | _PAGE_GUARDED) |
6c5d2d3f CL |
15 | #define PAGE_KERNEL_X __pgprot(_PAGE_BASE | _PAGE_KERNEL_RWX) |
16 | #define PAGE_KERNEL_RO __pgprot(_PAGE_BASE | _PAGE_KERNEL_RO) | |
17 | #define PAGE_KERNEL_ROX __pgprot(_PAGE_BASE | _PAGE_KERNEL_ROX) | |
18 | ||
ee4889c7 AK |
19 | #ifndef __ASSEMBLY__ |
20 | ||
21 | /* Generic accessors to PTE bits */ | |
a0da4bc1 | 22 | #ifndef pte_write |
ee4889c7 AK |
23 | static inline int pte_write(pte_t pte) |
24 | { | |
a0da4bc1 | 25 | return pte_val(pte) & _PAGE_RW; |
ee4889c7 | 26 | } |
a0da4bc1 | 27 | #endif |
5d9cea8a | 28 | #ifndef pte_read |
ca8afd40 | 29 | static inline int pte_read(pte_t pte) { return 1; } |
5d9cea8a | 30 | #endif |
ee4889c7 | 31 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } |
ee4889c7 AK |
32 | static inline int pte_special(pte_t pte) { return pte_val(pte) & _PAGE_SPECIAL; } |
33 | static inline int pte_none(pte_t pte) { return (pte_val(pte) & ~_PTE_NONE_MASK) == 0; } | |
daba7902 CL |
34 | static inline bool pte_hashpte(pte_t pte) { return false; } |
35 | static inline bool pte_ci(pte_t pte) { return pte_val(pte) & _PAGE_NO_CACHE; } | |
36 | static inline bool pte_exec(pte_t pte) { return pte_val(pte) & _PAGE_EXEC; } | |
ee4889c7 AK |
37 | |
38 | #ifdef CONFIG_NUMA_BALANCING | |
39 | /* | |
40 | * These work without NUMA balancing but the kernel does not care. See the | |
ca5999fd | 41 | * comment in include/linux/pgtable.h . On powerpc, this will only |
ee4889c7 AK |
42 | * work for user pages and always return true for kernel pages. |
43 | */ | |
44 | static inline int pte_protnone(pte_t pte) | |
45 | { | |
26973fa5 | 46 | return pte_present(pte) && !pte_user(pte); |
ee4889c7 AK |
47 | } |
48 | ||
49 | static inline int pmd_protnone(pmd_t pmd) | |
50 | { | |
51 | return pte_protnone(pmd_pte(pmd)); | |
52 | } | |
53 | #endif /* CONFIG_NUMA_BALANCING */ | |
54 | ||
55 | static inline int pte_present(pte_t pte) | |
56 | { | |
57 | return pte_val(pte) & _PAGE_PRESENT; | |
58 | } | |
59 | ||
daba7902 CL |
60 | static inline bool pte_hw_valid(pte_t pte) |
61 | { | |
62 | return pte_val(pte) & _PAGE_PRESENT; | |
63 | } | |
64 | ||
e0f57031 CL |
65 | /* |
66 | * Don't just check for any non zero bits in __PAGE_USER, since for book3e | |
67 | * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in | |
68 | * _PAGE_USER. Need to explicitly match _PAGE_BAP_UR bit in that case too. | |
69 | */ | |
a0da4bc1 | 70 | #ifndef pte_user |
e0f57031 CL |
71 | static inline bool pte_user(pte_t pte) |
72 | { | |
a0da4bc1 | 73 | return (pte_val(pte) & _PAGE_USER) == _PAGE_USER; |
e0f57031 | 74 | } |
a0da4bc1 | 75 | #endif |
e0f57031 | 76 | |
5769beaf AK |
77 | /* |
78 | * We only find page table entry in the last level | |
79 | * Hence no need for other accessors | |
80 | */ | |
81 | #define pte_access_permitted pte_access_permitted | |
82 | static inline bool pte_access_permitted(pte_t pte, bool write) | |
83 | { | |
5769beaf AK |
84 | /* |
85 | * A read-only access is controlled by _PAGE_USER bit. | |
86 | * We have _PAGE_READ set for WRITE and EXECUTE | |
87 | */ | |
810e9f86 CL |
88 | if (!pte_present(pte) || !pte_user(pte) || !pte_read(pte)) |
89 | return false; | |
5769beaf | 90 | |
810e9f86 | 91 | if (write && !pte_write(pte)) |
5769beaf AK |
92 | return false; |
93 | ||
94 | return true; | |
95 | } | |
96 | ||
ee4889c7 AK |
97 | /* Conversion functions: convert a page and protection to a page entry, |
98 | * and a page entry and page directory to the page they refer to. | |
99 | * | |
100 | * Even if PTEs can be unsigned long long, a PFN is always an unsigned | |
101 | * long for now. | |
102 | */ | |
103 | static inline pte_t pfn_pte(unsigned long pfn, pgprot_t pgprot) { | |
104 | return __pte(((pte_basic_t)(pfn) << PTE_RPN_SHIFT) | | |
105 | pgprot_val(pgprot)); } | |
ee4889c7 AK |
106 | |
107 | /* Generic modifiers for PTE bits */ | |
daba7902 CL |
108 | static inline pte_t pte_exprotect(pte_t pte) |
109 | { | |
110 | return __pte(pte_val(pte) & ~_PAGE_EXEC); | |
111 | } | |
112 | ||
10bd3808 AK |
113 | static inline pte_t pte_mkclean(pte_t pte) |
114 | { | |
a0da4bc1 | 115 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); |
10bd3808 AK |
116 | } |
117 | ||
118 | static inline pte_t pte_mkold(pte_t pte) | |
119 | { | |
120 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | |
121 | } | |
122 | ||
10bd3808 AK |
123 | static inline pte_t pte_mkspecial(pte_t pte) |
124 | { | |
125 | return __pte(pte_val(pte) | _PAGE_SPECIAL); | |
126 | } | |
127 | ||
a0da4bc1 | 128 | #ifndef pte_mkhuge |
10bd3808 | 129 | static inline pte_t pte_mkhuge(pte_t pte) |
ee4889c7 | 130 | { |
a0da4bc1 | 131 | return __pte(pte_val(pte)); |
ee4889c7 | 132 | } |
a0da4bc1 | 133 | #endif |
ee4889c7 | 134 | |
a0da4bc1 | 135 | #ifndef pte_mkprivileged |
daba7902 CL |
136 | static inline pte_t pte_mkprivileged(pte_t pte) |
137 | { | |
a0da4bc1 | 138 | return __pte(pte_val(pte) & ~_PAGE_USER); |
daba7902 | 139 | } |
a0da4bc1 | 140 | #endif |
daba7902 | 141 | |
a0da4bc1 | 142 | #ifndef pte_mkuser |
daba7902 CL |
143 | static inline pte_t pte_mkuser(pte_t pte) |
144 | { | |
a0da4bc1 | 145 | return __pte(pte_val(pte) | _PAGE_USER); |
daba7902 | 146 | } |
a0da4bc1 | 147 | #endif |
daba7902 | 148 | |
10bd3808 AK |
149 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) |
150 | { | |
151 | return __pte((pte_val(pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)); | |
152 | } | |
ee4889c7 | 153 | |
2bba2ffb DH |
154 | static inline int pte_swp_exclusive(pte_t pte) |
155 | { | |
156 | return pte_val(pte) & _PAGE_SWP_EXCLUSIVE; | |
157 | } | |
158 | ||
159 | static inline pte_t pte_swp_mkexclusive(pte_t pte) | |
160 | { | |
161 | return __pte(pte_val(pte) | _PAGE_SWP_EXCLUSIVE); | |
162 | } | |
163 | ||
164 | static inline pte_t pte_swp_clear_exclusive(pte_t pte) | |
165 | { | |
166 | return __pte(pte_val(pte) & ~_PAGE_SWP_EXCLUSIVE); | |
167 | } | |
168 | ||
ee4889c7 AK |
169 | /* This low level function performs the actual PTE insertion |
170 | * Setting the PTE depends on the MMU type and other factors. It's | |
171 | * an horrible mess that I'm not going to try to clean up now but | |
172 | * I'm keeping it in one place rather than spread around | |
173 | */ | |
174 | static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, | |
175 | pte_t *ptep, pte_t pte, int percpu) | |
176 | { | |
ee4889c7 AK |
177 | /* Second case is 32-bit with 64-bit PTE. In this case, we |
178 | * can just store as long as we do the two halves in the right order | |
45201c87 CL |
179 | * with a barrier in between. |
180 | * In the percpu case, we also fallback to the simple update | |
ee4889c7 | 181 | */ |
d5808ffa CL |
182 | if (IS_ENABLED(CONFIG_PPC32) && IS_ENABLED(CONFIG_PTE_64BIT) && !percpu) { |
183 | __asm__ __volatile__("\ | |
d85be8a4 | 184 | stw%X0 %2,%0\n\ |
2255411d | 185 | mbar\n\ |
d85be8a4 | 186 | stw%X1 %L2,%1" |
d5808ffa CL |
187 | : "=m" (*ptep), "=m" (*((unsigned char *)ptep+4)) |
188 | : "r" (pte) : "memory"); | |
ee4889c7 AK |
189 | return; |
190 | } | |
ee4889c7 AK |
191 | /* Anything else just stores the PTE normally. That covers all 64-bit |
192 | * cases, and 32-bit non-hash with 32-bit PTEs. | |
193 | */ | |
55c8fc3f | 194 | #if defined(CONFIG_PPC_8xx) && defined(CONFIG_PPC_16K_PAGES) |
0b472181 | 195 | ptep->pte3 = ptep->pte2 = ptep->pte1 = ptep->pte = pte_val(pte); |
55c8fc3f | 196 | #else |
ee4889c7 | 197 | *ptep = pte; |
55c8fc3f | 198 | #endif |
ee4889c7 | 199 | |
ee4889c7 AK |
200 | /* |
201 | * With hardware tablewalk, a sync is needed to ensure that | |
202 | * subsequent accesses see the PTE we just wrote. Unlike userspace | |
203 | * mappings, we can't tolerate spurious faults, so make sure | |
204 | * the new PTE will be seen the first time. | |
205 | */ | |
d5808ffa | 206 | if (IS_ENABLED(CONFIG_PPC_BOOK3E_64) && is_kernel_addr(addr)) |
ee4889c7 | 207 | mb(); |
ee4889c7 AK |
208 | } |
209 | ||
210 | ||
211 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS | |
212 | extern int ptep_set_access_flags(struct vm_area_struct *vma, unsigned long address, | |
213 | pte_t *ptep, pte_t entry, int dirty); | |
214 | ||
215 | /* | |
216 | * Macro to mark a page protection value as "uncacheable". | |
217 | */ | |
218 | ||
219 | #define _PAGE_CACHE_CTL (_PAGE_COHERENT | _PAGE_GUARDED | _PAGE_NO_CACHE | \ | |
220 | _PAGE_WRITETHRU) | |
221 | ||
222 | #define pgprot_noncached(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ | |
223 | _PAGE_NO_CACHE | _PAGE_GUARDED)) | |
224 | ||
225 | #define pgprot_noncached_wc(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ | |
226 | _PAGE_NO_CACHE)) | |
227 | ||
228 | #define pgprot_cached(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ | |
229 | _PAGE_COHERENT)) | |
230 | ||
5f356497 | 231 | #if _PAGE_WRITETHRU != 0 |
ee4889c7 AK |
232 | #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \ |
233 | _PAGE_COHERENT | _PAGE_WRITETHRU)) | |
56f3c141 CL |
234 | #else |
235 | #define pgprot_cached_wthru(prot) pgprot_noncached(prot) | |
5f356497 | 236 | #endif |
ee4889c7 AK |
237 | |
238 | #define pgprot_cached_noncoherent(prot) \ | |
239 | (__pgprot(pgprot_val(prot) & ~_PAGE_CACHE_CTL)) | |
240 | ||
241 | #define pgprot_writecombine pgprot_noncached_wc | |
242 | ||
243 | struct file; | |
244 | extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |
245 | unsigned long size, pgprot_t vma_prot); | |
246 | #define __HAVE_PHYS_MEM_ACCESS_PROT | |
247 | ||
26a344ae AK |
248 | #ifdef CONFIG_HUGETLB_PAGE |
249 | static inline int hugepd_ok(hugepd_t hpd) | |
250 | { | |
4b914286 | 251 | #ifdef CONFIG_PPC_8xx |
b250c8c0 | 252 | return ((hpd_val(hpd) & _PMD_PAGE_MASK) == _PMD_PAGE_8M); |
4b914286 | 253 | #else |
20717e1f | 254 | /* We clear the top bit to indicate hugepd */ |
3fb66a70 | 255 | return (hpd_val(hpd) && (hpd_val(hpd) & PD_HUGE) == 0); |
4b914286 | 256 | #endif |
26a344ae AK |
257 | } |
258 | ||
259 | static inline int pmd_huge(pmd_t pmd) | |
260 | { | |
261 | return 0; | |
262 | } | |
263 | ||
264 | static inline int pud_huge(pud_t pud) | |
265 | { | |
266 | return 0; | |
267 | } | |
268 | ||
26a344ae AK |
269 | #define is_hugepd(hpd) (hugepd_ok(hpd)) |
270 | #endif | |
271 | ||
d9642117 CL |
272 | /* |
273 | * This gets called at the end of handling a page fault, when | |
274 | * the kernel has put a new PTE into the page table for the process. | |
275 | * We use it to ensure coherency between the i-cache and d-cache | |
276 | * for the page which has just been mapped in. | |
277 | */ | |
3e731858 | 278 | #if defined(CONFIG_PPC_E500) && defined(CONFIG_HUGETLB_PAGE) |
9fee28ba MWO |
279 | void update_mmu_cache_range(struct vm_fault *vmf, struct vm_area_struct *vma, |
280 | unsigned long address, pte_t *ptep, unsigned int nr); | |
d9642117 | 281 | #else |
9fee28ba MWO |
282 | static inline void update_mmu_cache_range(struct vm_fault *vmf, |
283 | struct vm_area_struct *vma, unsigned long address, | |
284 | pte_t *ptep, unsigned int nr) {} | |
d9642117 CL |
285 | #endif |
286 | ||
ee4889c7 AK |
287 | #endif /* __ASSEMBLY__ */ |
288 | #endif |