]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ARM: 9446/1: Disallow kernel mode NEON when IRQs are disabled
authorArd Biesheuvel <ardb@kernel.org>
Wed, 2 Apr 2025 07:05:31 +0000 (08:05 +0100)
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Thu, 29 May 2025 10:22:25 +0000 (11:22 +0100)
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@roeck-us.net>
Tested-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/all/389b899f-893c-4855-9e30-d8920a5d6f91@roeck-us.net
Reviewed-by: Eric Biggers <ebiggers@kernel.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
arch/arm/include/asm/simd.h
arch/arm/vfp/vfpmodule.c

index 82191dbd7e78a036423e0e1518dca767c536cb86..e604a93829606eb40372d60d5013bc64076bb566 100644 (file)
@@ -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();
 }
index 7803d50b90f86b0822c775b4cc1189f18b316519..e559ad3cd1487e7dec6241b39327993a8046a765 100644 (file)
@@ -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;