mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v2 0/3] riscv: mm: Some optimizations for tlb flush
@ 2026-07-15 13:20 Xu Lu
  2026-07-15 13:20 ` [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache() Xu Lu
                   ` (2 more replies)
  0 siblings, 3 replies; 13+ messages in thread
From: Xu Lu @ 2026-07-15 13:20 UTC (permalink / raw)
  To: paul.walmsley, klarasmodin, palmer, aou, alex
  Cc: linux-riscv, linux-kernel, apw, joe, Xu Lu

Some optimizations for tlb flush on RISC-V smp:
1. Apply Svinval in update_mmu_cache() to avoid flushing irrelevant tlb
entries.
2. Clear bit of current cpu in mm_cpumask after local_flush_tlb_all_asid()
to avoid potential IPIs in the future.

Some false positive spacing error happens during patch checking. Thus I
CCed maintainers of checkpatch.pl as well.

Changes in V2:
1. Split the modification on update_mmu_cache() into two commits. Thanks
to Paul.
2. Fix address errors in the svinval processing path in V1. Thanks to
Klara.

Xu Lu (3):
  riscv: mm: Use ASID in update_mmu_cache()
  riscv: mm: Apply Svinval in update_mmu_cache()
  riscv: mm: Clear cpu in mm_cpumask after local_flush_tlb_all_asid

 arch/riscv/include/asm/pgtable.h  | 12 +++++-
 arch/riscv/include/asm/tlbflush.h | 23 +++++++++++
 arch/riscv/mm/tlbflush.c          | 64 ++++++++++++-------------------
 3 files changed, 59 insertions(+), 40 deletions(-)

-- 
2.39.5


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

* [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-15 13:20 [PATCH v2 0/3] riscv: mm: Some optimizations for tlb flush Xu Lu
@ 2026-07-15 13:20 ` Xu Lu
  2026-07-16 16:24   ` Klara Modin
  2026-07-15 13:20 ` [PATCH v2 2/3] riscv: mm: Apply Svinval " Xu Lu
  2026-07-15 13:20 ` [PATCH v2 3/3] riscv: mm: Clear cpu in mm_cpumask after local_flush_tlb_all_asid Xu Lu
  2 siblings, 1 reply; 13+ messages in thread
From: Xu Lu @ 2026-07-15 13:20 UTC (permalink / raw)
  To: paul.walmsley, klarasmodin, palmer, aou, alex
  Cc: linux-riscv, linux-kernel, apw, joe, Xu Lu

Only flush TLB entries for the specified mm in update_mmu_cache_range().

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
 arch/riscv/include/asm/pgtable.h  | 4 +++-
 arch/riscv/include/asm/tlbflush.h | 5 +++++
 arch/riscv/mm/tlbflush.c          | 5 -----
 3 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 5d5756bda82e..9926556099ae 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 		struct vm_area_struct *vma, unsigned long address,
 		pte_t *ptep, unsigned int nr)
 {
+	unsigned long asid = get_mm_asid(vma->vm_mm);
+
 	/*
 	 * Svvptc guarantees that the new valid pte will be visible within
 	 * a bounded timeframe, so when the uarch does not cache invalid
@@ -584,7 +586,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 	 * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
 	 */
 	while (nr--)
-		local_flush_tlb_page(address + nr * PAGE_SIZE);
+		local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
 
 }
 #define update_mmu_cache(vma, addr, ptep) \
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index eed0abc40514..7c2cd5cc92d3 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -15,6 +15,11 @@
 #define FLUSH_TLB_NO_ASID       ((unsigned long)-1)
 
 #ifdef CONFIG_MMU
+static inline unsigned long get_mm_asid(struct mm_struct *mm)
+{
+	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
+}
+
 static inline void local_flush_tlb_all(void)
 {
 	__asm__ __volatile__ ("sfence.vma" : : : "memory");
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
index 8404530ec00f..73c226f719c7 100644
--- a/arch/riscv/mm/tlbflush.c
+++ b/arch/riscv/mm/tlbflush.c
@@ -110,11 +110,6 @@ static void __ipi_flush_tlb_range_asid(void *info)
 	local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
 }
 
-static inline unsigned long get_mm_asid(struct mm_struct *mm)
-{
-	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
-}
-
 static void __flush_tlb_range(struct mm_struct *mm,
 			      const struct cpumask *cmask,
 			      unsigned long start, unsigned long size,
-- 
2.39.5


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

* [PATCH v2 2/3] riscv: mm: Apply Svinval in update_mmu_cache()
  2026-07-15 13:20 [PATCH v2 0/3] riscv: mm: Some optimizations for tlb flush Xu Lu
  2026-07-15 13:20 ` [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache() Xu Lu
@ 2026-07-15 13:20 ` Xu Lu
  2026-07-15 18:22   ` Klara Modin
  2026-07-17 18:23   ` Samuel Holland
  2026-07-15 13:20 ` [PATCH v2 3/3] riscv: mm: Clear cpu in mm_cpumask after local_flush_tlb_all_asid Xu Lu
  2 siblings, 2 replies; 13+ messages in thread
From: Xu Lu @ 2026-07-15 13:20 UTC (permalink / raw)
  To: paul.walmsley, klarasmodin, palmer, aou, alex
  Cc: linux-riscv, linux-kernel, apw, joe, Xu Lu

Use Svinval in update_mmu_cache_range() when the extension is available.

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
 arch/riscv/include/asm/pgtable.h  |  8 ++++++++
 arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++
 arch/riscv/mm/tlbflush.c          | 18 ------------------
 3 files changed, 26 insertions(+), 18 deletions(-)

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 9926556099ae..823805cc465a 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
 		return;
 
+	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
+		local_sfence_w_inval();
+		while (nr--)
+			local_sinval_vma(address + nr * PAGE_SIZE, asid);
+		local_sfence_inval_ir();
+		return;
+	}
+
 	/*
 	 * The kernel assumes that TLBs don't cache invalid entries, but
 	 * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
index 7c2cd5cc92d3..9636d07fe9ee 100644
--- a/arch/riscv/include/asm/tlbflush.h
+++ b/arch/riscv/include/asm/tlbflush.h
@@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
 	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
 }
 
+static inline void local_sfence_inval_ir(void)
+{
+	asm volatile(SFENCE_INVAL_IR() ::: "memory");
+}
+
+static inline void local_sfence_w_inval(void)
+{
+	asm volatile(SFENCE_W_INVAL() ::: "memory");
+}
+
+static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
+{
+	if (asid != FLUSH_TLB_NO_ASID)
+		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
+	else
+		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
+}
+
 static inline void local_flush_tlb_all(void)
 {
 	__asm__ __volatile__ ("sfence.vma" : : : "memory");
diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
index 73c226f719c7..962db300a166 100644
--- a/arch/riscv/mm/tlbflush.c
+++ b/arch/riscv/mm/tlbflush.c
@@ -11,24 +11,6 @@
 
 #define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
 
-static inline void local_sfence_inval_ir(void)
-{
-	asm volatile(SFENCE_INVAL_IR() ::: "memory");
-}
-
-static inline void local_sfence_w_inval(void)
-{
-	asm volatile(SFENCE_W_INVAL() ::: "memory");
-}
-
-static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
-{
-	if (asid != FLUSH_TLB_NO_ASID)
-		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
-	else
-		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
-}
-
 /*
  * Flush entire TLB if number of entries to be flushed is greater
  * than the threshold below.
-- 
2.39.5


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

* [PATCH v2 3/3] riscv: mm: Clear cpu in mm_cpumask after local_flush_tlb_all_asid
  2026-07-15 13:20 [PATCH v2 0/3] riscv: mm: Some optimizations for tlb flush Xu Lu
  2026-07-15 13:20 ` [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache() Xu Lu
  2026-07-15 13:20 ` [PATCH v2 2/3] riscv: mm: Apply Svinval " Xu Lu
@ 2026-07-15 13:20 ` Xu Lu
  2 siblings, 0 replies; 13+ messages in thread
From: Xu Lu @ 2026-07-15 13:20 UTC (permalink / raw)
  To: paul.walmsley, klarasmodin, palmer, aou, alex
  Cc: linux-riscv, linux-kernel, apw, joe, Xu Lu

Clear corresponding bit of current cpu in mm_cpumask after executing
local_flush_tlb_all_asid().

Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
---
 arch/riscv/mm/tlbflush.c | 41 ++++++++++++++++++++++++----------------
 1 file changed, 25 insertions(+), 16 deletions(-)

diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
index 962db300a166..571358f38587 100644
--- a/arch/riscv/mm/tlbflush.c
+++ b/arch/riscv/mm/tlbflush.c
@@ -17,7 +17,8 @@
  */
 unsigned long tlb_flush_all_threshold __read_mostly = 64;
 
-static void local_flush_tlb_range_threshold_asid(unsigned long start,
+static void local_flush_tlb_range_threshold_asid(struct mm_struct *mm,
+						 unsigned long start,
 						 unsigned long size,
 						 unsigned long stride,
 						 unsigned long asid)
@@ -27,6 +28,8 @@ static void local_flush_tlb_range_threshold_asid(unsigned long start,
 
 	if (nr_ptes_in_range > tlb_flush_all_threshold) {
 		local_flush_tlb_all_asid(asid);
+		if (mm && mm != current->active_mm)
+			cpumask_clear_cpu(raw_smp_processor_id(), mm_cpumask(mm));
 		return;
 	}
 
@@ -46,21 +49,28 @@ static void local_flush_tlb_range_threshold_asid(unsigned long start,
 	}
 }
 
-static inline void local_flush_tlb_range_asid(unsigned long start,
-		unsigned long size, unsigned long stride, unsigned long asid)
+static inline void local_flush_tlb_range_mm(struct mm_struct *mm,
+					    unsigned long start,
+					    unsigned long size,
+					    unsigned long stride)
 {
-	if (size <= stride)
+	unsigned long asid = get_mm_asid(mm);
+
+	if (size <= stride) {
 		local_flush_tlb_page_asid(start, asid);
-	else if (size == FLUSH_TLB_MAX_SIZE)
+	} else if (size == FLUSH_TLB_MAX_SIZE) {
 		local_flush_tlb_all_asid(asid);
-	else
-		local_flush_tlb_range_threshold_asid(start, size, stride, asid);
+		if (mm && mm != current->active_mm)
+			cpumask_clear_cpu(raw_smp_processor_id(), mm_cpumask(mm));
+	} else {
+		local_flush_tlb_range_threshold_asid(mm, start, size, stride, asid);
+	}
 }
 
 /* Flush a range of kernel pages without broadcasting */
 void local_flush_tlb_kernel_range(unsigned long start, unsigned long end)
 {
-	local_flush_tlb_range_asid(start, end - start, PAGE_SIZE, FLUSH_TLB_NO_ASID);
+	local_flush_tlb_range_mm(NULL, start, end - start, PAGE_SIZE);
 }
 
 static void __ipi_flush_tlb_all(void *info)
@@ -79,17 +89,17 @@ void flush_tlb_all(void)
 }
 
 struct flush_tlb_range_data {
-	unsigned long asid;
+	struct mm_struct *mm;
 	unsigned long start;
 	unsigned long size;
 	unsigned long stride;
 };
 
-static void __ipi_flush_tlb_range_asid(void *info)
+static void __ipi_flush_tlb_range_mm(void *info)
 {
 	struct flush_tlb_range_data *d = info;
 
-	local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
+	local_flush_tlb_range_mm(d->mm, d->start, d->size, d->stride);
 }
 
 static void __flush_tlb_range(struct mm_struct *mm,
@@ -97,7 +107,6 @@ static void __flush_tlb_range(struct mm_struct *mm,
 			      unsigned long start, unsigned long size,
 			      unsigned long stride)
 {
-	unsigned long asid = get_mm_asid(mm);
 	unsigned int cpu;
 
 	if (cpumask_empty(cmask))
@@ -107,17 +116,17 @@ static void __flush_tlb_range(struct mm_struct *mm,
 
 	/* Check if the TLB flush needs to be sent to other CPUs. */
 	if (cpumask_any_but(cmask, cpu) >= nr_cpu_ids) {
-		local_flush_tlb_range_asid(start, size, stride, asid);
+		local_flush_tlb_range_mm(mm, start, size, stride);
 	} else if (riscv_use_sbi_for_rfence()) {
-		sbi_remote_sfence_vma_asid(cmask, start, size, asid);
+		sbi_remote_sfence_vma_asid(cmask, start, size, get_mm_asid(mm));
 	} else {
 		struct flush_tlb_range_data ftd;
 
-		ftd.asid = asid;
+		ftd.mm = mm;
 		ftd.start = start;
 		ftd.size = size;
 		ftd.stride = stride;
-		on_each_cpu_mask(cmask, __ipi_flush_tlb_range_asid, &ftd, 1);
+		on_each_cpu_mask(cmask, __ipi_flush_tlb_range_mm, &ftd, 1);
 	}
 
 	put_cpu();
-- 
2.39.5


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

* Re: [PATCH v2 2/3] riscv: mm: Apply Svinval in update_mmu_cache()
  2026-07-15 13:20 ` [PATCH v2 2/3] riscv: mm: Apply Svinval " Xu Lu
@ 2026-07-15 18:22   ` Klara Modin
       [not found]     ` <CGME20260717070900eucas1p11e7d4abd6e0c32fa18fca2940cdcca70@eucas1p1.samsung.com>
  2026-07-17 18:23   ` Samuel Holland
  1 sibling, 1 reply; 13+ messages in thread
From: Klara Modin @ 2026-07-15 18:22 UTC (permalink / raw)
  To: Xu Lu
  Cc: paul.walmsley, palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

On 2026-07-15 21:20:08 +0800, Xu Lu wrote:
> Use Svinval in update_mmu_cache_range() when the extension is available.
> 
> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>

This version works fine for me.

Thanks,
Tested-by: Klara Modin <klarasmodin@gmail.com>

> ---
>  arch/riscv/include/asm/pgtable.h  |  8 ++++++++
>  arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++
>  arch/riscv/mm/tlbflush.c          | 18 ------------------
>  3 files changed, 26 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 9926556099ae..823805cc465a 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>  	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
>  		return;
>  
> +	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
> +		local_sfence_w_inval();
> +		while (nr--)
> +			local_sinval_vma(address + nr * PAGE_SIZE, asid);
> +		local_sfence_inval_ir();
> +		return;
> +	}
> +
>  	/*
>  	 * The kernel assumes that TLBs don't cache invalid entries, but
>  	 * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> index 7c2cd5cc92d3..9636d07fe9ee 100644
> --- a/arch/riscv/include/asm/tlbflush.h
> +++ b/arch/riscv/include/asm/tlbflush.h
> @@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
>  	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
>  }
>  
> +static inline void local_sfence_inval_ir(void)
> +{
> +	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> +}
> +
> +static inline void local_sfence_w_inval(void)
> +{
> +	asm volatile(SFENCE_W_INVAL() ::: "memory");
> +}
> +
> +static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> +{
> +	if (asid != FLUSH_TLB_NO_ASID)
> +		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> +	else
> +		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> +}
> +
>  static inline void local_flush_tlb_all(void)
>  {
>  	__asm__ __volatile__ ("sfence.vma" : : : "memory");
> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> index 73c226f719c7..962db300a166 100644
> --- a/arch/riscv/mm/tlbflush.c
> +++ b/arch/riscv/mm/tlbflush.c
> @@ -11,24 +11,6 @@
>  
>  #define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
>  
> -static inline void local_sfence_inval_ir(void)
> -{
> -	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> -}
> -
> -static inline void local_sfence_w_inval(void)
> -{
> -	asm volatile(SFENCE_W_INVAL() ::: "memory");
> -}
> -
> -static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> -{
> -	if (asid != FLUSH_TLB_NO_ASID)
> -		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> -	else
> -		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> -}
> -
>  /*
>   * Flush entire TLB if number of entries to be flushed is greater
>   * than the threshold below.
> -- 
> 2.39.5
> 

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

* Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-15 13:20 ` [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache() Xu Lu
@ 2026-07-16 16:24   ` Klara Modin
  2026-07-17  2:11     ` [External] " Xu Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Klara Modin @ 2026-07-16 16:24 UTC (permalink / raw)
  To: Xu Lu
  Cc: paul.walmsley, palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

Hi,

On 2026-07-15 21:20:07 +0800, Xu Lu wrote:
> Only flush TLB entries for the specified mm in update_mmu_cache_range().
> 
> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> ---
>  arch/riscv/include/asm/pgtable.h  | 4 +++-
>  arch/riscv/include/asm/tlbflush.h | 5 +++++
>  arch/riscv/mm/tlbflush.c          | 5 -----
>  3 files changed, 8 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 5d5756bda82e..9926556099ae 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>  		struct vm_area_struct *vma, unsigned long address,
>  		pte_t *ptep, unsigned int nr)
>  {
> +	unsigned long asid = get_mm_asid(vma->vm_mm);
> +

It seems the old version of this patch is still used (at least in
next-202650716, 15ce1d7c4ddfe0dff00fcaee4ccaeef3efbc62c6), which means
asid is not initialised here. We instead have:

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 5d5756bda82e..755495a542cc 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 		struct vm_area_struct *vma, unsigned long address,
 		pte_t *ptep, unsigned int nr)
 {
+	unsigned long asid;
+
 	/*
 	 * Svvptc guarantees that the new valid pte will be visible within
 	 * a bounded timeframe, so when the uarch does not cache invalid
@@ -583,10 +585,11 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
 	 * Relying on flush_tlb_fix_spurious_fault would suffice, but
 	 * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
 	 */
+	asid = get_mm_asid(vma->vm_mm);
 	while (nr--)
-		local_flush_tlb_page(address + nr * PAGE_SIZE);
-
+		local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
 }
+
 #define update_mmu_cache(vma, addr, ptep) \
 	update_mmu_cache_range(NULL, vma, addr, ptep, 1)
 

This means that patch 2 of this series will use the uninitialised asid
for local_svinval_vma() and I get the same behaviour as before (hang on
initramfs). If I revert the two patches of this series which are in next
and apply this again it's fine.

Regards,
Klara Modin

>  	/*
>  	 * Svvptc guarantees that the new valid pte will be visible within
>  	 * a bounded timeframe, so when the uarch does not cache invalid
> @@ -584,7 +586,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>  	 * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
>  	 */
>  	while (nr--)
> -		local_flush_tlb_page(address + nr * PAGE_SIZE);
> +		local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
>  
>  }
>  #define update_mmu_cache(vma, addr, ptep) \
> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> index eed0abc40514..7c2cd5cc92d3 100644
> --- a/arch/riscv/include/asm/tlbflush.h
> +++ b/arch/riscv/include/asm/tlbflush.h
> @@ -15,6 +15,11 @@
>  #define FLUSH_TLB_NO_ASID       ((unsigned long)-1)
>  
>  #ifdef CONFIG_MMU
> +static inline unsigned long get_mm_asid(struct mm_struct *mm)
> +{
> +	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> +}
> +
>  static inline void local_flush_tlb_all(void)
>  {
>  	__asm__ __volatile__ ("sfence.vma" : : : "memory");
> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> index 8404530ec00f..73c226f719c7 100644
> --- a/arch/riscv/mm/tlbflush.c
> +++ b/arch/riscv/mm/tlbflush.c
> @@ -110,11 +110,6 @@ static void __ipi_flush_tlb_range_asid(void *info)
>  	local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
>  }
>  
> -static inline unsigned long get_mm_asid(struct mm_struct *mm)
> -{
> -	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> -}
> -
>  static void __flush_tlb_range(struct mm_struct *mm,
>  			      const struct cpumask *cmask,
>  			      unsigned long start, unsigned long size,
> -- 
> 2.39.5
> 

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

* Re: [External] Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-16 16:24   ` Klara Modin
@ 2026-07-17  2:11     ` Xu Lu
  2026-07-17 16:57       ` Xu Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Xu Lu @ 2026-07-17  2:11 UTC (permalink / raw)
  To: Klara Modin
  Cc: paul.walmsley, palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

Hi Paul,

Klara found that linux-next cherry-picks the new version of patch 2
while picking the old version of patch 1, which leads to an
uninitialized asid. Could you please help correct this?

Best regards,
Xu Lu

On Fri, Jul 17, 2026 at 12:25 AM Klara Modin <klarasmodin@gmail.com> wrote:
>
> Hi,
>
> On 2026-07-15 21:20:07 +0800, Xu Lu wrote:
> > Only flush TLB entries for the specified mm in update_mmu_cache_range().
> >
> > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > ---
> >  arch/riscv/include/asm/pgtable.h  | 4 +++-
> >  arch/riscv/include/asm/tlbflush.h | 5 +++++
> >  arch/riscv/mm/tlbflush.c          | 5 -----
> >  3 files changed, 8 insertions(+), 6 deletions(-)
> >
> > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > index 5d5756bda82e..9926556099ae 100644
> > --- a/arch/riscv/include/asm/pgtable.h
> > +++ b/arch/riscv/include/asm/pgtable.h
> > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> >               struct vm_area_struct *vma, unsigned long address,
> >               pte_t *ptep, unsigned int nr)
> >  {
> > +     unsigned long asid = get_mm_asid(vma->vm_mm);
> > +
>
> It seems the old version of this patch is still used (at least in
> next-202650716, 15ce1d7c4ddfe0dff00fcaee4ccaeef3efbc62c6), which means
> asid is not initialised here. We instead have:
>
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 5d5756bda82e..755495a542cc 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>                 struct vm_area_struct *vma, unsigned long address,
>                 pte_t *ptep, unsigned int nr)
>  {
> +       unsigned long asid;
> +
>         /*
>          * Svvptc guarantees that the new valid pte will be visible within
>          * a bounded timeframe, so when the uarch does not cache invalid
> @@ -583,10 +585,11 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>          * Relying on flush_tlb_fix_spurious_fault would suffice, but
>          * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
>          */
> +       asid = get_mm_asid(vma->vm_mm);
>         while (nr--)
> -               local_flush_tlb_page(address + nr * PAGE_SIZE);
> -
> +               local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
>  }
> +
>  #define update_mmu_cache(vma, addr, ptep) \
>         update_mmu_cache_range(NULL, vma, addr, ptep, 1)
>
>
> This means that patch 2 of this series will use the uninitialised asid
> for local_svinval_vma() and I get the same behaviour as before (hang on
> initramfs). If I revert the two patches of this series which are in next
> and apply this again it's fine.
>
> Regards,
> Klara Modin
>
> >       /*
> >        * Svvptc guarantees that the new valid pte will be visible within
> >        * a bounded timeframe, so when the uarch does not cache invalid
> > @@ -584,7 +586,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> >        * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
> >        */
> >       while (nr--)
> > -             local_flush_tlb_page(address + nr * PAGE_SIZE);
> > +             local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
> >
> >  }
> >  #define update_mmu_cache(vma, addr, ptep) \
> > diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> > index eed0abc40514..7c2cd5cc92d3 100644
> > --- a/arch/riscv/include/asm/tlbflush.h
> > +++ b/arch/riscv/include/asm/tlbflush.h
> > @@ -15,6 +15,11 @@
> >  #define FLUSH_TLB_NO_ASID       ((unsigned long)-1)
> >
> >  #ifdef CONFIG_MMU
> > +static inline unsigned long get_mm_asid(struct mm_struct *mm)
> > +{
> > +     return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> > +}
> > +
> >  static inline void local_flush_tlb_all(void)
> >  {
> >       __asm__ __volatile__ ("sfence.vma" : : : "memory");
> > diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> > index 8404530ec00f..73c226f719c7 100644
> > --- a/arch/riscv/mm/tlbflush.c
> > +++ b/arch/riscv/mm/tlbflush.c
> > @@ -110,11 +110,6 @@ static void __ipi_flush_tlb_range_asid(void *info)
> >       local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
> >  }
> >
> > -static inline unsigned long get_mm_asid(struct mm_struct *mm)
> > -{
> > -     return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> > -}
> > -
> >  static void __flush_tlb_range(struct mm_struct *mm,
> >                             const struct cpumask *cmask,
> >                             unsigned long start, unsigned long size,
> > --
> > 2.39.5
> >

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

* Re: [PATCH v2 2/3] riscv: mm: Apply Svinval in update_mmu_cache()
       [not found]     ` <CGME20260717070900eucas1p11e7d4abd6e0c32fa18fca2940cdcca70@eucas1p1.samsung.com>
@ 2026-07-17  7:08       ` Marek Szyprowski
  2026-07-17  8:02         ` Klara Modin
  0 siblings, 1 reply; 13+ messages in thread
From: Marek Szyprowski @ 2026-07-17  7:08 UTC (permalink / raw)
  To: Klara Modin, Xu Lu
  Cc: paul.walmsley, palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

On 15.07.2026 20:22, Klara Modin wrote:
> On 2026-07-15 21:20:08 +0800, Xu Lu wrote:
>> Use Svinval in update_mmu_cache_range() when the extension is available.
>>
>> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> This version works fine for me.

Lucky You! Here BPiF3 gets frozen once userspace has started.


> Thanks,
> Tested-by: Klara Modin <klarasmodin@gmail.com>
>
>> ---
>>  arch/riscv/include/asm/pgtable.h  |  8 ++++++++
>>  arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++
>>  arch/riscv/mm/tlbflush.c          | 18 ------------------
>>  3 files changed, 26 insertions(+), 18 deletions(-)
>>
>> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
>> index 9926556099ae..823805cc465a 100644
>> --- a/arch/riscv/include/asm/pgtable.h
>> +++ b/arch/riscv/include/asm/pgtable.h
>> @@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>>  	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
>>  		return;
>>  
>> +	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
>> +		local_sfence_w_inval();
>> +		while (nr--)
>> +			local_sinval_vma(address + nr * PAGE_SIZE, asid);

'asid' is not initialized here. The following fixup is needed:

diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 3c17ad0786ab..e283649e1dee 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -570,32 +570,32 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
        /*
         * Svvptc guarantees that the new valid pte will be visible within
         * a bounded timeframe, so when the uarch does not cache invalid
         * entries, we don't have to do anything.
         */
        if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
                return;

+       asid = get_mm_asid(vma->vm_mm);
        if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
                local_sfence_w_inval();
                while (nr--)
                        local_sinval_vma(address + nr * PAGE_SIZE, asid);
                local_sfence_inval_ir();
                return;
        }

        /*
         * The kernel assumes that TLBs don't cache invalid entries, but
         * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
         * cache flush; it is necessary even after writing invalid entries.
         * Relying on flush_tlb_fix_spurious_fault would suffice, but
         * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
         */
-       asid = get_mm_asid(vma->vm_mm);
        while (nr--)
                local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
 }

 #define update_mmu_cache(vma, addr, ptep) \
        update_mmu_cache_range(NULL, vma, addr, ptep, 1)

 #define update_mmu_tlb_range(vma, addr, ptep, nr) \



>> +		local_sfence_inval_ir();
>> +		return;
>> +	}
>> +
>>  	/*
>>  	 * The kernel assumes that TLBs don't cache invalid entries, but
>>  	 * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
>> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
>> index 7c2cd5cc92d3..9636d07fe9ee 100644
>> --- a/arch/riscv/include/asm/tlbflush.h
>> +++ b/arch/riscv/include/asm/tlbflush.h
>> @@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
>>  	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
>>  }
>>  
>> +static inline void local_sfence_inval_ir(void)
>> +{
>> +	asm volatile(SFENCE_INVAL_IR() ::: "memory");
>> +}
>> +
>> +static inline void local_sfence_w_inval(void)
>> +{
>> +	asm volatile(SFENCE_W_INVAL() ::: "memory");
>> +}
>> +
>> +static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
>> +{
>> +	if (asid != FLUSH_TLB_NO_ASID)
>> +		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
>> +	else
>> +		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
>> +}
>> +
>>  static inline void local_flush_tlb_all(void)
>>  {
>>  	__asm__ __volatile__ ("sfence.vma" : : : "memory");
>> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
>> index 73c226f719c7..962db300a166 100644
>> --- a/arch/riscv/mm/tlbflush.c
>> +++ b/arch/riscv/mm/tlbflush.c
>> @@ -11,24 +11,6 @@
>>  
>>  #define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
>>  
>> -static inline void local_sfence_inval_ir(void)
>> -{
>> -	asm volatile(SFENCE_INVAL_IR() ::: "memory");
>> -}
>> -
>> -static inline void local_sfence_w_inval(void)
>> -{
>> -	asm volatile(SFENCE_W_INVAL() ::: "memory");
>> -}
>> -
>> -static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
>> -{
>> -	if (asid != FLUSH_TLB_NO_ASID)
>> -		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
>> -	else
>> -		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
>> -}
>> -
>>  /*
>>   * Flush entire TLB if number of entries to be flushed is greater
>>   * than the threshold below.
>> -- 
>> 2.39.5
>>
Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland


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

* Re: [PATCH v2 2/3] riscv: mm: Apply Svinval in update_mmu_cache()
  2026-07-17  7:08       ` Marek Szyprowski
@ 2026-07-17  8:02         ` Klara Modin
  0 siblings, 0 replies; 13+ messages in thread
From: Klara Modin @ 2026-07-17  8:02 UTC (permalink / raw)
  To: Marek Szyprowski
  Cc: Xu Lu, paul.walmsley, palmer, aou, alex, linux-riscv,
	linux-kernel, apw, joe

On 2026-07-17 09:08:59 +0200, Marek Szyprowski wrote:
> On 15.07.2026 20:22, Klara Modin wrote:
> > On 2026-07-15 21:20:08 +0800, Xu Lu wrote:
> >> Use Svinval in update_mmu_cache_range() when the extension is available.
> >>
> >> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > This version works fine for me.
> 
> Lucky You! Here BPiF3 gets frozen once userspace has started.

The old version of patch 1 of the series was used when the series was
applied for next, whereas I reverted the old series and applied the
entirety of the second version when I tested. I commented this on patch
1.

Regards,
Klara Modin

> 
> 
> > Thanks,
> > Tested-by: Klara Modin <klarasmodin@gmail.com>
> >
> >> ---
> >>  arch/riscv/include/asm/pgtable.h  |  8 ++++++++
> >>  arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++
> >>  arch/riscv/mm/tlbflush.c          | 18 ------------------
> >>  3 files changed, 26 insertions(+), 18 deletions(-)
> >>
> >> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> >> index 9926556099ae..823805cc465a 100644
> >> --- a/arch/riscv/include/asm/pgtable.h
> >> +++ b/arch/riscv/include/asm/pgtable.h
> >> @@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> >>  	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
> >>  		return;
> >>  
> >> +	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
> >> +		local_sfence_w_inval();
> >> +		while (nr--)
> >> +			local_sinval_vma(address + nr * PAGE_SIZE, asid);
> 
> 'asid' is not initialized here. The following fixup is needed:
> 
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 3c17ad0786ab..e283649e1dee 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -570,32 +570,32 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>         /*
>          * Svvptc guarantees that the new valid pte will be visible within
>          * a bounded timeframe, so when the uarch does not cache invalid
>          * entries, we don't have to do anything.
>          */
>         if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
>                 return;
> 
> +       asid = get_mm_asid(vma->vm_mm);
>         if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
>                 local_sfence_w_inval();
>                 while (nr--)
>                         local_sinval_vma(address + nr * PAGE_SIZE, asid);
>                 local_sfence_inval_ir();
>                 return;
>         }
> 
>         /*
>          * The kernel assumes that TLBs don't cache invalid entries, but
>          * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
>          * cache flush; it is necessary even after writing invalid entries.
>          * Relying on flush_tlb_fix_spurious_fault would suffice, but
>          * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
>          */
> -       asid = get_mm_asid(vma->vm_mm);
>         while (nr--)
>                 local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
>  }
> 
>  #define update_mmu_cache(vma, addr, ptep) \
>         update_mmu_cache_range(NULL, vma, addr, ptep, 1)
> 
>  #define update_mmu_tlb_range(vma, addr, ptep, nr) \
> 
> 
> 
> >> +		local_sfence_inval_ir();
> >> +		return;
> >> +	}
> >> +
> >>  	/*
> >>  	 * The kernel assumes that TLBs don't cache invalid entries, but
> >>  	 * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
> >> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> >> index 7c2cd5cc92d3..9636d07fe9ee 100644
> >> --- a/arch/riscv/include/asm/tlbflush.h
> >> +++ b/arch/riscv/include/asm/tlbflush.h
> >> @@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
> >>  	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> >>  }
> >>  
> >> +static inline void local_sfence_inval_ir(void)
> >> +{
> >> +	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> >> +}
> >> +
> >> +static inline void local_sfence_w_inval(void)
> >> +{
> >> +	asm volatile(SFENCE_W_INVAL() ::: "memory");
> >> +}
> >> +
> >> +static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> >> +{
> >> +	if (asid != FLUSH_TLB_NO_ASID)
> >> +		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> >> +	else
> >> +		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> >> +}
> >> +
> >>  static inline void local_flush_tlb_all(void)
> >>  {
> >>  	__asm__ __volatile__ ("sfence.vma" : : : "memory");
> >> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> >> index 73c226f719c7..962db300a166 100644
> >> --- a/arch/riscv/mm/tlbflush.c
> >> +++ b/arch/riscv/mm/tlbflush.c
> >> @@ -11,24 +11,6 @@
> >>  
> >>  #define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
> >>  
> >> -static inline void local_sfence_inval_ir(void)
> >> -{
> >> -	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> >> -}
> >> -
> >> -static inline void local_sfence_w_inval(void)
> >> -{
> >> -	asm volatile(SFENCE_W_INVAL() ::: "memory");
> >> -}
> >> -
> >> -static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> >> -{
> >> -	if (asid != FLUSH_TLB_NO_ASID)
> >> -		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> >> -	else
> >> -		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> >> -}
> >> -
> >>  /*
> >>   * Flush entire TLB if number of entries to be flushed is greater
> >>   * than the threshold below.
> >> -- 
> >> 2.39.5
> >>
> Best regards
> -- 
> Marek Szyprowski, PhD
> Samsung R&D Institute Poland
> 

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

* Re: [External] Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-17  2:11     ` [External] " Xu Lu
@ 2026-07-17 16:57       ` Xu Lu
  2026-07-17 17:14         ` Klara Modin
  0 siblings, 1 reply; 13+ messages in thread
From: Xu Lu @ 2026-07-17 16:57 UTC (permalink / raw)
  To: Klara Modin, Paul Walmsley, Paul Walmsley
  Cc: palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

Hi Paul,

A gentle ping.

I have no idea what I can do regarding linux-next. Could you please
help revert the patch from version 1 and cherry-pick all the patches
from version 2 instead? Or what can I do for this?

Best regards,
Xu Lu

On Fri, Jul 17, 2026 at 10:11 AM Xu Lu <luxu.kernel@bytedance.com> wrote:
>
> Hi Paul,
>
> Klara found that linux-next cherry-picks the new version of patch 2
> while picking the old version of patch 1, which leads to an
> uninitialized asid. Could you please help correct this?
>
> Best regards,
> Xu Lu
>
> On Fri, Jul 17, 2026 at 12:25 AM Klara Modin <klarasmodin@gmail.com> wrote:
> >
> > Hi,
> >
> > On 2026-07-15 21:20:07 +0800, Xu Lu wrote:
> > > Only flush TLB entries for the specified mm in update_mmu_cache_range().
> > >
> > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > ---
> > >  arch/riscv/include/asm/pgtable.h  | 4 +++-
> > >  arch/riscv/include/asm/tlbflush.h | 5 +++++
> > >  arch/riscv/mm/tlbflush.c          | 5 -----
> > >  3 files changed, 8 insertions(+), 6 deletions(-)
> > >
> > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > index 5d5756bda82e..9926556099ae 100644
> > > --- a/arch/riscv/include/asm/pgtable.h
> > > +++ b/arch/riscv/include/asm/pgtable.h
> > > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > >               struct vm_area_struct *vma, unsigned long address,
> > >               pte_t *ptep, unsigned int nr)
> > >  {
> > > +     unsigned long asid = get_mm_asid(vma->vm_mm);
> > > +
> >
> > It seems the old version of this patch is still used (at least in
> > next-202650716, 15ce1d7c4ddfe0dff00fcaee4ccaeef3efbc62c6), which means
> > asid is not initialised here. We instead have:
> >
> > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > index 5d5756bda82e..755495a542cc 100644
> > --- a/arch/riscv/include/asm/pgtable.h
> > +++ b/arch/riscv/include/asm/pgtable.h
> > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> >                 struct vm_area_struct *vma, unsigned long address,
> >                 pte_t *ptep, unsigned int nr)
> >  {
> > +       unsigned long asid;
> > +
> >         /*
> >          * Svvptc guarantees that the new valid pte will be visible within
> >          * a bounded timeframe, so when the uarch does not cache invalid
> > @@ -583,10 +585,11 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> >          * Relying on flush_tlb_fix_spurious_fault would suffice, but
> >          * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
> >          */
> > +       asid = get_mm_asid(vma->vm_mm);
> >         while (nr--)
> > -               local_flush_tlb_page(address + nr * PAGE_SIZE);
> > -
> > +               local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
> >  }
> > +
> >  #define update_mmu_cache(vma, addr, ptep) \
> >         update_mmu_cache_range(NULL, vma, addr, ptep, 1)
> >
> >
> > This means that patch 2 of this series will use the uninitialised asid
> > for local_svinval_vma() and I get the same behaviour as before (hang on
> > initramfs). If I revert the two patches of this series which are in next
> > and apply this again it's fine.
> >
> > Regards,
> > Klara Modin
> >
> > >       /*
> > >        * Svvptc guarantees that the new valid pte will be visible within
> > >        * a bounded timeframe, so when the uarch does not cache invalid
> > > @@ -584,7 +586,7 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > >        * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
> > >        */
> > >       while (nr--)
> > > -             local_flush_tlb_page(address + nr * PAGE_SIZE);
> > > +             local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
> > >
> > >  }
> > >  #define update_mmu_cache(vma, addr, ptep) \
> > > diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> > > index eed0abc40514..7c2cd5cc92d3 100644
> > > --- a/arch/riscv/include/asm/tlbflush.h
> > > +++ b/arch/riscv/include/asm/tlbflush.h
> > > @@ -15,6 +15,11 @@
> > >  #define FLUSH_TLB_NO_ASID       ((unsigned long)-1)
> > >
> > >  #ifdef CONFIG_MMU
> > > +static inline unsigned long get_mm_asid(struct mm_struct *mm)
> > > +{
> > > +     return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> > > +}
> > > +
> > >  static inline void local_flush_tlb_all(void)
> > >  {
> > >       __asm__ __volatile__ ("sfence.vma" : : : "memory");
> > > diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> > > index 8404530ec00f..73c226f719c7 100644
> > > --- a/arch/riscv/mm/tlbflush.c
> > > +++ b/arch/riscv/mm/tlbflush.c
> > > @@ -110,11 +110,6 @@ static void __ipi_flush_tlb_range_asid(void *info)
> > >       local_flush_tlb_range_asid(d->start, d->size, d->stride, d->asid);
> > >  }
> > >
> > > -static inline unsigned long get_mm_asid(struct mm_struct *mm)
> > > -{
> > > -     return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
> > > -}
> > > -
> > >  static void __flush_tlb_range(struct mm_struct *mm,
> > >                             const struct cpumask *cmask,
> > >                             unsigned long start, unsigned long size,
> > > --
> > > 2.39.5
> > >

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

* Re: [External] Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-17 16:57       ` Xu Lu
@ 2026-07-17 17:14         ` Klara Modin
  2026-07-17 17:19           ` Xu Lu
  0 siblings, 1 reply; 13+ messages in thread
From: Klara Modin @ 2026-07-17 17:14 UTC (permalink / raw)
  To: Xu Lu
  Cc: Paul Walmsley, Paul Walmsley, palmer, aou, alex, linux-riscv,
	linux-kernel, apw, joe

On 2026-07-18 00:57:06 +0800, Xu Lu wrote:
> Hi Paul,
> 
> A gentle ping.
> 
> I have no idea what I can do regarding linux-next. Could you please
> help revert the patch from version 1 and cherry-pick all the patches
> from version 2 instead? Or what can I do for this?

Paul has updated the for-next branch at
git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git so it should
sort itself out to either today's or monday's next version (depending on
if the tree has already been pulled or not). Even if it is not pulled
until monday I think it will be fine, this is what linux-next is for
after all.

Regards,
Klara Modin

> 
> Best regards,
> Xu Lu
> 
> On Fri, Jul 17, 2026 at 10:11 AM Xu Lu <luxu.kernel@bytedance.com> wrote:
> >
> > Hi Paul,
> >
> > Klara found that linux-next cherry-picks the new version of patch 2
> > while picking the old version of patch 1, which leads to an
> > uninitialized asid. Could you please help correct this?
> >
> > Best regards,
> > Xu Lu
> >
> > On Fri, Jul 17, 2026 at 12:25 AM Klara Modin <klarasmodin@gmail.com> wrote:
> > >
> > > Hi,
> > >
> > > On 2026-07-15 21:20:07 +0800, Xu Lu wrote:
> > > > Only flush TLB entries for the specified mm in update_mmu_cache_range().
> > > >
> > > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > > ---
> > > >  arch/riscv/include/asm/pgtable.h  | 4 +++-
> > > >  arch/riscv/include/asm/tlbflush.h | 5 +++++
> > > >  arch/riscv/mm/tlbflush.c          | 5 -----
> > > >  3 files changed, 8 insertions(+), 6 deletions(-)
> > > >
> > > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > > index 5d5756bda82e..9926556099ae 100644
> > > > --- a/arch/riscv/include/asm/pgtable.h
> > > > +++ b/arch/riscv/include/asm/pgtable.h
> > > > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > > >               struct vm_area_struct *vma, unsigned long address,
> > > >               pte_t *ptep, unsigned int nr)
> > > >  {
> > > > +     unsigned long asid = get_mm_asid(vma->vm_mm);
> > > > +
> > >
> > > It seems the old version of this patch is still used (at least in
> > > next-202650716, 15ce1d7c4ddfe0dff00fcaee4ccaeef3efbc62c6), which means
> > > asid is not initialised here. We instead have:
> > >
> > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > index 5d5756bda82e..755495a542cc 100644
> > > --- a/arch/riscv/include/asm/pgtable.h
> > > +++ b/arch/riscv/include/asm/pgtable.h
> > > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > >                 struct vm_area_struct *vma, unsigned long address,
> > >                 pte_t *ptep, unsigned int nr)
> > >  {
> > > +       unsigned long asid;
> > > +
> > >         /*
> > >          * Svvptc guarantees that the new valid pte will be visible within
> > >          * a bounded timeframe, so when the uarch does not cache invalid
> > > @@ -583,10 +585,11 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > >          * Relying on flush_tlb_fix_spurious_fault would suffice, but
> > >          * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
> > >          */
> > > +       asid = get_mm_asid(vma->vm_mm);
> > >         while (nr--)
> > > -               local_flush_tlb_page(address + nr * PAGE_SIZE);
> > > -
> > > +               local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
> > >  }
> > > +
> > >  #define update_mmu_cache(vma, addr, ptep) \
> > >         update_mmu_cache_range(NULL, vma, addr, ptep, 1)
> > >
> > >
> > > This means that patch 2 of this series will use the uninitialised asid
> > > for local_svinval_vma() and I get the same behaviour as before (hang on
> > > initramfs). If I revert the two patches of this series which are in next
> > > and apply this again it's fine.
> > >
> > > Regards,
> > > Klara Modin

...

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

* Re: [External] Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
  2026-07-17 17:14         ` Klara Modin
@ 2026-07-17 17:19           ` Xu Lu
  0 siblings, 0 replies; 13+ messages in thread
From: Xu Lu @ 2026-07-17 17:19 UTC (permalink / raw)
  To: Klara Modin, Paul Walmsley
  Cc: Paul Walmsley, palmer, aou, alex, linux-riscv, linux-kernel, apw, joe

Thanks, Klara. Thanks, Paul.

Best regards,
Xu Lu

On Sat, Jul 18, 2026 at 1:15 AM Klara Modin <klarasmodin@gmail.com> wrote:
>
> On 2026-07-18 00:57:06 +0800, Xu Lu wrote:
> > Hi Paul,
> >
> > A gentle ping.
> >
> > I have no idea what I can do regarding linux-next. Could you please
> > help revert the patch from version 1 and cherry-pick all the patches
> > from version 2 instead? Or what can I do for this?
>
> Paul has updated the for-next branch at
> git.kernel.org/pub/scm/linux/kernel/git/riscv/linux.git so it should
> sort itself out to either today's or monday's next version (depending on
> if the tree has already been pulled or not). Even if it is not pulled
> until monday I think it will be fine, this is what linux-next is for
> after all.
>
> Regards,
> Klara Modin
>
> >
> > Best regards,
> > Xu Lu
> >
> > On Fri, Jul 17, 2026 at 10:11 AM Xu Lu <luxu.kernel@bytedance.com> wrote:
> > >
> > > Hi Paul,
> > >
> > > Klara found that linux-next cherry-picks the new version of patch 2
> > > while picking the old version of patch 1, which leads to an
> > > uninitialized asid. Could you please help correct this?
> > >
> > > Best regards,
> > > Xu Lu
> > >
> > > On Fri, Jul 17, 2026 at 12:25 AM Klara Modin <klarasmodin@gmail.com> wrote:
> > > >
> > > > Hi,
> > > >
> > > > On 2026-07-15 21:20:07 +0800, Xu Lu wrote:
> > > > > Only flush TLB entries for the specified mm in update_mmu_cache_range().
> > > > >
> > > > > Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> > > > > ---
> > > > >  arch/riscv/include/asm/pgtable.h  | 4 +++-
> > > > >  arch/riscv/include/asm/tlbflush.h | 5 +++++
> > > > >  arch/riscv/mm/tlbflush.c          | 5 -----
> > > > >  3 files changed, 8 insertions(+), 6 deletions(-)
> > > > >
> > > > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > > > index 5d5756bda82e..9926556099ae 100644
> > > > > --- a/arch/riscv/include/asm/pgtable.h
> > > > > +++ b/arch/riscv/include/asm/pgtable.h
> > > > > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > > > >               struct vm_area_struct *vma, unsigned long address,
> > > > >               pte_t *ptep, unsigned int nr)
> > > > >  {
> > > > > +     unsigned long asid = get_mm_asid(vma->vm_mm);
> > > > > +
> > > >
> > > > It seems the old version of this patch is still used (at least in
> > > > next-202650716, 15ce1d7c4ddfe0dff00fcaee4ccaeef3efbc62c6), which means
> > > > asid is not initialised here. We instead have:
> > > >
> > > > diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> > > > index 5d5756bda82e..755495a542cc 100644
> > > > --- a/arch/riscv/include/asm/pgtable.h
> > > > +++ b/arch/riscv/include/asm/pgtable.h
> > > > @@ -568,6 +568,8 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > > >                 struct vm_area_struct *vma, unsigned long address,
> > > >                 pte_t *ptep, unsigned int nr)
> > > >  {
> > > > +       unsigned long asid;
> > > > +
> > > >         /*
> > > >          * Svvptc guarantees that the new valid pte will be visible within
> > > >          * a bounded timeframe, so when the uarch does not cache invalid
> > > > @@ -583,10 +585,11 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
> > > >          * Relying on flush_tlb_fix_spurious_fault would suffice, but
> > > >          * the extra traps reduce performance.  So, eagerly SFENCE.VMA.
> > > >          */
> > > > +       asid = get_mm_asid(vma->vm_mm);
> > > >         while (nr--)
> > > > -               local_flush_tlb_page(address + nr * PAGE_SIZE);
> > > > -
> > > > +               local_flush_tlb_page_asid(address + nr * PAGE_SIZE, asid);
> > > >  }
> > > > +
> > > >  #define update_mmu_cache(vma, addr, ptep) \
> > > >         update_mmu_cache_range(NULL, vma, addr, ptep, 1)
> > > >
> > > >
> > > > This means that patch 2 of this series will use the uninitialised asid
> > > > for local_svinval_vma() and I get the same behaviour as before (hang on
> > > > initramfs). If I revert the two patches of this series which are in next
> > > > and apply this again it's fine.
> > > >
> > > > Regards,
> > > > Klara Modin
>
> ...

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

* Re: [PATCH v2 2/3] riscv: mm: Apply Svinval in update_mmu_cache()
  2026-07-15 13:20 ` [PATCH v2 2/3] riscv: mm: Apply Svinval " Xu Lu
  2026-07-15 18:22   ` Klara Modin
@ 2026-07-17 18:23   ` Samuel Holland
  1 sibling, 0 replies; 13+ messages in thread
From: Samuel Holland @ 2026-07-17 18:23 UTC (permalink / raw)
  To: Xu Lu, paul.walmsley, klarasmodin, palmer, aou, alex
  Cc: linux-riscv, linux-kernel, apw, joe

Hi Xu Lu,

On 2026-07-15 8:20 AM, Xu Lu wrote:
> Use Svinval in update_mmu_cache_range() when the extension is available.
> 
> Signed-off-by: Xu Lu <luxu.kernel@bytedance.com>
> ---
>  arch/riscv/include/asm/pgtable.h  |  8 ++++++++
>  arch/riscv/include/asm/tlbflush.h | 18 ++++++++++++++++++
>  arch/riscv/mm/tlbflush.c          | 18 ------------------
>  3 files changed, 26 insertions(+), 18 deletions(-)
> 
> diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
> index 9926556099ae..823805cc465a 100644
> --- a/arch/riscv/include/asm/pgtable.h
> +++ b/arch/riscv/include/asm/pgtable.h
> @@ -578,6 +578,14 @@ static inline void update_mmu_cache_range(struct vm_fault *vmf,
>  	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVVPTC))
>  		return;
>  
> +	if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)) {
> +		local_sfence_w_inval();
> +		while (nr--)
> +			local_sinval_vma(address + nr * PAGE_SIZE, asid);
> +		local_sfence_inval_ir();
> +		return;
> +	}
> +

This duplicates the logic in local_flush_tlb_range_threshold_asid(). If you
exported local_flush_tlb_range_mm(), you could use that here without rearranging
any of the other functions, and it also be able to reuse the threshold logic,
which is important on platforms that set local_flush_tlb_range_mm = 1 to always
do full-address-space flushes.

Regards,
Samuel

>  	/*
>  	 * The kernel assumes that TLBs don't cache invalid entries, but
>  	 * in RISC-V, SFENCE.VMA specifies an ordering constraint, not a
> diff --git a/arch/riscv/include/asm/tlbflush.h b/arch/riscv/include/asm/tlbflush.h
> index 7c2cd5cc92d3..9636d07fe9ee 100644
> --- a/arch/riscv/include/asm/tlbflush.h
> +++ b/arch/riscv/include/asm/tlbflush.h
> @@ -20,6 +20,24 @@ static inline unsigned long get_mm_asid(struct mm_struct *mm)
>  	return mm ? cntx2asid(atomic_long_read(&mm->context.id)) : FLUSH_TLB_NO_ASID;
>  }
>  
> +static inline void local_sfence_inval_ir(void)
> +{
> +	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> +}
> +
> +static inline void local_sfence_w_inval(void)
> +{
> +	asm volatile(SFENCE_W_INVAL() ::: "memory");
> +}
> +
> +static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> +{
> +	if (asid != FLUSH_TLB_NO_ASID)
> +		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> +	else
> +		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> +}
> +
>  static inline void local_flush_tlb_all(void)
>  {
>  	__asm__ __volatile__ ("sfence.vma" : : : "memory");
> diff --git a/arch/riscv/mm/tlbflush.c b/arch/riscv/mm/tlbflush.c
> index 73c226f719c7..962db300a166 100644
> --- a/arch/riscv/mm/tlbflush.c
> +++ b/arch/riscv/mm/tlbflush.c
> @@ -11,24 +11,6 @@
>  
>  #define has_svinval()	riscv_has_extension_unlikely(RISCV_ISA_EXT_SVINVAL)
>  
> -static inline void local_sfence_inval_ir(void)
> -{
> -	asm volatile(SFENCE_INVAL_IR() ::: "memory");
> -}
> -
> -static inline void local_sfence_w_inval(void)
> -{
> -	asm volatile(SFENCE_W_INVAL() ::: "memory");
> -}
> -
> -static inline void local_sinval_vma(unsigned long vma, unsigned long asid)
> -{
> -	if (asid != FLUSH_TLB_NO_ASID)
> -		asm volatile(SINVAL_VMA(%0, %1) : : "r" (vma), "r" (asid) : "memory");
> -	else
> -		asm volatile(SINVAL_VMA(%0, zero) : : "r" (vma) : "memory");
> -}
> -
>  /*
>   * Flush entire TLB if number of entries to be flushed is greater
>   * than the threshold below.


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

end of thread, other threads:[~2026-07-17 18:23 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-07-15 13:20 [PATCH v2 0/3] riscv: mm: Some optimizations for tlb flush Xu Lu
2026-07-15 13:20 ` [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache() Xu Lu
2026-07-16 16:24   ` Klara Modin
2026-07-17  2:11     ` [External] " Xu Lu
2026-07-17 16:57       ` Xu Lu
2026-07-17 17:14         ` Klara Modin
2026-07-17 17:19           ` Xu Lu
2026-07-15 13:20 ` [PATCH v2 2/3] riscv: mm: Apply Svinval " Xu Lu
2026-07-15 18:22   ` Klara Modin
     [not found]     ` <CGME20260717070900eucas1p11e7d4abd6e0c32fa18fca2940cdcca70@eucas1p1.samsung.com>
2026-07-17  7:08       ` Marek Szyprowski
2026-07-17  8:02         ` Klara Modin
2026-07-17 18:23   ` Samuel Holland
2026-07-15 13:20 ` [PATCH v2 3/3] riscv: mm: Clear cpu in mm_cpumask after local_flush_tlb_all_asid Xu Lu

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

Powered by JetHome