s390: Revert "s390/irq/idle: Remove psw bits early"

This reverts commit d8b5cf9c63.

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: d8b5cf9c63 ("s390/irq/idle: Remove psw bits early") [1]
Reported-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Reported-by: Peter Zijlstra <peterz@infradead.org>
Closes: https://lore.kernel.org/r/af549a19-db99-4b16-8511-bf315177a13e@linux.ibm.com/ [2]
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Acked-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Tested-by: Mikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: Vasily Gorbik <gor@linux.ibm.com>
Link: https://lore.kernel.org/r/20260306111919.362559-1-hca@linux.ibm.com
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
This commit is contained in:
Heiko Carstens
2026-03-06 12:19:19 +01:00
committed by Vasily Gorbik
parent 674c5ff0f4
commit 75aa996ea6

View File

@@ -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)