Re: [External] Re: [PATCH v2 1/3] riscv: mm: Use ASID in update_mmu_cache()
From: Xu Lu
Date: Thu Jul 16 2026 - 22:12:15 EST
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@xxxxxxxxx> 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@xxxxxxxxxxxxx>
> > ---
> > 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
> >