[PATCH 03/20] arm64/fpsimd: signal: Clear PSTATE.SM when restoring FPSIMD frame only

Will Deacon will at kernel.org
Wed May 7 07:39:01 PDT 2025


On Wed, May 07, 2025 at 03:01:50PM +0100, Mark Rutland wrote:
> On Wed, May 07, 2025 at 01:46:45PM +0100, Will Deacon wrote:
> > On Tue, May 06, 2025 at 04:25:06PM +0100, Mark Rutland wrote:
> > > diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
> > > index 48d3c0129dade..fdce1b856f498 100644
> > > --- a/arch/arm64/kernel/signal.c
> > > +++ b/arch/arm64/kernel/signal.c
> > > @@ -280,6 +280,7 @@ static int restore_fpsimd_context(struct user_ctxs *user)
> > >  	__get_user_error(fpsimd.fpcr, &(user->fpsimd->fpcr), err);
> > >  
> > >  	clear_thread_flag(TIF_SVE);
> > > +	current->thread.svcr &= ~SVCR_SM_MASK;
> > >  	current->thread.fp_type = FP_STATE_FPSIMD;
> > 
> > Hmm, I think we're preemptible here so do we need some compiler barriers
> > to make sure that the context-switching code doesn't see these fields in
> > an inconsistent state?
> 
> We avoid that problem by ensuring that the task's FPSIMD/SVE/SME state isn't
> live on any CPU for the duration of the signal code, such that it is safe to
> manipulate the saved state in preemptible context. Details below.
> 
> That was handled in one of the earlier patches in the arm64 for-next/sme-fixes
> branch, queded as commit:
> 
>   929fa99b1215966f ("arm64/fpsimd: signal: Always save+flush state early")
> 
> As of that commit, in setup_rt_frame() we call
> fpsimd_save_and_flush_current_state(), which does:
> 
>   get_cpu_fpsimd_context();
>   fpsimd_save_user_state();
>   fpsimd_flush_task_state(current);
>   put_cpu_fpsimd_context();
> 
> That ensures (in a premption-safe way) that the tasks state has been saved
> to memory, TIF_FOREIGN_FPSTATE is set, and that
> task->thread.fpsimd_cpu==NR_CPUS. Thus on context switch:
> 
> * When switching away from this task, fpsimd_thread_switch() sees
>   TIF_FOREIGN_FPSTATE is set, and doesn't manipulate the task's saved state.
> 
> * When switching to this task, fpsimd_thread_switch() doesn't find any existing
>   state bound on the CPU, and sets TIF_FOREIGN_FPSTATE, without manipulating
>   the task's saved state.
> 
> The task's state will only be relaoded onto the CPU when returning to
> userspace, via fpsimd_restore_current_state().
> 
> Note that we changed fpsimd_update_current_state() to modify the saved state
> without reloading it onto the CPU.

Thanks, that makes sense!

Will



More information about the linux-arm-kernel mailing list