[PATCH v2 2/2] riscv: mm: Avoid spurious fault after hotplugging vmemmap
From: Vivian Wang
Date: Thu Jun 04 2026 - 07:24:02 EST
section_activate() creates new mappings in the vmemmap range without
flushing TLB, which may cause faults on some RISC-V implementations that
cache non-present PTEs and crashes.
This seems to be most easily reproduced with DEBUG_VM=y and
PAGE_POISONING=y, which causes these newly mapped struct pages to be
poisoned i.e. written to immediately after mapping.
Implement the newly added hook vmemmap_populate_finalize() on RISC-V, to
arrange for the existing exception handler code to deal with these
faults if they happen.
Signed-off-by: Vivian Wang <wangruikang@xxxxxxxxxxx>
---
I put the declaration here since it's the file where vmemmap and the
vmemmap area addresses are defined.
Depends on my kfence patches for mark_new_valid_map() (see cover).
---
arch/riscv/include/asm/pgtable.h | 4 ++++
arch/riscv/mm/init.c | 6 ++++++
2 files changed, 10 insertions(+)
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index a1a7c6520a09..aa0f50e3d534 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -1243,6 +1243,10 @@ static inline pte_t pte_swp_clear_exclusive(pte_t pte)
#define TASK_SIZE FIXADDR_START
#endif
+/* Needed on SPARSEMEM_VMEMMAP */
+#define vmemmap_populate_finalize vmemmap_populate_finalize
+void __meminit vmemmap_populate_finalize(void);
+
#else /* CONFIG_MMU */
#define PAGE_SHARED __pgprot(0)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 706f43523935..cf9ae4099f82 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1360,6 +1360,12 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
*/
return vmemmap_populate_hugepages(start, end, node, altmap);
}
+
+void __meminit vmemmap_populate_finalize(void)
+{
+ /* Avoid faults on cached non-present TLB entries. */
+ mark_new_valid_map();
+}
#endif
#if defined(CONFIG_MMU) && defined(CONFIG_64BIT)
--
2.54.0