diff options
Diffstat (limited to 'arch/x86/include/asm/pgtable.h')
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 147 |
1 files changed, 146 insertions, 1 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index a34c785c5a63..18601c86fab1 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -28,11 +28,14 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)]; | |||
28 | extern spinlock_t pgd_lock; | 28 | extern spinlock_t pgd_lock; |
29 | extern struct list_head pgd_list; | 29 | extern struct list_head pgd_list; |
30 | 30 | ||
31 | extern struct mm_struct *pgd_page_get_mm(struct page *page); | ||
32 | |||
31 | #ifdef CONFIG_PARAVIRT | 33 | #ifdef CONFIG_PARAVIRT |
32 | #include <asm/paravirt.h> | 34 | #include <asm/paravirt.h> |
33 | #else /* !CONFIG_PARAVIRT */ | 35 | #else /* !CONFIG_PARAVIRT */ |
34 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) | 36 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) |
35 | #define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte) | 37 | #define set_pte_at(mm, addr, ptep, pte) native_set_pte_at(mm, addr, ptep, pte) |
38 | #define set_pmd_at(mm, addr, pmdp, pmd) native_set_pmd_at(mm, addr, pmdp, pmd) | ||
36 | 39 | ||
37 | #define set_pte_atomic(ptep, pte) \ | 40 | #define set_pte_atomic(ptep, pte) \ |
38 | native_set_pte_atomic(ptep, pte) | 41 | native_set_pte_atomic(ptep, pte) |
@@ -57,6 +60,8 @@ extern struct list_head pgd_list; | |||
57 | 60 | ||
58 | #define pte_update(mm, addr, ptep) do { } while (0) | 61 | #define pte_update(mm, addr, ptep) do { } while (0) |
59 | #define pte_update_defer(mm, addr, ptep) do { } while (0) | 62 | #define pte_update_defer(mm, addr, ptep) do { } while (0) |
63 | #define pmd_update(mm, addr, ptep) do { } while (0) | ||
64 | #define pmd_update_defer(mm, addr, ptep) do { } while (0) | ||
60 | 65 | ||
61 | #define pgd_val(x) native_pgd_val(x) | 66 | #define pgd_val(x) native_pgd_val(x) |
62 | #define __pgd(x) native_make_pgd(x) | 67 | #define __pgd(x) native_make_pgd(x) |
@@ -92,6 +97,11 @@ static inline int pte_young(pte_t pte) | |||
92 | return pte_flags(pte) & _PAGE_ACCESSED; | 97 | return pte_flags(pte) & _PAGE_ACCESSED; |
93 | } | 98 | } |
94 | 99 | ||
100 | static inline int pmd_young(pmd_t pmd) | ||
101 | { | ||
102 | return pmd_flags(pmd) & _PAGE_ACCESSED; | ||
103 | } | ||
104 | |||
95 | static inline int pte_write(pte_t pte) | 105 | static inline int pte_write(pte_t pte) |
96 | { | 106 | { |
97 | return pte_flags(pte) & _PAGE_RW; | 107 | return pte_flags(pte) & _PAGE_RW; |
@@ -140,6 +150,23 @@ static inline int pmd_large(pmd_t pte) | |||
140 | (_PAGE_PSE | _PAGE_PRESENT); | 150 | (_PAGE_PSE | _PAGE_PRESENT); |
141 | } | 151 | } |
142 | 152 | ||
153 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
154 | static inline int pmd_trans_splitting(pmd_t pmd) | ||
155 | { | ||
156 | return pmd_val(pmd) & _PAGE_SPLITTING; | ||
157 | } | ||
158 | |||
159 | static inline int pmd_trans_huge(pmd_t pmd) | ||
160 | { | ||
161 | return pmd_val(pmd) & _PAGE_PSE; | ||
162 | } | ||
163 | |||
164 | static inline int has_transparent_hugepage(void) | ||
165 | { | ||
166 | return cpu_has_pse; | ||
167 | } | ||
168 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | ||
169 | |||
143 | static inline pte_t pte_set_flags(pte_t pte, pteval_t set) | 170 | static inline pte_t pte_set_flags(pte_t pte, pteval_t set) |
144 | { | 171 | { |
145 | pteval_t v = native_pte_val(pte); | 172 | pteval_t v = native_pte_val(pte); |
@@ -214,6 +241,55 @@ static inline pte_t pte_mkspecial(pte_t pte) | |||
214 | return pte_set_flags(pte, _PAGE_SPECIAL); | 241 | return pte_set_flags(pte, _PAGE_SPECIAL); |
215 | } | 242 | } |
216 | 243 | ||
244 | static inline pmd_t pmd_set_flags(pmd_t pmd, pmdval_t set) | ||
245 | { | ||
246 | pmdval_t v = native_pmd_val(pmd); | ||
247 | |||
248 | return __pmd(v | set); | ||
249 | } | ||
250 | |||
251 | static inline pmd_t pmd_clear_flags(pmd_t pmd, pmdval_t clear) | ||
252 | { | ||
253 | pmdval_t v = native_pmd_val(pmd); | ||
254 | |||
255 | return __pmd(v & ~clear); | ||
256 | } | ||
257 | |||
258 | static inline pmd_t pmd_mkold(pmd_t pmd) | ||
259 | { | ||
260 | return pmd_clear_flags(pmd, _PAGE_ACCESSED); | ||
261 | } | ||
262 | |||
263 | static inline pmd_t pmd_wrprotect(pmd_t pmd) | ||
264 | { | ||
265 | return pmd_clear_flags(pmd, _PAGE_RW); | ||
266 | } | ||
267 | |||
268 | static inline pmd_t pmd_mkdirty(pmd_t pmd) | ||
269 | { | ||
270 | return pmd_set_flags(pmd, _PAGE_DIRTY); | ||
271 | } | ||
272 | |||
273 | static inline pmd_t pmd_mkhuge(pmd_t pmd) | ||
274 | { | ||
275 | return pmd_set_flags(pmd, _PAGE_PSE); | ||
276 | } | ||
277 | |||
278 | static inline pmd_t pmd_mkyoung(pmd_t pmd) | ||
279 | { | ||
280 | return pmd_set_flags(pmd, _PAGE_ACCESSED); | ||
281 | } | ||
282 | |||
283 | static inline pmd_t pmd_mkwrite(pmd_t pmd) | ||
284 | { | ||
285 | return pmd_set_flags(pmd, _PAGE_RW); | ||
286 | } | ||
287 | |||
288 | static inline pmd_t pmd_mknotpresent(pmd_t pmd) | ||
289 | { | ||
290 | return pmd_clear_flags(pmd, _PAGE_PRESENT); | ||
291 | } | ||
292 | |||
217 | /* | 293 | /* |
218 | * Mask out unsupported bits in a present pgprot. Non-present pgprots | 294 | * Mask out unsupported bits in a present pgprot. Non-present pgprots |
219 | * can use those bits for other purposes, so leave them be. | 295 | * can use those bits for other purposes, so leave them be. |
@@ -254,6 +330,16 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
254 | return __pte(val); | 330 | return __pte(val); |
255 | } | 331 | } |
256 | 332 | ||
333 | static inline pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
334 | { | ||
335 | pmdval_t val = pmd_val(pmd); | ||
336 | |||
337 | val &= _HPAGE_CHG_MASK; | ||
338 | val |= massage_pgprot(newprot) & ~_HPAGE_CHG_MASK; | ||
339 | |||
340 | return __pmd(val); | ||
341 | } | ||
342 | |||
257 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ | 343 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ |
258 | #define pgprot_modify pgprot_modify | 344 | #define pgprot_modify pgprot_modify |
259 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) | 345 | static inline pgprot_t pgprot_modify(pgprot_t oldprot, pgprot_t newprot) |
@@ -348,7 +434,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) | |||
348 | * Currently stuck as a macro due to indirect forward reference to | 434 | * Currently stuck as a macro due to indirect forward reference to |
349 | * linux/mmzone.h's __section_mem_map_addr() definition: | 435 | * linux/mmzone.h's __section_mem_map_addr() definition: |
350 | */ | 436 | */ |
351 | #define pmd_page(pmd) pfn_to_page(pmd_val(pmd) >> PAGE_SHIFT) | 437 | #define pmd_page(pmd) pfn_to_page((pmd_val(pmd) & PTE_PFN_MASK) >> PAGE_SHIFT) |
352 | 438 | ||
353 | /* | 439 | /* |
354 | * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] | 440 | * the pmd page can be thought of an array like this: pmd_t[PTRS_PER_PMD] |
@@ -522,12 +608,26 @@ static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep) | |||
522 | return res; | 608 | return res; |
523 | } | 609 | } |
524 | 610 | ||
611 | static inline pmd_t native_local_pmdp_get_and_clear(pmd_t *pmdp) | ||
612 | { | ||
613 | pmd_t res = *pmdp; | ||
614 | |||
615 | native_pmd_clear(pmdp); | ||
616 | return res; | ||
617 | } | ||
618 | |||
525 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, | 619 | static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr, |
526 | pte_t *ptep , pte_t pte) | 620 | pte_t *ptep , pte_t pte) |
527 | { | 621 | { |
528 | native_set_pte(ptep, pte); | 622 | native_set_pte(ptep, pte); |
529 | } | 623 | } |
530 | 624 | ||
625 | static inline void native_set_pmd_at(struct mm_struct *mm, unsigned long addr, | ||
626 | pmd_t *pmdp , pmd_t pmd) | ||
627 | { | ||
628 | native_set_pmd(pmdp, pmd); | ||
629 | } | ||
630 | |||
531 | #ifndef CONFIG_PARAVIRT | 631 | #ifndef CONFIG_PARAVIRT |
532 | /* | 632 | /* |
533 | * Rules for using pte_update - it must be called after any PTE update which | 633 | * Rules for using pte_update - it must be called after any PTE update which |
@@ -603,6 +703,51 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, | |||
603 | pte_update(mm, addr, ptep); | 703 | pte_update(mm, addr, ptep); |
604 | } | 704 | } |
605 | 705 | ||
706 | #define flush_tlb_fix_spurious_fault(vma, address) | ||
707 | |||
708 | #define mk_pmd(page, pgprot) pfn_pmd(page_to_pfn(page), (pgprot)) | ||
709 | |||
710 | #define __HAVE_ARCH_PMDP_SET_ACCESS_FLAGS | ||
711 | extern int pmdp_set_access_flags(struct vm_area_struct *vma, | ||
712 | unsigned long address, pmd_t *pmdp, | ||
713 | pmd_t entry, int dirty); | ||
714 | |||
715 | #define __HAVE_ARCH_PMDP_TEST_AND_CLEAR_YOUNG | ||
716 | extern int pmdp_test_and_clear_young(struct vm_area_struct *vma, | ||
717 | unsigned long addr, pmd_t *pmdp); | ||
718 | |||
719 | #define __HAVE_ARCH_PMDP_CLEAR_YOUNG_FLUSH | ||
720 | extern int pmdp_clear_flush_young(struct vm_area_struct *vma, | ||
721 | unsigned long address, pmd_t *pmdp); | ||
722 | |||
723 | |||
724 | #define __HAVE_ARCH_PMDP_SPLITTING_FLUSH | ||
725 | extern void pmdp_splitting_flush(struct vm_area_struct *vma, | ||
726 | unsigned long addr, pmd_t *pmdp); | ||
727 | |||
728 | #define __HAVE_ARCH_PMD_WRITE | ||
729 | static inline int pmd_write(pmd_t pmd) | ||
730 | { | ||
731 | return pmd_flags(pmd) & _PAGE_RW; | ||
732 | } | ||
733 | |||
734 | #define __HAVE_ARCH_PMDP_GET_AND_CLEAR | ||
735 | static inline pmd_t pmdp_get_and_clear(struct mm_struct *mm, unsigned long addr, | ||
736 | pmd_t *pmdp) | ||
737 | { | ||
738 | pmd_t pmd = native_pmdp_get_and_clear(pmdp); | ||
739 | pmd_update(mm, addr, pmdp); | ||
740 | return pmd; | ||
741 | } | ||
742 | |||
743 | #define __HAVE_ARCH_PMDP_SET_WRPROTECT | ||
744 | static inline void pmdp_set_wrprotect(struct mm_struct *mm, | ||
745 | unsigned long addr, pmd_t *pmdp) | ||
746 | { | ||
747 | clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp); | ||
748 | pmd_update(mm, addr, pmdp); | ||
749 | } | ||
750 | |||
606 | /* | 751 | /* |
607 | * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); | 752 | * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); |
608 | * | 753 | * |