[PATCH] ARM: Disallow kernel mode NEON when IRQs are disabled

Ard Biesheuvel ardb+git at google.com
Mon Mar 24 11:59:28 PDT 2025


From: Ard Biesheuvel <ardb at kernel.org>

Commit

  c79f81631142 ("ARM: 9283/1: permit non-nested kernel mode NEON in softirq context")

relaxed the rules around the use of SIMD instructions in kernel mode on
ARM, to allow such use when serving a softirq. To avoid having to
preserve/restore kernel mode NEON state when such a softirq is taken,
softirqs are now disabled when using the NEON from task context.

However, the fact that the softirq API does not allow unmasking of
softirqs with interrupts disabled was overlooked, resulting in a WARN()
in some cases, as reported by Guenter:

  WARNING: CPU: 0 PID: 1145 at kernel/softirq.c:369 __local_bh_enable_ip+0x118/0x194
  Call trace:
   unwind_backtrace from show_stack+0x10/0x14
   show_stack from dump_stack_lvl+0x7c/0xac
   dump_stack_lvl from __warn+0x7c/0x1b8
   __warn from warn_slowpath_fmt+0x19c/0x1a4
   warn_slowpath_fmt from __local_bh_enable_ip+0x118/0x194
   __local_bh_enable_ip from crc_t10dif_arch+0xd4/0xe8
   crc_t10dif_arch from crc_t10dif_wrapper+0x14/0x1c
   crc_t10dif_wrapper from crc_main_test+0x178/0x360
   crc_main_test from kunit_try_run_case+0x78/0x1e0
   kunit_try_run_case from kunit_generic_run_threadfn_adapter+0x1c/0x34
   kunit_generic_run_threadfn_adapter from kthread+0x118/0x254
   kthread from ret_from_fork+0x14/0x28

While disabling softirqs is not really needed when running with IRQs
disabled (given that the only way a softirq can be delivered
asynchrously is over the back of an IRQ), let's not complicate this
logic more than needed, and simply disallow use of the NEON in kernel
mode when IRQs are disabled.

Another approach might be to only disable and re-enable softirqs if IRQs
are enabled, but other than the test case above, there are no clear use
cases for doing non-trivial arithmetic processing (hence using an
accelerated SIMD implementation) with IRQs disabled.

Reported-by: Guenter Roeck <linux at roeck-us.net>
Tested-by: Guenter Roeck <linux at roeck-us.net>
Link: https://lore.kernel.org/all/389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net
Signed-off-by: Ard Biesheuvel <ardb at kernel.org>
---
 arch/arm/include/asm/simd.h | 3 ++-
 arch/arm/vfp/vfpmodule.c    | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/simd.h b/arch/arm/include/asm/simd.h
index 82191dbd7e78..e604a9382960 100644
--- a/arch/arm/include/asm/simd.h
+++ b/arch/arm/include/asm/simd.h
@@ -4,5 +4,6 @@
 
 static __must_check inline bool may_use_simd(void)
 {
-	return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq();
+	return IS_ENABLED(CONFIG_KERNEL_MODE_NEON) && !in_hardirq()
+	       && !irqs_disabled();
 }
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 7803d50b90f8..e559ad3cd148 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -877,6 +877,7 @@ void kernel_neon_begin(void)
 	 * the kernel mode NEON register contents never need to be preserved.
 	 */
 	BUG_ON(in_hardirq());
+	BUG_ON(irqs_disabled());
 	cpu = __smp_processor_id();
 
 	fpexc = fmrx(FPEXC) | FPEXC_EN;
-- 
2.49.0.395.g12beb8f557-goog




More information about the linux-arm-kernel mailing list