]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
arm64/fpsimd: signal: Use SMSTOP behaviour in setup_return()
authorMark Rutland <mark.rutland@arm.com>
Thu, 8 May 2025 13:26:29 +0000 (14:26 +0100)
committerWill Deacon <will@kernel.org>
Thu, 8 May 2025 14:29:09 +0000 (15:29 +0100)
Historically the behaviour of setup_return() was nondeterministic,
depending on whether the task's FSIMD/SVE/SME state happened to be live.
We fixed most of that in commit:

  929fa99b1215 ("arm64/fpsimd: signal: Always save+flush state early")

... but we didn't decide on how clearing PSTATE.SM should behave, and left a
TODO comment to that effect.

Use the new task_smstop_sm() helper to make this behave as if an SMSTOP
instruction was used to exit streaming mode. This would have been the
most common behaviour prior to the commit above.

Fixes: 40a8e87bb328 ("arm64/sme: Disable ZA and streaming mode when handling signals")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Mark Brown <broonie@kernel.org>
Cc: Will Deacon <will@kernel.org>
Link: https://lore.kernel.org/r/20250508132644.1395904-10-mark.rutland@arm.com
Signed-off-by: Will Deacon <will@kernel.org>
arch/arm64/kernel/signal.c

index d42d83b45249657debdfb7f319e3e43359cc9e97..417140cd399b3dfc1f7e4f717ec2b3aa67a7e14c 100644 (file)
@@ -1476,22 +1476,8 @@ static int setup_return(struct pt_regs *regs, struct ksignal *ksig,
 
        /* Signal handlers are invoked with ZA and streaming mode disabled */
        if (system_supports_sme()) {
-               /*
-                * If we were in streaming mode the saved register
-                * state was SVE but we will exit SM and use the
-                * FPSIMD register state.
-                *
-                * TODO: decide if this should behave as SMSTOP (e.g. reset
-                * FPSR + FPMR), or whether this should only clear the scalable
-                * registers + ZA state.
-                */
-               if (current->thread.svcr & SVCR_SM_MASK) {
-                       memset(&current->thread.uw.fpsimd_state, 0,
-                              sizeof(current->thread.uw.fpsimd_state));
-                       current->thread.fp_type = FP_STATE_FPSIMD;
-               }
-
-               current->thread.svcr &= ~(SVCR_ZA_MASK | SVCR_SM_MASK);
+               task_smstop_sm(current);
+               current->thread.svcr &= ~SVCR_ZA_MASK;
                write_sysreg_s(0, SYS_TPIDR2_EL0);
        }