diff options
author | Al Viro <viro@zeniv.linux.org.uk> | 2008-08-17 21:05:42 -0400 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-10-23 01:55:20 -0400 |
commit | bb8985586b7a906e116db835c64773b7a7d51663 (patch) | |
tree | de93ae58e88cc563d95cc124a73f3930594c6100 /arch/x86/include/asm/pgtable.h | |
parent | 8ede0bdb63305d3353efd97e9af6210afb05734e (diff) |
x86, um: ... and asm-x86 move
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/include/asm/pgtable.h')
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 561 |
1 files changed, 561 insertions, 0 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h new file mode 100644 index 000000000000..88a53b1a17f0 --- /dev/null +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -0,0 +1,561 @@ | |||
1 | #ifndef ASM_X86__PGTABLE_H | ||
2 | #define ASM_X86__PGTABLE_H | ||
3 | |||
4 | #define FIRST_USER_ADDRESS 0 | ||
5 | |||
6 | #define _PAGE_BIT_PRESENT 0 /* is present */ | ||
7 | #define _PAGE_BIT_RW 1 /* writeable */ | ||
8 | #define _PAGE_BIT_USER 2 /* userspace addressable */ | ||
9 | #define _PAGE_BIT_PWT 3 /* page write through */ | ||
10 | #define _PAGE_BIT_PCD 4 /* page cache disabled */ | ||
11 | #define _PAGE_BIT_ACCESSED 5 /* was accessed (raised by CPU) */ | ||
12 | #define _PAGE_BIT_DIRTY 6 /* was written to (raised by CPU) */ | ||
13 | #define _PAGE_BIT_FILE 6 | ||
14 | #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */ | ||
15 | #define _PAGE_BIT_PAT 7 /* on 4KB pages */ | ||
16 | #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */ | ||
17 | #define _PAGE_BIT_UNUSED1 9 /* available for programmer */ | ||
18 | #define _PAGE_BIT_IOMAP 10 /* flag used to indicate IO mapping */ | ||
19 | #define _PAGE_BIT_UNUSED3 11 | ||
20 | #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ | ||
21 | #define _PAGE_BIT_SPECIAL _PAGE_BIT_UNUSED1 | ||
22 | #define _PAGE_BIT_CPA_TEST _PAGE_BIT_UNUSED1 | ||
23 | #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ | ||
24 | |||
25 | #define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT) | ||
26 | #define _PAGE_RW (_AT(pteval_t, 1) << _PAGE_BIT_RW) | ||
27 | #define _PAGE_USER (_AT(pteval_t, 1) << _PAGE_BIT_USER) | ||
28 | #define _PAGE_PWT (_AT(pteval_t, 1) << _PAGE_BIT_PWT) | ||
29 | #define _PAGE_PCD (_AT(pteval_t, 1) << _PAGE_BIT_PCD) | ||
30 | #define _PAGE_ACCESSED (_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED) | ||
31 | #define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY) | ||
32 | #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) | ||
33 | #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) | ||
34 | #define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) | ||
35 | #define _PAGE_IOMAP (_AT(pteval_t, 1) << _PAGE_BIT_IOMAP) | ||
36 | #define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) | ||
37 | #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) | ||
38 | #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) | ||
39 | #define _PAGE_SPECIAL (_AT(pteval_t, 1) << _PAGE_BIT_SPECIAL) | ||
40 | #define _PAGE_CPA_TEST (_AT(pteval_t, 1) << _PAGE_BIT_CPA_TEST) | ||
41 | #define __HAVE_ARCH_PTE_SPECIAL | ||
42 | |||
43 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | ||
44 | #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) | ||
45 | #else | ||
46 | #define _PAGE_NX (_AT(pteval_t, 0)) | ||
47 | #endif | ||
48 | |||
49 | /* If _PAGE_PRESENT is clear, we use these: */ | ||
50 | #define _PAGE_FILE _PAGE_DIRTY /* nonlinear file mapping, | ||
51 | * saved PTE; unset:swap */ | ||
52 | #define _PAGE_PROTNONE _PAGE_PSE /* if the user mapped it with PROT_NONE; | ||
53 | pte_present gives true */ | ||
54 | |||
55 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ | ||
56 | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
57 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ | ||
58 | _PAGE_DIRTY) | ||
59 | |||
60 | /* Set of bits not changed in pte_modify */ | ||
61 | #define _PAGE_CHG_MASK (PTE_PFN_MASK | _PAGE_PCD | _PAGE_PWT | \ | ||
62 | _PAGE_SPECIAL | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
63 | |||
64 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) | ||
65 | #define _PAGE_CACHE_WB (0) | ||
66 | #define _PAGE_CACHE_WC (_PAGE_PWT) | ||
67 | #define _PAGE_CACHE_UC_MINUS (_PAGE_PCD) | ||
68 | #define _PAGE_CACHE_UC (_PAGE_PCD | _PAGE_PWT) | ||
69 | |||
70 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) | ||
71 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ | ||
72 | _PAGE_ACCESSED | _PAGE_NX) | ||
73 | |||
74 | #define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | \ | ||
75 | _PAGE_USER | _PAGE_ACCESSED) | ||
76 | #define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
77 | _PAGE_ACCESSED | _PAGE_NX) | ||
78 | #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
79 | _PAGE_ACCESSED) | ||
80 | #define PAGE_COPY PAGE_COPY_NOEXEC | ||
81 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
82 | _PAGE_ACCESSED | _PAGE_NX) | ||
83 | #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
84 | _PAGE_ACCESSED) | ||
85 | |||
86 | #define __PAGE_KERNEL_EXEC \ | ||
87 | (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_GLOBAL) | ||
88 | #define __PAGE_KERNEL (__PAGE_KERNEL_EXEC | _PAGE_NX) | ||
89 | |||
90 | #define __PAGE_KERNEL_RO (__PAGE_KERNEL & ~_PAGE_RW) | ||
91 | #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW) | ||
92 | #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT) | ||
93 | #define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC) | ||
94 | #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) | ||
95 | #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) | ||
96 | #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) | ||
97 | #define __PAGE_KERNEL_VSYSCALL_NOCACHE (__PAGE_KERNEL_VSYSCALL | _PAGE_PCD | _PAGE_PWT) | ||
98 | #define __PAGE_KERNEL_LARGE (__PAGE_KERNEL | _PAGE_PSE) | ||
99 | #define __PAGE_KERNEL_LARGE_NOCACHE (__PAGE_KERNEL | _PAGE_CACHE_UC | _PAGE_PSE) | ||
100 | #define __PAGE_KERNEL_LARGE_EXEC (__PAGE_KERNEL_EXEC | _PAGE_PSE) | ||
101 | |||
102 | #define __PAGE_KERNEL_IO (__PAGE_KERNEL | _PAGE_IOMAP) | ||
103 | #define __PAGE_KERNEL_IO_NOCACHE (__PAGE_KERNEL_NOCACHE | _PAGE_IOMAP) | ||
104 | #define __PAGE_KERNEL_IO_UC_MINUS (__PAGE_KERNEL_UC_MINUS | _PAGE_IOMAP) | ||
105 | #define __PAGE_KERNEL_IO_WC (__PAGE_KERNEL_WC | _PAGE_IOMAP) | ||
106 | |||
107 | #define PAGE_KERNEL __pgprot(__PAGE_KERNEL) | ||
108 | #define PAGE_KERNEL_RO __pgprot(__PAGE_KERNEL_RO) | ||
109 | #define PAGE_KERNEL_EXEC __pgprot(__PAGE_KERNEL_EXEC) | ||
110 | #define PAGE_KERNEL_RX __pgprot(__PAGE_KERNEL_RX) | ||
111 | #define PAGE_KERNEL_WC __pgprot(__PAGE_KERNEL_WC) | ||
112 | #define PAGE_KERNEL_NOCACHE __pgprot(__PAGE_KERNEL_NOCACHE) | ||
113 | #define PAGE_KERNEL_UC_MINUS __pgprot(__PAGE_KERNEL_UC_MINUS) | ||
114 | #define PAGE_KERNEL_EXEC_NOCACHE __pgprot(__PAGE_KERNEL_EXEC_NOCACHE) | ||
115 | #define PAGE_KERNEL_LARGE __pgprot(__PAGE_KERNEL_LARGE) | ||
116 | #define PAGE_KERNEL_LARGE_NOCACHE __pgprot(__PAGE_KERNEL_LARGE_NOCACHE) | ||
117 | #define PAGE_KERNEL_LARGE_EXEC __pgprot(__PAGE_KERNEL_LARGE_EXEC) | ||
118 | #define PAGE_KERNEL_VSYSCALL __pgprot(__PAGE_KERNEL_VSYSCALL) | ||
119 | #define PAGE_KERNEL_VSYSCALL_NOCACHE __pgprot(__PAGE_KERNEL_VSYSCALL_NOCACHE) | ||
120 | |||
121 | #define PAGE_KERNEL_IO __pgprot(__PAGE_KERNEL_IO) | ||
122 | #define PAGE_KERNEL_IO_NOCACHE __pgprot(__PAGE_KERNEL_IO_NOCACHE) | ||
123 | #define PAGE_KERNEL_IO_UC_MINUS __pgprot(__PAGE_KERNEL_IO_UC_MINUS) | ||
124 | #define PAGE_KERNEL_IO_WC __pgprot(__PAGE_KERNEL_IO_WC) | ||
125 | |||
126 | /* xwr */ | ||
127 | #define __P000 PAGE_NONE | ||
128 | #define __P001 PAGE_READONLY | ||
129 | #define __P010 PAGE_COPY | ||
130 | #define __P011 PAGE_COPY | ||
131 | #define __P100 PAGE_READONLY_EXEC | ||
132 | #define __P101 PAGE_READONLY_EXEC | ||
133 | #define __P110 PAGE_COPY_EXEC | ||
134 | #define __P111 PAGE_COPY_EXEC | ||
135 | |||
136 | #define __S000 PAGE_NONE | ||
137 | #define __S001 PAGE_READONLY | ||
138 | #define __S010 PAGE_SHARED | ||
139 | #define __S011 PAGE_SHARED | ||
140 | #define __S100 PAGE_READONLY_EXEC | ||
141 | #define __S101 PAGE_READONLY_EXEC | ||
142 | #define __S110 PAGE_SHARED_EXEC | ||
143 | #define __S111 PAGE_SHARED_EXEC | ||
144 | |||
145 | /* | ||
146 | * early identity mapping pte attrib macros. | ||
147 | */ | ||
148 | #ifdef CONFIG_X86_64 | ||
149 | #define __PAGE_KERNEL_IDENT_LARGE_EXEC __PAGE_KERNEL_LARGE_EXEC | ||
150 | #else | ||
151 | /* | ||
152 | * For PDE_IDENT_ATTR include USER bit. As the PDE and PTE protection | ||
153 | * bits are combined, this will alow user to access the high address mapped | ||
154 | * VDSO in the presence of CONFIG_COMPAT_VDSO | ||
155 | */ | ||
156 | #define PTE_IDENT_ATTR 0x003 /* PRESENT+RW */ | ||
157 | #define PDE_IDENT_ATTR 0x067 /* PRESENT+RW+USER+DIRTY+ACCESSED */ | ||
158 | #define PGD_IDENT_ATTR 0x001 /* PRESENT (no other attributes) */ | ||
159 | #endif | ||
160 | |||
161 | #ifndef __ASSEMBLY__ | ||
162 | |||
163 | /* | ||
164 | * ZERO_PAGE is a global shared page that is always zero: used | ||
165 | * for zero-mapped memory areas etc.. | ||
166 | */ | ||
167 | extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; | ||
168 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | ||
169 | |||
170 | extern spinlock_t pgd_lock; | ||
171 | extern struct list_head pgd_list; | ||
172 | |||
173 | /* | ||
174 | * The following only work if pte_present() is true. | ||
175 | * Undefined behaviour if not.. | ||
176 | */ | ||
177 | static inline int pte_dirty(pte_t pte) | ||
178 | { | ||
179 | return pte_flags(pte) & _PAGE_DIRTY; | ||
180 | } | ||
181 | |||
182 | static inline int pte_young(pte_t pte) | ||
183 | { | ||
184 | return pte_flags(pte) & _PAGE_ACCESSED; | ||
185 | } | ||
186 | |||
187 | static inline int pte_write(pte_t pte) | ||
188 | { | ||
189 | return pte_flags(pte) & _PAGE_RW; | ||
190 | } | ||
191 | |||
192 | static inline int pte_file(pte_t pte) | ||
193 | { | ||
194 | return pte_flags(pte) & _PAGE_FILE; | ||
195 | } | ||
196 | |||
197 | static inline int pte_huge(pte_t pte) | ||
198 | { | ||
199 | return pte_flags(pte) & _PAGE_PSE; | ||
200 | } | ||
201 | |||
202 | static inline int pte_global(pte_t pte) | ||
203 | { | ||
204 | return pte_flags(pte) & _PAGE_GLOBAL; | ||
205 | } | ||
206 | |||
207 | static inline int pte_exec(pte_t pte) | ||
208 | { | ||
209 | return !(pte_flags(pte) & _PAGE_NX); | ||
210 | } | ||
211 | |||
212 | static inline int pte_special(pte_t pte) | ||
213 | { | ||
214 | return pte_flags(pte) & _PAGE_SPECIAL; | ||
215 | } | ||
216 | |||
217 | static inline unsigned long pte_pfn(pte_t pte) | ||
218 | { | ||
219 | return (pte_val(pte) & PTE_PFN_MASK) >> PAGE_SHIFT; | ||
220 | } | ||
221 | |||
222 | #define pte_page(pte) pfn_to_page(pte_pfn(pte)) | ||
223 | |||
224 | static inline int pmd_large(pmd_t pte) | ||
225 | { | ||
226 | return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == | ||
227 | (_PAGE_PSE | _PAGE_PRESENT); | ||
228 | } | ||
229 | |||
230 | static inline pte_t pte_mkclean(pte_t pte) | ||
231 | { | ||
232 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); | ||
233 | } | ||
234 | |||
235 | static inline pte_t pte_mkold(pte_t pte) | ||
236 | { | ||
237 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); | ||
238 | } | ||
239 | |||
240 | static inline pte_t pte_wrprotect(pte_t pte) | ||
241 | { | ||
242 | return __pte(pte_val(pte) & ~_PAGE_RW); | ||
243 | } | ||
244 | |||
245 | static inline pte_t pte_mkexec(pte_t pte) | ||
246 | { | ||
247 | return __pte(pte_val(pte) & ~_PAGE_NX); | ||
248 | } | ||
249 | |||
250 | static inline pte_t pte_mkdirty(pte_t pte) | ||
251 | { | ||
252 | return __pte(pte_val(pte) | _PAGE_DIRTY); | ||
253 | } | ||
254 | |||
255 | static inline pte_t pte_mkyoung(pte_t pte) | ||
256 | { | ||
257 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | ||
258 | } | ||
259 | |||
260 | static inline pte_t pte_mkwrite(pte_t pte) | ||
261 | { | ||
262 | return __pte(pte_val(pte) | _PAGE_RW); | ||
263 | } | ||
264 | |||
265 | static inline pte_t pte_mkhuge(pte_t pte) | ||
266 | { | ||
267 | return __pte(pte_val(pte) | _PAGE_PSE); | ||
268 | } | ||
269 | |||
270 | static inline pte_t pte_clrhuge(pte_t pte) | ||
271 | { | ||
272 | return __pte(pte_val(pte) & ~_PAGE_PSE); | ||
273 | } | ||
274 | |||
275 | static inline pte_t pte_mkglobal(pte_t pte) | ||
276 | { | ||
277 | return __pte(pte_val(pte) | _PAGE_GLOBAL); | ||
278 | } | ||
279 | |||
280 | static inline pte_t pte_clrglobal(pte_t pte) | ||
281 | { | ||
282 | return __pte(pte_val(pte) & ~_PAGE_GLOBAL); | ||
283 | } | ||
284 | |||
285 | static inline pte_t pte_mkspecial(pte_t pte) | ||
286 | { | ||
287 | return __pte(pte_val(pte) | _PAGE_SPECIAL); | ||
288 | } | ||
289 | |||
290 | extern pteval_t __supported_pte_mask; | ||
291 | |||
292 | static inline pte_t pfn_pte(unsigned long page_nr, pgprot_t pgprot) | ||
293 | { | ||
294 | return __pte((((phys_addr_t)page_nr << PAGE_SHIFT) | | ||
295 | pgprot_val(pgprot)) & __supported_pte_mask); | ||
296 | } | ||
297 | |||
298 | static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) | ||
299 | { | ||
300 | return __pmd((((phys_addr_t)page_nr << PAGE_SHIFT) | | ||
301 | pgprot_val(pgprot)) & __supported_pte_mask); | ||
302 | } | ||
303 | |||
304 | static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | ||
305 | { | ||
306 | pteval_t val = pte_val(pte); | ||
307 | |||
308 | /* | ||
309 | * Chop off the NX bit (if present), and add the NX portion of | ||
310 | * the newprot (if present): | ||
311 | */ | ||
312 | val &= _PAGE_CHG_MASK; | ||
313 | val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask; | ||
314 | |||
315 | return __pte(val); | ||
316 | } | ||
317 | |||
318 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ | ||
319 | #define pgprot_modify pgprot_modify | ||
320 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) | ||
321 | { | ||
322 | pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK; | ||
323 | pgprotval_t addbits = pgprot_val(newprot); | ||
324 | return __pgprot(preservebits | addbits); | ||
325 | } | ||
326 | |||
327 | #define pte_pgprot(x) __pgprot(pte_flags(x) & PTE_FLAGS_MASK) | ||
328 | |||
329 | #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) | ||
330 | |||
331 | #ifndef __ASSEMBLY__ | ||
332 | #define __HAVE_PHYS_MEM_ACCESS_PROT | ||
333 | struct file; | ||
334 | pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | ||
335 | unsigned long size, pgprot_t vma_prot); | ||
336 | int phys_mem_access_prot_allowed(struct file *file, unsigned long pfn, | ||
337 | unsigned long size, pgprot_t *vma_prot); | ||
338 | #endif | ||
339 | |||
340 | /* Install a pte for a particular vaddr in kernel space. */ | ||
341 | void set_pte_vaddr(unsigned long vaddr, pte_t pte); | ||
342 | |||
343 | #ifdef CONFIG_X86_32 | ||
344 | extern void native_pagetable_setup_start(pgd_t *base); | ||
345 | extern void native_pagetable_setup_done(pgd_t *base); | ||
346 | #else | ||
347 | static inline void native_pagetable_setup_start(pgd_t *base) {} | ||
348 | static inline void native_pagetable_setup_done(pgd_t *base) {} | ||
349 | #endif | ||
350 | |||
351 | extern int arch_report_meminfo(char *page); | ||
352 | |||
353 | #ifdef CONFIG_PARAVIRT | ||
354 | #include <asm/paravirt.h> | ||
355 | #else /* !CONFIG_PARAVIRT */ | ||
356 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) | ||
357 | #define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte) | ||
358 | |||
359 | #define set_pte_present(mm, addr, ptep, pte) \ | ||
360 | native_set_pte_present(mm, addr, ptep, pte) | ||
361 | #define set_pte_atomic(ptep, pte) \ | ||
362 | native_set_pte_atomic(ptep, pte) | ||
363 | |||
364 | #define set_pmd(pmdp, pmd) native_set_pmd(pmdp, pmd) | ||
365 | |||
366 | #ifndef __PAGETABLE_PUD_FOLDED | ||
367 | #define set_pgd(pgdp, pgd) native_set_pgd(pgdp, pgd) | ||
368 | #define pgd_clear(pgd) native_pgd_clear(pgd) | ||
369 | #endif | ||
370 | |||
371 | #ifndef set_pud | ||
372 | # define set_pud(pudp, pud) native_set_pud(pudp, pud) | ||
373 | #endif | ||
374 | |||
375 | #ifndef __PAGETABLE_PMD_FOLDED | ||
376 | #define pud_clear(pud) native_pud_clear(pud) | ||
377 | #endif | ||
378 | |||
379 | #define pte_clear(mm, addr, ptep) native_pte_clear(mm, addr, ptep) | ||
380 | #define pmd_clear(pmd) native_pmd_clear(pmd) | ||
381 | |||
382 | #define pte_update(mm, addr, ptep) do { } while (0) | ||
383 | #define pte_update_defer(mm, addr, ptep) do { } while (0) | ||
384 | |||
385 | static inline void __init paravirt_pagetable_setup_start(pgd_t *base) | ||
386 | { | ||
387 | native_pagetable_setup_start(base); | ||
388 | } | ||
389 | |||
390 | static inline void __init paravirt_pagetable_setup_done(pgd_t *base) | ||
391 | { | ||
392 | native_pagetable_setup_done(base); | ||
393 | } | ||
394 | #endif /* CONFIG_PARAVIRT */ | ||
395 | |||
396 | #endif /* __ASSEMBLY__ */ | ||
397 | |||
398 | #ifdef CONFIG_X86_32 | ||
399 | # include "pgtable_32.h" | ||
400 | #else | ||
401 | # include "pgtable_64.h" | ||
402 | #endif | ||
403 | |||
404 | /* | ||
405 | * the pgd page can be thought of an array like this: pgd_t[PTRS_PER_PGD] | ||
406 | * | ||
407 | * this macro returns the index of the entry in the pgd page which would | ||
408 | * control the given virtual address | ||
409 | */ | ||
410 | #define pgd_index(address) (((address) >> PGDIR_SHIFT) & (PTRS_PER_PGD - 1)) | ||
411 | |||
412 | /* | ||
413 | * pgd_offset() returns a (pgd_t *) | ||
414 | * pgd_index() is used get the offset into the pgd page's array of pgd_t's; | ||
415 | */ | ||
416 | #define pgd_offset(mm, address) ((mm)->pgd + pgd_index((address))) | ||
417 | /* | ||
418 | * a shortcut which implies the use of the kernel's pgd, instead | ||
419 | * of a process's | ||
420 | */ | ||
421 | #define pgd_offset_k(address) pgd_offset(&init_mm, (address)) | ||
422 | |||
423 | |||
424 | #define KERNEL_PGD_BOUNDARY pgd_index(PAGE_OFFSET) | ||
425 | #define KERNEL_PGD_PTRS (PTRS_PER_PGD - KERNEL_PGD_BOUNDARY) | ||
426 | |||
427 | #ifndef __ASSEMBLY__ | ||
428 | |||
429 | enum { | ||
430 | PG_LEVEL_NONE, | ||
431 | PG_LEVEL_4K, | ||
432 | PG_LEVEL_2M, | ||
433 | PG_LEVEL_1G, | ||
434 | PG_LEVEL_NUM | ||
435 | }; | ||
436 | |||
437 | #ifdef CONFIG_PROC_FS | ||
438 | extern void update_page_count(int level, unsigned long pages); | ||
439 | #else | ||
440 | static inline void update_page_count(int level, unsigned long pages) { } | ||
441 | #endif | ||
442 | |||
443 | /* | ||
444 | * Helper function that returns the kernel pagetable entry controlling | ||
445 | * the virtual address 'address'. NULL means no pagetable entry present. | ||
446 | * NOTE: the return type is pte_t but if the pmd is PSE then we return it | ||
447 | * as a pte too. | ||
448 | */ | ||
449 | extern pte_t *lookup_address(unsigned long address, unsigned int *level); | ||
450 | |||
451 | /* local pte updates need not use xchg for locking */ | ||
452 | static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep) | ||
453 | { | ||
454 | pte_t res = *ptep; | ||
455 | |||
456 | /* Pure native function needs no input for mm, addr */ | ||
457 | native_pte_clear(NULL, 0, ptep); | ||
458 | return res; | ||
459 | } | ||
460 | |||
461 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | ||
462 | pte_t *ptep , pte_t pte) | ||
463 | { | ||
464 | native_set_pte(ptep, pte); | ||
465 | } | ||
466 | |||
467 | #ifndef CONFIG_PARAVIRT | ||
468 | /* | ||
469 | * Rules for using pte_update - it must be called after any PTE update which | ||
470 | * has not been done using the set_pte / clear_pte interfaces. It is used by | ||
471 | * shadow mode hypervisors to resynchronize the shadow page tables. Kernel PTE | ||
472 | * updates should either be sets, clears, or set_pte_atomic for P->P | ||
473 | * transitions, which means this hook should only be called for user PTEs. | ||
474 | * This hook implies a P->P protection or access change has taken place, which | ||
475 | * requires a subsequent TLB flush. The notification can optionally be delayed | ||
476 | * until the TLB flush event by using the pte_update_defer form of the | ||
477 | * interface, but care must be taken to assure that the flush happens while | ||
478 | * still holding the same page table lock so that the shadow and primary pages | ||
479 | * do not become out of sync on SMP. | ||
480 | */ | ||
481 | #define pte_update(mm, addr, ptep) do { } while (0) | ||
482 | #define pte_update_defer(mm, addr, ptep) do { } while (0) | ||
483 | #endif | ||
484 | |||
485 | /* | ||
486 | * We only update the dirty/accessed state if we set | ||
487 | * the dirty bit by hand in the kernel, since the hardware | ||
488 | * will do the accessed bit for us, and we don't want to | ||
489 | * race with other CPU's that might be updating the dirty | ||
490 | * bit at the same time. | ||
491 | */ | ||
492 | struct vm_area_struct; | ||
493 | |||
494 | #define __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS | ||
495 | extern int ptep_set_access_flags(struct vm_area_struct *vma, | ||
496 | unsigned long address, pte_t *ptep, | ||
497 | pte_t entry, int dirty); | ||
498 | |||
499 | #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG | ||
500 | extern int ptep_test_and_clear_young(struct vm_area_struct *vma, | ||
501 | unsigned long addr, pte_t *ptep); | ||
502 | |||
503 | #define __HAVE_ARCH_PTEP_CLEAR_YOUNG_FLUSH | ||
504 | extern int ptep_clear_flush_young(struct vm_area_struct *vma, | ||
505 | unsigned long address, pte_t *ptep); | ||
506 | |||
507 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR | ||
508 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | ||
509 | pte_t *ptep) | ||
510 | { | ||
511 | pte_t pte = native_ptep_get_and_clear(ptep); | ||
512 | pte_update(mm, addr, ptep); | ||
513 | return pte; | ||
514 | } | ||
515 | |||
516 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL | ||
517 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, | ||
518 | unsigned long addr, pte_t *ptep, | ||
519 | int full) | ||
520 | { | ||
521 | pte_t pte; | ||
522 | if (full) { | ||
523 | /* | ||
524 | * Full address destruction in progress; paravirt does not | ||
525 | * care about updates and native needs no locking | ||
526 | */ | ||
527 | pte = native_local_ptep_get_and_clear(ptep); | ||
528 | } else { | ||
529 | pte = ptep_get_and_clear(mm, addr, ptep); | ||
530 | } | ||
531 | return pte; | ||
532 | } | ||
533 | |||
534 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT | ||
535 | static inline void ptep_set_wrprotect(struct mm_struct *mm, | ||
536 | unsigned long addr, pte_t *ptep) | ||
537 | { | ||
538 | clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte); | ||
539 | pte_update(mm, addr, ptep); | ||
540 | } | ||
541 | |||
542 | /* | ||
543 | * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); | ||
544 | * | ||
545 | * dst - pointer to pgd range anwhere on a pgd page | ||
546 | * src - "" | ||
547 | * count - the number of pgds to copy. | ||
548 | * | ||
549 | * dst and src can be on the same page, but the range must not overlap, | ||
550 | * and must not cross a page boundary. | ||
551 | */ | ||
552 | static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count) | ||
553 | { | ||
554 | memcpy(dst, src, count * sizeof(pgd_t)); | ||
555 | } | ||
556 | |||
557 | |||
558 | #include <asm-generic/pgtable.h> | ||
559 | #endif /* __ASSEMBLY__ */ | ||
560 | |||
561 | #endif /* ASM_X86__PGTABLE_H */ | ||