From nobody Thu Oct 2 21:56:28 2025 Received: from cstnet.cn (smtp81.cstnet.cn [159.226.251.81]) (using TLSv1.2 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1D2312EC09A; Thu, 11 Sep 2025 09:57:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=159.226.251.81 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757584632; cv=none; b=NFZqTwfPnJD/UTAEOviB9BHJ8l/qRLbZ5D9G8m/1gj3/C6SdH6YGfvFw9lAfO28KCPM8fQ5UIVM8i3nl/5HcEJj5Lo3tzaKpNBlKV9t3nPJrh6V1nRNeGVywtri3I/9haQEfxm8A5MKjRnL9mqNdms9x4mt039iZlGmq+/q1WR0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1757584632; c=relaxed/simple; bh=k59JVGfSX+Y/8f3hJFKFBtvQrPzA0CyDiA8xD0ZaDMM=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=l/q6MStveMfVfKAAdg7PZ39v6C+uO6alFMheamQbdfkQHgerrjCEsFqkmgwR1KogvzPs3etpImCuLLxjwodIWxxK5Vg1rnb1MEzD32c6he8VE+dxIWCe81lLjsYdiT/NTK4ofXWVqpUUkRAIulWl80nsf3cHD+XcOkUezjhD3mk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn; spf=pass smtp.mailfrom=iscas.ac.cn; arc=none smtp.client-ip=159.226.251.81 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=iscas.ac.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=iscas.ac.cn Received: from ubt.. (unknown [210.73.43.101]) by APP-03 (Coremail) with SMTP id rQCowACH2IK5nMJoo6pCAg--.44660S3; Thu, 11 Sep 2025 17:56:11 +0800 (CST) From: Chunyan Zhang To: linux-riscv@lists.infradead.org, linux-fsdevel@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: Paul Walmsley , Palmer Dabbelt , Albert Ou , Alexandre Ghiti , Deepak Gupta , Ved Shanbhogue , Alexander Viro , Christian Brauner , Jan Kara , Andrew Morton , Peter Xu , Arnd Bergmann , David Hildenbrand , Lorenzo Stoakes , "Liam R . Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Axel Rasmussen , Yuanchu Xie , Chunyan Zhang Subject: [PATCH v11 1/5] mm: softdirty: Add pgtable_soft_dirty_supported() Date: Thu, 11 Sep 2025 17:55:58 +0800 Message-Id: <20250911095602.1130290-2-zhangchunyan@iscas.ac.cn> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20250911095602.1130290-1-zhangchunyan@iscas.ac.cn> References: <20250911095602.1130290-1-zhangchunyan@iscas.ac.cn> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: rQCowACH2IK5nMJoo6pCAg--.44660S3 X-Coremail-Antispam: 1UD129KBjvJXoWxtrWfArW7XF1UKF4UZr17trb_yoW3Wr4Dpa yrGa4Fq3y8JF1vgayfJF4qqryaqF1Sqa47JryfC348J3y5G345WF4vqFyFvF1SgFy8XayS vrsrta13Gwsrtr7anT9S1TB71UUUUU7qnTZGkaVYY2UrUUUUjbIjqfuFe4nvWSU5nxnvy2 9KBjDU0xBIdaVrnRJUUUmvb7Iv0xC_Kw4lb4IE77IF4wAFF20E14v26rWj6s0DM7CY07I2 0VC2zVCF04k26cxKx2IYs7xG6rWj6s0DM7CIcVAFz4kK6r1j6r18M28IrcIa0xkI8VA2jI 8067AKxVWUGwA2048vs2IY020Ec7CjxVAFwI0_Xr0E3s1l8cAvFVAK0II2c7xJM28CjxkF 64kEwVA0rcxSw2x7M28EF7xvwVC0I7IYx2IY67AKxVW8JVW5JwA2z4x0Y4vE2Ix0cI8IcV CY1x0267AKxVWxJVW8Jr1l84ACjcxK6I8E87Iv67AKxVW0oVCq3wA2z4x0Y4vEx4A2jsIE c7CjxVAFwI0_GcCE3s1le2I262IYc4CY6c8Ij28IcVAaY2xG8wAqx4xG64xvF2IEw4CE5I 8CrVC2j2WlYx0E2Ix0cI8IcVAFwI0_JrI_JrylYx0Ex4A2jsIE14v26r4j6F4UMcvjeVCF s4IE7xkEbVWUJVW8JwACjcxG0xvY0x0EwIxGrwACI402YVCY1x02628vn2kIc2xKxwCY1x 0262kKe7AKxVW8ZVWrXwCY02Avz4vE14v_GFWl42xK82IYc2Ij64vIr41l4I8I3I0E4IkC 6x0Yz7v_Jr0_Gr1lx2IqxVAqx4xG67AKxVWUJVWUGwC20s026x8GjcxK67AKxVWUGVWUWw C2zVAF1VAY17CE14v26r4a6rW5MIIYrxkI7VAKI48JMIIF0xvE2Ix0cI8IcVAFwI0_Jr0_ JF4lIxAIcVC0I7IYx2IY6xkF7I0E14v26F4j6r4UJwCI42IY6xAIw20EY4v20xvaj40_Jr 0_JF4lIxAIcVC2z280aVAFwI0_Jr0_Gr1lIxAIcVC2z280aVCY1x0267AKxVW8JVW8JrUv cSsGvfC2KfnxnUUI43ZEXa7IUYk-P5UUUUU== X-CM-SenderInfo: x2kd0wxfkx051dq6x2xfdvhtffof0/1tbiBwoCB2jCjnQ4OgAAsa Content-Type: text/plain; charset="utf-8" Some platforms can customize the PTE PMD entry soft-dirty bit making it unavailable even if the architecture provides the resource. Add an API which architectures can define their specific implementations to detect if soft-dirty bit is available on which device the kernel is running. Signed-off-by: Chunyan Zhang --- fs/proc/task_mmu.c | 17 ++++++++++++++++- include/linux/pgtable.h | 12 ++++++++++++ mm/debug_vm_pgtable.c | 10 +++++----- mm/huge_memory.c | 13 +++++++------ mm/internal.h | 2 +- mm/mremap.c | 13 +++++++------ mm/userfaultfd.c | 10 ++++------ 7 files changed, 52 insertions(+), 25 deletions(-) diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 29cca0e6d0ff..9e8083b6d4cd 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -1058,7 +1058,7 @@ static void show_smap_vma_flags(struct seq_file *m, s= truct vm_area_struct *vma) * -Werror=3Dunterminated-string-initialization warning * with GCC 15 */ - static const char mnemonics[BITS_PER_LONG][3] =3D { + static char mnemonics[BITS_PER_LONG][3] =3D { /* * In case if we meet a flag we don't know about. */ @@ -1129,6 +1129,16 @@ static void show_smap_vma_flags(struct seq_file *m, = struct vm_area_struct *vma) [ilog2(VM_SEALED)] =3D "sl", #endif }; +/* + * We should remove the VM_SOFTDIRTY flag if the soft-dirty bit is + * unavailable on which the kernel is running, even if the architecture + * provides the resource and soft-dirty is compiled in. + */ +#ifdef CONFIG_MEM_SOFT_DIRTY + if (!pgtable_soft_dirty_supported()) + mnemonics[ilog2(VM_SOFTDIRTY)][0] =3D 0; +#endif + size_t i; =20 seq_puts(m, "VmFlags: "); @@ -1531,6 +1541,8 @@ static inline bool pte_is_pinned(struct vm_area_struc= t *vma, unsigned long addr, static inline void clear_soft_dirty(struct vm_area_struct *vma, unsigned long addr, pte_t *pte) { + if (!pgtable_soft_dirty_supported()) + return; /* * The soft-dirty tracker uses #PF-s to catch writes * to pages, so write-protect the pte as well. See the @@ -1566,6 +1578,9 @@ static inline void clear_soft_dirty_pmd(struct vm_are= a_struct *vma, { pmd_t old, pmd =3D *pmdp; =20 + if (!pgtable_soft_dirty_supported()) + return; + if (pmd_present(pmd)) { /* See comment in change_huge_pmd() */ old =3D pmdp_invalidate(vma, addr, pmdp); diff --git a/include/linux/pgtable.h b/include/linux/pgtable.h index 4c035637eeb7..2a3578a4ae4c 100644 --- a/include/linux/pgtable.h +++ b/include/linux/pgtable.h @@ -1537,6 +1537,18 @@ static inline pgprot_t pgprot_modify(pgprot_t oldpro= t, pgprot_t newprot) #define arch_start_context_switch(prev) do {} while (0) #endif =20 +/* + * Some platforms can customize the PTE soft-dirty bit making it unavailab= le + * even if the architecture provides the resource. + * Adding this API allows architectures to add their own checks for the + * devices on which the kernel is running. + * Note: When overiding it, please make sure the CONFIG_MEM_SOFT_DIRTY + * is part of this macro. + */ +#ifndef pgtable_soft_dirty_supported +#define pgtable_soft_dirty_supported() IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) +#endif + #ifdef CONFIG_HAVE_ARCH_SOFT_DIRTY #ifndef CONFIG_ARCH_ENABLE_THP_MIGRATION static inline pmd_t pmd_swp_mksoft_dirty(pmd_t pmd) diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c index 830107b6dd08..b32ce2b0b998 100644 --- a/mm/debug_vm_pgtable.c +++ b/mm/debug_vm_pgtable.c @@ -690,7 +690,7 @@ static void __init pte_soft_dirty_tests(struct pgtable_= debug_args *args) { pte_t pte =3D pfn_pte(args->fixed_pte_pfn, args->page_prot); =20 - if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY)) + if (!pgtable_soft_dirty_supported()) return; =20 pr_debug("Validating PTE soft dirty\n"); @@ -702,7 +702,7 @@ static void __init pte_swap_soft_dirty_tests(struct pgt= able_debug_args *args) { pte_t pte; =20 - if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY)) + if (!pgtable_soft_dirty_supported()) return; =20 pr_debug("Validating PTE swap soft dirty\n"); @@ -718,7 +718,7 @@ static void __init pmd_soft_dirty_tests(struct pgtable_= debug_args *args) { pmd_t pmd; =20 - if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY)) + if (!pgtable_soft_dirty_supported()) return; =20 if (!has_transparent_hugepage()) @@ -734,8 +734,8 @@ static void __init pmd_swap_soft_dirty_tests(struct pgt= able_debug_args *args) { pmd_t pmd; =20 - if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY) || - !IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION)) + if (!pgtable_soft_dirty_supported() || + !IS_ENABLED(CONFIG_ARCH_ENABLE_THP_MIGRATION)) return; =20 if (!has_transparent_hugepage()) diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 9c38a95e9f09..218d430a2ec6 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2271,12 +2271,13 @@ static inline int pmd_move_must_withdraw(spinlock_t= *new_pmd_ptl, =20 static pmd_t move_soft_dirty_pmd(pmd_t pmd) { -#ifdef CONFIG_MEM_SOFT_DIRTY - if (unlikely(is_pmd_migration_entry(pmd))) - pmd =3D pmd_swp_mksoft_dirty(pmd); - else if (pmd_present(pmd)) - pmd =3D pmd_mksoft_dirty(pmd); -#endif + if (pgtable_soft_dirty_supported()) { + if (unlikely(is_pmd_migration_entry(pmd))) + pmd =3D pmd_swp_mksoft_dirty(pmd); + else if (pmd_present(pmd)) + pmd =3D pmd_mksoft_dirty(pmd); + } + return pmd; } =20 diff --git a/mm/internal.h b/mm/internal.h index 45b725c3dc03..c6ca62f8ecf3 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1538,7 +1538,7 @@ static inline bool vma_soft_dirty_enabled(struct vm_a= rea_struct *vma) * VM_SOFTDIRTY is defined as 0x0, then !(vm_flags & VM_SOFTDIRTY) * will be constantly true. */ - if (!IS_ENABLED(CONFIG_MEM_SOFT_DIRTY)) + if (!pgtable_soft_dirty_supported()) return false; =20 /* diff --git a/mm/mremap.c b/mm/mremap.c index e618a706aff5..7beb3114dbf5 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -162,12 +162,13 @@ static pte_t move_soft_dirty_pte(pte_t pte) * Set soft dirty bit so we can notice * in userspace the ptes were moved. */ -#ifdef CONFIG_MEM_SOFT_DIRTY - if (pte_present(pte)) - pte =3D pte_mksoft_dirty(pte); - else if (is_swap_pte(pte)) - pte =3D pte_swp_mksoft_dirty(pte); -#endif + if (pgtable_soft_dirty_supported()) { + if (pte_present(pte)) + pte =3D pte_mksoft_dirty(pte); + else if (is_swap_pte(pte)) + pte =3D pte_swp_mksoft_dirty(pte); + } + return pte; } =20 diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index 45e6290e2e8b..85f43479b67a 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -1065,9 +1065,8 @@ static int move_present_pte(struct mm_struct *mm, =20 orig_dst_pte =3D folio_mk_pte(src_folio, dst_vma->vm_page_prot); /* Set soft dirty bit so userspace can notice the pte was moved */ -#ifdef CONFIG_MEM_SOFT_DIRTY - orig_dst_pte =3D pte_mksoft_dirty(orig_dst_pte); -#endif + if (pgtable_soft_dirty_supported()) + orig_dst_pte =3D pte_mksoft_dirty(orig_dst_pte); if (pte_dirty(orig_src_pte)) orig_dst_pte =3D pte_mkdirty(orig_dst_pte); orig_dst_pte =3D pte_mkwrite(orig_dst_pte, dst_vma); @@ -1134,9 +1133,8 @@ static int move_swap_pte(struct mm_struct *mm, struct= vm_area_struct *dst_vma, } =20 orig_src_pte =3D ptep_get_and_clear(mm, src_addr, src_pte); -#ifdef CONFIG_MEM_SOFT_DIRTY - orig_src_pte =3D pte_swp_mksoft_dirty(orig_src_pte); -#endif + if (pgtable_soft_dirty_supported()) + orig_src_pte =3D pte_swp_mksoft_dirty(orig_src_pte); set_pte_at(mm, dst_addr, dst_pte, orig_src_pte); double_pt_unlock(dst_ptl, src_ptl); =20 --=20 2.34.1