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.

Merge branch 'merge' of git://git.kernel.org/pub/scm/linux/kernel/git/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

+44 -13
+31 -13
arch/powerpc/kernel/entry_64.S
··· 588 588 fast_exc_return_irq: 589 589 restore: 590 590 /* 591 - * This is the main kernel exit path, we first check if we 592 - * have to change our interrupt state. 591 + * This is the main kernel exit path. First we check if we 592 + * are about to re-enable interrupts 593 593 */ 594 594 ld r5,SOFTE(r1) 595 595 lbz r6,PACASOFTIRQEN(r13) 596 - cmpwi cr1,r5,0 597 - cmpw cr0,r5,r6 598 - beq cr0,4f 596 + cmpwi cr0,r5,0 597 + beq restore_irq_off 599 598 600 - /* We do, handle disable first, which is easy */ 601 - bne cr1,3f; 602 - li r0,0 603 - stb r0,PACASOFTIRQEN(r13); 604 - TRACE_DISABLE_INTS 605 - b 4f 599 + /* We are enabling, were we already enabled ? Yes, just return */ 600 + cmpwi cr0,r6,1 601 + beq cr0,do_restore 606 602 607 - 3: /* 603 + /* 608 604 * We are about to soft-enable interrupts (we are hard disabled 609 605 * at this point). We check if there's anything that needs to 610 606 * be replayed first. ··· 622 626 /* 623 627 * Final return path. BookE is handled in a different file 624 628 */ 625 - 4: 629 + do_restore: 626 630 #ifdef CONFIG_PPC_BOOK3E 627 631 b .exception_return_book3e 628 632 #else ··· 696 700 #endif /* CONFIG_PPC_BOOK3E */ 697 701 698 702 /* 703 + * We are returning to a context with interrupts soft disabled. 704 + * 705 + * However, we may also about to hard enable, so we need to 706 + * make sure that in this case, we also clear PACA_IRQ_HARD_DIS 707 + * or that bit can get out of sync and bad things will happen 708 + */ 709 + restore_irq_off: 710 + ld r3,_MSR(r1) 711 + lbz r7,PACAIRQHAPPENED(r13) 712 + andi. r0,r3,MSR_EE 713 + beq 1f 714 + rlwinm r7,r7,0,~PACA_IRQ_HARD_DIS 715 + stb r7,PACAIRQHAPPENED(r13) 716 + 1: li r0,0 717 + stb r0,PACASOFTIRQEN(r13); 718 + TRACE_DISABLE_INTS 719 + b do_restore 720 + 721 + /* 699 722 * Something did happen, check if a re-emit is needed 700 723 * (this also clears paca->irq_happened) 701 724 */ ··· 763 748 #endif /* CONFIG_PPC_BOOK3E */ 764 749 1: b .ret_from_except /* What else to do here ? */ 765 750 751 + 752 + 753 + 3: 766 754 do_work: 767 755 #ifdef CONFIG_PREEMPT 768 756 andi. r0,r3,MSR_PR /* Returning to user mode? */
+13
arch/powerpc/kernel/irq.c
··· 229 229 */ 230 230 if (unlikely(irq_happened != PACA_IRQ_HARD_DIS)) 231 231 __hard_irq_disable(); 232 + #ifdef CONFIG_TRACE_IRQFLAG 233 + else { 234 + /* 235 + * We should already be hard disabled here. We had bugs 236 + * where that wasn't the case so let's dbl check it and 237 + * warn if we are wrong. Only do that when IRQ tracing 238 + * is enabled as mfmsr() can be costly. 239 + */ 240 + if (WARN_ON(mfmsr() & MSR_EE)) 241 + __hard_irq_disable(); 242 + } 243 + #endif /* CONFIG_TRACE_IRQFLAG */ 244 + 232 245 set_soft_enabled(0); 233 246 234 247 /*