Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 56dfa7fa authored by Benjamin Herrenschmidt's avatar Benjamin Herrenschmidt
Browse files

powerpc/irq: Fix bug with new lazy IRQ handling code



We had a case where we could turn on hard interrupts while
leaving the PACA_IRQ_HARD_DIS bit set in the PACA. This can
in turn cause a BUG_ON() to hit in __check_irq_replay() due
to interrupt state getting out of sync.

The assembly code was also way too convoluted. Instead, we
now leave it to the C code to do the right thing which ends
up being smaller and more readable.

Signed-off-by: default avatarBenjamin Herrenschmidt <benh@kernel.crashing.org>
parent 810b4de2
Loading
Loading
Loading
Loading
+0 −18
Original line number Diff line number Diff line
@@ -767,16 +767,6 @@ do_work:
	SOFT_DISABLE_INTS(r3,r4)
1:	bl	.preempt_schedule_irq

	/* Hard-disable interrupts again (and update PACA) */
#ifdef CONFIG_PPC_BOOK3E
	wrteei	0
#else
	ld	r10,PACAKMSR(r13) /* Get kernel MSR without EE */
	mtmsrd	r10,1
#endif /* CONFIG_PPC_BOOK3E */
	li	r0,PACA_IRQ_HARD_DIS
	stb	r0,PACAIRQHAPPENED(r13)

	/* Re-test flags and eventually loop */
	clrrdi	r9,r1,THREAD_SHIFT
	ld	r4,TI_FLAGS(r9)
@@ -787,14 +777,6 @@ do_work:
user_work:
#endif /* CONFIG_PREEMPT */

	/* Enable interrupts */
#ifdef CONFIG_PPC_BOOK3E
	wrteei	1
#else
	ori	r10,r10,MSR_EE
	mtmsrd	r10,1
#endif /* CONFIG_PPC_BOOK3E */

	andi.	r0,r4,_TIF_NEED_RESCHED
	beq	1f
	bl	.restore_interrupts
+7 −1
Original line number Diff line number Diff line
@@ -260,11 +260,17 @@ EXPORT_SYMBOL(arch_local_irq_restore);
 * if they are currently disabled. This is typically called before
 * schedule() or do_signal() when returning to userspace. We do it
 * in C to avoid the burden of dealing with lockdep etc...
 *
 * NOTE: This is called with interrupts hard disabled but not marked
 * as such in paca->irq_happened, so we need to resync this.
 */
void restore_interrupts(void)
{
	if (irqs_disabled())
	if (irqs_disabled()) {
		local_paca->irq_happened |= PACA_IRQ_HARD_DIS;
		local_irq_enable();
	} else
		__hard_irq_enable();
}

#endif /* CONFIG_PPC64 */