[PATCH 2/2] arm64: tlbflush: Reset active_cpu on ASID rollover

Catalin Marinas catalin.marinas at arm.com
Thu Jun 11 08:37:07 PDT 2026


On Tue, Jun 09, 2026 at 02:34:33PM -0700, sk at gentwo.org wrote:
> From: Sayali Kulkarni <sskulkarni at amperecomputing.com>
> 
> Once active_cpu flips to ACTIVE_CPU_MULTIPLE, it never resets, even if
> the process settles back to one CPU. Reset it to ACTIVE_CPU_NONE when
> a new ASID is assigned after rollover, since flush_context() already
> issued a global TLB flush at that point meaning no stale TLB entries
> exist on any CPU.
> 
> This gives processes a fresh chance at the local-only flush fast path
> after each ASID generation rollover.

flush_context() does not invalidate any TLBs, just marks the in a bitmap
which CPUs need to flush, locally, on the next context switch.

Check Sashiko's comments, it has some good points (you can ignore the
comments on the first patch as we no longer rely on DVM for SVA.

https://sashiko.dev/#/patchset/20260609213615.2788698-1-sk@gentwo.org

> Signed-off-by: Sayali Kulkarni <sskulkarni at amperecomputing.com>
> ---
>  arch/arm64/mm/context.c | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
> index f34ed78393e0..0c92cc8fb4cd 100644
> --- a/arch/arm64/mm/context.c
> +++ b/arch/arm64/mm/context.c
> @@ -250,6 +250,7 @@ void check_and_switch_context(struct mm_struct *mm)
>  	if (!asid_gen_match(asid)) {
>  		asid = new_context(mm);
>  		atomic64_set(&mm->context.id, asid);
> +		WRITE_ONCE(mm->context.active_cpu, ACTIVE_CPU_NONE);
>  	}

This breaks the case where you have another thread of the current
process running on a different CPU. new_context(mm) will reuse the
current ASID, just bump the generation, so setting active_cpu to
ACTIVE_CPU_NONE is incorrect.

A better place for this would be in new_context() after the "set_asid"
label.

>  	if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
> @@ -321,6 +322,7 @@ unsigned long arm64_mm_context_get(struct mm_struct *mm)
>  		 */
>  		asid = new_context(mm);
>  		atomic64_set(&mm->context.id, asid);
> +		WRITE_ONCE(mm->context.active_cpu, ACTIVE_CPU_NONE);
>  	}

And it would cover this path as well (not that this function is used
currently).

-- 
Catalin



More information about the linux-arm-kernel mailing list