Skip to content

Commit

Permalink
powerpc/irq: Fix bug with new lazy IRQ handling code
Browse files Browse the repository at this point in the history
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: Benjamin Herrenschmidt <benh@kernel.crashing.org>
  • Loading branch information
Benjamin Herrenschmidt committed May 8, 2012
1 parent 810b4de commit 56dfa7f
Show file tree
Hide file tree
Showing 2 changed files with 7 additions and 19 deletions.
18 changes: 0 additions & 18 deletions arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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
Expand Down
8 changes: 7 additions & 1 deletion arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down

0 comments on commit 56dfa7f

Please sign in to comment.