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@xxxxxxxxxx> --- 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