|
33 | 33 | #include <linux/mmdebug.h>
|
34 | 34 | #include <linux/mm_types.h>
|
35 | 35 | #include <linux/sched.h>
|
| 36 | +#include <linux/page_table_check.h> |
36 | 37 |
|
37 | 38 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
38 | 39 | #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
|
@@ -96,6 +97,7 @@ static inline pteval_t __phys_to_pte_val(phys_addr_t phys)
|
96 | 97 | #define pte_young(pte) (!!(pte_val(pte) & PTE_AF))
|
97 | 98 | #define pte_special(pte) (!!(pte_val(pte) & PTE_SPECIAL))
|
98 | 99 | #define pte_write(pte) (!!(pte_val(pte) & PTE_WRITE))
|
| 100 | +#define pte_user(pte) (!!(pte_val(pte) & PTE_USER)) |
99 | 101 | #define pte_user_exec(pte) (!(pte_val(pte) & PTE_UXN))
|
100 | 102 | #define pte_cont(pte) (!!(pte_val(pte) & PTE_CONT))
|
101 | 103 | #define pte_devmap(pte) (!!(pte_val(pte) & PTE_DEVMAP))
|
@@ -312,8 +314,8 @@ static inline void __check_racy_pte_update(struct mm_struct *mm, pte_t *ptep,
|
312 | 314 | __func__, pte_val(old_pte), pte_val(pte));
|
313 | 315 | }
|
314 | 316 |
|
315 |
| -static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
316 |
| - pte_t *ptep, pte_t pte) |
| 317 | +static inline void __set_pte_at(struct mm_struct *mm, unsigned long addr, |
| 318 | + pte_t *ptep, pte_t pte) |
317 | 319 | {
|
318 | 320 | if (pte_present(pte) && pte_user_exec(pte) && !pte_special(pte))
|
319 | 321 | __sync_icache_dcache(pte);
|
@@ -343,6 +345,13 @@ static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
|
343 | 345 | set_pte(ptep, pte);
|
344 | 346 | }
|
345 | 347 |
|
| 348 | +static inline void set_pte_at(struct mm_struct *mm, unsigned long addr, |
| 349 | + pte_t *ptep, pte_t pte) |
| 350 | +{ |
| 351 | + page_table_check_pte_set(mm, addr, ptep, pte); |
| 352 | + return __set_pte_at(mm, addr, ptep, pte); |
| 353 | +} |
| 354 | + |
346 | 355 | /*
|
347 | 356 | * Huge pte definitions.
|
348 | 357 | */
|
@@ -454,6 +463,8 @@ static inline int pmd_trans_huge(pmd_t pmd)
|
454 | 463 | #define pmd_dirty(pmd) pte_dirty(pmd_pte(pmd))
|
455 | 464 | #define pmd_young(pmd) pte_young(pmd_pte(pmd))
|
456 | 465 | #define pmd_valid(pmd) pte_valid(pmd_pte(pmd))
|
| 466 | +#define pmd_user(pmd) pte_user(pmd_pte(pmd)) |
| 467 | +#define pmd_user_exec(pmd) pte_user_exec(pmd_pte(pmd)) |
457 | 468 | #define pmd_cont(pmd) pte_cont(pmd_pte(pmd))
|
458 | 469 | #define pmd_wrprotect(pmd) pte_pmd(pte_wrprotect(pmd_pte(pmd)))
|
459 | 470 | #define pmd_mkold(pmd) pte_pmd(pte_mkold(pmd_pte(pmd)))
|
@@ -501,8 +512,19 @@ static inline pmd_t pmd_mkdevmap(pmd_t pmd)
|
501 | 512 | #define pud_pfn(pud) ((__pud_to_phys(pud) & PUD_MASK) >> PAGE_SHIFT)
|
502 | 513 | #define pfn_pud(pfn,prot) __pud(__phys_to_pud_val((phys_addr_t)(pfn) << PAGE_SHIFT) | pgprot_val(prot))
|
503 | 514 |
|
504 |
| -#define set_pmd_at(mm, addr, pmdp, pmd) set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)) |
505 |
| -#define set_pud_at(mm, addr, pudp, pud) set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud)) |
| 515 | +static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr, |
| 516 | + pmd_t *pmdp, pmd_t pmd) |
| 517 | +{ |
| 518 | + page_table_check_pmd_set(mm, addr, pmdp, pmd); |
| 519 | + return __set_pte_at(mm, addr, (pte_t *)pmdp, pmd_pte(pmd)); |
| 520 | +} |
| 521 | + |
| 522 | +static inline void set_pud_at(struct mm_struct *mm, unsigned long addr, |
| 523 | + pud_t *pudp, pud_t pud) |
| 524 | +{ |
| 525 | + page_table_check_pud_set(mm, addr, pudp, pud); |
| 526 | + return __set_pte_at(mm, addr, (pte_t *)pudp, pud_pte(pud)); |
| 527 | +} |
506 | 528 |
|
507 | 529 | #define __p4d_to_phys(p4d) __pte_to_phys(p4d_pte(p4d))
|
508 | 530 | #define __phys_to_p4d_val(phys) __phys_to_pte_val(phys)
|
@@ -643,6 +665,24 @@ static inline unsigned long pmd_page_vaddr(pmd_t pmd)
|
643 | 665 | #define pud_present(pud) pte_present(pud_pte(pud))
|
644 | 666 | #define pud_leaf(pud) (pud_present(pud) && !pud_table(pud))
|
645 | 667 | #define pud_valid(pud) pte_valid(pud_pte(pud))
|
| 668 | +#define pud_user(pud) pte_user(pud_pte(pud)) |
| 669 | + |
| 670 | +#ifdef CONFIG_PAGE_TABLE_CHECK |
| 671 | +static inline bool pte_user_accessible_page(pte_t pte) |
| 672 | +{ |
| 673 | + return pte_present(pte) && (pte_user(pte) || pte_user_exec(pte)); |
| 674 | +} |
| 675 | + |
| 676 | +static inline bool pmd_user_accessible_page(pmd_t pmd) |
| 677 | +{ |
| 678 | + return pmd_present(pmd) && (pmd_user(pmd) || pmd_user_exec(pmd)); |
| 679 | +} |
| 680 | + |
| 681 | +static inline bool pud_user_accessible_page(pud_t pud) |
| 682 | +{ |
| 683 | + return pud_present(pud) && pud_user(pud); |
| 684 | +} |
| 685 | +#endif |
646 | 686 |
|
647 | 687 | static inline void set_pud(pud_t *pudp, pud_t pud)
|
648 | 688 | {
|
@@ -876,15 +916,23 @@ static inline int pmdp_test_and_clear_young(struct vm_area_struct *vma,
|
876 | 916 | static inline pte_t ptep_get_and_clear(struct mm_struct *mm,
|
877 | 917 | unsigned long address, pte_t *ptep)
|
878 | 918 | {
|
879 |
| - return __pte(xchg_relaxed(&pte_val(*ptep), 0)); |
| 919 | + pte_t pte = __pte(xchg_relaxed(&pte_val(*ptep), 0)); |
| 920 | + |
| 921 | + page_table_check_pte_clear(mm, address, pte); |
| 922 | + |
| 923 | + return pte; |
880 | 924 | }
|
881 | 925 |
|
882 | 926 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE
|
883 | 927 | #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR
|
884 | 928 | static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm,
|
885 | 929 | unsigned long address, pmd_t *pmdp)
|
886 | 930 | {
|
887 |
| - return pte_pmd(ptep_get_and_clear(mm, address, (pte_t *)pmdp)); |
| 931 | + pmd_t pmd = __pmd(xchg_relaxed(&pmd_val(*pmdp), 0)); |
| 932 | + |
| 933 | + page_table_check_pmd_clear(mm, address, pmd); |
| 934 | + |
| 935 | + return pmd; |
888 | 936 | }
|
889 | 937 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
|
890 | 938 |
|
@@ -918,6 +966,7 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm,
|
918 | 966 | static inline pmd_t pmdp_establish(struct vm_area_struct *vma,
|
919 | 967 | unsigned long address, pmd_t *pmdp, pmd_t pmd)
|
920 | 968 | {
|
| 969 | + page_table_check_pmd_set(vma->vm_mm, address, pmdp, pmd); |
921 | 970 | return __pmd(xchg_relaxed(&pmd_val(*pmdp), pmd_val(pmd)));
|
922 | 971 | }
|
923 | 972 | #endif
|
|
0 commit comments