summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorMark Rutland <mark.rutland@arm.com>2026-06-03 12:06:17 +0100
committerWill Deacon <will@kernel.org>2026-06-03 16:50:48 +0100
commit3efb6c7f22c60a1440a80ddfa3d30b9406f01ccc (patch)
treee146063df79c5dbabf6be65352af0a7c7e4a1b0b /arch
parentafd7af2b56ec7553e4bdc6387bb923b01d2ad2b6 (diff)
arm64: fpsimd: Fold sve_init_regs() into do_sve_acc()
For historical reasons, do_sve_acc() is structurally different from do_sme_acc(), and the logic to convert the task from FPSIMD to SVE is out-of-line in sve_init_regs(). We only use sve_init_regs() within do_sve_acc(), so it's not necessary for this to be a separate function. Fold sve_init_regs() into do_sve_acc(), and simplify the associated comments. This makes do_sve_acc() structurally similar to do_sme_acc(), making it easier to see similarities and differences. There should be no functional change as a result of this patch. Signed-off-by: Mark Rutland <mark.rutland@arm.com> Reviewed-by: Mark Brown <broonie@kernel.org> Reviewed-by: Vladimir Murzin <vladimir.murzin@arm.com> Cc: Catalin Marinas <catalin.marinas@arm.com> Cc: Fuad Tabba <tabba@google.com> Cc: James Morse <james.morse@arm.com> Cc: Marc Zyngier <maz@kernel.org> Cc: Oliver Upton <oupton@kernel.org> Cc: Will Deacon <will@kernel.org> Signed-off-by: Will Deacon <will@kernel.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm64/kernel/fpsimd.c48
1 files changed, 17 insertions, 31 deletions
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 60a45d600b46..a8395cb30334 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1293,31 +1293,6 @@ void sme_suspend_exit(void)
#endif /* CONFIG_ARM64_SME */
-static void sve_init_regs(void)
-{
- /*
- * Convert the FPSIMD state to SVE, zeroing all the state that
- * is not shared with FPSIMD. If (as is likely) the current
- * state is live in the registers then do this there and
- * update our metadata for the current task including
- * disabling the trap, otherwise update our in-memory copy.
- * We are guaranteed to not be in streaming mode, we can only
- * take a SVE trap when not in streaming mode and we can't be
- * in streaming mode when taking a SME trap.
- */
- if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
- unsigned long vq_minus_one =
- sve_vq_from_vl(task_get_sve_vl(current)) - 1;
- sve_set_vq(vq_minus_one);
- sve_flush_live(true, vq_minus_one);
- fpsimd_bind_task_to_cpu();
- } else {
- fpsimd_to_sve(current);
- current->thread.fp_type = FP_STATE_SVE;
- fpsimd_flush_task_state(current);
- }
-}
-
/*
* Trapped SVE access
*
@@ -1349,13 +1324,24 @@ void do_sve_acc(unsigned long esr, struct pt_regs *regs)
WARN_ON(1); /* SVE access shouldn't have trapped */
/*
- * Even if the task can have used streaming mode we can only
- * generate SVE access traps in normal SVE mode and
- * transitioning out of streaming mode may discard any
- * streaming mode state. Always clear the high bits to avoid
- * any potential errors tracking what is properly initialised.
+ * Convert the FPSIMD state to SVE. Stale SVE state can be present in
+ * registers or memory, so we must zero all state that is not shared
+ * with FPSIMD.
+ *
+ * SVE traps cannot be taken from streaming mode, so there cannot be
+ * any effective streaming mode SVE state.
*/
- sve_init_regs();
+ if (!test_thread_flag(TIF_FOREIGN_FPSTATE)) {
+ unsigned long vq_minus_one =
+ sve_vq_from_vl(task_get_sve_vl(current)) - 1;
+ sve_set_vq(vq_minus_one);
+ sve_flush_live(true, vq_minus_one);
+ fpsimd_bind_task_to_cpu();
+ } else {
+ fpsimd_to_sve(current);
+ current->thread.fp_type = FP_STATE_SVE;
+ fpsimd_flush_task_state(current);
+ }
put_cpu_fpsimd_context();
}