Skip to content

Commit 4edd70e

Browse files
dramforeverPaul Walmsley
authored andcommitted
mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
section_activate() does not flush TLB after populating new vmemmap pages. On most architectures, this is okay. However it is a problem on RISC-V since there the TLB caching non-present entries is permitted, which causes spurious faults on some hardwares. 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. Extend the RISC-V flush_cache_vmap() to also handle the vmemmap range, and call it after hotplugging vmemmap, which gets the possible spurious fault handled in the exception handler. At least for now, the only other architecture with both SPARSEMEM_VMEMMAP and flush_cache_vmap() is PowerPC, which has a similar problem with newly valid PTEs. But there flush_cache_vmap() is just a ptesync. So it should be safe to do this for generic code while having minimal performance impact. Suggested-by: Muchun Song <muchun.song@linux.dev> Signed-off-by: Vivian Wang <wangruikang@iscas.ac.cn> Reviewed-by: Muchun Song <muchun.song@linux.dev> Acked-by: David Hildenbrand (Arm) <david@kernel.org> Link: https://patch.msgid.link/20260713-mark-after-vmemmap-populate-v6-2-b945ceba29d4@iscas.ac.cn Signed-off-by: Paul Walmsley <pjw@kernel.org>
1 parent b6ea968 commit 4edd70e

2 files changed

Lines changed: 4 additions & 1 deletion

File tree

arch/riscv/include/asm/cacheflush.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,8 @@ static inline void mark_new_valid_map(void)
5656
#define flush_cache_vmap flush_cache_vmap
5757
static inline void flush_cache_vmap(unsigned long start, unsigned long end)
5858
{
59-
if (is_vmalloc_or_module_addr((void *)start))
59+
if (is_vmalloc_or_module_addr((void *)start) ||
60+
(start >= VMEMMAP_START && end <= VMEMMAP_END))
6061
mark_new_valid_map();
6162
}
6263
#define flush_cache_vmap_early(start, end) local_flush_tlb_kernel_range(start, end)

mm/sparse-vmemmap.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,8 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn,
564564
if (r < 0)
565565
return NULL;
566566

567+
flush_cache_vmap(start, end);
568+
567569
return pfn_to_page(pfn);
568570
}
569571

0 commit comments

Comments
 (0)