diff options
Diffstat (limited to 'arch/x86/include/asm/pgtable.h')
-rw-r--r-- | arch/x86/include/asm/pgtable.h | 143 |
1 files changed, 142 insertions, 1 deletions
diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index ada823a13c7c..18601c86fab1 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h | |||
@@ -35,6 +35,7 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); | |||
35 | #else /* !CONFIG_PARAVIRT */ | 35 | #else /* !CONFIG_PARAVIRT */ |
36 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) | 36 | #define set_pte(ptep, pte) native_set_pte(ptep, pte) |
37 | #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) | ||
38 | 39 | ||
39 | #define set_pte_atomic(ptep, pte) \ | 40 | #define set_pte_atomic(ptep, pte) \ |
40 | native_set_pte_atomic(ptep, pte) | 41 | native_set_pte_atomic(ptep, pte) |
@@ -59,6 +60,8 @@ extern struct mm_struct *pgd_page_get_mm(struct page *page); | |||
59 | 60 | ||
60 | #define pte_update(mm, addr, ptep) do { } while (0) | 61 | #define pte_update(mm, addr, ptep) do { } while (0) |
61 | #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) | ||
62 | 65 | ||
63 | #define pgd_val(x) native_pgd_val(x) | 66 | #define pgd_val(x) native_pgd_val(x) |
64 | #define __pgd(x) native_make_pgd(x) | 67 | #define __pgd(x) native_make_pgd(x) |
@@ -94,6 +97,11 @@ static inline int pte_young(pte_t pte) | |||
94 | return pte_flags(pte) & _PAGE_ACCESSED; | 97 | return pte_flags(pte) & _PAGE_ACCESSED; |
95 | } | 98 | } |
96 | 99 | ||
100 | static inline int pmd_young(pmd_t pmd) | ||
101 | { | ||
102 | return pmd_flags(pmd) & _PAGE_ACCESSED; | ||
103 | } | ||
104 | |||
97 | static inline int pte_write(pte_t pte) | 105 | static inline int pte_write(pte_t pte) |
98 | { | 106 | { |
99 | return pte_flags(pte) & _PAGE_RW; | 107 | return pte_flags(pte) & _PAGE_RW; |
@@ -142,6 +150,23 @@ static inline int pmd_large(pmd_t pte) | |||
142 | (_PAGE_PSE | _PAGE_PRESENT); | 150 | (_PAGE_PSE | _PAGE_PRESENT); |
143 | } | 151 | } |
144 | 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 | |||
145 | 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) |
146 | { | 171 | { |
147 | pteval_t v = native_pte_val(pte); | 172 | pteval_t v = native_pte_val(pte); |
@@ -216,6 +241,55 @@ static inline pte_t pte_mkspecial(pte_t pte) | |||
216 | return pte_set_flags(pte, _PAGE_SPECIAL); | 241 | return pte_set_flags(pte, _PAGE_SPECIAL); |
217 | } | 242 | } |
218 | 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 | |||
219 | /* | 293 | /* |
220 | * Mask out unsupported bits in a present pgprot. Non-present pgprots | 294 | * Mask out unsupported bits in a present pgprot. Non-present pgprots |
221 | * can use those bits for other purposes, so leave them be. | 295 | * can use those bits for other purposes, so leave them be. |
@@ -256,6 +330,16 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) | |||
256 | return __pte(val); | 330 | return __pte(val); |
257 | } | 331 | } |
258 | 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 | |||
259 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ | 343 | /* mprotect needs to preserve PAT bits when updating vm_page_prot */ |
260 | #define pgprot_modify pgprot_modify | 344 | #define pgprot_modify pgprot_modify |
261 | 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) |
@@ -350,7 +434,7 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd) | |||
350 | * Currently stuck as a macro due to indirect forward reference to | 434 | * Currently stuck as a macro due to indirect forward reference to |
351 | * linux/mmzone.h's __section_mem_map_addr() definition: | 435 | * linux/mmzone.h's __section_mem_map_addr() definition: |
352 | */ | 436 | */ |
353 | #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) |
354 | 438 | ||
355 | /* | 439 | /* |
356 | * 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] |
@@ -524,12 +608,26 @@ static inline pte_t native_local_ptep_get_and_clear(pte_t *ptep) | |||
524 | return res; | 608 | return res; |
525 | } | 609 | } |
526 | 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 | |||
527 | 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, |
528 | pte_t *ptep , pte_t pte) | 620 | pte_t *ptep , pte_t pte) |
529 | { | 621 | { |
530 | native_set_pte(ptep, pte); | 622 | native_set_pte(ptep, pte); |
531 | } | 623 | } |
532 | 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 | |||
533 | #ifndef CONFIG_PARAVIRT | 631 | #ifndef CONFIG_PARAVIRT |
534 | /* | 632 | /* |
535 | * 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 |
@@ -607,6 +705,49 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, | |||
607 | 705 | ||
608 | #define flush_tlb_fix_spurious_fault(vma, address) | 706 | #define flush_tlb_fix_spurious_fault(vma, address) |
609 | 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 | |||
610 | /* | 751 | /* |
611 | * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); | 752 | * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); |
612 | * | 753 | * |