Commit 75aa996e authored by Heiko Carstens's avatar Heiko Carstens Committed by Vasily Gorbik
Browse files

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



This reverts commit d8b5cf9c.

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: d8b5cf9c ("s390/irq/idle: Remove psw bits early") [1]
Reported-by: default avatarMikhail Zaslonko <zaslonko@linux.ibm.com>
Reported-by: default avatarPeter Zijlstra <peterz@infradead.org>
Closes: https://lore.kernel.org/r/af549a19-db99-4b16-8511-bf315177a13e@linux.ibm.com/

 [2]
Signed-off-by: default avatarHeiko Carstens <hca@linux.ibm.com>
Acked-by: default avatarMikhail Zaslonko <zaslonko@linux.ibm.com>
Tested-by: default avatarMikhail Zaslonko <zaslonko@linux.ibm.com>
Acked-by: default avatarVasily Gorbik <gor@linux.ibm.com>
Link: https://lore.kernel.org/r/20260306111919.362559-1-hca@linux.ibm.com


Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent 674c5ff0
Loading
Loading
Loading
Loading
+8 −6
Original line number Diff line number Diff line
@@ -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)