summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2025-05-08 14:26:29 +0100
committerWill Deacon <will@kernel.org>2025-05-08 15:29:09 +0100
commit99560c9452bb9819334bdb9c6e9e27c0f45f8829 (patch)
tree6701067203318be50d2489b7b50ec3e7611b8c2e
parent6ef1d778ce56c5bde1ac0a1f85fd9710efde6724 (diff)
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: 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>
-rw-r--r--arch/arm64/kernel/signal.c18
1 files changed, 2 insertions, 16 deletions
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index d42d83b45249..417140cd399b 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -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);
}