Skip to content

Commit

Permalink
riscv: mm: execute local TLB flush after populating vmemmap
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
VincentZWC authored and Alexandre Ghiti committed Jan 23, 2024
1 parent 6613476 commit 756d187
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/riscv/include/asm/tlbflush.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ static inline void flush_tlb_kernel_range(unsigned long start,

#define flush_tlb_mm(mm) flush_tlb_all()
#define flush_tlb_mm_range(mm, start, end, page_size) flush_tlb_all()
#define local_flush_tlb_kernel_range(start, end) flush_tlb_all()
#endif /* !CONFIG_SMP || !CONFIG_MMU */

#endif /* _ASM_RISCV_TLBFLUSH_H */
6 changes: 6 additions & 0 deletions arch/riscv/mm/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,10 @@ void __init misc_mem_init(void)
early_memtest(min_low_pfn << PAGE_SHIFT, max_low_pfn << PAGE_SHIFT);
arch_numa_init();
sparse_init();
#ifdef CONFIG_SPARSEMEM_VMEMMAP
/* The entire VMEMMAP region has been populated. Flush TLB for this region */
local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
#endif
zone_sizes_init();
arch_reserve_crashkernel();
memblock_dump_all();
Expand Down Expand Up @@ -1412,6 +1416,8 @@ int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
* can't use hugepage mappings for 2-level page table because in case of
* memory hotplug, we are not able to update all the page tables with
* the new PMDs.
* Defer the required TLB flush until the entire VMEMMAP region has been
* populated.
*/
return vmemmap_populate_hugepages(start, end, node, NULL);
}
Expand Down

0 comments on commit 756d187

Please sign in to comment.