Skip to content

Commit

Permalink
Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git…
Browse files Browse the repository at this point in the history
…/benh/powerpc

Pull another powerpc irq fix from Benjamin Herrenschmidt:
 "It looks like my previous fix for the lazy irq masking problem wasn't
  quite enough.  There was another problem related to performance
  monitor interrupts acting as NMIs leaving the flags in an incorrect
  state.  Here's a fix that finally seems to make perf solid again."

* 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc:
  powerpc/irq: Fix another case of lazy IRQ state getting out of sync
  • Loading branch information
torvalds committed May 11, 2012
2 parents 04e5335 + 7c0482e commit ec53646
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 13 deletions.
44 changes: 31 additions & 13 deletions arch/powerpc/kernel/entry_64.S
Original file line number Diff line number Diff line change
Expand Up @@ -588,23 +588,19 @@ _GLOBAL(ret_from_except_lite)
fast_exc_return_irq:
restore:
/*
* This is the main kernel exit path, we first check if we
* have to change our interrupt state.
* This is the main kernel exit path. First we check if we
* are about to re-enable interrupts
*/
ld r5,SOFTE(r1)
lbz r6,PACASOFTIRQEN(r13)
cmpwi cr1,r5,0
cmpw cr0,r5,r6
beq cr0,4f
cmpwi cr0,r5,0
beq restore_irq_off

/* We do, handle disable first, which is easy */
bne cr1,3f;
li r0,0
stb r0,PACASOFTIRQEN(r13);
TRACE_DISABLE_INTS
b 4f
/* We are enabling, were we already enabled ? Yes, just return */
cmpwi cr0,r6,1
beq cr0,do_restore

3: /*
/*
* We are about to soft-enable interrupts (we are hard disabled
* at this point). We check if there's anything that needs to
* be replayed first.
Expand All @@ -626,7 +622,7 @@ restore_no_replay:
/*
* Final return path. BookE is handled in a different file
*/
4:
do_restore:
#ifdef CONFIG_PPC_BOOK3E
b .exception_return_book3e
#else
Expand Down Expand Up @@ -699,6 +695,25 @@ fast_exception_return:

#endif /* CONFIG_PPC_BOOK3E */

/*
* We are returning to a context with interrupts soft disabled.
*
* However, we may also about to hard enable, so we need to
* make sure that in this case, we also clear PACA_IRQ_HARD_DIS
* or that bit can get out of sync and bad things will happen
*/
restore_irq_off:
ld r3,_MSR(r1)
lbz r7,PACAIRQHAPPENED(r13)
andi. r0,r3,MSR_EE
beq 1f
rlwinm r7,r7,0,~PACA_IRQ_HARD_DIS
stb r7,PACAIRQHAPPENED(r13)
1: li r0,0
stb r0,PACASOFTIRQEN(r13);
TRACE_DISABLE_INTS
b do_restore

/*
* Something did happen, check if a re-emit is needed
* (this also clears paca->irq_happened)
Expand Down Expand Up @@ -748,6 +763,9 @@ restore_check_irq_replay:
#endif /* CONFIG_PPC_BOOK3E */
1: b .ret_from_except /* What else to do here ? */



3:
do_work:
#ifdef CONFIG_PREEMPT
andi. r0,r3,MSR_PR /* Returning to user mode? */
Expand Down
13 changes: 13 additions & 0 deletions arch/powerpc/kernel/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,19 @@ notrace void arch_local_irq_restore(unsigned long en)
*/
if (unlikely(irq_happened != PACA_IRQ_HARD_DIS))
__hard_irq_disable();
#ifdef CONFIG_TRACE_IRQFLAG
else {
/*
* We should already be hard disabled here. We had bugs
* where that wasn't the case so let's dbl check it and
* warn if we are wrong. Only do that when IRQ tracing
* is enabled as mfmsr() can be costly.
*/
if (WARN_ON(mfmsr() & MSR_EE))
__hard_irq_disable();
}
#endif /* CONFIG_TRACE_IRQFLAG */

set_soft_enabled(0);

/*
Expand Down

0 comments on commit ec53646

Please sign in to comment.