Commit 8e12ab7c authored by Mark Rutland's avatar Mark Rutland Committed by Peter Zijlstra

arm64: entry: Centralize preemption decision

For historical reasons, the decision of whether or not to preempt is
spread across arm64_preempt_schedule_irq() and __el1_irq(), and it would
be clearer if this were all in one place.

Also, arm64_preempt_schedule_irq() calls lockdep_assert_irqs_disabled(),
but this is redundant, as we have a subsequent identical assertion in
__exit_to_kernel_mode(), and preempt_schedule_irq() will
BUG_ON(!irqs_disabled()) anyway.

This patch removes the redundant assertion and centralizes the
preemption decision making within arm64_preempt_schedule_irq().

Other than the slight change to assertion behaviour, there should be no
functional change as a result of this patch.
Signed-off-by: default avatarMark Rutland <mark.rutland@arm.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Acked-by: default avatarArd Biesheuvel <ardb@kernel.org>
Acked-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Acked-by: default avatarFrederic Weisbecker <frederic@kernel.org>
Link: https://lore.kernel.org/r/20220214165216.2231574-7-mark.rutland@arm.com
parent 99cf983c
...@@ -222,7 +222,16 @@ static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs) ...@@ -222,7 +222,16 @@ static void noinstr arm64_exit_el1_dbg(struct pt_regs *regs)
static void __sched arm64_preempt_schedule_irq(void) static void __sched arm64_preempt_schedule_irq(void)
{ {
lockdep_assert_irqs_disabled(); if (!IS_ENABLED(CONFIG_PREEMPTION))
return;
/*
* Note: thread_info::preempt_count includes both thread_info::count
* and thread_info::need_resched, and is not equivalent to
* preempt_count().
*/
if (READ_ONCE(current_thread_info()->preempt_count) != 0)
return;
/* /*
* DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC * DAIF.DA are cleared at the start of IRQ/FIQ handling, and when GIC
...@@ -438,14 +447,7 @@ static __always_inline void __el1_irq(struct pt_regs *regs, ...@@ -438,14 +447,7 @@ static __always_inline void __el1_irq(struct pt_regs *regs,
do_interrupt_handler(regs, handler); do_interrupt_handler(regs, handler);
irq_exit_rcu(); irq_exit_rcu();
/* arm64_preempt_schedule_irq();
* Note: thread_info::preempt_count includes both thread_info::count
* and thread_info::need_resched, and is not equivalent to
* preempt_count().
*/
if (IS_ENABLED(CONFIG_PREEMPTION) &&
READ_ONCE(current_thread_info()->preempt_count) == 0)
arm64_preempt_schedule_irq();
exit_to_kernel_mode(regs); exit_to_kernel_mode(regs);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment