From: Mark Rutland <mark.rutland@arm.com>
To: linux-arm-kernel@lists.infradead.org
Cc: ardb@kernel.org, broonie@kernel.org, catalin.marinas@arm.com,
mark.rutland@arm.com, maz@kernel.org, will@kernel.org
Subject: [PATCH v2 09/13] arm64/fpsimd: Fix merging of FPSIMD state during signal return
Date: Wed, 9 Apr 2025 17:40:06 +0100 [thread overview]
Message-ID: <20250409164010.3480271-10-mark.rutland@arm.com> (raw)
In-Reply-To: <20250409164010.3480271-1-mark.rutland@arm.com>
For backwards compatibility reasons, when a signal return occurs which
restores SVE state, the effective lower 128 bits of each of the SVE
vector registers are restored from the corresponding FPSIMD vector
register in the FPSIMD signal frame, overriding the values in the SVE
signal frame. This is intended to be the case regardless of streaming
mode.
To make this happen, restore_sve_fpsimd_context() uses
fpsimd_update_current_state() to merge the lower 128 bits from the
FPSIMD signal frame into the SVE register state. Unfortunately,
fpsimd_update_current_state() performs this merging dependent upon
TIF_SVE, which is not always correct for streaming SVE register state:
* When restoring non-streaming SVE register state there is no observable
problem, as the signal return code configures TIF_SVE and the saved
fp_type to match before calling fpsimd_update_current_state(), which
observes either:
- TIF_SVE set AND fp_type == FP_STATE_SVE
- TIF_SVE clear AND fp_type == FP_STATE_FPSIMD
* On systems which have SME but not SVE, TIF_SVE cannot be set. Thus the
merging will never happen for the streaming SVE register state.
* On systems which have SVE and SME, TIF_SVE can be set and cleared
independently of PSTATE.SM. Thus the merging may or may not happen for
streaming SVE register state.
As TIF_SVE can be cleared non-deterministically during syscalls
(including at the start of sigreturn()), the merging may occur
non-deterministically from the perspective of userspace.
This logic has been broken since its introduction in commit:
85ed24dad2904f7c ("arm64/sme: Implement streaming SVE signal handling")
... at which point both fpsimd_signal_preserve_current_state() and
fpsimd_update_current_state() only checked TIF SVE. When PSTATE.SM==1
and TIF_SVE was clear, signal delivery would place stale FPSIMD state
into the FPSIMD signal frame, and signal return would not merge this
into the restored register state.
Subsequently, signal delivery was fixed as part of commit:
61da7c8e2a602f66 ("arm64/signal: Don't assume that TIF_SVE means we saved SVE state")
... but signal restore was not given a corresponding fix, and when
TIF_SVE was clear, signal restore would still fail to merge the FPSIMD
state into the restored SVE register state. The 'Fixes' tag did not
indicate that this had been broken since its introduction.
Fix this by merging the FPSIMD state dependent upon the saved fp_type,
matching what we (currently) do during signal delivery.
As described above, when backporting this commit, it will also be
necessary to backport commit:
61da7c8e2a602f66 ("arm64/signal: Don't assume that TIF_SVE means we saved SVE state")
... and prior to commit:
baa8515281b30861 ("arm64/fpsimd: Track the saved FPSIMD state type separately to TIF_SVE")
... it will be necessary for fpsimd_signal_preserve_current_state() and
fpsimd_update_current_state() to consider both TIF_SVE and
thread_sm_enabled(¤t->thread), in place of the saved fp_type.
Fixes: 85ed24dad2904f7c ("arm64/sme: Implement streaming SVE signal handling")
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>
Reviewed-by: Mark Brown <broonie@kernel.org>
---
arch/arm64/kernel/fpsimd.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 0b6fda5b7bad5..11f21809d3b7d 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1781,7 +1781,7 @@ void fpsimd_update_current_state(struct user_fpsimd_state const *state)
get_cpu_fpsimd_context();
current->thread.uw.fpsimd_state = *state;
- if (test_thread_flag(TIF_SVE))
+ if (current->thread.fp_type == FP_STATE_SVE)
fpsimd_to_sve(current);
task_fpsimd_load();
--
2.30.2
next prev parent reply other threads:[~2025-04-09 16:58 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-09 16:39 [PATCH v2 00/13] arm64: Preparatory FPSIMD/SVE/SME fixes Mark Rutland
2025-04-09 16:39 ` [PATCH v2 01/13] arm64/fpsimd: Avoid RES0 bits in the SME trap handler Mark Rutland
2025-04-09 16:39 ` [PATCH v2 02/13] arm64/fpsimd: Remove unused fpsimd_force_sync_to_sve() Mark Rutland
2025-04-09 17:32 ` Mark Brown
2025-04-09 16:40 ` [PATCH v2 03/13] arm64/fpsimd: Remove redundant SVE trap manipulation Mark Rutland
2025-04-09 16:40 ` [PATCH v2 04/13] arm64/fpsimd: Remove opportunistic freeing of SME state Mark Rutland
2025-04-09 16:40 ` [PATCH v2 05/13] arm64/fpsimd: Discard stale CPU state when handling SME traps Mark Rutland
2025-04-09 16:40 ` [PATCH v2 06/13] arm64/fpsimd: Don't corrupt FPMR when streaming mode changes Mark Rutland
2025-04-09 16:40 ` [PATCH v2 07/13] arm64/fpsimd: Avoid clobbering kernel FPSIMD state with SMSTOP Mark Rutland
2025-04-09 16:40 ` [PATCH v2 08/13] arm64/fpsimd: Reset FPMR upon exec() Mark Rutland
2025-04-09 16:40 ` Mark Rutland [this message]
2025-04-09 16:40 ` [PATCH v2 10/13] arm64/fpsimd: Add fpsimd_save_and_flush_current_state() Mark Rutland
2025-04-09 16:40 ` [PATCH v2 11/13] arm64/fpsimd: signal32: Always save+flush state early Mark Rutland
2025-04-09 16:40 ` [PATCH v2 12/13] arm64/fpsimd: signal: " Mark Rutland
2025-04-09 16:40 ` [PATCH v2 13/13] arm64/fpsimd: signal: Simplify preserve_tpidr2_context() Mark Rutland
2025-04-09 17:17 ` [PATCH v2 00/13] arm64: Preparatory FPSIMD/SVE/SME fixes Catalin Marinas
2025-04-29 19:46 ` Will Deacon
2025-04-30 13:24 ` Mark Rutland
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20250409164010.3480271-10-mark.rutland@arm.com \
--to=mark.rutland@arm.com \
--cc=ardb@kernel.org \
--cc=broonie@kernel.org \
--cc=catalin.marinas@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=maz@kernel.org \
--cc=will@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox