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

Ard Biesheuvel ardb at kernel.org
Thu Dec 10 13:11:56 EST 2020


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 at kernel.org>
---
 arch/arm/include/asm/simd.h | 12 ++++++++++++
 arch/arm/vfp/vfpmodule.c    | 11 +++++++----
 2 files changed, 19 insertions(+), 4 deletions(-)

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);
-- 
2.17.1




More information about the linux-arm-kernel mailing list