diff options
-rw-r--r-- | arch/arm64/kernel/entry-common.c | 9 | ||||
-rw-r--r-- | arch/arm64/kernel/entry.S | 12 |
2 files changed, 10 insertions, 11 deletions
diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c index 1fe60578e556..08d17eb0ce13 100644 --- a/arch/arm64/kernel/entry-common.c +++ b/arch/arm64/kernel/entry-common.c @@ -122,6 +122,15 @@ asmlinkage void __sched arm64_preempt_schedule_irq(void) lockdep_assert_irqs_disabled(); /* + * DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC + * priority masking is used the GIC irqchip driver will clear DAIF.IF + * using gic_arch_enable_irqs() for normal IRQs. If anything is set in + * DAIF we must have handled an NMI, so skip preemption. + */ + if (system_uses_irq_prio_masking() && read_sysreg(daif)) + return; + + /* * Preempting a task from an IRQ means we leave copies of PSTATE * on the stack. cpufeature's enable calls may modify PSTATE, but * resuming one of these preempted tasks would undo those changes. diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index 656f3129bfef..449628290ce8 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -562,17 +562,7 @@ tsk .req x28 // current thread_info #ifdef CONFIG_PREEMPTION ldr x24, [tsk, #TSK_TI_PREEMPT] // get preempt count -alternative_if ARM64_HAS_IRQ_PRIO_MASKING - /* - * DA were cleared at start of handling, and IF are cleared by - * the GIC irqchip driver using gic_arch_enable_irqs() for - * normal IRQs. If anything is set, it means we come back from - * an NMI instead of a normal IRQ, so skip preemption - */ - mrs x0, daif - orr x24, x24, x0 -alternative_else_nop_endif - cbnz x24, 1f // preempt count != 0 || NMI return path + cbnz x24, 1f // preempt count != 0 bl arm64_preempt_schedule_irq // irq en/disable is done inside 1: #endif |