Linux-RISC-V Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
@ 2026-07-07  4:10 Vivian Wang
  2026-07-07  5:03 ` Vivian Wang
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Vivian Wang @ 2026-07-07  4:10 UTC (permalink / raw)
  To: Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Paul Walmsley, Suren Baghdasaryan,
	Vlastimil Babka
  Cc: linux-kernel, linux-mm, linux-riscv, Muchun Song, Vivian Wang

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>
---
Changes in v5:
- Remove hook, use existing flush_cache_vmap() (Muchun)
- Link to v4: https://patch.msgid.link/20260630-mark-after-vmemmap-populate-v4-1-febbc15da028@iscas.ac.cn

Changes in v4:
- Rebase on v7.2-rc1, drop dependencies
- (No code changes otherwise)
- (A concurrency fix for mark_new_valid_map was sent independently)
  https://lore.kernel.org/linux-riscv/20260629-riscv-mm-new-valid-map-ordering-v1-1-60d8c10c6292@iscas.ac.cn/
- Link to v3: https://patch.msgid.link/20260605-mark-after-vmemmap-populate-v3-1-a06001ac9264@iscas.ac.cn

(See v3 link for older changes)
---
 arch/riscv/include/asm/cacheflush.h | 3 ++-
 arch/riscv/mm/init.c                | 1 +
 mm/sparse-vmemmap.c                 | 2 ++
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
index 8cfe59483a8f..e935db27f09f 100644
--- a/arch/riscv/include/asm/cacheflush.h
+++ b/arch/riscv/include/asm/cacheflush.h
@@ -56,7 +56,8 @@ static inline void mark_new_valid_map(void)
 #define flush_cache_vmap flush_cache_vmap
 static inline void flush_cache_vmap(unsigned long start, unsigned long end)
 {
-	if (is_vmalloc_or_module_addr((void *)start))
+	if (is_vmalloc_or_module_addr((void *)start) ||
+	    (start >= VMEMMAP_START && end <= VMEMMAP_END))
 		mark_new_valid_map();
 }
 #define flush_cache_vmap_early(start, end)	local_flush_tlb_kernel_range(start, end)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 5b1b3c88b4d1..1b4f16704133 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -24,6 +24,7 @@
 #include <linux/execmem.h>
 
 #include <asm/alternative.h>
+#include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/io.h>
 #include <asm/kasan.h>
diff --git a/mm/sparse-vmemmap.c b/mm/sparse-vmemmap.c
index 99e2be39671b..ebd3ac997f64 100644
--- a/mm/sparse-vmemmap.c
+++ b/mm/sparse-vmemmap.c
@@ -564,6 +564,8 @@ struct page * __meminit __populate_section_memmap(unsigned long pfn,
 	if (r < 0)
 		return NULL;
 
+	flush_cache_vmap(start, end);
+
 	return pfn_to_page(pfn);
 }
 

---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260525-mark-after-vmemmap-populate-68bd790839c9

Best regards,
--  
Vivian "dramforever" Wang


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
  2026-07-07  4:10 [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap Vivian Wang
@ 2026-07-07  5:03 ` Vivian Wang
  2026-07-07  9:07   ` Muchun Song
  2026-07-09 13:34 ` kernel test robot
  2026-07-10  1:58 ` Paul Walmsley
  2 siblings, 1 reply; 6+ messages in thread
From: Vivian Wang @ 2026-07-07  5:03 UTC (permalink / raw)
  To: Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Paul Walmsley, Suren Baghdasaryan,
	Vlastimil Babka
  Cc: linux-kernel, linux-mm, linux-riscv, Muchun Song

Please disregard. I made a mistake while submitting this patch.

I'll send a fixed v6 later. Sorry.

On 7/7/26 12:10, Vivian Wang wrote:
> 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>
> ---
[...]


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
  2026-07-07  5:03 ` Vivian Wang
@ 2026-07-07  9:07   ` Muchun Song
  0 siblings, 0 replies; 6+ messages in thread
From: Muchun Song @ 2026-07-07  9:07 UTC (permalink / raw)
  To: Vivian Wang
  Cc: Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Paul Walmsley, Suren Baghdasaryan,
	Vlastimil Babka, linux-kernel, linux-mm, linux-riscv



> On Jul 7, 2026, at 13:03, Vivian Wang <wangruikang@iscas.ac.cn> wrote:
> 
> Please disregard. I made a mistake while submitting this patch.
> 
> I'll send a fixed v6 later. Sorry.

Please fix issues reported by Sashiko excluding pre-existing ones.

Thanks.

> 
> On 7/7/26 12:10, Vivian Wang wrote:
>> 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>
>> ---
> [...]



_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
  2026-07-07  4:10 [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap Vivian Wang
  2026-07-07  5:03 ` Vivian Wang
@ 2026-07-09 13:34 ` kernel test robot
  2026-07-10  1:58 ` Paul Walmsley
  2 siblings, 0 replies; 6+ messages in thread
From: kernel test robot @ 2026-07-09 13:34 UTC (permalink / raw)
  To: Vivian Wang, Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Paul Walmsley, Suren Baghdasaryan,
	Vlastimil Babka
  Cc: oe-kbuild-all, Linux Memory Management List, linux-kernel,
	linux-riscv, Muchun Song, Vivian Wang

Hi Vivian,

kernel test robot noticed the following build errors:

[auto build test ERROR on dc59e4fea9d83f03bad6bddf3fa2e52491777482]

url:    https://github.com/intel-lab-lkp/linux/commits/Vivian-Wang/mm-sparse-vmemmap-flush_cache_vmap-after-hotplugging-vmemmap/20260707-121114
base:   dc59e4fea9d83f03bad6bddf3fa2e52491777482
patch link:    https://lore.kernel.org/r/20260707-mark-after-vmemmap-populate-v5-1-77d1ded3cae3%40iscas.ac.cn
patch subject: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
config: riscv-randconfig-002-20260709 (https://download.01.org/0day-ci/archive/20260709/202607092128.yG6dYQOt-lkp@intel.com/config)
compiler: riscv64-linux-gcc (GCC) 10.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20260709/202607092128.yG6dYQOt-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202607092128.yG6dYQOt-lkp@intel.com/

All errors (new ones prefixed by >>):

   In file included from include/linux/cacheflush.h:5,
                    from include/linux/highmem.h:8,
                    from include/linux/bvec.h:10,
                    from include/linux/blk_types.h:10,
                    from include/linux/writeback.h:13,
                    from include/linux/memcontrol.h:23,
                    from include/linux/swap.h:9,
                    from include/linux/suspend.h:5,
                    from arch/riscv/kernel/asm-offsets.c:12:
   arch/riscv/include/asm/cacheflush.h: In function 'flush_cache_vmap':
>> arch/riscv/include/asm/cacheflush.h:60:16: error: 'VMEMMAP_START' undeclared (first use in this function)
      60 |      (start >= VMEMMAP_START && end <= VMEMMAP_END))
         |                ^~~~~~~~~~~~~
   arch/riscv/include/asm/cacheflush.h:60:16: note: each undeclared identifier is reported only once for each function it appears in
>> arch/riscv/include/asm/cacheflush.h:60:40: error: 'VMEMMAP_END' undeclared (first use in this function); did you mean 'MEMREMAP_ENC'?
      60 |      (start >= VMEMMAP_START && end <= VMEMMAP_END))
         |                                        ^~~~~~~~~~~
         |                                        MEMREMAP_ENC
   make[3]: *** [scripts/Makefile.build:184: arch/riscv/kernel/asm-offsets.s] Error 1 shuffle=275821313
   make[3]: Target 'prepare' not remade because of errors.
   make[2]: *** [Makefile:1405: prepare0] Error 2 shuffle=275821313
   make[2]: Target 'prepare' not remade because of errors.
   make[1]: *** [Makefile:248: __sub-make] Error 2 shuffle=275821313
   make[1]: Target 'prepare' not remade because of errors.
   make: *** [Makefile:248: __sub-make] Error 2 shuffle=275821313
   make: Target 'prepare' not remade because of errors.


vim +/VMEMMAP_START +60 arch/riscv/include/asm/cacheflush.h

    42	
    43	#ifdef CONFIG_64BIT
    44	/* This is accessed in assembly code. cpumask_var_t would be too complex. */
    45	extern DECLARE_BITMAP(new_valid_map_cpus, NR_CPUS);
    46	extern char _end[];
    47	static inline void mark_new_valid_map(void)
    48	{
    49		/*
    50		 * We don't care if concurrently a cpu resets this value since
    51		 * the only place this can happen is in handle_exception() where
    52		 * an sfence.vma is emitted.
    53		 */
    54		bitmap_fill(new_valid_map_cpus, NR_CPUS);
    55	}
    56	#define flush_cache_vmap flush_cache_vmap
    57	static inline void flush_cache_vmap(unsigned long start, unsigned long end)
    58	{
    59		if (is_vmalloc_or_module_addr((void *)start) ||
  > 60		    (start >= VMEMMAP_START && end <= VMEMMAP_END))
    61			mark_new_valid_map();
    62	}
    63	#define flush_cache_vmap_early(start, end)	local_flush_tlb_kernel_range(start, end)
    64	#endif
    65	

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
  2026-07-07  4:10 [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap Vivian Wang
  2026-07-07  5:03 ` Vivian Wang
  2026-07-09 13:34 ` kernel test robot
@ 2026-07-10  1:58 ` Paul Walmsley
  2026-07-10  3:51   ` Vivian Wang
  2 siblings, 1 reply; 6+ messages in thread
From: Paul Walmsley @ 2026-07-10  1:58 UTC (permalink / raw)
  To: Vivian Wang
  Cc: Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Paul Walmsley, Suren Baghdasaryan,
	Vlastimil Babka, linux-kernel, linux-mm, linux-riscv, Muchun Song

Hi Vivian,

On Tue, 7 Jul 2026, Vivian Wang wrote:

> 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>
> ---
> Changes in v5:
> - Remove hook, use existing flush_cache_vmap() (Muchun)
> - Link to v4: https://patch.msgid.link/20260630-mark-after-vmemmap-populate-v4-1-febbc15da028@iscas.ac.cn
> 
> Changes in v4:
> - Rebase on v7.2-rc1, drop dependencies
> - (No code changes otherwise)
> - (A concurrency fix for mark_new_valid_map was sent independently)
>   https://lore.kernel.org/linux-riscv/20260629-riscv-mm-new-valid-map-ordering-v1-1-60d8c10c6292@iscas.ac.cn/
> - Link to v3: https://patch.msgid.link/20260605-mark-after-vmemmap-populate-v3-1-a06001ac9264@iscas.ac.cn
> 
> (See v3 link for older changes)
> ---
>  arch/riscv/include/asm/cacheflush.h | 3 ++-
>  arch/riscv/mm/init.c                | 1 +
>  mm/sparse-vmemmap.c                 | 2 ++
>  3 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
> index 8cfe59483a8f..e935db27f09f 100644
> --- a/arch/riscv/include/asm/cacheflush.h
> +++ b/arch/riscv/include/asm/cacheflush.h
> @@ -56,7 +56,8 @@ static inline void mark_new_valid_map(void)
>  #define flush_cache_vmap flush_cache_vmap
>  static inline void flush_cache_vmap(unsigned long start, unsigned long end)
>  {
> -	if (is_vmalloc_or_module_addr((void *)start))
> +	if (is_vmalloc_or_module_addr((void *)start) ||
> +	    (start >= VMEMMAP_START && end <= VMEMMAP_END))

Is there an off-by-one error here?  VMEMMAP_END is currently set to
VMALLOC_START on RISC-V.

Am assuming you'll update this patch one more time?  At that point I'll 
plan to add it into v7.2-rc, assuming Andrew doesn't object.


- Paul

_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap
  2026-07-10  1:58 ` Paul Walmsley
@ 2026-07-10  3:51   ` Vivian Wang
  0 siblings, 0 replies; 6+ messages in thread
From: Vivian Wang @ 2026-07-10  3:51 UTC (permalink / raw)
  To: Paul Walmsley
  Cc: Alexandre Ghiti, Andrew Morton, David Hildenbrand,
	Liam R. Howlett, Lorenzo Stoakes, Michal Hocko, Mike Rapoport,
	Palmer Dabbelt, Suren Baghdasaryan, Vlastimil Babka, linux-kernel,
	linux-mm, linux-riscv, Muchun Song

On 7/10/26 09:58, Paul Walmsley wrote:

> Hi Vivian,
>
> On Tue, 7 Jul 2026, Vivian Wang wrote:
>
>> [...]
>>
>> diff --git a/arch/riscv/include/asm/cacheflush.h b/arch/riscv/include/asm/cacheflush.h
>> index 8cfe59483a8f..e935db27f09f 100644
>> --- a/arch/riscv/include/asm/cacheflush.h
>> +++ b/arch/riscv/include/asm/cacheflush.h
>> @@ -56,7 +56,8 @@ static inline void mark_new_valid_map(void)
>>  #define flush_cache_vmap flush_cache_vmap
>>  static inline void flush_cache_vmap(unsigned long start, unsigned long end)
>>  {
>> -	if (is_vmalloc_or_module_addr((void *)start))
>> +	if (is_vmalloc_or_module_addr((void *)start) ||
>> +	    (start >= VMEMMAP_START && end <= VMEMMAP_END))
> Is there an off-by-one error here?  VMEMMAP_END is currently set to
> VMALLOC_START on RISC-V.

I do think end <= VMEMMAP_END is correct.
Documentation/core-api/cachetlb.rst says:

6) ``void flush_cache_vmap(unsigned long start, unsigned long end)``
   ``void flush_cache_vunmap(unsigned long start, unsigned long end)``

    Here in these two interfaces we are flushing a specific range
    of (kernel) virtual addresses from the cache.  After running,
    there will be no entries in the cache for the kernel address
    space for virtual addresses in the range 'start' to 'end-1'.
                                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

So this is one of those half-open ranges. When end == VMEMMAP_END, it
means that the end of the range is exactly at the end of the vmemmap.

> Am assuming you'll update this patch one more time?  At that point I'll 
> plan to add it into v7.2-rc, assuming Andrew doesn't object.

Yes I will. There's an extraneous hunk for arch/riscv/mm/init.c that I
accidentally added to this patch, which was the thing that prompted the
"oops I'll send a v6 to fix" earlier. And there's a build failure for
MMU=n, which I will also fix for v6. (Why is this code even compiled for
MMU=n...)

(Muchun: Also thanks for the hint on the latter point reported by Sashiko.)

I haven't been able to get to it this week, unfortunately. I'll
definitely get to it next week if possible.

Vivian "dramforever" Wang


_______________________________________________
linux-riscv mailing list
linux-riscv@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-riscv

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-07-10  3:52 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-07  4:10 [PATCH v5] mm/sparse-vmemmap: flush_cache_vmap() after hotplugging vmemmap Vivian Wang
2026-07-07  5:03 ` Vivian Wang
2026-07-07  9:07   ` Muchun Song
2026-07-09 13:34 ` kernel test robot
2026-07-10  1:58 ` Paul Walmsley
2026-07-10  3:51   ` Vivian Wang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox