diff mbox series

ARM: Disallow kernel mode NEON when IRQs are disabled

Message ID 20250324185927.1024543-2-ardb+git@google.com (mailing list archive)
State New
Headers show
Series ARM: Disallow kernel mode NEON when IRQs are disabled | expand

Commit Message

Ard Biesheuvel March 24, 2025, 6:59 p.m. UTC
From: Ard Biesheuvel <ardb@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@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
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
---
 arch/arm/include/asm/simd.h | 3 ++-
 arch/arm/vfp/vfpmodule.c    | 1 +
 2 files changed, 3 insertions(+), 1 deletion(-)

Comments

Eric Biggers March 25, 2025, 3:39 p.m. UTC | #1
On Mon, Mar 24, 2025 at 07:59:28PM +0100, Ard Biesheuvel wrote:
> From: Ard Biesheuvel <ardb@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@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
> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
> ---
>  arch/arm/include/asm/simd.h | 3 ++-
>  arch/arm/vfp/vfpmodule.c    | 1 +
>  2 files changed, 3 insertions(+), 1 deletion(-)

Reviewed-by: Eric Biggers <ebiggers@kernel.org>

- Eric
diff mbox series

Patch

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;