Merge tag 'fpga-fixes-for-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/mdf...
[linux-2.6-microblaze.git] / mm / khugepaged.c
index 3afc1e2..99d77ff 100644 (file)
@@ -29,6 +29,7 @@ enum scan_result {
        SCAN_PMD_NULL,
        SCAN_EXCEED_NONE_PTE,
        SCAN_PTE_NON_PRESENT,
+       SCAN_PTE_UFFD_WP,
        SCAN_PAGE_RO,
        SCAN_LACK_REFERENCED_PAGE,
        SCAN_PAGE_NULL,
@@ -1137,6 +1138,15 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
                pte_t pteval = *_pte;
                if (is_swap_pte(pteval)) {
                        if (++unmapped <= khugepaged_max_ptes_swap) {
+                               /*
+                                * Always be strict with uffd-wp
+                                * enabled swap entries.  Please see
+                                * comment below for pte_uffd_wp().
+                                */
+                               if (pte_swp_uffd_wp(pteval)) {
+                                       result = SCAN_PTE_UFFD_WP;
+                                       goto out_unmap;
+                               }
                                continue;
                        } else {
                                result = SCAN_EXCEED_SWAP_PTE;
@@ -1156,6 +1166,19 @@ static int khugepaged_scan_pmd(struct mm_struct *mm,
                        result = SCAN_PTE_NON_PRESENT;
                        goto out_unmap;
                }
+               if (pte_uffd_wp(pteval)) {
+                       /*
+                        * Don't collapse the page if any of the small
+                        * PTEs are armed with uffd write protection.
+                        * Here we can also mark the new huge pmd as
+                        * write protected if any of the small ones is
+                        * marked but that could bring uknown
+                        * userfault messages that falls outside of
+                        * the registered range.  So, just be simple.
+                        */
+                       result = SCAN_PTE_UFFD_WP;
+                       goto out_unmap;
+               }
                if (pte_write(pteval))
                        writable = true;