FROMGIT: arm64/fpsimd: signal: Use SMSTOP behaviour in setup_return()

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: 40a8e87bb3 ("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>
(cherry picked from commit 99560c9452bb9819334bdb9c6e9e27c0f45f8829
 https://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
 for-next/sme-fixes)
Bug: 393087661
Signed-off-by: Will Deacon <willdeacon@google.com>
Change-Id: I25a3816b83fc83668d7c958515b0316262fedd7a
This commit is contained in:
Mark Rutland
2025-05-08 14:26:29 +01:00
committed by Will Deacon
parent f940d322b6
commit 57f5b387c4

View File

@@ -1249,22 +1249,8 @@ static void setup_return(struct pt_regs *regs, struct k_sigaction *ka,
/* 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);
}