[PATCH v2] arm64/fpsimd: Add interface for kernel use of SVE and SME

Mark Brown broonie at kernel.org
Thu Nov 3 11:21:05 PDT 2022


We currently support in kernel use of FPSIMD via the kernel_neon_begin()
and kernel_neon_end() interface but there is no corresponding interface
for SVE or SME. Given that SVE hardware is now becoming widely available
there is interest in using these more modern floating point instruction
sets for in kernel applications let's add an interface which allows them
to be selected in addition to FPSIMD.

The sharing of registers and code means that using kernel_neon_begin()
is actually doing most of the setup required, the only problem is that we
are not configuring the vector length so any SVE or SME code would just use
whatever vector length is configured in the hardware potentially leading to
uneven performance on systems which support multiple vector lengths. Add
a new kernel_fp_begin()/end() interface which allows the caller to flag if
it will use SVE or SME and initialises the vector length if requested.

We allow simultaneous specification of multiple extensions since it is
possible that a user may wish to mix them in a single algorithm, there is
no cost to allowing this.

Signed-off-by: Mark Brown <broonie at kernel.org>
---

v2: Check for system_supports_sme() for setting the SME VL.

 arch/arm64/include/asm/fpsimd.h |  7 +++++
 arch/arm64/kernel/fpsimd.c      | 45 +++++++++++++++++++++++++++++++++
 2 files changed, 52 insertions(+)

diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 6f86b7ab6c28..d4045fb73483 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -44,6 +44,13 @@
  */
 #define SME_VQ_MAX	16
 
+#define KERNEL_FP_FPSIMD	1
+#define KERNEL_FP_SVE		2
+#define KERNEL_FP_SME		4
+
+void kernel_fp_begin(unsigned int flags);
+void kernel_fp_end(void);
+
 struct task_struct;
 
 extern void fpsimd_save_state(struct user_fpsimd_state *state);
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 23834d96d1e7..01a79a8fe9f6 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -1858,6 +1858,51 @@ void kernel_neon_end(void)
 }
 EXPORT_SYMBOL(kernel_neon_end);
 
+/**
+ * kernel_fp_begin(): obtain the CPU floating point registers for use
+ * by the calling context
+ *
+ * @flags: KERNEL_FP_ flags specifying which FP features will be used.
+ *
+ * The caller is responsible for ensuring that the requested floating
+ * point features are available on the current system.  Task context
+ * in the registers is saved back to memory as necessary.  If SVE or
+ * SME support is enabled then the maximum available vector length
+ * will be selected.
+ *
+ * A matching call to kernel_fp_end() must be made before returning from the
+ * calling context.
+ *
+ * The caller may freely use the floating point registers until
+ * kernel_fp_end() is called.
+ */
+void kernel_fp_begin(unsigned int flags)
+{
+	kernel_neon_begin();
+
+	if (system_supports_sve() && (flags & KERNEL_FP_SVE))
+		sve_set_vq(sve_vq_from_vl(sve_max_vl()) - 1);
+
+	if (system_supports_sme() && (flags & KERNEL_FP_SME))
+		sme_set_vq(sve_vq_from_vl(sme_max_vl()) - 1);
+}
+EXPORT_SYMBOL(kernel_fp_begin);
+
+/**
+ * kernel_fp_end(): end kernel usage of the floating point registers
+ *
+ * Must be called from a context in which kernel_fp_begin() was previously
+ * called, with no call to kernel_fp_end() in the meantime.
+ *
+ * The caller must not use the FPSIMD registers after this function is called,
+ * unless kernel_fp_begin() is called again in the meantime.
+ */
+void kernel_fp_end(void)
+{
+	kernel_neon_end();
+}
+EXPORT_SYMBOL(kernel_fp_end);
+
 #ifdef CONFIG_EFI
 
 static DEFINE_PER_CPU(struct user_fpsimd_state, efi_fpsimd_state);
-- 
2.30.2




More information about the linux-arm-kernel mailing list