diff mbox series

riscv: mm: execute local TLB flush after populating vmemmap

Message ID 20230414081605.471375-1-vincent.chen@sifive.com (mailing list archive)
State Superseded
Headers show
Series riscv: mm: execute local TLB flush after populating vmemmap | expand

Checks

Context Check Description
conchuod/cover_letter success Single patches do not need cover letters
conchuod/tree_selection success Guessed tree name to be fixes at HEAD 1b50f956c8fe
conchuod/fixes_present success Fixes tag present in non-next series
conchuod/maintainers_pattern success MAINTAINERS pattern errors before the patch: 1 and now 1
conchuod/verify_signedoff success Signed-off-by tag matches author and committer
conchuod/kdoc success Errors and warnings before: 0 this patch: 0
conchuod/build_rv64_clang_allmodconfig success Errors and warnings before: 3288 this patch: 3288
conchuod/module_param success Was 0 now: 0
conchuod/build_rv64_gcc_allmodconfig success Errors and warnings before: 17609 this patch: 17609
conchuod/build_rv32_defconfig success Build OK
conchuod/dtb_warn_rv64 success Errors and warnings before: 3 this patch: 3
conchuod/header_inline success No static functions without inline keyword in header files
conchuod/checkpatch success total: 0 errors, 0 warnings, 0 checks, 28 lines checked
conchuod/source_inline success Was 0 now: 0
conchuod/build_rv64_nommu_k210_defconfig success Build OK
conchuod/verify_fixes success Fixes tag looks correct
conchuod/build_rv64_nommu_virt_defconfig success Build OK

Commit Message

Vincent Chen April 14, 2023, 8:16 a.m. UTC
The spare_init() calls memmap_populate() many times to create VA to PA
mapping for the VMEMMAP area, where all "strcut 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 work
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 spare_init() to execute a sfence.vma instruction for the
VMEMMAP area, ensuring that all data related to the address translation
is visible to the hart.

Fixes: d95f1a542c3d ("RISC-V: Implement sparsemem")
Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
---
 arch/riscv/include/asm/tlbflush.h | 7 +++++++
 arch/riscv/mm/init.c              | 5 +++++
 2 files changed, 12 insertions(+)

Comments

Andrew Jones April 14, 2023, 9:14 a.m. UTC | #1
On Fri, Apr 14, 2023 at 04:16:05PM +0800, Vincent Chen wrote:
> The spare_init() calls memmap_populate() many times to create VA to PA
> mapping for the VMEMMAP area, where all "strcut page" are located once

struct

> 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 work

s/work/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 spare_init() to execute a sfence.vma instruction for the
> VMEMMAP area, ensuring that all data related to the address translation
> is visible to the hart.
> 
> Fixes: d95f1a542c3d ("RISC-V: Implement sparsemem")
> Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
> ---
>  arch/riscv/include/asm/tlbflush.h | 7 +++++++
>  arch/riscv/mm/init.c              | 5 +++++
>  2 files changed, 12 insertions(+)
> 
> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> index a09196f8de68..f9d3712bd93b 100644
> --- a/arch/riscv/include/asm/tlbflush.h
> +++ b/arch/riscv/include/asm/tlbflush.h
> @@ -61,4 +61,11 @@ static inline void flush_tlb_kernel_range(unsigned long start,
>  	flush_tlb_all();
>  }
>  
> +/* Flush a range of kernel pages without broadcasting */
> +static inline void local_flush_tlb_kernel_range(unsigned long start,
> +						unsigned long end)
> +{
> +	local_flush_tlb_all();
> +}
> +
>  #endif /* _ASM_RISCV_TLBFLUSH_H */
> diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> index 478d6763a01a..5bd96f6c8f19 100644
> --- a/arch/riscv/mm/init.c
> +++ b/arch/riscv/mm/init.c
> @@ -1231,6 +1231,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 propulated. Flush TLB for this region */

populated

> +	local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
> +#endif
>  	zone_sizes_init();
>  	reserve_crashkernel();
>  	memblock_dump_all();
> @@ -1240,6 +1244,7 @@ void __init misc_mem_init(void)
>  int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
>  			       struct vmem_altmap *altmap)
>  {
> +	/* Defer the required TLB flush until the entire VMEMMAP region has been populated */
>  	return vmemmap_populate_basepages(start, end, node, NULL);
>  }
>  #endif
> -- 
> 2.25.1
> 

Besides the typos,

Reviewed-by: Andrew Jones <ajones@ventanamicro.com>

Thanks,
drew
Vincent Chen April 17, 2023, 5:59 a.m. UTC | #2
On Fri, Apr 14, 2023 at 5:14 PM Andrew Jones <ajones@ventanamicro.com> wrote:
>
> On Fri, Apr 14, 2023 at 04:16:05PM +0800, Vincent Chen wrote:
> > The spare_init() calls memmap_populate() many times to create VA to PA
> > mapping for the VMEMMAP area, where all "strcut page" are located once
>
> struct
>
> > 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 work
>
> s/work/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 spare_init() to execute a sfence.vma instruction for the
> > VMEMMAP area, ensuring that all data related to the address translation
> > is visible to the hart.
> >
> > Fixes: d95f1a542c3d ("RISC-V: Implement sparsemem")
> > Signed-off-by: Vincent Chen <vincent.chen@sifive.com>
> > Reviewed-by: Alexandre Ghiti <alexghiti@rivosinc.com>
> > ---
> >  arch/riscv/include/asm/tlbflush.h | 7 +++++++
> >  arch/riscv/mm/init.c              | 5 +++++
> >  2 files changed, 12 insertions(+)
> >
> > diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> > index a09196f8de68..f9d3712bd93b 100644
> > --- a/arch/riscv/include/asm/tlbflush.h
> > +++ b/arch/riscv/include/asm/tlbflush.h
> > @@ -61,4 +61,11 @@ static inline void flush_tlb_kernel_range(unsigned long start,
> >       flush_tlb_all();
> >  }
> >
> > +/* Flush a range of kernel pages without broadcasting */
> > +static inline void local_flush_tlb_kernel_range(unsigned long start,
> > +                                             unsigned long end)
> > +{
> > +     local_flush_tlb_all();
> > +}
> > +
> >  #endif /* _ASM_RISCV_TLBFLUSH_H */
> > diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
> > index 478d6763a01a..5bd96f6c8f19 100644
> > --- a/arch/riscv/mm/init.c
> > +++ b/arch/riscv/mm/init.c
> > @@ -1231,6 +1231,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 propulated. Flush TLB for this region */
>
> populated
>
> > +     local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
> > +#endif
> >       zone_sizes_init();
> >       reserve_crashkernel();
> >       memblock_dump_all();
> > @@ -1240,6 +1244,7 @@ void __init misc_mem_init(void)
> >  int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
> >                              struct vmem_altmap *altmap)
> >  {
> > +     /* Defer the required TLB flush until the entire VMEMMAP region has been populated */
> >       return vmemmap_populate_basepages(start, end, node, NULL);
> >  }
> >  #endif
> > --
> > 2.25.1
> >
>
> Besides the typos,

Thank you for finding these typos. It's really embarrassing. I will
fix these issues in the patch for v3.

Thanks,
Vincent
>
> Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
>
> Thanks,
> drew
diff mbox series

Patch

diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index a09196f8de68..f9d3712bd93b 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -61,4 +61,11 @@  static inline void flush_tlb_kernel_range(unsigned long start,
 	flush_tlb_all();
 }
 
+/* Flush a range of kernel pages without broadcasting */
+static inline void local_flush_tlb_kernel_range(unsigned long start,
+						unsigned long end)
+{
+	local_flush_tlb_all();
+}
+
 #endif /* _ASM_RISCV_TLBFLUSH_H */
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 478d6763a01a..5bd96f6c8f19 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1231,6 +1231,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 propulated. Flush TLB for this region */
+	local_flush_tlb_kernel_range(VMEMMAP_START, VMEMMAP_END);
+#endif
 	zone_sizes_init();
 	reserve_crashkernel();
 	memblock_dump_all();
@@ -1240,6 +1244,7 @@  void __init misc_mem_init(void)
 int __meminit vmemmap_populate(unsigned long start, unsigned long end, int node,
 			       struct vmem_altmap *altmap)
 {
+	/* Defer the required TLB flush until the entire VMEMMAP region has been populated */
 	return vmemmap_populate_basepages(start, end, node, NULL);
 }
 #endif