[PATCH v9 09/32] mm/debug_vm_pgtable: test PMD swap-exclusive helpers

From: Usama Arif

Date: Thu Nov 05 2026 - 13:42:50 EST


An architecture that picked a PMD exclusive bit overlapping the swap type
or offset field would otherwise only be caught by data corruption at
runtime. Mirror pte_swap_exclusive_tests() at PMD level.

Also check that setting swap soft-dirty leaves the PMD non-present.

Suggested-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
Signed-off-by: Usama Arif <usama.arif@xxxxxxxxx>
Acked-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
Reviewed-by: Kiryl Shutsemau (Meta) <kas@xxxxxxxxxx>
Reviewed-by: Zi Yan <ziy@xxxxxxxxxx>
---
mm/debug_vm_pgtable.c | 44 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 43 insertions(+), 1 deletion(-)

diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index 2875fd22d7bb0..80686e2baaa14 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -762,7 +762,9 @@ static void __init pmd_leaf_soft_dirty_tests(struct pgtable_debug_args *args)
WARN_ON(!pmd_is_huge(pmd));
WARN_ON(!pmd_is_valid_softleaf(pmd));

- WARN_ON(!pmd_swp_soft_dirty(pmd_swp_mksoft_dirty(pmd)));
+ pmd = pmd_swp_mksoft_dirty(pmd);
+ WARN_ON(!pmd_swp_soft_dirty(pmd));
+ WARN_ON(pmd_present(pmd));
WARN_ON(pmd_swp_soft_dirty(pmd_swp_clear_soft_dirty(pmd)));
}
#else /* !CONFIG_TRANSPARENT_HUGEPAGE */
@@ -802,6 +804,45 @@ static void __init pte_swap_exclusive_tests(struct pgtable_debug_args *args)
WARN_ON(memcmp(&entry, &softleaf, sizeof(entry)));
}

+#ifdef CONFIG_ARCH_HAS_PMD_SOFTLEAVES
+static void __init pmd_swap_exclusive_tests(struct pgtable_debug_args *args)
+{
+ swp_entry_t entry;
+ softleaf_t softleaf;
+ pmd_t pmd;
+
+ if (!has_transparent_hugepage())
+ return;
+
+ pr_debug("Validating PMD swap exclusive\n");
+ entry = args->swp_entry;
+
+ pmd = softleaf_to_pmd(entry);
+ softleaf = softleaf_from_pmd(pmd);
+
+ WARN_ON(pmd_swp_exclusive(pmd));
+ WARN_ON(!softleaf_is_swap(softleaf));
+ WARN_ON(memcmp(&entry, &softleaf, sizeof(entry)));
+
+ pmd = pmd_swp_mkexclusive(pmd);
+ softleaf = softleaf_from_pmd(pmd);
+
+ WARN_ON(!pmd_swp_exclusive(pmd));
+ WARN_ON(!softleaf_is_swap(softleaf));
+ WARN_ON(pmd_swp_soft_dirty(pmd));
+ WARN_ON(memcmp(&entry, &softleaf, sizeof(entry)));
+
+ pmd = pmd_swp_clear_exclusive(pmd);
+ softleaf = softleaf_from_pmd(pmd);
+
+ WARN_ON(pmd_swp_exclusive(pmd));
+ WARN_ON(!softleaf_is_swap(softleaf));
+ WARN_ON(memcmp(&entry, &softleaf, sizeof(entry)));
+}
+#else /* !CONFIG_ARCH_HAS_PMD_SOFTLEAVES */
+static void __init pmd_swap_exclusive_tests(struct pgtable_debug_args *args) { }
+#endif /* CONFIG_ARCH_HAS_PMD_SOFTLEAVES */
+
static void __init pte_swap_tests(struct pgtable_debug_args *args)
{
swp_entry_t arch_entry;
@@ -1322,6 +1363,7 @@ static int __init debug_vm_pgtable(void)
pmd_leaf_soft_dirty_tests(&args);

pte_swap_exclusive_tests(&args);
+ pmd_swap_exclusive_tests(&args);

pte_swap_tests(&args);
pmd_softleaf_tests(&args);
--
2.53.0-Meta