From 901830e6b2d1eae17430d8b53c962e93eef48c34 Mon Sep 17 00:00:00 2001 From: Vivian Wang Date: Mon, 25 May 2026 12:23:29 +0800 Subject: [PATCH] riscv: mm: Call mark_new_valid_map() after hotplugging vmemmap 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. Add a hook vmemmap_populate_finalize() in __populate_section_memmap(), and implement it as calling mark_new_valid_map() on RISC-V, which arranges for the exception handler to deal with these faults if they happen. Signed-off-by: Vivian Wang Signed-off-by: Linux RISC-V bot --- arch/riscv/mm/init.c | 6 ++++++ include/linux/mm.h | 1 + mm/sparse-vmemmap.c | 6 ++++++ 3 files changed, 13 insertions(+) diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c index fa8d2f6f554b57..1bb3a5bc560c3c 100644 --- a/arch/riscv/mm/init.c +++ b/arch/riscv/mm/init.c @@ -1385,6 +1385,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) diff --git a/include/linux/mm.h b/include/linux/mm.h index af23453e9dbd0b..600abf8af8a9c0 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -4882,6 +4882,7 @@ int vmemmap_populate_hugepages(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap); int vmemmap_populate(unsigned long start, unsigned long end, int node, struct vmem_altmap *altmap); +void vmemmap_populate_finalize(void); int vmemmap_populate_hvo(unsigned long start, unsigned long end, unsigned int order, struct zone *zone, unsigned long headsize); diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c index 6eadb9d116e433..2b860d2b170344 100644 --- a/mm/sparse-vmemmap.c +++ b/mm/sparse-vmemmap.c @@ -544,6 +544,10 @@ static int __meminit vmemmap_populate_compound_pages(unsigned long start_pfn, #endif +void __weak __meminit vmemmap_populate_finalize(void) +{ +} + struct page * __meminit __populate_section_memmap(unsigned long pfn, unsigned long nr_pages, int nid, struct vmem_altmap *altmap, struct dev_pagemap *pgmap) @@ -561,6 +565,8 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn, else r = vmemmap_populate(start, end, nid, altmap); + vmemmap_populate_finalize(); + if (r < 0) return NULL;