diff mbox series

[RFC,v2,02/22] arm64/fpsimd: Make SVE<->FPSIMD rewriting available to KVM

Message ID 20231222-kvm-arm64-sme-v2-2-da226cb180bb@kernel.org (mailing list archive)
State New
Headers show
Series KVM: arm64: Implement support for SME in non-protected guests | expand

Commit Message

Mark Brown Dec. 22, 2023, 4:21 p.m. UTC
We have routines to rewrite between FPSIMD and SVE data formats, make these
visible to the KVM host code so that we can use them to present the FP
register state in SVE format for guests which have SME without SVE.

Signed-off-by: Mark Brown <broonie@kernel.org>
---
 arch/arm64/include/asm/fpsimd.h |  5 +++++
 arch/arm64/kernel/fpsimd.c      | 23 +++++++++++++++--------
 2 files changed, 20 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 50e5f25d3024..7092e7f944ae 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -157,6 +157,11 @@  extern void cpu_enable_fa64(const struct arm64_cpu_capabilities *__unused);
 
 extern u64 read_smcr_features(void);
 
+void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
+		     unsigned int vq);
+void __sve_to_fpsimd(struct user_fpsimd_state *fst, void const *sst,
+		     unsigned int vq);
+
 /*
  * Helpers to translate bit indices in sve_vq_map to VQ values (and
  * vice versa).  This allows find_next_bit() to be used to find the
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 1559c706d32d..e6a4dd68f62a 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -647,8 +647,8 @@  static __uint128_t arm64_cpu_to_le128(__uint128_t x)
 
 #define arm64_le128_to_cpu(x) arm64_cpu_to_le128(x)
 
-static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
-			    unsigned int vq)
+void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
+		     unsigned int vq)
 {
 	unsigned int i;
 	__uint128_t *p;
@@ -659,6 +659,18 @@  static void __fpsimd_to_sve(void *sst, struct user_fpsimd_state const *fst,
 	}
 }
 
+void __sve_to_fpsimd(struct user_fpsimd_state *fst, const void *sst,
+		     unsigned int vq)
+{
+	unsigned int i;
+	__uint128_t const *p;
+
+	for (i = 0; i < SVE_NUM_ZREGS; ++i) {
+		p = (__uint128_t const *)ZREG(sst, vq, i);
+		fst->vregs[i] = arm64_le128_to_cpu(*p);
+	}
+}
+
 /*
  * Transfer the FPSIMD state in task->thread.uw.fpsimd_state to
  * task->thread.sve_state.
@@ -700,18 +712,13 @@  static void sve_to_fpsimd(struct task_struct *task)
 	unsigned int vq, vl;
 	void const *sst = task->thread.sve_state;
 	struct user_fpsimd_state *fst = &task->thread.uw.fpsimd_state;
-	unsigned int i;
-	__uint128_t const *p;
 
 	if (!system_supports_sve() && !system_supports_sme())
 		return;
 
 	vl = thread_get_cur_vl(&task->thread);
 	vq = sve_vq_from_vl(vl);
-	for (i = 0; i < SVE_NUM_ZREGS; ++i) {
-		p = (__uint128_t const *)ZREG(sst, vq, i);
-		fst->vregs[i] = arm64_le128_to_cpu(*p);
-	}
+	__sve_to_fpsimd(fst, sst, vq);
 }
 
 #ifdef CONFIG_ARM64_SVE