Re: [PATCH RFC Dovetail 7.1] arm64: irq_pipeline: 7.1 specific adjustments

Florian Bezdeka <[email protected]>
Newsgroups dev.linux.lists.xenomai
Message-ID <[email protected]>
On Thu, 2026-06-11 at 15:40 +0200, Florian Bezdeka wrote:
> Signed-off-by: Florian Bezdeka <[email protected]>
> ---
> 
> Hi Philippe,
> 
> final tests are still running but the local tests are looking good.
> The EVL testsuite triggered a WARN_ONCE() - see process.c below - which
> caused the systems to hang.
> 
> Turned out the arm64 entry code got some refactorings that needed some
> adjustments - pipline wise.
> 
> I would fold the following into 7.1, so could you please double check?
> Thanks!
> 
>  arch/arm64/kernel/entry-common.c | 35 ++++++++++++++++++++++++++++----
>  arch/arm64/kernel/process.c      |  6 +++---
>  include/linux/irq-entry-common.h |  3 +++
>  3 files changed, 37 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index b0e141266349..97f6d6904a5d 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -166,7 +166,16 @@ static noinstr irqentry_state_t arm64_enter_from_kernel_mode(struct pt_regs *reg
>  static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
>  					      irqentry_state_t state)
>  {
> -	local_irq_disable();
> +	if (irqs_pipelined()) {
> +		hard_local_irq_disable();
> +		if (running_inband()) {
> +			stall_inband_nocheck();
> +			trace_hardirqs_off();
> +		}
> +	} else {
> +		local_irq_disable();
> +	}
> +
>  	irqentry_exit_to_kernel_mode_preempt(regs, state);
>  	local_daif_mask();
>  	mte_check_tfsr_exit();
> @@ -175,7 +184,14 @@ static void noinstr arm64_exit_to_kernel_mode(struct pt_regs *regs,
>  
>  static __always_inline void arm64_syscall_enter_from_user_mode(struct pt_regs *regs)
>  {
> -	enter_from_user_mode(regs);
> +	if (running_inband()) {
> +		WARN_ON_ONCE(irq_pipeline_debug() && irqs_disabled());
> +		stall_inband_nocheck();
> +		enter_from_user_mode(regs);
> +		trace_hardirqs_on();
> +		unstall_inband_nocheck();
> +	}

Should enter_from_user_mode() be called while the inband stage is
stalled, or after unstalling? The exit part is called while being
stalled, so I kept that in sync, but I'm not 100% sure.

> +
>  	mte_disable_tco_entry(current);
>  	sme_enter_from_user_mode();
>  }
> @@ -191,6 +207,7 @@ static __always_inline void arm64_enter_from_user_mode(struct pt_regs *regs)
>  		WARN_ON_ONCE(irq_pipeline_debug() && irqs_disabled());
>  		stall_inband_nocheck();
>  		enter_from_user_mode(regs);
> +		rseq_note_user_irq_entry();
>  		trace_hardirqs_on();
>  		unstall_inband_nocheck();
>  	}
> @@ -226,8 +243,18 @@ static __always_inline void arm64_syscall_exit_to_user_mode(struct pt_regs *regs
>   */
>  static __always_inline void arm64_exit_to_user_mode(struct pt_regs *regs)
>  {
> -	local_irq_disable();
> -	irqentry_exit_to_user_mode_prepare(regs);
> +	if (irqs_pipelined()) {
> +		hard_local_irq_disable();
> +		if (running_inband()) {
> +			stall_inband_nocheck();
> +			trace_hardirqs_off();
> +			irqentry_exit_to_user_mode_prepare(regs);
> +		}
> +	} else {
> +		local_irq_disable();
> +		irqentry_exit_to_user_mode_prepare(regs);
> +	}
> +
>  	local_daif_mask();
>  	sme_exit_to_user_mode();
>  	mte_check_tfsr_exit();
> diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
> index b1eac5fd75c1..0047d0bdedd9 100644
> --- a/arch/arm64/kernel/process.c
> +++ b/arch/arm64/kernel/process.c
> @@ -748,8 +748,8 @@ static inline void debug_switch_state(void)
>  		unsigned long pmr_expected = GIC_PRIO_IRQOFF;
>  		unsigned long pmr_actual = read_sysreg_s(SYS_ICC_PMR_EL1);
>  
> -		WARN_ONCE(daif_actual != daif_expected ||
> -			  pmr_actual != pmr_expected,
> +		WARN_ONCE(running_inband() && (daif_actual != daif_expected ||
> +			  pmr_actual != pmr_expected),
>  			  "Unexpected DAIF + PMR: 0x%lx + 0x%lx (expected 0x%lx + 0x%lx)\n",
>  			  daif_actual, pmr_actual,
>  			  daif_expected, pmr_expected);
> @@ -757,7 +757,7 @@ static inline void debug_switch_state(void)
>  		unsigned long daif_expected = DAIF_PROCCTX_NOIRQ;
>  		unsigned long daif_actual = read_sysreg(daif);
>  
> -		WARN_ONCE(daif_actual != daif_expected,
> +		WARN_ONCE(running_inband() && daif_actual != daif_expected,
>  			  "Unexpected DAIF value: 0x%lx (expected 0x%lx)\n",
>  			  daif_actual, daif_expected);

That was the warning triggered by CI, that stalled the system. Is that
expected? I'm quite sure that in the oob case the DAIF flags are
different, but is WARN_ONCE() expected to completely halt the system?


>  	}
> diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h
> index 58c28b2a8f2b..61a8e129e71f 100644
> --- a/include/linux/irq-entry-common.h
> +++ b/include/linux/irq-entry-common.h
> @@ -600,6 +600,9 @@ irqentry_exit_to_kernel_mode_after_preempt(struct pt_regs *regs, irqentry_state_
>  {
>  	bool synchronized;
>  
> +	if (running_oob())
> +		return;
> +

The enter/exit code moved one layer down, from irqentry_enter() to
irqentry_enter_from_kernel_mode(), so this code needs the oob check as
well.

>  	instrumentation_begin();
>  	synchronized = irqentry_syncstage(state);
>  
> -- 
> 2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.