From: Peter Xu Date: Wed, 2 Jun 2021 03:52:49 +0000 (+1000) Subject: mm/userfaultfd: fix a few thp pmd missing uffd-wp bit X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=02ccf21d624619b92ae696df1e207d4c0bdff3df;p=users%2Fjedix%2Flinux-maple.git mm/userfaultfd: fix a few thp pmd missing uffd-wp bit These include: 1. When remove migration pmd entry, should keep the uffd-wp bit from swap pte. Note that we need to do this after setting write bit just in case we need to remove it. 2. When change huge pmd and convert write -> read migration entry, persist the same uffd-wp bit. 3. When convert pmd to swap entry, should drop the uffd-wp bit always. Link: https://lkml.kernel.org/r/20210428225030.9708-4-peterx@redhat.com Signed-off-by: Peter Xu Cc: Alexander Viro Cc: Andrea Arcangeli Cc: Axel Rasmussen Cc: Brian Geffon Cc: "Dr . David Alan Gilbert" Cc: Hugh Dickins Cc: Jerome Glisse Cc: Joe Perches Cc: Kirill A. Shutemov Cc: Lokesh Gidra Cc: Mike Kravetz Cc: Mike Rapoport Cc: Mina Almasry Cc: Oliver Upton Cc: Shaohua Li Cc: Shuah Khan Cc: Stephen Rothwell Cc: Wang Qing Signed-off-by: Andrew Morton Signed-off-by: Stephen Rothwell --- diff --git a/include/linux/swapops.h b/include/linux/swapops.h index 3ed89479cf1b1..af3d2661e41e8 100644 --- a/include/linux/swapops.h +++ b/include/linux/swapops.h @@ -281,6 +281,8 @@ static inline swp_entry_t pmd_to_swp_entry(pmd_t pmd) if (pmd_swp_soft_dirty(pmd)) pmd = pmd_swp_clear_soft_dirty(pmd); + if (pmd_swp_uffd_wp(pmd)) + pmd = pmd_swp_clear_uffd_wp(pmd); arch_entry = __pmd_to_swp_entry(pmd); return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); } diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 0c86ad8f1b3d8..68c78f72380ca 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1831,6 +1831,8 @@ int change_huge_pmd(struct vm_area_struct *vma, pmd_t *pmd, newpmd = swp_entry_to_pmd(entry); if (pmd_swp_soft_dirty(*pmd)) newpmd = pmd_swp_mksoft_dirty(newpmd); + if (pmd_swp_uffd_wp(*pmd)) + newpmd = pmd_swp_mkuffd_wp(newpmd); set_pmd_at(mm, addr, pmd, newpmd); } goto unlock; @@ -3255,6 +3257,8 @@ void remove_migration_pmd(struct page_vma_mapped_walk *pvmw, struct page *new) pmde = pmd_mksoft_dirty(pmde); if (is_writable_migration_entry(entry)) pmde = maybe_pmd_mkwrite(pmde, vma); + if (pmd_swp_uffd_wp(*pvmw->pmd)) + pmde = pmd_wrprotect(pmd_mkuffd_wp(pmde)); flush_cache_range(vma, mmun_start, mmun_start + HPAGE_PMD_SIZE); if (PageAnon(new))