Re: [PATCH] s390: Revert "s390/irq/idle: Remove psw bits early"
From: Mikhail Zaslonko
Date: Fri Mar 06 2026 - 09:50:50 EST
On 06-Mar-26 12:19, Heiko Carstens wrote:
> This reverts commit d8b5cf9c63143fae54a734c41e3bb55cf3f365c7.
>
> Mikhail Zaslonko reported that linux-next doesn't boot anymore [2]. Reason
> for this is recent change [2] was supposed to slightly optimize the irq
> entry/exit path by removing some psw bits early in case of an idle exit.
>
> This however is incorrect since irqentry_exit() requires the correct old
> psw state at irq entry. Otherwise the embedded regs_irqs_disabled() will
> not provide the correct result.
>
> With linux-next and HRTIMER_REARM_DEFERRED this leads to the observed boot
> problems, however the commit is broken in any case.
>
> Revert the commit which introduced this.
>
> Thanks to Peter Zijlstra for pointing out that this is a bug in the s390
> entry code.
>
> Fixes: d8b5cf9c6314 ("s390/irq/idle: Remove psw bits early") [1]
> Reported-by: Mikhail Zaslonko <zaslonko@xxxxxxxxxxxxx>
> Reported-by: Peter Zijlstra <peterz@xxxxxxxxxxxxx>
> Closes: https://lore.kernel.org/r/af549a19-db99-4b16-8511-bf315177a13e@xxxxxxxxxxxxx/ [2]
> Signed-off-by: Heiko Carstens <hca@xxxxxxxxxxxxx>
> ---
> arch/s390/kernel/irq.c | 14 ++++++++------
> 1 file changed, 8 insertions(+), 6 deletions(-)
>
> diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
> index 7fdf960191d3..d10a17e6531d 100644
> --- a/arch/s390/kernel/irq.c
> +++ b/arch/s390/kernel/irq.c
> @@ -147,10 +147,8 @@ void noinstr do_io_irq(struct pt_regs *regs)
> bool from_idle;
>
> from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
> - if (from_idle) {
> + if (from_idle)
> update_timer_idle();
> - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
> - }
>
> irq_enter_rcu();
>
> @@ -176,6 +174,9 @@ void noinstr do_io_irq(struct pt_regs *regs)
>
> set_irq_regs(old_regs);
> irqentry_exit(regs, state);
> +
> + if (from_idle)
> + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
> }
>
> void noinstr do_ext_irq(struct pt_regs *regs)
> @@ -185,10 +186,8 @@ void noinstr do_ext_irq(struct pt_regs *regs)
> bool from_idle;
>
> from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT);
> - if (from_idle) {
> + if (from_idle)
> update_timer_idle();
> - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
> - }
>
> irq_enter_rcu();
>
> @@ -210,6 +209,9 @@ void noinstr do_ext_irq(struct pt_regs *regs)
> irq_exit_rcu();
> set_irq_regs(old_regs);
> irqentry_exit(regs, state);
> +
> + if (from_idle)
> + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT);
> }
>
> static void show_msi_interrupt(struct seq_file *p, int irq)
Indeed, with this revert no more kernel-next boot problems observed.
Acked-by: Mikhail Zaslonko <zaslonko@xxxxxxxxxxxxx>
Tested-by: Mikhail Zaslonko <zaslonko@xxxxxxxxxxxxx>