Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

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

authored by

Heiko Carstens and committed by
Vasily Gorbik
75aa996e 674c5ff0

+8 -6
+8 -6
arch/s390/kernel/irq.c
··· 147 147 bool from_idle; 148 148 149 149 from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 150 - if (from_idle) { 150 + if (from_idle) 151 151 update_timer_idle(); 152 - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 153 - } 154 152 155 153 irq_enter_rcu(); 156 154 ··· 174 176 175 177 set_irq_regs(old_regs); 176 178 irqentry_exit(regs, state); 179 + 180 + if (from_idle) 181 + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 177 182 } 178 183 179 184 void noinstr do_ext_irq(struct pt_regs *regs) ··· 186 185 bool from_idle; 187 186 188 187 from_idle = test_and_clear_cpu_flag(CIF_ENABLED_WAIT); 189 - if (from_idle) { 188 + if (from_idle) 190 189 update_timer_idle(); 191 - regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 192 - } 193 190 194 191 irq_enter_rcu(); 195 192 ··· 209 210 irq_exit_rcu(); 210 211 set_irq_regs(old_regs); 211 212 irqentry_exit(regs, state); 213 + 214 + if (from_idle) 215 + regs->psw.mask &= ~(PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_WAIT); 212 216 } 213 217 214 218 static void show_msi_interrupt(struct seq_file *p, int irq)