diff options
Diffstat (limited to 'include/asm-x86/pgtable.h')
-rw-r--r-- | include/asm-x86/pgtable.h | 89 |
1 files changed, 51 insertions, 38 deletions
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 801b31f71452..bcb5446a08d1 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
@@ -20,30 +20,25 @@ | |||
20 | #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ | 20 | #define _PAGE_BIT_PAT_LARGE 12 /* On 2MB or 1GB pages */ |
21 | #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ | 21 | #define _PAGE_BIT_NX 63 /* No execute: only valid after cpuid check */ |
22 | 22 | ||
23 | /* | 23 | #define _PAGE_PRESENT (_AT(pteval_t, 1) << _PAGE_BIT_PRESENT) |
24 | * Note: we use _AC(1, L) instead of _AC(1, UL) so that we get a | 24 | #define _PAGE_RW (_AT(pteval_t, 1) << _PAGE_BIT_RW) |
25 | * sign-extended value on 32-bit with all 1's in the upper word, | 25 | #define _PAGE_USER (_AT(pteval_t, 1) << _PAGE_BIT_USER) |
26 | * which preserves the upper pte values on 64-bit ptes: | 26 | #define _PAGE_PWT (_AT(pteval_t, 1) << _PAGE_BIT_PWT) |
27 | */ | 27 | #define _PAGE_PCD (_AT(pteval_t, 1) << _PAGE_BIT_PCD) |
28 | #define _PAGE_PRESENT (_AC(1, L)<<_PAGE_BIT_PRESENT) | 28 | #define _PAGE_ACCESSED (_AT(pteval_t, 1) << _PAGE_BIT_ACCESSED) |
29 | #define _PAGE_RW (_AC(1, L)<<_PAGE_BIT_RW) | 29 | #define _PAGE_DIRTY (_AT(pteval_t, 1) << _PAGE_BIT_DIRTY) |
30 | #define _PAGE_USER (_AC(1, L)<<_PAGE_BIT_USER) | 30 | #define _PAGE_PSE (_AT(pteval_t, 1) << _PAGE_BIT_PSE) |
31 | #define _PAGE_PWT (_AC(1, L)<<_PAGE_BIT_PWT) | 31 | #define _PAGE_GLOBAL (_AT(pteval_t, 1) << _PAGE_BIT_GLOBAL) |
32 | #define _PAGE_PCD (_AC(1, L)<<_PAGE_BIT_PCD) | 32 | #define _PAGE_UNUSED1 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED1) |
33 | #define _PAGE_ACCESSED (_AC(1, L)<<_PAGE_BIT_ACCESSED) | 33 | #define _PAGE_UNUSED2 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED2) |
34 | #define _PAGE_DIRTY (_AC(1, L)<<_PAGE_BIT_DIRTY) | 34 | #define _PAGE_UNUSED3 (_AT(pteval_t, 1) << _PAGE_BIT_UNUSED3) |
35 | #define _PAGE_PSE (_AC(1, L)<<_PAGE_BIT_PSE) /* 2MB page */ | 35 | #define _PAGE_PAT (_AT(pteval_t, 1) << _PAGE_BIT_PAT) |
36 | #define _PAGE_GLOBAL (_AC(1, L)<<_PAGE_BIT_GLOBAL) /* Global TLB entry */ | 36 | #define _PAGE_PAT_LARGE (_AT(pteval_t, 1) << _PAGE_BIT_PAT_LARGE) |
37 | #define _PAGE_UNUSED1 (_AC(1, L)<<_PAGE_BIT_UNUSED1) | ||
38 | #define _PAGE_UNUSED2 (_AC(1, L)<<_PAGE_BIT_UNUSED2) | ||
39 | #define _PAGE_UNUSED3 (_AC(1, L)<<_PAGE_BIT_UNUSED3) | ||
40 | #define _PAGE_PAT (_AC(1, L)<<_PAGE_BIT_PAT) | ||
41 | #define _PAGE_PAT_LARGE (_AC(1, L)<<_PAGE_BIT_PAT_LARGE) | ||
42 | 37 | ||
43 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) | 38 | #if defined(CONFIG_X86_64) || defined(CONFIG_X86_PAE) |
44 | #define _PAGE_NX (_AC(1, ULL) << _PAGE_BIT_NX) | 39 | #define _PAGE_NX (_AT(pteval_t, 1) << _PAGE_BIT_NX) |
45 | #else | 40 | #else |
46 | #define _PAGE_NX 0 | 41 | #define _PAGE_NX (_AT(pteval_t, 0)) |
47 | #endif | 42 | #endif |
48 | 43 | ||
49 | /* If _PAGE_PRESENT is clear, we use these: */ | 44 | /* If _PAGE_PRESENT is clear, we use these: */ |
@@ -57,7 +52,9 @@ | |||
57 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ | 52 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ |
58 | _PAGE_DIRTY) | 53 | _PAGE_DIRTY) |
59 | 54 | ||
60 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 55 | /* Set of bits not changed in pte_modify */ |
56 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_PCD | _PAGE_PWT | \ | ||
57 | _PAGE_ACCESSED | _PAGE_DIRTY) | ||
61 | 58 | ||
62 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) | 59 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) |
63 | #define _PAGE_CACHE_WB (0) | 60 | #define _PAGE_CACHE_WB (0) |
@@ -162,37 +159,37 @@ extern struct list_head pgd_list; | |||
162 | */ | 159 | */ |
163 | static inline int pte_dirty(pte_t pte) | 160 | static inline int pte_dirty(pte_t pte) |
164 | { | 161 | { |
165 | return pte_val(pte) & _PAGE_DIRTY; | 162 | return pte_flags(pte) & _PAGE_DIRTY; |
166 | } | 163 | } |
167 | 164 | ||
168 | static inline int pte_young(pte_t pte) | 165 | static inline int pte_young(pte_t pte) |
169 | { | 166 | { |
170 | return pte_val(pte) & _PAGE_ACCESSED; | 167 | return pte_flags(pte) & _PAGE_ACCESSED; |
171 | } | 168 | } |
172 | 169 | ||
173 | static inline int pte_write(pte_t pte) | 170 | static inline int pte_write(pte_t pte) |
174 | { | 171 | { |
175 | return pte_val(pte) & _PAGE_RW; | 172 | return pte_flags(pte) & _PAGE_RW; |
176 | } | 173 | } |
177 | 174 | ||
178 | static inline int pte_file(pte_t pte) | 175 | static inline int pte_file(pte_t pte) |
179 | { | 176 | { |
180 | return pte_val(pte) & _PAGE_FILE; | 177 | return pte_flags(pte) & _PAGE_FILE; |
181 | } | 178 | } |
182 | 179 | ||
183 | static inline int pte_huge(pte_t pte) | 180 | static inline int pte_huge(pte_t pte) |
184 | { | 181 | { |
185 | return pte_val(pte) & _PAGE_PSE; | 182 | return pte_flags(pte) & _PAGE_PSE; |
186 | } | 183 | } |
187 | 184 | ||
188 | static inline int pte_global(pte_t pte) | 185 | static inline int pte_global(pte_t pte) |
189 | { | 186 | { |
190 | return pte_val(pte) & _PAGE_GLOBAL; | 187 | return pte_flags(pte) & _PAGE_GLOBAL; |
191 | } | 188 | } |
192 | 189 | ||
193 | static inline int pte_exec(pte_t pte) | 190 | static inline int pte_exec(pte_t pte) |
194 | { | 191 | { |
195 | return !(pte_val(pte) & _PAGE_NX); | 192 | return !(pte_flags(pte) & _PAGE_NX); |
196 | } | 193 | } |
197 | 194 | ||
198 | static inline int pte_special(pte_t pte) | 195 | static inline int pte_special(pte_t pte) |
@@ -208,22 +205,22 @@ static inline int pmd_large(pmd_t pte) | |||
208 | 205 | ||
209 | static inline pte_t pte_mkclean(pte_t pte) | 206 | static inline pte_t pte_mkclean(pte_t pte) |
210 | { | 207 | { |
211 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); | 208 | return __pte(pte_val(pte) & ~_PAGE_DIRTY); |
212 | } | 209 | } |
213 | 210 | ||
214 | static inline pte_t pte_mkold(pte_t pte) | 211 | static inline pte_t pte_mkold(pte_t pte) |
215 | { | 212 | { |
216 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); | 213 | return __pte(pte_val(pte) & ~_PAGE_ACCESSED); |
217 | } | 214 | } |
218 | 215 | ||
219 | static inline pte_t pte_wrprotect(pte_t pte) | 216 | static inline pte_t pte_wrprotect(pte_t pte) |
220 | { | 217 | { |
221 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW); | 218 | return __pte(pte_val(pte) & ~_PAGE_RW); |
222 | } | 219 | } |
223 | 220 | ||
224 | static inline pte_t pte_mkexec(pte_t pte) | 221 | static inline pte_t pte_mkexec(pte_t pte) |
225 | { | 222 | { |
226 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); | 223 | return __pte(pte_val(pte) & ~_PAGE_NX); |
227 | } | 224 | } |
228 | 225 | ||
229 | static inline pte_t pte_mkdirty(pte_t pte) | 226 | static inline pte_t pte_mkdirty(pte_t pte) |
@@ -248,7 +245,7 @@ static inline pte_t pte_mkhuge(pte_t pte) | |||
248 | 245 | ||
249 | static inline pte_t pte_clrhuge(pte_t pte) | 246 | static inline pte_t pte_clrhuge(pte_t pte) |
250 | { | 247 | { |
251 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); | 248 | return __pte(pte_val(pte) & ~_PAGE_PSE); |
252 | } | 249 | } |
253 | 250 | ||
254 | static inline pte_t pte_mkglobal(pte_t pte) | 251 | static inline pte_t pte_mkglobal(pte_t pte) |
@@ -258,7 +255,7 @@ static inline pte_t pte_mkglobal(pte_t pte) | |||
258 | 255 | ||
259 | static inline pte_t pte_clrglobal(pte_t pte) | 256 | static inline pte_t pte_clrglobal(pte_t pte) |
260 | { | 257 | { |
261 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); | 258 | return __pte(pte_val(pte) & ~_PAGE_GLOBAL); |
262 | } | 259 | } |
263 | 260 | ||
264 | static inline pte_t pte_mkspecial(pte_t pte) | 261 | static inline pte_t pte_mkspecial(pte_t pte) |
@@ -288,13 +285,22 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
288 | * Chop off the NX bit (if present), and add the NX portion of | 285 | * Chop off the NX bit (if present), and add the NX portion of |
289 | * the newprot (if present): | 286 | * the newprot (if present): |
290 | */ | 287 | */ |
291 | val &= _PAGE_CHG_MASK & ~_PAGE_NX; | 288 | val &= _PAGE_CHG_MASK; |
292 | val |= pgprot_val(newprot) & __supported_pte_mask; | 289 | val |= pgprot_val(newprot) & (~_PAGE_CHG_MASK) & __supported_pte_mask; |
293 | 290 | ||
294 | return __pte(val); | 291 | return __pte(val); |
295 | } | 292 | } |
296 | 293 | ||
297 | #define pte_pgprot(x) __pgprot(pte_val(x) & (0xfff | _PAGE_NX)) | 294 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ |
295 | #define pgprot_modify pgprot_modify | ||
296 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) | ||
297 | { | ||
298 | pgprotval_t preservebits = pgprot_val(oldprot) & _PAGE_CHG_MASK; | ||
299 | pgprotval_t addbits = pgprot_val(newprot); | ||
300 | return __pgprot(preservebits | addbits); | ||
301 | } | ||
302 | |||
303 | #define pte_pgprot(x) __pgprot(pte_flags(x) & ~PTE_MASK) | ||
298 | 304 | ||
299 | #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) | 305 | #define canon_pgprot(p) __pgprot(pgprot_val(p) & __supported_pte_mask) |
300 | 306 | ||
@@ -358,8 +364,15 @@ enum { | |||
358 | PG_LEVEL_4K, | 364 | PG_LEVEL_4K, |
359 | PG_LEVEL_2M, | 365 | PG_LEVEL_2M, |
360 | PG_LEVEL_1G, | 366 | PG_LEVEL_1G, |
367 | PG_LEVEL_NUM | ||
361 | }; | 368 | }; |
362 | 369 | ||
370 | #ifdef CONFIG_PROC_FS | ||
371 | extern void update_page_count(int level, unsigned long pages); | ||
372 | #else | ||
373 | static inline void update_page_count(int level, unsigned long pages) { } | ||
374 | #endif | ||
375 | |||
363 | /* | 376 | /* |
364 | * Helper function that returns the kernel pagetable entry controlling | 377 | * Helper function that returns the kernel pagetable entry controlling |
365 | * the virtual address 'address'. NULL means no pagetable entry present. | 378 | * the virtual address 'address'. NULL means no pagetable entry present. |