diff --git a/mm/page_table_check.c b/mm/page_table_check.c index c75138d1831f6c4267c82f2c127e31f5769b79c1..8c937b896f570b8360fa98a9909cf550bb2d4149 100644 --- a/mm/page_table_check.c +++ b/mm/page_table_check.c @@ -9,6 +9,7 @@ #include #include #include +#include #undef pr_fmt #define pr_fmt(fmt) "page_table_check: " fmt @@ -160,12 +161,24 @@ void __page_table_check_zero(struct page *page, unsigned int order) page_ext_put(page_ext); } +#ifdef CONFIG_TRANSPARENT_HUGEPAGE +static inline bool page_table_check_huge_zero_pmd(pmd_t pmd) +{ + return is_huge_zero_pmd(pmd); +} +#else +static inline bool page_table_check_huge_zero_pmd(pmd_t pmd) +{ + return false; +} +#endif + void __page_table_check_pte_clear(struct mm_struct *mm, pte_t pte) { if (&init_mm == mm) return; - if (pte_user_accessible_page(pte)) { + if (pte_user_accessible_page(pte) && !pte_special(pte)) { page_table_check_clear(pte_pfn(pte), PAGE_SIZE >> PAGE_SHIFT); } } @@ -176,7 +189,8 @@ void __page_table_check_pmd_clear(struct mm_struct *mm, pmd_t pmd) if (&init_mm == mm) return; - if (pmd_user_accessible_page(pmd)) { + if (pmd_user_accessible_page(pmd) && + !page_table_check_huge_zero_pmd(pmd)) { page_table_check_clear(pmd_pfn(pmd), PMD_SIZE >> PAGE_SHIFT); } } @@ -221,7 +235,7 @@ void __page_table_check_ptes_set(struct mm_struct *mm, pte_t *ptep, pte_t pte, for (i = 0; i < nr; i++) __page_table_check_pte_clear(mm, ptep_get(ptep + i)); - if (pte_user_accessible_page(pte)) + if (pte_user_accessible_page(pte) && !pte_special(pte)) page_table_check_set(pte_pfn(pte), nr, pte_write(pte)); } EXPORT_SYMBOL(__page_table_check_ptes_set); @@ -247,7 +261,8 @@ void __page_table_check_pmds_set(struct mm_struct *mm, pmd_t *pmdp, pmd_t pmd, for (i = 0; i < nr; i++) __page_table_check_pmd_clear(mm, *(pmdp + i)); - if (pmd_user_accessible_page(pmd)) + if (pmd_user_accessible_page(pmd) && + !page_table_check_huge_zero_pmd(pmd)) page_table_check_set(pmd_pfn(pmd), stride * nr, pmd_write(pmd)); } EXPORT_SYMBOL(__page_table_check_pmds_set);