[PATCH] x86/mm: Clear PUD entry before populating PMD table when splitting 1GB page in phys_pud_init

From: Phineas Su

Date: Sun Jul 19 2026 - 14:41:49 EST


When phys_pud_init() splits an existing 1 GB huge page (pud_leaf(*pud))
into PMD table entries, it extracts the page protection attributes but
does not clear the existing PUD entry (*pud).

Subsequently, pud_populate_init() -> set_pud_safe() is invoked to link
the new PMD table. Because *pud is still populated with the 1 GB huge
page entry, set_pud_safe() detects a present entry that differs from the
new PMD table pointer, triggering a WARN_ON_ONCE call trace in dmesg:

WARNING: CPU: 0 PID: 0 at arch/x86/mm/init_64.c:89 phys_pud_init+0x2d6/0x390

Call pud_clear(pud) right after extracting protection attributes when
splitting the 1 GB page so that set_pud_safe() can populate the PMD
table cleanly without issuing a warning.

Signed-off-by: Phineas Su <pohaosu@xxxxxxxxxx>
---
arch/x86/mm/init_64.c | 1 +
1 file changed, 1 insertion(+)

diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index d57f29ca23a5..fdfcf4a7b090 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -659,6 +659,7 @@ phys_pud_init(pud_t *pud_page, unsigned long paddr, unsigned long paddr_end,
continue;
}
prot = pte_pgprot(pte_clrhuge(*(pte_t *)pud));
+ pud_clear(pud);
}

if (page_size_mask & (1<<PG_LEVEL_1G)) {
--
2.55.0.229.g6434b31f56-goog