[RFC v1 03/10] mm/debug_vm_pgtable.c: Add test to zap THP migration entry

Ritesh Harjani (IBM)
2026-02-25T11:05:05Z

As discussed in the previous patch, there is a race possible with
zap_huge_pmd() and migrate_pages().
This adds a verification test.

Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
---
mm/debug_vm_pgtable.c | 38 ++++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)

diff --git a/mm/debug_vm_pgtable.c b/mm/debug_vm_pgtable.c
index 83cf07269f13..802f9f03c8ef 100644
--- a/mm/debug_vm_pgtable.c
+++ b/mm/debug_vm_pgtable.c
@@ -837,8 +837,45 @@ static void __init pmd_softleaf_tests(struct pgtable_debug_args *args)
pmd2 = __swp_entry_to_pmd(arch_entry);
WARN_ON(memcmp(&pmd1, &pmd2, sizeof(pmd1)));
}
+
+
+static void __init pmd_thp_migration_zap_tests(struct pgtable_debug_args *args)
+{
+ pmd_t pmd;
+ unsigned long vaddr = args->vaddr & HPAGE_PMD_MASK;
+
+ if (!has_transparent_hugepage() || !thp_migration_supported())
+ return;
+
+ pr_debug("Validating PMD zap on THP migration entry\n");
+
+ pmd = swp_entry_to_pmd(args->leaf_entry);
+ pgtable_trans_huge_deposit(args->mm, args->pmdp, args->start_ptep);
+
+ /* Verify that it's a valid migration PMD before we proceed */
+ WARN_ON(!pmd_is_huge(pmd));
+ WARN_ON(!pmd_is_valid_softleaf(pmd));
+ WARN_ON(pmd_present(pmd));
+ WARN_ON(pmd_none(pmd));
+
+ /* Install the migration PMD entry */
+ set_pmd_at(args->mm, vaddr, args->pmdp, pmd);
+
+ /*
+ * THP migration path can race with zap_huge_pmd(), which calls
+ * pmdp_huge_get_and_clear_full().
+ */
+ pmd = pmdp_huge_get_and_clear_full(args->vma, vaddr, args->pmdp, 1);
+
+ WARN_ON(!pmd_is_valid_softleaf(pmd));
+ WARN_ON(!pmd_none(pmdp_get(args->pmdp)));
+
+ pgtable_trans_huge_withdraw(args->mm, args->pmdp);
+}
+
#else /* !CONFIG_ARCH_ENABLE_THP_MIGRATION */
static void __init pmd_softleaf_tests(struct pgtable_debug_args *args) { }
+static void __init pmd_thp_migration_zap_tests(struct pgtable_debug_args *args) { }
#endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */

static void __init swap_migration_tests(struct pgtable_debug_args *args)
@@ -1348,6 +1385,7 @@ static int __init debug_vm_pgtable(void)
pmd_clear_tests(&args);
pmd_advanced_tests(&args);
pmd_huge_tests(&args);
+ pmd_thp_migration_zap_tests(&args);
pmd_populate_tests(&args);
spin_unlock(ptl);

--
2.53.0