[PATCH] riscv: mm: mark KASAN vmalloc shadow mappings as valid
From: Shaoqing Qin
Date: Wed Aug 12 2026 - 02:24:43 EST
With CONFIG_KASAN_VMALLOC, KASAN allocates shadow memory for vmalloc
mappings on demand. After installing new shadow PTEs, KASAN calls
flush_cache_vmap() for the shadow address range.
RISC-V uses flush_cache_vmap() to mark newly valid kernel mappings. If
an access subsequently faults, the early exception handler checks this
mark, executes sfence.vma when required, and retries the faulting
instruction.
However, flush_cache_vmap() currently recognizes only vmalloc, module,
and vmemmap addresses. KASAN shadow addresses are outside these ranges,
so creating a KASAN vmalloc shadow mapping does not mark it as newly
valid.
On implementations without Svvptc, an invalid PTE may remain cached
after the PTE has been made valid in memory. This caused a store page
fault in __memset() while KASAN was unpoisoning shadow memory for a DMA
atomic pool vmap mapping. The page table dump showed that the PTE in
memory was already valid and writable.
Recognize the KASAN shadow range and mark these mappings as newly valid,
allowing the existing fault-time sfence.vma and retry mechanism to
handle the stale invalid PTE.
Tested on a single-core RISC-V FPGA without Svvptc using Sv48 and
CONFIG_KASAN_VMALLOC=y. The kernel boots successfully through DMA
atomic pool initialization after this change.
Fixes: 503638e0babf ("riscv: Stop emitting preventive sfence.vma for new vmalloc mappings")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:GPT-5
Signed-off-by: Shaoqing Qin <shaoqing.qin@xxxxxxxxxxx>
---
arch/riscv/include/asm/cacheflush.h | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
index c2b0a2928f06..056aaf894644 100644
--- a/arch/riscv/include/asm/cacheflush.h
+++ b/arch/riscv/include/asm/cacheflush.h
@@ -7,6 +7,7 @@
#define _ASM_RISCV_CACHEFLUSH_H
#include <linux/mm.h>
+#include <asm/kasan.h>
static inline void local_flush_icache_all(void)
{
@@ -57,7 +58,9 @@ static inline void mark_new_valid_map(void)
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
{
if (is_vmalloc_or_module_addr((void *)start) ||
- (start >= VMEMMAP_START && end <= VMEMMAP_END))
+ (start >= VMEMMAP_START && end <= VMEMMAP_END) ||
+ (IS_ENABLED(CONFIG_KASAN_VMALLOC) &&
+ start >= KASAN_SHADOW_START && end <= KASAN_SHADOW_END))
mark_new_valid_map();
}
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)
--
2.53.0