public inbox for xenomai@lists.linux.dev
 help / color / mirror / Atom feed
* [PATCH Dovetail 0/2] Dovetail: Fix for arm64 IRQ pipelining, API for co-kernels
@ 2026-02-16 19:05 Florian Bezdeka
  2026-02-16 19:05 ` [PATCH Dovetail 1/2] dovetail: genirq: Add request_percpu_irq_affinity_flags() Florian Bezdeka
  2026-02-16 19:05 ` [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs Florian Bezdeka
  0 siblings, 2 replies; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-16 19:05 UTC (permalink / raw)
  To: Xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka

Hi all,

There were two issues detected while doing the forward port to 6.19:

  - The signature of __request_percpu_irq() has been changed in 6.19 and
    7.0 will remove the function entirely. We need a replacement for
    that function as co-kernels (evl, cobalt) relied on it for
    registering the OOB IRQs. All existing alternatives are missing the
    flags parameter that we require.

    Patch 1 is trying to address that by introducing a dovetail specific
    helper.

    The implementation has to be adjusted a bit during the forward
    porting to 7.0, but the API can stay the same.

  - While reviewing the pipeline entry code for arm64 - triggered by a
    patch review - I noticed that the checks for the demotion case are
    wrong on arm64.

Both patches should be backported to older Dovetail branches:

  - Patch 1: Allows co-kernels to migrate to the new API without any
    need for Linux / Dovetail version checks.

  - Patch 2: Fixes a bug.

To: Xenomai <xenomai@lists.linux.dev>
Cc: Philippe Gerum <rpm@xenomai.org>
Cc: Jan Kiszka <jan.kiszka@siemens.com>

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
Florian Bezdeka (2):
      dovetail: genirq: Add request_percpu_irq_affinity_flags()
      arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs

 arch/arm64/kernel/entry-common.c |  8 ++++----
 include/linux/interrupt.h        |  5 +++++
 kernel/irq/manage.c              | 10 ++++++++++
 3 files changed, 19 insertions(+), 4 deletions(-)
---
base-commit: 61ac9499b2a582aad9e190db04bb48747e7f5821
change-id: 20260216-wip-flo-v6-19-dovetail-rebase-cdb12bee0c98

Best regards,
-- 
Florian Bezdeka <florian.bezdeka@siemens.com>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* [PATCH Dovetail 1/2] dovetail: genirq: Add request_percpu_irq_affinity_flags()
  2026-02-16 19:05 [PATCH Dovetail 0/2] Dovetail: Fix for arm64 IRQ pipelining, API for co-kernels Florian Bezdeka
@ 2026-02-16 19:05 ` Florian Bezdeka
  2026-02-16 19:05 ` [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs Florian Bezdeka
  1 sibling, 0 replies; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-16 19:05 UTC (permalink / raw)
  To: Xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka

cobalt / evl are currently using __request_percpu_irq() for setting up
OOB IRQs. In 6.19 the signature of __request_percpu_irq() has been
updated and 7.0 will remove the function entirely, so we need a
replacement.

All other variants (like the upcoming request_percpu_irq_affinity())
are missing the flags parameter which we require.

This could be backported to all supported dovetail versions. That
would allow co-kernels to switch to the new API unconditionally.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 include/linux/interrupt.h |  5 +++++
 kernel/irq/manage.c       | 10 ++++++++++
 2 files changed, 15 insertions(+)

diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index bf0511b438c65e119af917763ce92a8f3bfb4c4c..6cd8ad02ffbd87f71869d6737fbc8c1ae477c1ee 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -213,6 +213,11 @@ request_percpu_irq_affinity(unsigned int irq, irq_handler_t handler,
 				    devname, affinity, percpu_dev_id);
 }
 
+int request_percpu_irq_affinity_flags(unsigned int irq, irq_handler_t handler,
+				      unsigned long flags, const char *devname,
+				      const cpumask_t *affinity,
+				      void __percpu *dev_id);
+
 extern int __must_check
 request_percpu_nmi(unsigned int irq, irq_handler_t handler, const char *name,
 		   const struct cpumask *affinity, void __percpu *dev_id);
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index 2a2991d529e4e21e88b8f15fcd51cdb01b69411c..b2290c7ba087e4e9a4b9e94163be1f45631d7c3f 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -2580,6 +2580,16 @@ struct irqaction *create_percpu_irqaction(irq_handler_t handler, unsigned long f
 	return action;
 }
 
+int request_percpu_irq_affinity_flags(unsigned int irq, irq_handler_t handler,
+				      unsigned long flags, const char *devname,
+				      const cpumask_t *affinity,
+				      void __percpu *dev_id)
+{
+	return __request_percpu_irq(irq, handler, flags, devname, affinity,
+				    dev_id);
+}
+EXPORT_SYMBOL_GPL(request_percpu_irq_affinity_flags);
+
 /**
  * __request_percpu_irq - allocate a percpu interrupt line
  * @irq:	Interrupt line to allocate

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-16 19:05 [PATCH Dovetail 0/2] Dovetail: Fix for arm64 IRQ pipelining, API for co-kernels Florian Bezdeka
  2026-02-16 19:05 ` [PATCH Dovetail 1/2] dovetail: genirq: Add request_percpu_irq_affinity_flags() Florian Bezdeka
@ 2026-02-16 19:05 ` Florian Bezdeka
  2026-02-17  8:00   ` Philippe Gerum
  1 sibling, 1 reply; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-16 19:05 UTC (permalink / raw)
  To: Xenomai; +Cc: Philippe Gerum, Jan Kiszka, Florian Bezdeka

While reviewing some of the low level pipeline code I realized that
the checks for task demotion are wrong on arm64.

el0: The demotion check was missing in the oob case. We have to check
     for running_inband() only as user_mode(regs) will always be true.
     We are serving an IRQ over el0, so application / user mode.

el1: The demotion check was unnecessary and "inactive" as
     user_mode(regs) is never true on el1, we are serving an IRQ over
     kernel mode.

Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
---
 arch/arm64/kernel/entry-common.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
 	do_interrupt_handler(regs, handler);
 	/* Done, unwind now. */
 	handle_irq_pipelined_finish(prevd, regs);
+	if (running_inband()) {
+		stall_inband_nocheck();
+		irqentry_exit_to_user_mode(regs);
+	}
 	instrumentation_end();
 	arm64_exit_to_user_mode(regs);
 }
@@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
 		prevd = handle_irq_pipelined_prepare(regs);
 		do_interrupt_handler(regs, handler);
 		handle_irq_pipelined_finish(prevd, regs);
-		if (running_inband() && user_mode(regs)) {
-			stall_inband_nocheck();
-			irqentry_exit_to_user_mode(regs);
-		}
 		instrumentation_end();
 		mte_check_tfsr_exit();
 		return;

-- 
2.53.0


^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-16 19:05 ` [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs Florian Bezdeka
@ 2026-02-17  8:00   ` Philippe Gerum
  2026-02-17  8:12     ` Florian Bezdeka
  0 siblings, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17  8:00 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> While reviewing some of the low level pipeline code I realized that
> the checks for task demotion are wrong on arm64.
>
> el0: The demotion check was missing in the oob case. We have to check
>      for running_inband() only as user_mode(regs) will always be true.
>      We are serving an IRQ over el0, so application / user mode.
>
> el1: The demotion check was unnecessary and "inactive" as
>      user_mode(regs) is never true on el1, we are serving an IRQ over
>      kernel mode.
>

If the demotion happens from el1, you still want to check for a
rescheduling opportunity (i.e. kernel preemption case).

> Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> ---
>  arch/arm64/kernel/entry-common.c | 8 ++++----
>  1 file changed, 4 insertions(+), 4 deletions(-)
>
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
>  	do_interrupt_handler(regs, handler);
>  	/* Done, unwind now. */
>  	handle_irq_pipelined_finish(prevd, regs);
> +	if (running_inband()) {
> +		stall_inband_nocheck();
> +		irqentry_exit_to_user_mode(regs);
> +	}
>  	instrumentation_end();
>  	arm64_exit_to_user_mode(regs);
>  }
> @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>  		prevd = handle_irq_pipelined_prepare(regs);
>  		do_interrupt_handler(regs, handler);
>  		handle_irq_pipelined_finish(prevd, regs);
> -		if (running_inband() && user_mode(regs)) {
> -			stall_inband_nocheck();
> -			irqentry_exit_to_user_mode(regs);
> -		}
>  		instrumentation_end();
>  		mte_check_tfsr_exit();
>  		return;

diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
index e0227d467cef4..770fc4059e083 100644
--- a/arch/arm64/kernel/entry-common.c
+++ b/arch/arm64/kernel/entry-common.c
@@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
 		prevd = handle_irq_pipelined_prepare(regs);
 		do_interrupt_handler(regs, handler);
 		handle_irq_pipelined_finish(prevd, regs);
-		if (running_inband() && user_mode(regs)) {
-			stall_inband_nocheck();
-			irqentry_exit_to_user_mode(regs);
-		}
+		if (running_inband())
+			goto out_irqentry;
 		instrumentation_end();
 		mte_check_tfsr_exit();
 		return;
@@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
 	trace_hardirqs_on();
 	unstall_inband_nocheck();
 	handle_irq_pipelined_finish(prevd, regs);
+out_irqentry:
 	stall_inband_nocheck();
 	trace_hardirqs_off();
 	instrumentation_end();

-- 
Philippe.

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:00   ` Philippe Gerum
@ 2026-02-17  8:12     ` Florian Bezdeka
  2026-02-17  8:24       ` Florian Bezdeka
  0 siblings, 1 reply; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17  8:12 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> 
> > While reviewing some of the low level pipeline code I realized that
> > the checks for task demotion are wrong on arm64.
> > 
> > el0: The demotion check was missing in the oob case. We have to check
> >      for running_inband() only as user_mode(regs) will always be true.
> >      We are serving an IRQ over el0, so application / user mode.
> > 
> > el1: The demotion check was unnecessary and "inactive" as
> >      user_mode(regs) is never true on el1, we are serving an IRQ over
> >      kernel mode.
> > 
> 
> If the demotion happens from el1, you still want to check for a
> rescheduling opportunity (i.e. kernel preemption case).
> 
> > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > ---
> >  arch/arm64/kernel/entry-common.c | 8 ++++----
> >  1 file changed, 4 insertions(+), 4 deletions(-)
> > 
> > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
> > --- a/arch/arm64/kernel/entry-common.c
> > +++ b/arch/arm64/kernel/entry-common.c
> > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
> >  	do_interrupt_handler(regs, handler);
> >  	/* Done, unwind now. */
> >  	handle_irq_pipelined_finish(prevd, regs);
> > +	if (running_inband()) {
> > +		stall_inband_nocheck();
> > +		irqentry_exit_to_user_mode(regs);
> > +	}
> >  	instrumentation_end();
> >  	arm64_exit_to_user_mode(regs);
> >  }
> > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> >  		prevd = handle_irq_pipelined_prepare(regs);
> >  		do_interrupt_handler(regs, handler);
> >  		handle_irq_pipelined_finish(prevd, regs);
> > -		if (running_inband() && user_mode(regs)) {
> > -			stall_inband_nocheck();
> > -			irqentry_exit_to_user_mode(regs);
> > -		}
> >  		instrumentation_end();
> >  		mte_check_tfsr_exit();
> >  		return;
> 
> diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> index e0227d467cef4..770fc4059e083 100644
> --- a/arch/arm64/kernel/entry-common.c
> +++ b/arch/arm64/kernel/entry-common.c
> @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>  		prevd = handle_irq_pipelined_prepare(regs);
>  		do_interrupt_handler(regs, handler);
>  		handle_irq_pipelined_finish(prevd, regs);
> -		if (running_inband() && user_mode(regs)) {
> -			stall_inband_nocheck();
> -			irqentry_exit_to_user_mode(regs);
> -		}
> +		if (running_inband())
> +			goto out_irqentry;
>  		instrumentation_end();
>  		mte_check_tfsr_exit();
>  		return;
> @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>  	trace_hardirqs_on();
>  	unstall_inband_nocheck();
>  	handle_irq_pipelined_finish(prevd, regs);
> +out_irqentry:
>  	stall_inband_nocheck();
>  	trace_hardirqs_off();
>  	instrumentation_end();
> 

That would look a bit imbalanced. We would have one additional
trace_hardirqs_off() and one irqentry_exit() call without counterparts.

Is that really OK? Testing...

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:12     ` Florian Bezdeka
@ 2026-02-17  8:24       ` Florian Bezdeka
  2026-02-17  8:41         ` Philippe Gerum
  2026-02-17  8:49         ` Philippe Gerum
  0 siblings, 2 replies; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17  8:24 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 09:12 +0100, Florian Bezdeka wrote:
> On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> > 
> > > While reviewing some of the low level pipeline code I realized that
> > > the checks for task demotion are wrong on arm64.
> > > 
> > > el0: The demotion check was missing in the oob case. We have to check
> > >      for running_inband() only as user_mode(regs) will always be true.
> > >      We are serving an IRQ over el0, so application / user mode.
> > > 
> > > el1: The demotion check was unnecessary and "inactive" as
> > >      user_mode(regs) is never true on el1, we are serving an IRQ over
> > >      kernel mode.
> > > 
> > 
> > If the demotion happens from el1, you still want to check for a
> > rescheduling opportunity (i.e. kernel preemption case).
> > 
> > > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > > ---
> > >  arch/arm64/kernel/entry-common.c | 8 ++++----
> > >  1 file changed, 4 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
> > > --- a/arch/arm64/kernel/entry-common.c
> > > +++ b/arch/arm64/kernel/entry-common.c
> > > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
> > >  	do_interrupt_handler(regs, handler);
> > >  	/* Done, unwind now. */
> > >  	handle_irq_pipelined_finish(prevd, regs);
> > > +	if (running_inband()) {
> > > +		stall_inband_nocheck();
> > > +		irqentry_exit_to_user_mode(regs);
> > > +	}
> > >  	instrumentation_end();
> > >  	arm64_exit_to_user_mode(regs);
> > >  }
> > > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> > >  		prevd = handle_irq_pipelined_prepare(regs);
> > >  		do_interrupt_handler(regs, handler);
> > >  		handle_irq_pipelined_finish(prevd, regs);
> > > -		if (running_inband() && user_mode(regs)) {
> > > -			stall_inband_nocheck();
> > > -			irqentry_exit_to_user_mode(regs);
> > > -		}
> > >  		instrumentation_end();
> > >  		mte_check_tfsr_exit();
> > >  		return;
> > 
> > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > index e0227d467cef4..770fc4059e083 100644
> > --- a/arch/arm64/kernel/entry-common.c
> > +++ b/arch/arm64/kernel/entry-common.c
> > @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> >  		prevd = handle_irq_pipelined_prepare(regs);
> >  		do_interrupt_handler(regs, handler);
> >  		handle_irq_pipelined_finish(prevd, regs);
> > -		if (running_inband() && user_mode(regs)) {
> > -			stall_inband_nocheck();
> > -			irqentry_exit_to_user_mode(regs);
> > -		}
> > +		if (running_inband())
> > +			goto out_irqentry;
> >  		instrumentation_end();
> >  		mte_check_tfsr_exit();
> >  		return;
> > @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> >  	trace_hardirqs_on();
> >  	unstall_inband_nocheck();
> >  	handle_irq_pipelined_finish(prevd, regs);
> > +out_irqentry:
> >  	stall_inband_nocheck();
> >  	trace_hardirqs_off();
> >  	instrumentation_end();
> > 
> 
> That would look a bit imbalanced. We would have one additional
> trace_hardirqs_off() and one irqentry_exit() call without counterparts.
> 
> Is that really OK? Testing...

Nope, doesn't boot up on my arm64 qemu.

Comparing with x86 again, I think that my proposal is "correct" in terms
of identical to what x86 does. Do all architectures have a gap here?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:24       ` Florian Bezdeka
@ 2026-02-17  8:41         ` Philippe Gerum
  2026-02-17  9:16           ` Florian Bezdeka
  2026-02-17  8:49         ` Philippe Gerum
  1 sibling, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17  8:41 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

WFlorian Bezdeka <florian.bezdeka@siemens.com> writes:

> On Tue, 2026-02-17 at 09:12 +0100, Florian Bezdeka wrote:
>> On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
>> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> > 
>> > > While reviewing some of the low level pipeline code I realized that
>> > > the checks for task demotion are wrong on arm64.
>> > > 
>> > > el0: The demotion check was missing in the oob case. We have to check
>> > >      for running_inband() only as user_mode(regs) will always be true.
>> > >      We are serving an IRQ over el0, so application / user mode.
>> > > 
>> > > el1: The demotion check was unnecessary and "inactive" as
>> > >      user_mode(regs) is never true on el1, we are serving an IRQ over
>> > >      kernel mode.
>> > > 
>> > 
>> > If the demotion happens from el1, you still want to check for a
>> > rescheduling opportunity (i.e. kernel preemption case).
>> > 
>> > > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
>> > > ---
>> > >  arch/arm64/kernel/entry-common.c | 8 ++++----
>> > >  1 file changed, 4 insertions(+), 4 deletions(-)
>> > > 
>> > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
>> > > --- a/arch/arm64/kernel/entry-common.c
>> > > +++ b/arch/arm64/kernel/entry-common.c
>> > > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
>> > >  	do_interrupt_handler(regs, handler);
>> > >  	/* Done, unwind now. */
>> > >  	handle_irq_pipelined_finish(prevd, regs);
>> > > +	if (running_inband()) {
>> > > +		stall_inband_nocheck();
>> > > +		irqentry_exit_to_user_mode(regs);
>> > > +	}
>> > >  	instrumentation_end();
>> > >  	arm64_exit_to_user_mode(regs);
>> > >  }
>> > > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> > >  		prevd = handle_irq_pipelined_prepare(regs);
>> > >  		do_interrupt_handler(regs, handler);
>> > >  		handle_irq_pipelined_finish(prevd, regs);
>> > > -		if (running_inband() && user_mode(regs)) {
>> > > -			stall_inband_nocheck();
>> > > -			irqentry_exit_to_user_mode(regs);
>> > > -		}
>> > >  		instrumentation_end();
>> > >  		mte_check_tfsr_exit();
>> > >  		return;
>> > 
>> > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > index e0227d467cef4..770fc4059e083 100644
>> > --- a/arch/arm64/kernel/entry-common.c
>> > +++ b/arch/arm64/kernel/entry-common.c
>> > @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> >  		prevd = handle_irq_pipelined_prepare(regs);
>> >  		do_interrupt_handler(regs, handler);
>> >  		handle_irq_pipelined_finish(prevd, regs);
>> > -		if (running_inband() && user_mode(regs)) {
>> > -			stall_inband_nocheck();
>> > -			irqentry_exit_to_user_mode(regs);
>> > -		}
>> > +		if (running_inband())
>> > +			goto out_irqentry;
>> >  		instrumentation_end();
>> >  		mte_check_tfsr_exit();
>> >  		return;
>> > @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> >  	trace_hardirqs_on();
>> >  	unstall_inband_nocheck();
>> >  	handle_irq_pipelined_finish(prevd, regs);
>> > +out_irqentry:
>> >  	stall_inband_nocheck();
>> >  	trace_hardirqs_off();
>> >  	instrumentation_end();
>> > 
>> 
>> That would look a bit imbalanced. We would have one additional
>> trace_hardirqs_off() and one irqentry_exit() call without counterparts.
>> 
>> Is that really OK? Testing...
>
> Nope, doesn't boot up on my arm64 qemu.
>
> Comparing with x86 again, I think that my proposal is "correct" in terms
> of identical to what x86 does. Do all architectures have a gap here?

x86 has a single implementation for both user and kernel preemption
paths, arm64 has two since the privilege level is explicitly stated by
the irq handler being called, but this still must translate identically
logically speaking. Your implementation is missing the kernel preemption
path after demotion.

i.e. when checking for running_oob() || irqs_disabled(), the cases
covered are:

(1) in-band user path on entry (implies !irqs_disabled())
(2) oob user path on entry (might be demoted)
(3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
  filtered out by irqentry_exit())
(4) oob kernel path on entry (might be demoted)

Therefore, with your patch in, el1 is now missing (4).

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:24       ` Florian Bezdeka
  2026-02-17  8:41         ` Philippe Gerum
@ 2026-02-17  8:49         ` Philippe Gerum
  2026-02-17  9:01           ` Florian Bezdeka
  1 sibling, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17  8:49 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On Tue, 2026-02-17 at 09:12 +0100, Florian Bezdeka wrote:
>> On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
>> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> > 
>> > > While reviewing some of the low level pipeline code I realized that
>> > > the checks for task demotion are wrong on arm64.
>> > > 
>> > > el0: The demotion check was missing in the oob case. We have to check
>> > >      for running_inband() only as user_mode(regs) will always be true.
>> > >      We are serving an IRQ over el0, so application / user mode.
>> > > 
>> > > el1: The demotion check was unnecessary and "inactive" as
>> > >      user_mode(regs) is never true on el1, we are serving an IRQ over
>> > >      kernel mode.
>> > > 
>> > 
>> > If the demotion happens from el1, you still want to check for a
>> > rescheduling opportunity (i.e. kernel preemption case).
>> > 
>> > > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
>> > > ---
>> > >  arch/arm64/kernel/entry-common.c | 8 ++++----
>> > >  1 file changed, 4 insertions(+), 4 deletions(-)
>> > > 
>> > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
>> > > --- a/arch/arm64/kernel/entry-common.c
>> > > +++ b/arch/arm64/kernel/entry-common.c
>> > > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
>> > >  	do_interrupt_handler(regs, handler);
>> > >  	/* Done, unwind now. */
>> > >  	handle_irq_pipelined_finish(prevd, regs);
>> > > +	if (running_inband()) {
>> > > +		stall_inband_nocheck();
>> > > +		irqentry_exit_to_user_mode(regs);
>> > > +	}
>> > >  	instrumentation_end();
>> > >  	arm64_exit_to_user_mode(regs);
>> > >  }
>> > > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> > >  		prevd = handle_irq_pipelined_prepare(regs);
>> > >  		do_interrupt_handler(regs, handler);
>> > >  		handle_irq_pipelined_finish(prevd, regs);
>> > > -		if (running_inband() && user_mode(regs)) {
>> > > -			stall_inband_nocheck();
>> > > -			irqentry_exit_to_user_mode(regs);
>> > > -		}
>> > >  		instrumentation_end();
>> > >  		mte_check_tfsr_exit();
>> > >  		return;
>> > 
>> > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > index e0227d467cef4..770fc4059e083 100644
>> > --- a/arch/arm64/kernel/entry-common.c
>> > +++ b/arch/arm64/kernel/entry-common.c
>> > @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> >  		prevd = handle_irq_pipelined_prepare(regs);
>> >  		do_interrupt_handler(regs, handler);
>> >  		handle_irq_pipelined_finish(prevd, regs);
>> > -		if (running_inband() && user_mode(regs)) {
>> > -			stall_inband_nocheck();
>> > -			irqentry_exit_to_user_mode(regs);
>> > -		}
>> > +		if (running_inband())
>> > +			goto out_irqentry;
>> >  		instrumentation_end();
>> >  		mte_check_tfsr_exit();
>> >  		return;
>> > @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> >  	trace_hardirqs_on();
>> >  	unstall_inband_nocheck();
>> >  	handle_irq_pipelined_finish(prevd, regs);
>> > +out_irqentry:
>> >  	stall_inband_nocheck();
>> >  	trace_hardirqs_off();
>> >  	instrumentation_end();
>> > 
>> 
>> That would look a bit imbalanced. We would have one additional
>> trace_hardirqs_off() and one irqentry_exit() call without counterparts.
>> 
>> Is that really OK? Testing...
>
> Nope, doesn't boot up on my arm64 qemu.
>

This patch runs fine on my end, survives the full evl test suite,
including the hectic test. Which kernel preemption model are you using?
mine is this one:

Linux qemu-arm64-evl 6.18.7-00979-gb2cf536d0898-dirty #286 SMP PREEMPT_RT EVL Tue Feb 17 09:45:50 CET 2026 aarch64 GNU/Linux

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:49         ` Philippe Gerum
@ 2026-02-17  9:01           ` Florian Bezdeka
  2026-02-17  9:10             ` Philippe Gerum
  0 siblings, 1 reply; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17  9:01 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 09:49 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> 
> > On Tue, 2026-02-17 at 09:12 +0100, Florian Bezdeka wrote:
> > > On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
> > > > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> > > > 
> > > > > While reviewing some of the low level pipeline code I realized that
> > > > > the checks for task demotion are wrong on arm64.
> > > > > 
> > > > > el0: The demotion check was missing in the oob case. We have to check
> > > > >      for running_inband() only as user_mode(regs) will always be true.
> > > > >      We are serving an IRQ over el0, so application / user mode.
> > > > > 
> > > > > el1: The demotion check was unnecessary and "inactive" as
> > > > >      user_mode(regs) is never true on el1, we are serving an IRQ over
> > > > >      kernel mode.
> > > > > 
> > > > 
> > > > If the demotion happens from el1, you still want to check for a
> > > > rescheduling opportunity (i.e. kernel preemption case).
> > > > 
> > > > > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
> > > > > ---
> > > > >  arch/arm64/kernel/entry-common.c | 8 ++++----
> > > > >  1 file changed, 4 insertions(+), 4 deletions(-)
> > > > > 
> > > > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > > > > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
> > > > > --- a/arch/arm64/kernel/entry-common.c
> > > > > +++ b/arch/arm64/kernel/entry-common.c
> > > > > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
> > > > >  	do_interrupt_handler(regs, handler);
> > > > >  	/* Done, unwind now. */
> > > > >  	handle_irq_pipelined_finish(prevd, regs);
> > > > > +	if (running_inband()) {
> > > > > +		stall_inband_nocheck();
> > > > > +		irqentry_exit_to_user_mode(regs);
> > > > > +	}
> > > > >  	instrumentation_end();
> > > > >  	arm64_exit_to_user_mode(regs);
> > > > >  }
> > > > > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> > > > >  		prevd = handle_irq_pipelined_prepare(regs);
> > > > >  		do_interrupt_handler(regs, handler);
> > > > >  		handle_irq_pipelined_finish(prevd, regs);
> > > > > -		if (running_inband() && user_mode(regs)) {
> > > > > -			stall_inband_nocheck();
> > > > > -			irqentry_exit_to_user_mode(regs);
> > > > > -		}
> > > > >  		instrumentation_end();
> > > > >  		mte_check_tfsr_exit();
> > > > >  		return;
> > > > 
> > > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
> > > > index e0227d467cef4..770fc4059e083 100644
> > > > --- a/arch/arm64/kernel/entry-common.c
> > > > +++ b/arch/arm64/kernel/entry-common.c
> > > > @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> > > >  		prevd = handle_irq_pipelined_prepare(regs);
> > > >  		do_interrupt_handler(regs, handler);
> > > >  		handle_irq_pipelined_finish(prevd, regs);
> > > > -		if (running_inband() && user_mode(regs)) {
> > > > -			stall_inband_nocheck();
> > > > -			irqentry_exit_to_user_mode(regs);
> > > > -		}
> > > > +		if (running_inband())
> > > > +			goto out_irqentry;
> > > >  		instrumentation_end();
> > > >  		mte_check_tfsr_exit();
> > > >  		return;
> > > > @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
> > > >  	trace_hardirqs_on();
> > > >  	unstall_inband_nocheck();
> > > >  	handle_irq_pipelined_finish(prevd, regs);
> > > > +out_irqentry:
> > > >  	stall_inband_nocheck();
> > > >  	trace_hardirqs_off();
> > > >  	instrumentation_end();
> > > > 
> > > 
> > > That would look a bit imbalanced. We would have one additional
> > > trace_hardirqs_off() and one irqentry_exit() call without counterparts.
> > > 
> > > Is that really OK? Testing...
> > 
> > Nope, doesn't boot up on my arm64 qemu.
> > 
> 
> This patch runs fine on my end, survives the full evl test suite,
> including the hectic test. Which kernel preemption model are you using?
> mine is this one:
> 
> Linux qemu-arm64-evl 6.18.7-00979-gb2cf536d0898-dirty #286 SMP PREEMPT_RT EVL Tue Feb 17 09:45:50 CET 2026 aarch64 GNU/Linux

Linux demo 6.19.0-00150-gcb2e9689c529-dirty #232 SMP PREEMPT DOVETAIL Tue Feb 17 09:55:00 CET 2026 aarch64 GNU/Linux

Let me schedule a CI run to see what real devices do.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  9:01           ` Florian Bezdeka
@ 2026-02-17  9:10             ` Philippe Gerum
  0 siblings, 0 replies; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17  9:10 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On Tue, 2026-02-17 at 09:49 +0100, Philippe Gerum wrote:
>> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> 
>> > On Tue, 2026-02-17 at 09:12 +0100, Florian Bezdeka wrote:
>> > > On Tue, 2026-02-17 at 09:00 +0100, Philippe Gerum wrote:
>> > > > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> > > > 
>> > > > > While reviewing some of the low level pipeline code I realized that
>> > > > > the checks for task demotion are wrong on arm64.
>> > > > > 
>> > > > > el0: The demotion check was missing in the oob case. We have to check
>> > > > >      for running_inband() only as user_mode(regs) will always be true.
>> > > > >      We are serving an IRQ over el0, so application / user mode.
>> > > > > 
>> > > > > el1: The demotion check was unnecessary and "inactive" as
>> > > > >      user_mode(regs) is never true on el1, we are serving an IRQ over
>> > > > >      kernel mode.
>> > > > > 
>> > > > 
>> > > > If the demotion happens from el1, you still want to check for a
>> > > > rescheduling opportunity (i.e. kernel preemption case).
>> > > > 
>> > > > > Signed-off-by: Florian Bezdeka <florian.bezdeka@siemens.com>
>> > > > > ---
>> > > > >  arch/arm64/kernel/entry-common.c | 8 ++++----
>> > > > >  1 file changed, 4 insertions(+), 4 deletions(-)
>> > > > > 
>> > > > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > > > > index 07fa70713ce04eaf3df9223354babcecde923280..9c99eb3d18c459a90e1f7ce4e4c307e235e457a2 100644
>> > > > > --- a/arch/arm64/kernel/entry-common.c
>> > > > > +++ b/arch/arm64/kernel/entry-common.c
>> > > > > @@ -73,6 +73,10 @@ static noinstr void arm64_pipeline_el0_irq(struct pt_regs *regs,
>> > > > >  	do_interrupt_handler(regs, handler);
>> > > > >  	/* Done, unwind now. */
>> > > > >  	handle_irq_pipelined_finish(prevd, regs);
>> > > > > +	if (running_inband()) {
>> > > > > +		stall_inband_nocheck();
>> > > > > +		irqentry_exit_to_user_mode(regs);
>> > > > > +	}
>> > > > >  	instrumentation_end();
>> > > > >  	arm64_exit_to_user_mode(regs);
>> > > > >  }
>> > > > > @@ -90,10 +94,6 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> > > > >  		prevd = handle_irq_pipelined_prepare(regs);
>> > > > >  		do_interrupt_handler(regs, handler);
>> > > > >  		handle_irq_pipelined_finish(prevd, regs);
>> > > > > -		if (running_inband() && user_mode(regs)) {
>> > > > > -			stall_inband_nocheck();
>> > > > > -			irqentry_exit_to_user_mode(regs);
>> > > > > -		}
>> > > > >  		instrumentation_end();
>> > > > >  		mte_check_tfsr_exit();
>> > > > >  		return;
>> > > > 
>> > > > diff --git a/arch/arm64/kernel/entry-common.c b/arch/arm64/kernel/entry-common.c
>> > > > index e0227d467cef4..770fc4059e083 100644
>> > > > --- a/arch/arm64/kernel/entry-common.c
>> > > > +++ b/arch/arm64/kernel/entry-common.c
>> > > > @@ -90,10 +90,8 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> > > >  		prevd = handle_irq_pipelined_prepare(regs);
>> > > >  		do_interrupt_handler(regs, handler);
>> > > >  		handle_irq_pipelined_finish(prevd, regs);
>> > > > -		if (running_inband() && user_mode(regs)) {
>> > > > -			stall_inband_nocheck();
>> > > > -			irqentry_exit_to_user_mode(regs);
>> > > > -		}
>> > > > +		if (running_inband())
>> > > > +			goto out_irqentry;
>> > > >  		instrumentation_end();
>> > > >  		mte_check_tfsr_exit();
>> > > >  		return;
>> > > > @@ -109,6 +107,7 @@ static noinstr void arm64_pipeline_el1_irq(struct pt_regs *regs,
>> > > >  	trace_hardirqs_on();
>> > > >  	unstall_inband_nocheck();
>> > > >  	handle_irq_pipelined_finish(prevd, regs);
>> > > > +out_irqentry:
>> > > >  	stall_inband_nocheck();
>> > > >  	trace_hardirqs_off();
>> > > >  	instrumentation_end();
>> > > > 
>> > > 
>> > > That would look a bit imbalanced. We would have one additional
>> > > trace_hardirqs_off() and one irqentry_exit() call without counterparts.
>> > > 
>> > > Is that really OK? Testing...
>> > 
>> > Nope, doesn't boot up on my arm64 qemu.
>> > 
>> 
>> This patch runs fine on my end, survives the full evl test suite,
>> including the hectic test. Which kernel preemption model are you using?
>> mine is this one:
>> 
>> Linux qemu-arm64-evl 6.18.7-00979-gb2cf536d0898-dirty #286 SMP PREEMPT_RT EVL Tue Feb 17 09:45:50 CET 2026 aarch64 GNU/Linux
>
> Linux demo 6.19.0-00150-gcb2e9689c529-dirty #232 SMP PREEMPT DOVETAIL Tue Feb 17 09:55:00 CET 2026 aarch64 GNU/Linux
>
> Let me schedule a CI run to see what real devices do.

Nah, this can't work. My patch is giving trash to irqentry_exit()
instead of a proper state.

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  8:41         ` Philippe Gerum
@ 2026-02-17  9:16           ` Florian Bezdeka
  2026-02-17  9:40             ` Philippe Gerum
  0 siblings, 1 reply; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17  9:16 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
> > Comparing with x86 again, I think that my proposal is "correct" in terms
> > of identical to what x86 does. Do all architectures have a gap here?
> 
> x86 has a single implementation for both user and kernel preemption
> paths, arm64 has two since the privilege level is explicitly stated by
> the irq handler being called, but this still must translate identically
> logically speaking. Your implementation is missing the kernel preemption
> path after demotion.
> 
> i.e. when checking for running_oob() || irqs_disabled(), the cases
> covered are:
> 
> (1) in-band user path on entry (implies !irqs_disabled())
> (2) oob user path on entry (might be demoted)
> (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
>   filtered out by irqentry_exit())
> (4) oob kernel path on entry (might be demoted)
> 
> Therefore, with your patch in, el1 is now missing (4).

Right, but I'm wondering if x86 ignores this case as well.

After demotion of a oob kernel path entry, user_mode() should still be
false - bypassing the call to irqentry_exit_to_user_mode() - No?

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  9:16           ` Florian Bezdeka
@ 2026-02-17  9:40             ` Philippe Gerum
  2026-02-17 10:11               ` Philippe Gerum
  0 siblings, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17  9:40 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
>> > Comparing with x86 again, I think that my proposal is "correct" in terms
>> > of identical to what x86 does. Do all architectures have a gap here?
>> 
>> x86 has a single implementation for both user and kernel preemption
>> paths, arm64 has two since the privilege level is explicitly stated by
>> the irq handler being called, but this still must translate identically
>> logically speaking. Your implementation is missing the kernel preemption
>> path after demotion.
>> 
>> i.e. when checking for running_oob() || irqs_disabled(), the cases
>> covered are:
>> 
>> (1) in-band user path on entry (implies !irqs_disabled())
>> (2) oob user path on entry (might be demoted)
>> (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
>>   filtered out by irqentry_exit())
>> (4) oob kernel path on entry (might be demoted)
>> 
>> Therefore, with your patch in, el1 is now missing (4).
>
> Right, but I'm wondering if x86 ignores this case as well.
>
> After demotion of a oob kernel path entry, user_mode() should still be
> false - bypassing the call to irqentry_exit_to_user_mode() - No?

Yes, x86 assumes that a kernel path demoted to in-band is going to cross
an IRQ synchronization point shortly after on return to the preempted
context. Now, with hindsight, the question is: are we 100% certain of
that? Any real (hw) IRQ over the in-band stage would trigger the
synchronization as expected, but a synthetic one posted from the oob
stage might linger if this assumption ends up being wrong. I need to
have a second look at this code.

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17  9:40             ` Philippe Gerum
@ 2026-02-17 10:11               ` Philippe Gerum
  2026-02-17 11:23                 ` Florian Bezdeka
  0 siblings, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17 10:11 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Philippe Gerum <rpm@xenomai.org> writes:

> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>
>> On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
>>> > Comparing with x86 again, I think that my proposal is "correct" in terms
>>> > of identical to what x86 does. Do all architectures have a gap here?
>>> 
>>> x86 has a single implementation for both user and kernel preemption
>>> paths, arm64 has two since the privilege level is explicitly stated by
>>> the irq handler being called, but this still must translate identically
>>> logically speaking. Your implementation is missing the kernel preemption
>>> path after demotion.
>>> 
>>> i.e. when checking for running_oob() || irqs_disabled(), the cases
>>> covered are:
>>> 
>>> (1) in-band user path on entry (implies !irqs_disabled())
>>> (2) oob user path on entry (might be demoted)
>>> (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
>>>   filtered out by irqentry_exit())
>>> (4) oob kernel path on entry (might be demoted)
>>> 
>>> Therefore, with your patch in, el1 is now missing (4).
>>
>> Right, but I'm wondering if x86 ignores this case as well.
>>
>> After demotion of a oob kernel path entry, user_mode() should still be
>> false - bypassing the call to irqentry_exit_to_user_mode() - No?
>
> Yes, x86 assumes that a kernel path demoted to in-band is going to cross
> an IRQ synchronization point shortly after on return to the preempted
> context. Now, with hindsight, the question is: are we 100% certain of
> that? Any real (hw) IRQ over the in-band stage would trigger the
> synchronization as expected, but a synthetic one posted from the oob
> stage might linger if this assumption ends up being wrong. I need to
> have a second look at this code.

Which means that your latest patch series is ok and complete. The change
if any would most likely happen in the generic pipeline bits.

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17 10:11               ` Philippe Gerum
@ 2026-02-17 11:23                 ` Florian Bezdeka
  2026-02-17 13:31                   ` Philippe Gerum
  0 siblings, 1 reply; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17 11:23 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 11:11 +0100, Philippe Gerum wrote:
> Philippe Gerum <rpm@xenomai.org> writes:
> 
> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> > 
> > > On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
> > > > > Comparing with x86 again, I think that my proposal is "correct" in terms
> > > > > of identical to what x86 does. Do all architectures have a gap here?
> > > > 
> > > > x86 has a single implementation for both user and kernel preemption
> > > > paths, arm64 has two since the privilege level is explicitly stated by
> > > > the irq handler being called, but this still must translate identically
> > > > logically speaking. Your implementation is missing the kernel preemption
> > > > path after demotion.
> > > > 
> > > > i.e. when checking for running_oob() || irqs_disabled(), the cases
> > > > covered are:
> > > > 
> > > > (1) in-band user path on entry (implies !irqs_disabled())
> > > > (2) oob user path on entry (might be demoted)
> > > > (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
> > > >   filtered out by irqentry_exit())
> > > > (4) oob kernel path on entry (might be demoted)
> > > > 
> > > > Therefore, with your patch in, el1 is now missing (4).
> > > 
> > > Right, but I'm wondering if x86 ignores this case as well.
> > > 
> > > After demotion of a oob kernel path entry, user_mode() should still be
> > > false - bypassing the call to irqentry_exit_to_user_mode() - No?
> > 
> > Yes, x86 assumes that a kernel path demoted to in-band is going to cross
> > an IRQ synchronization point shortly after on return to the preempted
> > context. Now, with hindsight, the question is: are we 100% certain of
> > that? Any real (hw) IRQ over the in-band stage would trigger the
> > synchronization as expected, but a synthetic one posted from the oob
> > stage might linger if this assumption ends up being wrong. I need to
> > have a second look at this code.
> 
> Which means that your latest patch series is ok and complete. The change
> if any would most likely happen in the generic pipeline bits.

I think (2) is still wrong on arm64 now, so:

@@ -65,15 +65,17 @@ static noinstr void arm64_pipeline_el0_irq(struct
pt_regs *regs,
                                void (*handler)(struct pt_regs *))
 {
        struct irq_stage_data *prevd;
+       bool oob_on_enter;
 
        arm64_enter_from_user_mode(regs);
        instrumentation_begin();
        /* Prep for handling, switching oob if needed. */
+       oob_on_enter = running_oob();
        prevd = handle_irq_pipelined_prepare(regs);
        do_interrupt_handler(regs, handler);
        /* Done, unwind now. */
        handle_irq_pipelined_finish(prevd, regs);
-       if (running_inband()) {
+       if (oob_on_enter && running_inband()) {
                stall_inband_nocheck();
                irqentry_exit_to_user_mode(regs);
        }

Do you agree?

I will prepare a v2 after some more CI testing.

Florian


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17 11:23                 ` Florian Bezdeka
@ 2026-02-17 13:31                   ` Philippe Gerum
  2026-02-17 14:37                     ` Florian Bezdeka
  0 siblings, 1 reply; 16+ messages in thread
From: Philippe Gerum @ 2026-02-17 13:31 UTC (permalink / raw)
  To: Florian Bezdeka; +Cc: Xenomai, Jan Kiszka

Florian Bezdeka <florian.bezdeka@siemens.com> writes:

> On Tue, 2026-02-17 at 11:11 +0100, Philippe Gerum wrote:
>> Philippe Gerum <rpm@xenomai.org> writes:
>> 
>> > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
>> > 
>> > > On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
>> > > > > Comparing with x86 again, I think that my proposal is "correct" in terms
>> > > > > of identical to what x86 does. Do all architectures have a gap here?
>> > > > 
>> > > > x86 has a single implementation for both user and kernel preemption
>> > > > paths, arm64 has two since the privilege level is explicitly stated by
>> > > > the irq handler being called, but this still must translate identically
>> > > > logically speaking. Your implementation is missing the kernel preemption
>> > > > path after demotion.
>> > > > 
>> > > > i.e. when checking for running_oob() || irqs_disabled(), the cases
>> > > > covered are:
>> > > > 
>> > > > (1) in-band user path on entry (implies !irqs_disabled())
>> > > > (2) oob user path on entry (might be demoted)
>> > > > (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
>> > > >   filtered out by irqentry_exit())
>> > > > (4) oob kernel path on entry (might be demoted)
>> > > > 
>> > > > Therefore, with your patch in, el1 is now missing (4).
>> > > 
>> > > Right, but I'm wondering if x86 ignores this case as well.
>> > > 
>> > > After demotion of a oob kernel path entry, user_mode() should still be
>> > > false - bypassing the call to irqentry_exit_to_user_mode() - No?
>> > 
>> > Yes, x86 assumes that a kernel path demoted to in-band is going to cross
>> > an IRQ synchronization point shortly after on return to the preempted
>> > context. Now, with hindsight, the question is: are we 100% certain of
>> > that? Any real (hw) IRQ over the in-band stage would trigger the
>> > synchronization as expected, but a synthetic one posted from the oob
>> > stage might linger if this assumption ends up being wrong. I need to
>> > have a second look at this code.
>> 
>> Which means that your latest patch series is ok and complete. The change
>> if any would most likely happen in the generic pipeline bits.
>
> I think (2) is still wrong on arm64 now, so:
>
> @@ -65,15 +65,17 @@ static noinstr void arm64_pipeline_el0_irq(struct
> pt_regs *regs,
>                                 void (*handler)(struct pt_regs *))
>  {
>         struct irq_stage_data *prevd;
> +       bool oob_on_enter;
>  
>         arm64_enter_from_user_mode(regs);
>         instrumentation_begin();
>         /* Prep for handling, switching oob if needed. */
> +       oob_on_enter = running_oob();
>         prevd = handle_irq_pipelined_prepare(regs);
>         do_interrupt_handler(regs, handler);
>         /* Done, unwind now. */
>         handle_irq_pipelined_finish(prevd, regs);
> -       if (running_inband()) {
> +       if (oob_on_enter && running_inband()) {
>                 stall_inband_nocheck();
>                 irqentry_exit_to_user_mode(regs);
>         }
>
> Do you agree?
>

On a second look, _el0 needs no particular handling of the demotion
case, because arm64_exit_to_user_mode() already does what is required.

-- 
Philippe.

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs
  2026-02-17 13:31                   ` Philippe Gerum
@ 2026-02-17 14:37                     ` Florian Bezdeka
  0 siblings, 0 replies; 16+ messages in thread
From: Florian Bezdeka @ 2026-02-17 14:37 UTC (permalink / raw)
  To: Philippe Gerum; +Cc: Xenomai, Jan Kiszka

On Tue, 2026-02-17 at 14:31 +0100, Philippe Gerum wrote:
> Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> 
> > On Tue, 2026-02-17 at 11:11 +0100, Philippe Gerum wrote:
> > > Philippe Gerum <rpm@xenomai.org> writes:
> > > 
> > > > Florian Bezdeka <florian.bezdeka@siemens.com> writes:
> > > > 
> > > > > On Tue, 2026-02-17 at 09:41 +0100, Philippe Gerum wrote:
> > > > > > > Comparing with x86 again, I think that my proposal is "correct" in terms
> > > > > > > of identical to what x86 does. Do all architectures have a gap here?
> > > > > > 
> > > > > > x86 has a single implementation for both user and kernel preemption
> > > > > > paths, arm64 has two since the privilege level is explicitly stated by
> > > > > > the irq handler being called, but this still must translate identically
> > > > > > logically speaking. Your implementation is missing the kernel preemption
> > > > > > path after demotion.
> > > > > > 
> > > > > > i.e. when checking for running_oob() || irqs_disabled(), the cases
> > > > > > covered are:
> > > > > > 
> > > > > > (1) in-band user path on entry (implies !irqs_disabled())
> > > > > > (2) oob user path on entry (might be demoted)
> > > > > > (3) (virtually) stalled in-band kernel path on entry (implies no reschedule,
> > > > > >   filtered out by irqentry_exit())
> > > > > > (4) oob kernel path on entry (might be demoted)
> > > > > > 
> > > > > > Therefore, with your patch in, el1 is now missing (4).
> > > > > 
> > > > > Right, but I'm wondering if x86 ignores this case as well.
> > > > > 
> > > > > After demotion of a oob kernel path entry, user_mode() should still be
> > > > > false - bypassing the call to irqentry_exit_to_user_mode() - No?
> > > > 
> > > > Yes, x86 assumes that a kernel path demoted to in-band is going to cross
> > > > an IRQ synchronization point shortly after on return to the preempted
> > > > context. Now, with hindsight, the question is: are we 100% certain of
> > > > that? Any real (hw) IRQ over the in-band stage would trigger the
> > > > synchronization as expected, but a synthetic one posted from the oob
> > > > stage might linger if this assumption ends up being wrong. I need to
> > > > have a second look at this code.
> > > 
> > > Which means that your latest patch series is ok and complete. The change
> > > if any would most likely happen in the generic pipeline bits.
> > 
> > I think (2) is still wrong on arm64 now, so:
> > 
> > @@ -65,15 +65,17 @@ static noinstr void arm64_pipeline_el0_irq(struct
> > pt_regs *regs,
> >                                 void (*handler)(struct pt_regs *))
> >  {
> >         struct irq_stage_data *prevd;
> > +       bool oob_on_enter;
> >  
> >         arm64_enter_from_user_mode(regs);
> >         instrumentation_begin();
> >         /* Prep for handling, switching oob if needed. */
> > +       oob_on_enter = running_oob();
> >         prevd = handle_irq_pipelined_prepare(regs);
> >         do_interrupt_handler(regs, handler);
> >         /* Done, unwind now. */
> >         handle_irq_pipelined_finish(prevd, regs);
> > -       if (running_inband()) {
> > +       if (oob_on_enter && running_inband()) {
> >                 stall_inband_nocheck();
> >                 irqentry_exit_to_user_mode(regs);
> >         }
> > 
> > Do you agree?
> > 
> 
> On a second look, _el0 needs no particular handling of the demotion
> case, because arm64_exit_to_user_mode() already does what is required.
> 

Right. All this funny findings along the way:
/* Temporary workaround to keep ARM64 alive */

Preparing v2 now.

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2026-02-17 14:37 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-02-16 19:05 [PATCH Dovetail 0/2] Dovetail: Fix for arm64 IRQ pipelining, API for co-kernels Florian Bezdeka
2026-02-16 19:05 ` [PATCH Dovetail 1/2] dovetail: genirq: Add request_percpu_irq_affinity_flags() Florian Bezdeka
2026-02-16 19:05 ` [PATCH Dovetail 2/2] arm64: irq_pipeline: Fix the demotion checks for el0 and el1 IRQs Florian Bezdeka
2026-02-17  8:00   ` Philippe Gerum
2026-02-17  8:12     ` Florian Bezdeka
2026-02-17  8:24       ` Florian Bezdeka
2026-02-17  8:41         ` Philippe Gerum
2026-02-17  9:16           ` Florian Bezdeka
2026-02-17  9:40             ` Philippe Gerum
2026-02-17 10:11               ` Philippe Gerum
2026-02-17 11:23                 ` Florian Bezdeka
2026-02-17 13:31                   ` Philippe Gerum
2026-02-17 14:37                     ` Florian Bezdeka
2026-02-17  8:49         ` Philippe Gerum
2026-02-17  9:01           ` Florian Bezdeka
2026-02-17  9:10             ` Philippe Gerum

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox