diff options
Diffstat (limited to 'include/asm-x86/pgtable.h')
| -rw-r--r-- | include/asm-x86/pgtable.h | 178 |
1 files changed, 135 insertions, 43 deletions
diff --git a/include/asm-x86/pgtable.h b/include/asm-x86/pgtable.h index 9cf472aeb9ce..f1d9f4a03f6f 100644 --- a/include/asm-x86/pgtable.h +++ b/include/asm-x86/pgtable.h | |||
| @@ -4,13 +4,13 @@ | |||
| 4 | #define USER_PTRS_PER_PGD ((TASK_SIZE-1)/PGDIR_SIZE+1) | 4 | #define USER_PTRS_PER_PGD ((TASK_SIZE-1)/PGDIR_SIZE+1) |
| 5 | #define FIRST_USER_ADDRESS 0 | 5 | #define FIRST_USER_ADDRESS 0 |
| 6 | 6 | ||
| 7 | #define _PAGE_BIT_PRESENT 0 | 7 | #define _PAGE_BIT_PRESENT 0 /* is present */ |
| 8 | #define _PAGE_BIT_RW 1 | 8 | #define _PAGE_BIT_RW 1 /* writeable */ |
| 9 | #define _PAGE_BIT_USER 2 | 9 | #define _PAGE_BIT_USER 2 /* userspace addressable */ |
| 10 | #define _PAGE_BIT_PWT 3 | 10 | #define _PAGE_BIT_PWT 3 /* page write through */ |
| 11 | #define _PAGE_BIT_PCD 4 | 11 | #define _PAGE_BIT_PCD 4 /* page cache disabled */ |
| 12 | #define _PAGE_BIT_ACCESSED 5 | 12 | #define _PAGE_BIT_ACCESSED 5 /* was accessed (raised by CPU) */ |
| 13 | #define _PAGE_BIT_DIRTY 6 | 13 | #define _PAGE_BIT_DIRTY 6 /* was written to (raised by CPU) */ |
| 14 | #define _PAGE_BIT_FILE 6 | 14 | #define _PAGE_BIT_FILE 6 |
| 15 | #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */ | 15 | #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page */ |
| 16 | #define _PAGE_BIT_PAT 7 /* on 4KB pages */ | 16 | #define _PAGE_BIT_PAT 7 /* on 4KB pages */ |
| @@ -48,24 +48,39 @@ | |||
| 48 | #endif | 48 | #endif |
| 49 | 49 | ||
| 50 | /* If _PAGE_PRESENT is clear, we use these: */ | 50 | /* If _PAGE_PRESENT is clear, we use these: */ |
| 51 | #define _PAGE_FILE _PAGE_DIRTY /* nonlinear file mapping, saved PTE; unset:swap */ | 51 | #define _PAGE_FILE _PAGE_DIRTY /* nonlinear file mapping, |
| 52 | * saved PTE; unset:swap */ | ||
| 52 | #define _PAGE_PROTNONE _PAGE_PSE /* if the user mapped it with PROT_NONE; | 53 | #define _PAGE_PROTNONE _PAGE_PSE /* if the user mapped it with PROT_NONE; |
| 53 | pte_present gives true */ | 54 | pte_present gives true */ |
| 54 | 55 | ||
| 55 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY) | 56 | #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ |
| 56 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY) | 57 | _PAGE_ACCESSED | _PAGE_DIRTY) |
| 58 | #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | \ | ||
| 59 | _PAGE_DIRTY) | ||
| 57 | 60 | ||
| 58 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) | 61 | #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY) |
| 59 | 62 | ||
| 60 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) | 63 | #define _PAGE_CACHE_MASK (_PAGE_PCD | _PAGE_PWT) |
| 61 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) | 64 | #define _PAGE_CACHE_WB (0) |
| 65 | #define _PAGE_CACHE_WC (_PAGE_PWT) | ||
| 66 | #define _PAGE_CACHE_UC_MINUS (_PAGE_PCD) | ||
| 67 | #define _PAGE_CACHE_UC (_PAGE_PCD | _PAGE_PWT) | ||
| 62 | 68 | ||
| 63 | #define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED) | 69 | #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED) |
| 64 | #define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) | 70 | #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | \ |
| 65 | #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 71 | _PAGE_ACCESSED | _PAGE_NX) |
| 72 | |||
| 73 | #define PAGE_SHARED_EXEC __pgprot(_PAGE_PRESENT | _PAGE_RW | \ | ||
| 74 | _PAGE_USER | _PAGE_ACCESSED) | ||
| 75 | #define PAGE_COPY_NOEXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
| 76 | _PAGE_ACCESSED | _PAGE_NX) | ||
| 77 | #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
| 78 | _PAGE_ACCESSED) | ||
| 66 | #define PAGE_COPY PAGE_COPY_NOEXEC | 79 | #define PAGE_COPY PAGE_COPY_NOEXEC |
| 67 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_NX) | 80 | #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | \ |
| 68 | #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED) | 81 | _PAGE_ACCESSED | _PAGE_NX) |
| 82 | #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | \ | ||
| 83 | _PAGE_ACCESSED) | ||
| 69 | 84 | ||
| 70 | #ifdef CONFIG_X86_32 | 85 | #ifdef CONFIG_X86_32 |
| 71 | #define _PAGE_KERNEL_EXEC \ | 86 | #define _PAGE_KERNEL_EXEC \ |
| @@ -84,6 +99,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; | |||
| 84 | #define __PAGE_KERNEL_RO (__PAGE_KERNEL & ~_PAGE_RW) | 99 | #define __PAGE_KERNEL_RO (__PAGE_KERNEL & ~_PAGE_RW) |
| 85 | #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW) | 100 | #define __PAGE_KERNEL_RX (__PAGE_KERNEL_EXEC & ~_PAGE_RW) |
| 86 | #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT) | 101 | #define __PAGE_KERNEL_EXEC_NOCACHE (__PAGE_KERNEL_EXEC | _PAGE_PCD | _PAGE_PWT) |
| 102 | #define __PAGE_KERNEL_WC (__PAGE_KERNEL | _PAGE_CACHE_WC) | ||
| 87 | #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) | 103 | #define __PAGE_KERNEL_NOCACHE (__PAGE_KERNEL | _PAGE_PCD | _PAGE_PWT) |
| 88 | #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) | 104 | #define __PAGE_KERNEL_UC_MINUS (__PAGE_KERNEL | _PAGE_PCD) |
| 89 | #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) | 105 | #define __PAGE_KERNEL_VSYSCALL (__PAGE_KERNEL_RX | _PAGE_USER) |
| @@ -101,6 +117,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; | |||
| 101 | #define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO) | 117 | #define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO) |
| 102 | #define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC) | 118 | #define PAGE_KERNEL_EXEC MAKE_GLOBAL(__PAGE_KERNEL_EXEC) |
| 103 | #define PAGE_KERNEL_RX MAKE_GLOBAL(__PAGE_KERNEL_RX) | 119 | #define PAGE_KERNEL_RX MAKE_GLOBAL(__PAGE_KERNEL_RX) |
| 120 | #define PAGE_KERNEL_WC MAKE_GLOBAL(__PAGE_KERNEL_WC) | ||
| 104 | #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) | 121 | #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE) |
| 105 | #define PAGE_KERNEL_UC_MINUS MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS) | 122 | #define PAGE_KERNEL_UC_MINUS MAKE_GLOBAL(__PAGE_KERNEL_UC_MINUS) |
| 106 | #define PAGE_KERNEL_EXEC_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE) | 123 | #define PAGE_KERNEL_EXEC_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_EXEC_NOCACHE) |
| @@ -134,7 +151,7 @@ extern pteval_t __PAGE_KERNEL, __PAGE_KERNEL_EXEC; | |||
| 134 | * ZERO_PAGE is a global shared page that is always zero: used | 151 | * ZERO_PAGE is a global shared page that is always zero: used |
| 135 | * for zero-mapped memory areas etc.. | 152 | * for zero-mapped memory areas etc.. |
| 136 | */ | 153 | */ |
| 137 | extern unsigned long empty_zero_page[PAGE_SIZE/sizeof(unsigned long)]; | 154 | extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; |
| 138 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) | 155 | #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page)) |
| 139 | 156 | ||
| 140 | extern spinlock_t pgd_lock; | 157 | extern spinlock_t pgd_lock; |
| @@ -144,30 +161,101 @@ extern struct list_head pgd_list; | |||
| 144 | * The following only work if pte_present() is true. | 161 | * The following only work if pte_present() is true. |
| 145 | * Undefined behaviour if not.. | 162 | * Undefined behaviour if not.. |
| 146 | */ | 163 | */ |
| 147 | static inline int pte_dirty(pte_t pte) { return pte_val(pte) & _PAGE_DIRTY; } | 164 | static inline int pte_dirty(pte_t pte) |
| 148 | static inline int pte_young(pte_t pte) { return pte_val(pte) & _PAGE_ACCESSED; } | 165 | { |
| 149 | static inline int pte_write(pte_t pte) { return pte_val(pte) & _PAGE_RW; } | 166 | return pte_val(pte) & _PAGE_DIRTY; |
| 150 | static inline int pte_file(pte_t pte) { return pte_val(pte) & _PAGE_FILE; } | 167 | } |
| 151 | static inline int pte_huge(pte_t pte) { return pte_val(pte) & _PAGE_PSE; } | 168 | |
| 152 | static inline int pte_global(pte_t pte) { return pte_val(pte) & _PAGE_GLOBAL; } | 169 | static inline int pte_young(pte_t pte) |
| 153 | static inline int pte_exec(pte_t pte) { return !(pte_val(pte) & _PAGE_NX); } | 170 | { |
| 154 | 171 | return pte_val(pte) & _PAGE_ACCESSED; | |
| 155 | static inline int pmd_large(pmd_t pte) { | 172 | } |
| 156 | return (pmd_val(pte) & (_PAGE_PSE|_PAGE_PRESENT)) == | 173 | |
| 157 | (_PAGE_PSE|_PAGE_PRESENT); | 174 | static inline int pte_write(pte_t pte) |
| 175 | { | ||
| 176 | return pte_val(pte) & _PAGE_RW; | ||
| 177 | } | ||
| 178 | |||
| 179 | static inline int pte_file(pte_t pte) | ||
| 180 | { | ||
| 181 | return pte_val(pte) & _PAGE_FILE; | ||
| 182 | } | ||
| 183 | |||
| 184 | static inline int pte_huge(pte_t pte) | ||
| 185 | { | ||
| 186 | return pte_val(pte) & _PAGE_PSE; | ||
| 187 | } | ||
| 188 | |||
| 189 | static inline int pte_global(pte_t pte) | ||
| 190 | { | ||
| 191 | return pte_val(pte) & _PAGE_GLOBAL; | ||
| 192 | } | ||
| 193 | |||
| 194 | static inline int pte_exec(pte_t pte) | ||
| 195 | { | ||
| 196 | return !(pte_val(pte) & _PAGE_NX); | ||
| 197 | } | ||
| 198 | |||
| 199 | static inline int pmd_large(pmd_t pte) | ||
| 200 | { | ||
| 201 | return (pmd_val(pte) & (_PAGE_PSE | _PAGE_PRESENT)) == | ||
| 202 | (_PAGE_PSE | _PAGE_PRESENT); | ||
| 203 | } | ||
| 204 | |||
| 205 | static inline pte_t pte_mkclean(pte_t pte) | ||
| 206 | { | ||
| 207 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); | ||
| 208 | } | ||
| 209 | |||
| 210 | static inline pte_t pte_mkold(pte_t pte) | ||
| 211 | { | ||
| 212 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); | ||
| 213 | } | ||
| 214 | |||
| 215 | static inline pte_t pte_wrprotect(pte_t pte) | ||
| 216 | { | ||
| 217 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW); | ||
| 218 | } | ||
| 219 | |||
| 220 | static inline pte_t pte_mkexec(pte_t pte) | ||
| 221 | { | ||
| 222 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); | ||
| 223 | } | ||
| 224 | |||
| 225 | static inline pte_t pte_mkdirty(pte_t pte) | ||
| 226 | { | ||
| 227 | return __pte(pte_val(pte) | _PAGE_DIRTY); | ||
| 228 | } | ||
| 229 | |||
| 230 | static inline pte_t pte_mkyoung(pte_t pte) | ||
| 231 | { | ||
| 232 | return __pte(pte_val(pte) | _PAGE_ACCESSED); | ||
| 158 | } | 233 | } |
| 159 | 234 | ||
| 160 | static inline pte_t pte_mkclean(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_DIRTY); } | 235 | static inline pte_t pte_mkwrite(pte_t pte) |
| 161 | static inline pte_t pte_mkold(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_ACCESSED); } | 236 | { |
| 162 | static inline pte_t pte_wrprotect(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_RW); } | 237 | return __pte(pte_val(pte) | _PAGE_RW); |
| 163 | static inline pte_t pte_mkexec(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_NX); } | 238 | } |
| 164 | static inline pte_t pte_mkdirty(pte_t pte) { return __pte(pte_val(pte) | _PAGE_DIRTY); } | 239 | |
| 165 | static inline pte_t pte_mkyoung(pte_t pte) { return __pte(pte_val(pte) | _PAGE_ACCESSED); } | 240 | static inline pte_t pte_mkhuge(pte_t pte) |
| 166 | static inline pte_t pte_mkwrite(pte_t pte) { return __pte(pte_val(pte) | _PAGE_RW); } | 241 | { |
| 167 | static inline pte_t pte_mkhuge(pte_t pte) { return __pte(pte_val(pte) | _PAGE_PSE); } | 242 | return __pte(pte_val(pte) | _PAGE_PSE); |
| 168 | static inline pte_t pte_clrhuge(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); } | 243 | } |
| 169 | static inline pte_t pte_mkglobal(pte_t pte) { return __pte(pte_val(pte) | _PAGE_GLOBAL); } | 244 | |
| 170 | static inline pte_t pte_clrglobal(pte_t pte) { return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); } | 245 | static inline pte_t pte_clrhuge(pte_t pte) |
| 246 | { | ||
| 247 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_PSE); | ||
| 248 | } | ||
| 249 | |||
| 250 | static inline pte_t pte_mkglobal(pte_t pte) | ||
| 251 | { | ||
| 252 | return __pte(pte_val(pte) | _PAGE_GLOBAL); | ||
| 253 | } | ||
| 254 | |||
| 255 | static inline pte_t pte_clrglobal(pte_t pte) | ||
| 256 | { | ||
| 257 | return __pte(pte_val(pte) & ~(pteval_t)_PAGE_GLOBAL); | ||
| 258 | } | ||
| 171 | 259 | ||
| 172 | extern pteval_t __supported_pte_mask; | 260 | extern pteval_t __supported_pte_mask; |
| 173 | 261 | ||
| @@ -334,7 +422,8 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | |||
| 334 | }) | 422 | }) |
| 335 | 423 | ||
| 336 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR | 424 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR |
| 337 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 425 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, |
| 426 | pte_t *ptep) | ||
| 338 | { | 427 | { |
| 339 | pte_t pte = native_ptep_get_and_clear(ptep); | 428 | pte_t pte = native_ptep_get_and_clear(ptep); |
| 340 | pte_update(mm, addr, ptep); | 429 | pte_update(mm, addr, ptep); |
| @@ -342,7 +431,9 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, | |||
| 342 | } | 431 | } |
| 343 | 432 | ||
| 344 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL | 433 | #define __HAVE_ARCH_PTEP_GET_AND_CLEAR_FULL |
| 345 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full) | 434 | static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, |
| 435 | unsigned long addr, pte_t *ptep, | ||
| 436 | int full) | ||
| 346 | { | 437 | { |
| 347 | pte_t pte; | 438 | pte_t pte; |
| 348 | if (full) { | 439 | if (full) { |
| @@ -358,7 +449,8 @@ static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long | |||
| 358 | } | 449 | } |
| 359 | 450 | ||
| 360 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT | 451 | #define __HAVE_ARCH_PTEP_SET_WRPROTECT |
| 361 | static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr, pte_t *ptep) | 452 | static inline void ptep_set_wrprotect(struct mm_struct *mm, |
| 453 | unsigned long addr, pte_t *ptep) | ||
| 362 | { | 454 | { |
| 363 | clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte); | 455 | clear_bit(_PAGE_BIT_RW, (unsigned long *)&ptep->pte); |
| 364 | pte_update(mm, addr, ptep); | 456 | pte_update(mm, addr, ptep); |
