Re: [PATCH dovetail] irq_pipeline: synchronize inband IRQ log in exit_to_user_mode_prepare()
Tobias Schaffner <[email protected]>
| Newsgroups | dev.linux.lists.xenomai |
|---|---|
| Message-ID | <[email protected]> |
Hi Florian, On 2/16/26 10:27, Florian Bezdeka wrote: > On Sun, 2026-02-15 at 00:25 +0100, Florian Bezdeka wrote: >> On 2/14/26 12:39, Tobias Schaffner wrote: >>> Architectures using the generic handle_irq_pipelined() path do not >> >> arm64 and x86 are not using that, so the only arch left is arm. >> See below... >> >>> synchronize the inband IRQ log in handle_irq_pipelined_finish() >>> because inband is still stalled from irqentry_enter() when it gets >>> called. >> >> I think the real issue / correct wording is: >> >> _TIF_WORK is left pending on IRQ exit. >> >>> >>> As a result, deferred inband IRQs may not be played before the kernel >>> checks for pending work in exit_to_user_mode_loop(), causing >>> those IRQs to be missed on the return path to userspace. >>> >>> Flush the inband IRQ log in exit_to_user_mode_prepare() before >>> entering the work loop. >>> >>> Signed-off-by: Tobias Schaffner <[email protected]> >>> --- >>> include/linux/irq-entry-common.h | 6 ++++++ >>> 1 file changed, 6 insertions(+) >>> >>> diff --git a/include/linux/irq-entry-common.h b/include/linux/irq-entry-common.h >>> index b21fb5893a67..e5815511a80a 100644 >>> --- a/include/linux/irq-entry-common.h >>> +++ b/include/linux/irq-entry-common.h >>> @@ -8,6 +8,7 @@ >>> #include <linux/tick.h> >>> #include <linux/kmsan.h> >>> #include <linux/unwind_deferred.h> >>> +#include <linux/irq_pipeline.h> >>> >>> #include <asm/entry-common.h> >>> >>> @@ -237,6 +238,11 @@ static __always_inline void exit_to_user_mode_prepare(struct pt_regs *regs) >>> /* Flush pending rcuog wakeup before the last need_resched() check */ >>> tick_nohz_user_enter_prepare(); >>> >>> + /* Synchronize the in-band log before the work loop so that any deferred >>> + * IRQs are played before we check for pending work. */ >>> + if (running_inband()) >>> + sync_inband_irqs(); >>> + >> >> I think there is more behind it. Seems your architecture (most likely >> risc-v) is missing one corner case in the low level IRQ entry code: >> >> Potential stage demotion of the preempted task which originally entered >> on the oob stage, then left it for the in-band stage as a result of IRQ >> handling. This should happen in handle_irq_pipeline_finish() - if required. >> >> So on IRQ entry you are OOB, after the call to >> handle_irq_pipeline_finish() you might be inband. >> >> In that case you most likely want to call irqentry_exit_to_user_mode() >> with the inband stage stalled: >> >> Taken from arm64/x86: >> if (unlikely(running_oob() || irqs_disabled())) { >> ... >> handle_irq_pipelined_finish(prevd, regs); >> if (running_inband() && user_mode(regs)) { >> stall_inband_nocheck(); >> irqentry_exit_to_user_mode(regs); >> } >> ... >> } >> >>> again: >>> ti_work = read_thread_flags(); >>> if (unlikely(ti_work & EXIT_TO_USER_MODE_WORK)) >> >> That said, we should double check that this corner case is handled right >> on arm. If arm suffers from the same problem, this corner case is >> missing in handle_irq_pipelined(). > > ARM is doing the right thing on assembly level already by calling into > do_work_pending() on the way back. You are right. This seems to be a leftover of a prior oob irq handling. Thanks for pointing me in the right direction. A first test draft ''' diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 51e1407ee066..96d79cc3d3d4 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -527,6 +527,16 @@ DEFINE_PER_CPU(int, irq_nesting); asmlinkage void noinstr do_irq(struct pt_regs *regs) { + // OOB fast path + if (unlikely(running_oob() || irqs_disabled())) { + handle_irq_pipelined(regs); + if (running_inband() && user_mode(regs)) { + stall_inband_nocheck(); + irqentry_exit_to_user_mode(regs); + } + return; + } + irqentry_state_t state = irqentry_enter(regs); #ifdef CONFIG_IRQ_STACKS ''' fixes it without touching the generic irq pipelining. Seems like I can solve this issue in the riscv specific IRQ path. Best, Tobias >> >> I hope all of this makes sense at the end. It's late... >> >> Best regards, >> Florian