[RFC PATCH v2 09/45] arm64: entry: Avoid unnecessary local_irq_disable() on kernel exit

Jinjie Ruan ruanjinjie at huawei.com
Mon Jul 27 20:18:33 PDT 2026



在 2026/7/28 0:34, Vladimir Murzin 写道:
> Currently, when exiting to kernel mode, we attempt involuntary
> preemption. The preemption logic expects IRQs to be disabled, which is
> why we call local_irq_disable() before attempting preemption.
> 
> However, depending on the context, local_irq_disable() may be
> unnecessary:
> 
> - __el1_irq(), the non-NMI EL1 IRQ path, already has IRQs disabled, so
>   local_irq_disable() is redundant.
> 
> - irqentry_exit_to_kernel_mode_preempt() immediately returns when
>   exiting from an NMI-like context, so calling local_irq_disable()
>   beforehand is unnecessary work.
> 
> Split arm64_exit_to_kernel_mode() into preempt, non-preempt, and
> dispatch parts so that we can avoid this extra work where it is not
> needed.

Make sense for me, in an NMI-like context,
irqentry_exit_to_kernel_mode_preempt() and local_irq_disable() are both
unnecessary.

> 
> Signed-off-by: Vladimir Murzin <vladimir.murzin at arm.com>
> ---
>  arch/arm64/kernel/entry-common.c | 30 +++++++++++++++++++++++++-----
>  1 file changed, 25 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index 2be42d7f4eaa..72c03ccea59f 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -52,16 +52,36 @@ static noinstr irqentry_state_t arm64_enter_from_kernel_mode(struct pt_regs *reg
>   * After this function returns it is not safe to call regular kernel code,
>   * instrumentable code, or any code which may trigger an exception.
>   */
> -static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
> -					      irqentry_state_t state)
> +static void noinstr __arm64_exit_to_kernel_mode(struct pt_regs *regs,
> +						irqentry_state_t state)
>  {
> -	local_irq_disable();
> -	irqentry_exit_to_kernel_mode_preempt(regs, state);
>  	local_daif_mask();
>  	mte_check_tfsr_exit();
>  	irqentry_exit_to_kernel_mode_after_preempt(regs, state);
>  }
>  
> +/*
> + * We are returning from the context which allows involuntary kernel preemption

Should we add the irq disabled status for preemption?

We are returning from the context which allows involuntary kernel
preemption "with irq disabled" ?

Reviewed-by: Jinjie Ruan <ruanjinjie at huawei.com>

> + */
> +static void noinstr arm64_exit_to_kernel_mode_preempt(struct pt_regs *regs,
> +						      irqentry_state_t state)
> +{
> +	irqentry_exit_to_kernel_mode_preempt(regs, state);
> +	__arm64_exit_to_kernel_mode(regs, state);
> +}
> +
> +static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
> +					      irqentry_state_t state)
> +{
> +	if (!regs_irqs_disabled(regs)) {
> +		local_irq_disable();
> +		arm64_exit_to_kernel_mode_preempt(regs, state);
> +		return;
> +	}
> +
> +	__arm64_exit_to_kernel_mode(regs, state);
> +}
> +
>  static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
>  {
>  	enter_from_user_mode(regs);
> @@ -510,7 +530,7 @@ static __always_inline void __el1_irq(struct pt_regs *regs,
>  	do_interrupt_handler(regs, handler);
>  	irq_exit_rcu();
>  
> -	arm64_exit_to_kernel_mode(regs, state);
> +	arm64_exit_to_kernel_mode_preempt(regs, state);
>  }
>  static void noinstr el1_interrupt(struct pt_regs *regs,
>  				  void (*handler)(struct pt_regs *))




More information about the linux-arm-kernel mailing list