arm64: fpsimd: run kernel mode NEON with softirqs disabled
Kernel mode NEON can be used in task or softirq context, but only in a non-nesting manner, i.e., softirq context is only permitted if the interrupt was not taken at a point where the kernel was using the NEON in task context. This means all users of kernel mode NEON have to be aware of this limitation, and either need to provide scalar fallbacks that may be much slower (up to 20x for AES instructions) and potentially less safe, or use an asynchronous interface that defers processing to a later time when the NEON is guaranteed to be available. Given that grabbing and releasing the NEON is cheap, we can relax this restriction, by increasing the granularity of kernel mode NEON code, and always disabling softirq processing while the NEON is being used in task context. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Will Deacon <will@kernel.org> Link: https://lore.kernel.org/r/20210302090118.30666-4-ardb@kernel.org Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
committed by
Catalin Marinas
parent
4c4dcd3541
commit
13150149aa
@@ -15,6 +15,7 @@
|
||||
#include <asm-generic/export.h>
|
||||
|
||||
#include <asm/asm-offsets.h>
|
||||
#include <asm/alternative.h>
|
||||
#include <asm/cpufeature.h>
|
||||
#include <asm/cputype.h>
|
||||
#include <asm/debug-monitors.h>
|
||||
@@ -701,19 +702,32 @@ USER(\label, ic ivau, \tmp2) // invalidate I line PoU
|
||||
.endm
|
||||
|
||||
/*
|
||||
* Check whether preempt-disabled code should yield as soon as it
|
||||
* is able. This is the case if re-enabling preemption a single
|
||||
* time results in a preempt count of zero, and the TIF_NEED_RESCHED
|
||||
* flag is set. (Note that the latter is stored negated in the
|
||||
* top word of the thread_info::preempt_count field)
|
||||
* Check whether preempt/bh-disabled asm code should yield as soon as
|
||||
* it is able. This is the case if we are currently running in task
|
||||
* context, and either a softirq is pending, or the TIF_NEED_RESCHED
|
||||
* flag is set and re-enabling preemption a single time would result in
|
||||
* a preempt count of zero. (Note that the TIF_NEED_RESCHED flag is
|
||||
* stored negated in the top word of the thread_info::preempt_count
|
||||
* field)
|
||||
*/
|
||||
.macro cond_yield, lbl:req, tmp:req
|
||||
#ifdef CONFIG_PREEMPTION
|
||||
.macro cond_yield, lbl:req, tmp:req, tmp2:req
|
||||
get_current_task \tmp
|
||||
ldr \tmp, [\tmp, #TSK_TI_PREEMPT]
|
||||
/*
|
||||
* If we are serving a softirq, there is no point in yielding: the
|
||||
* softirq will not be preempted no matter what we do, so we should
|
||||
* run to completion as quickly as we can.
|
||||
*/
|
||||
tbnz \tmp, #SOFTIRQ_SHIFT, .Lnoyield_\@
|
||||
#ifdef CONFIG_PREEMPTION
|
||||
sub \tmp, \tmp, #PREEMPT_DISABLE_OFFSET
|
||||
cbz \tmp, \lbl
|
||||
#endif
|
||||
adr_l \tmp, irq_stat + IRQ_CPUSTAT_SOFTIRQ_PENDING
|
||||
this_cpu_offset \tmp2
|
||||
ldr w\tmp, [\tmp, \tmp2]
|
||||
cbnz w\tmp, \lbl // yield on pending softirq in task context
|
||||
.Lnoyield_\@:
|
||||
.endm
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user