]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
mm: zap_install_uffd_wp_if_needed: return whether uffd-wp pte has been re-installed
authorQi Zheng <zhengqi.arch@bytedance.com>
Wed, 4 Dec 2024 11:09:46 +0000 (19:09 +0800)
committerAndrew Morton <akpm@linux-foundation.org>
Tue, 14 Jan 2025 06:40:47 +0000 (22:40 -0800)
In some cases, we'll replace the none pte with an uffd-wp swap special pte
marker when necessary.  Let's expose this information to the caller
through the return value, so that subsequent commits can use this
information to detect whether the PTE page is empty.

Link: https://lkml.kernel.org/r/9d4516554724eda87d6576468042a1741c475413.1733305182.git.zhengqi.arch@bytedance.com
Signed-off-by: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Hildenbrand <david@redhat.com>
Cc: David Rientjes <rientjes@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jann Horn <jannh@google.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mel Gorman <mgorman@suse.de>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Peter Xu <peterx@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Will Deacon <will@kernel.org>
Cc: Zach O'Keefe <zokeefe@google.com>
Cc: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
include/linux/mm_inline.h
mm/memory.c

index 1b6a917fffa4b1fd30066aa7d4bee7c9498c4b54..34e5097182a02cdfb54133a4f40db58de4e2a045 100644 (file)
@@ -564,9 +564,9 @@ static inline pte_marker copy_pte_marker(
  * Must be called with pgtable lock held so that no thread will see the none
  * pte, and if they see it, they'll fault and serialize at the pgtable lock.
  *
- * This function is a no-op if PTE_MARKER_UFFD_WP is not enabled.
+ * Returns true if an uffd-wp pte was installed, false otherwise.
  */
-static inline void
+static inline bool
 pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
                              pte_t *pte, pte_t pteval)
 {
@@ -583,7 +583,7 @@ pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
         * with a swap pte.  There's no way of leaking the bit.
         */
        if (vma_is_anonymous(vma) || !userfaultfd_wp(vma))
-               return;
+               return false;
 
        /* A uffd-wp wr-protected normal pte */
        if (unlikely(pte_present(pteval) && pte_uffd_wp(pteval)))
@@ -596,10 +596,13 @@ pte_install_uffd_wp_if_needed(struct vm_area_struct *vma, unsigned long addr,
        if (unlikely(pte_swp_uffd_wp_any(pteval)))
                arm_uffd_pte = true;
 
-       if (unlikely(arm_uffd_pte))
+       if (unlikely(arm_uffd_pte)) {
                set_pte_at(vma->vm_mm, addr, pte,
                           make_pte_marker(PTE_MARKER_UFFD_WP));
+               return true;
+       }
 #endif
+       return false;
 }
 
 static inline bool vma_has_recency(struct vm_area_struct *vma)
index 576eb9c4b57c7421c93a9fe05e78926701893c26..67406cb662eae11ac99f0f87d18dec1b4732418b 100644 (file)
@@ -1466,27 +1466,35 @@ static inline bool zap_drop_markers(struct zap_details *details)
 /*
  * This function makes sure that we'll replace the none pte with an uffd-wp
  * swap special pte marker when necessary. Must be with the pgtable lock held.
+ *
+ * Returns true if uffd-wp ptes was installed, false otherwise.
  */
-static inline void
+static inline bool
 zap_install_uffd_wp_if_needed(struct vm_area_struct *vma,
                              unsigned long addr, pte_t *pte, int nr,
                              struct zap_details *details, pte_t pteval)
 {
+       bool was_installed = false;
+
+#ifdef CONFIG_PTE_MARKER_UFFD_WP
        /* Zap on anonymous always means dropping everything */
        if (vma_is_anonymous(vma))
-               return;
+               return false;
 
        if (zap_drop_markers(details))
-               return;
+               return false;
 
        for (;;) {
                /* the PFN in the PTE is irrelevant. */
-               pte_install_uffd_wp_if_needed(vma, addr, pte, pteval);
+               if (pte_install_uffd_wp_if_needed(vma, addr, pte, pteval))
+                       was_installed = true;
                if (--nr == 0)
                        break;
                pte++;
                addr += PAGE_SIZE;
        }
+#endif
+       return was_installed;
 }
 
 static __always_inline void zap_present_folio_ptes(struct mmu_gather *tlb,