diff mbox series

[RFC,1/3] ARM: vfp: allow kernel mode NEON in softirq context

Message ID 20201210181158.28960-2-ardb@kernel.org
State New
Headers show
Series crypto: ARM - run kernel mode NEON with softirqs disabled | expand

Commit Message

Ard Biesheuvel Dec. 10, 2020, 6:11 p.m. UTC
Allow kernel mode NEON to be used in softirq context as well as process
context. To avoid nested use of the NEON, which would require the kernel
mode process context NEON state to be preserved while the NEON is used in
softirq context, turn off softirq processing when enabling kernel mode NEON.

Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/simd.h | 12 ++++++++++++
 arch/arm/vfp/vfpmodule.c    | 11 +++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
new file mode 100644
index 000000000000..0f44f0d9df4a
--- /dev/null
+++ b/arch/arm/include/asm/simd.h
@@ -0,0 +1,12 @@ 
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/hardirq.h>
+
+/*
+ * may_use_simd - whether it is allowable at this time to issue SIMD
+ *                instructions or access the SIMD register file
+ */
+static __must_check inline bool may_use_simd(void)
+{
+	return !in_irq() && !irqs_disabled() && !in_nmi();
+}
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index c3b6451c18bd..849703571ffa 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -21,6 +21,7 @@ 
 
 #include <asm/cp15.h>
 #include <asm/cputype.h>
+#include <asm/simd.h>
 #include <asm/system_info.h>
 #include <asm/thread_notify.h>
 #include <asm/traps.h>
@@ -719,12 +720,13 @@  void kernel_neon_begin(void)
 	u32 fpexc;
 
 	/*
-	 * Kernel mode NEON is only allowed outside of interrupt context
-	 * with preemption disabled. This will make sure that the kernel
-	 * mode NEON register contents never need to be preserved.
+	 * Kernel mode NEON is only allowed outside of hard interrupt context
+	 * with preemption and softirq processing disabled. This ensures that
+	 * the kernel mode NEON register contents never need to be preserved.
 	 */
-	BUG_ON(in_interrupt());
+	BUG_ON(!may_use_simd());
 	cpu = get_cpu();
+	local_bh_disable();
 
 	fpexc = fmrx(FPEXC) | FPEXC_EN;
 	fmxr(FPEXC, fpexc);
@@ -747,6 +749,7 @@  void kernel_neon_end(void)
 {
 	/* Disable the NEON/VFP unit. */
 	fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
+	local_bh_enable();
 	put_cpu();
 }
 EXPORT_SYMBOL(kernel_neon_end);