Skip to content

Commit d9807d6

Browse files
VincentZWCpalmer-dabbelt
authored andcommitted
riscv: mm: execute local TLB flush after populating vmemmap
The spare_init() calls memmap_populate() many times to create VA to PA mapping for the VMEMMAP area, where all "struct page" are located once CONFIG_SPARSEMEM_VMEMMAP is defined. These "struct page" are later initialized in the zone_sizes_init() function. However, during this process, no sfence.vma instruction is executed for this VMEMMAP area. This omission may cause the hart to fail to perform page table walk because some data related to the address translation is invisible to the hart. To solve this issue, the local_flush_tlb_kernel_range() is called right after the sparse_init() to execute a sfence.vma instruction for this VMEMMAP area, ensuring that all data related to the address translation is visible to the hart. Fixes: d95f1a5 ("RISC-V: Implement sparsemem") Signed-off-by: Vincent Chen <vincent.chen@sifive.com> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com> Link: https://lore.kernel.org/r/20240117140333.2479667-1-vincent.chen@sifive.com Fixes: 7a92fc8 ("mm: Introduce flush_cache_vmap_early()") Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
1 parent 6613476 commit d9807d6

File tree

3 files changed

+7
-1
lines changed

3 files changed

+7
-1
lines changed

arch/riscv/include/asm/tlbflush.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static inline void flush_tlb_kernel_range(unsigned long start,
7575

7676
#define flush_tlb_mm(mm) flush_tlb_all()
7777
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
78+
#define local_flush_tlb_kernel_range(start, end) flush_tlb_all()
7879
#endif /* !CONFIG_SMP || !CONFIG_MMU */
7980

8081
#endif /* _ASM_RISCV_TLBFLUSH_H */

arch/riscv/mm/init.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,6 +1385,10 @@ void __init misc_mem_init(void)
13851385
early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
13861386
arch_numa_init();
13871387
sparse_init();
1388+
#ifdef CONFIG_SPARSEMEM_VMEMMAP
1389+
/* The entire VMEMMAP region has been populated. Flush TLB for this region */
1390+
local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
1391+
#endif
13881392
zone_sizes_init();
13891393
arch_reserve_crashkernel();
13901394
memblock_dump_all();

arch/riscv/mm/tlbflush.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,9 +66,10 @@ static inline void local_flush_tlb_range_asid(unsigned long start,
6666
local_flush_tlb_range_threshold_asid(start, size, stride, asid);
6767
}
6868

69+
/* Flush a range of kernel pages without broadcasting */
6970
void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
7071
{
71-
local_flush_tlb_range_asid(start, end, PAGE_SIZE, FLUSH_TLB_NO_ASID);
72+
local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID);
7273
}
7374

7475
static void __ipi_flush_tlb_all(void *info)

0 commit comments

Comments
 (0)