[SRU][J:linux-bluefield][PATCH v1 2/7] arm64/fp: Use a struct to pass data to fpsimd_bind_state_to_cpu()
Stav Aviram
saviram at nvidia.com
Thu Aug 7 13:33:20 UTC 2025
From: Mark Brown <broonie at kernel.org>
BugLink: https://bugs.launchpad.net/bugs/2119457
For reasons that are unclear to this reader fpsimd_bind_state_to_cpu()
populates the struct fpsimd_last_state_struct that it uses to store the
active floating point state for KVM guests by passing an argument for
each member of the structure. As the richness of the architecture increases
this is resulting in a function with a rather large number of arguments
which isn't ideal.
Simplify the interface by using the struct directly as the single argument
for the function, renaming it as we lift the definition into the header.
This could be built on further to reduce the work we do adding storage for
new FP state in various places but for now it just simplifies this one
interface.
Signed-off-by: Mark Brown <broonie at kernel.org>
Reviewed-by: Catalin Marinas <catalin.marinas at arm.com>
Reviewed-by: Marc Zyngier <maz at kernel.org>
Link: https://lore.kernel.org/r/20221115094640.112848-9-broonie@kernel.org
Signed-off-by: Will Deacon <will at kernel.org>
(backported from commit 1192b93ba3528feaf37dc4b5d8d6bdbb475791ad)
[Conflict resolution: Kept SME-related fields (za_state, svcr, sme_vl)
in cpu_fp_state struct for API compatibility but these fields remain
unused since SME is not supported in linux-bluefield-5.15.]
Signed-off-by: Stav Aviram <saviram at nvidia.com>
---
arch/arm64/include/asm/fpsimd.h | 15 ++++++++++++---
arch/arm64/kernel/fpsimd.c | 29 +++++++----------------------
arch/arm64/kvm/fpsimd.c | 23 ++++++++++++++---------
3 files changed, 33 insertions(+), 34 deletions(-)
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 7a407c3767b6..149927d7b576 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -46,9 +46,18 @@ extern void fpsimd_restore_current_state(void);
extern void fpsimd_update_current_state(struct user_fpsimd_state const *state);
extern void fpsimd_kvm_prepare(void);
-extern void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *state,
- void *sve_state, unsigned int sve_vl,
- enum fp_type *type, enum fp_type to_save);
+struct cpu_fp_state {
+ struct user_fpsimd_state *st;
+ void *sve_state;
+ void *za_state;
+ u64 *svcr;
+ unsigned int sve_vl;
+ unsigned int sme_vl;
+ enum fp_type *fp_type;
+ enum fp_type to_save;
+};
+
+extern void fpsimd_bind_state_to_cpu(struct cpu_fp_state *fp_state);
extern void fpsimd_flush_task_state(struct task_struct *target);
extern void fpsimd_save_and_flush_cpu_state(void);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 4be9d9fd4fb7..67f397a55d8c 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -113,15 +113,8 @@
* returned from the 2nd syscall yet, TIF_FOREIGN_FPSTATE is still set so
* whatever is in the FPSIMD registers is not saved to memory, but discarded.
*/
-struct fpsimd_last_state_struct {
- struct user_fpsimd_state *st;
- void *sve_state;
- unsigned int sve_vl;
- enum fp_type *fp_type;
- enum fp_type to_save;
-};
-static DEFINE_PER_CPU(struct fpsimd_last_state_struct, fpsimd_last_state);
+static DEFINE_PER_CPU(struct cpu_fp_state, fpsimd_last_state);
/* Default VL for tasks that don't set it explicitly: */
static int __sve_default_vl = -1;
@@ -328,7 +321,7 @@ static void task_fpsimd_load(void)
*/
static void fpsimd_save(void)
{
- struct fpsimd_last_state_struct const *last =
+ struct cpu_fp_state const *last =
this_cpu_ptr(&fpsimd_last_state);
/* set by fpsimd_bind_task_to_cpu() or fpsimd_bind_state_to_cpu() */
bool save_sve_regs = false;
@@ -1161,8 +1154,7 @@ void fpsimd_signal_preserve_current_state(void)
*/
static void fpsimd_bind_task_to_cpu(void)
{
- struct fpsimd_last_state_struct *last =
- this_cpu_ptr(&fpsimd_last_state);
+ struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
WARN_ON(!system_supports_fpsimd());
last->st = ¤t->thread.uw.fpsimd_state;
@@ -1183,21 +1175,14 @@ static void fpsimd_bind_task_to_cpu(void)
}
}
-void fpsimd_bind_state_to_cpu(struct user_fpsimd_state *st, void *sve_state,
- unsigned int sve_vl, enum fp_type *type,
- enum fp_type to_save)
-{
- struct fpsimd_last_state_struct *last =
- this_cpu_ptr(&fpsimd_last_state);
+void fpsimd_bind_state_to_cpu(struct cpu_fp_state *state)
+ {
+ struct cpu_fp_state *last = this_cpu_ptr(&fpsimd_last_state);
WARN_ON(!system_supports_fpsimd());
WARN_ON(!in_softirq() && !irqs_disabled());
- last->st = st;
- last->sve_state = sve_state;
- last->sve_vl = sve_vl;
- last->fp_type = type;
- last->to_save = to_save;
+ *last = *state;
}
/*
diff --git a/arch/arm64/kvm/fpsimd.c b/arch/arm64/kvm/fpsimd.c
index cfda503c8b3f..61c8f5952129 100644
--- a/arch/arm64/kvm/fpsimd.c
+++ b/arch/arm64/kvm/fpsimd.c
@@ -93,24 +93,29 @@ void kvm_arch_vcpu_load_fp(struct kvm_vcpu *vcpu)
*/
void kvm_arch_vcpu_ctxsync_fp(struct kvm_vcpu *vcpu)
{
- enum fp_type fp_type;
+ struct cpu_fp_state fp_state;
WARN_ON_ONCE(!irqs_disabled());
if (vcpu->arch.flags & KVM_ARM64_FP_ENABLED) {
- if (vcpu_has_sve(vcpu))
- fp_type = FP_STATE_SVE;
- else
- fp_type = FP_STATE_FPSIMD;
/*
* Currently we do not support SME guests so SVCR is
* always 0 and we just need a variable to point to.
*/
- fpsimd_bind_state_to_cpu(&vcpu->arch.ctxt.fp_regs,
- vcpu->arch.sve_state,
- vcpu->arch.sve_max_vl,
- &vcpu->arch.fp_type, fp_type);
+ fp_state.st = &vcpu->arch.ctxt.fp_regs;
+ fp_state.sve_state = vcpu->arch.sve_state;
+ fp_state.sve_vl = vcpu->arch.sve_max_vl;
+ fp_state.za_state = NULL;
+ fp_state.svcr = &vcpu->arch.svcr;
+ fp_state.fp_type = &vcpu->arch.fp_type;
+
+ if (vcpu_has_sve(vcpu))
+ fp_state.to_save = FP_STATE_SVE;
+ else
+ fp_state.to_save = FP_STATE_FPSIMD;
+
+ fpsimd_bind_state_to_cpu(&fp_state);
clear_thread_flag(TIF_FOREIGN_FPSTATE);
}
--
2.34.1
More information about the kernel-team
mailing list