diff options
| -rw-r--r-- | arch/powerpc/kernel/entry_64.S | 13 | ||||
| -rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 37 | ||||
| -rw-r--r-- | arch/powerpc/kernel/irq.c | 11 |
3 files changed, 45 insertions, 16 deletions
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index b310a0573625..73c1f083ba21 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
| @@ -836,13 +836,22 @@ restore_check_irq_replay: | |||
| 836 | addi r3,r1,STACK_FRAME_OVERHEAD; | 836 | addi r3,r1,STACK_FRAME_OVERHEAD; |
| 837 | bl .timer_interrupt | 837 | bl .timer_interrupt |
| 838 | b .ret_from_except | 838 | b .ret_from_except |
| 839 | #ifdef CONFIG_PPC_DOORBELL | ||
| 840 | 1: | ||
| 839 | #ifdef CONFIG_PPC_BOOK3E | 841 | #ifdef CONFIG_PPC_BOOK3E |
| 840 | 1: cmpwi cr0,r3,0x280 | 842 | cmpwi cr0,r3,0x280 |
| 843 | #else | ||
| 844 | BEGIN_FTR_SECTION | ||
| 845 | cmpwi cr0,r3,0xe80 | ||
| 846 | FTR_SECTION_ELSE | ||
| 847 | cmpwi cr0,r3,0xa00 | ||
| 848 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | ||
| 849 | #endif /* CONFIG_PPC_BOOK3E */ | ||
| 841 | bne 1f | 850 | bne 1f |
| 842 | addi r3,r1,STACK_FRAME_OVERHEAD; | 851 | addi r3,r1,STACK_FRAME_OVERHEAD; |
| 843 | bl .doorbell_exception | 852 | bl .doorbell_exception |
| 844 | b .ret_from_except | 853 | b .ret_from_except |
| 845 | #endif /* CONFIG_PPC_BOOK3E */ | 854 | #endif /* CONFIG_PPC_DOORBELL */ |
| 846 | 1: b .ret_from_except /* What else to do here ? */ | 855 | 1: b .ret_from_except /* What else to do here ? */ |
| 847 | 856 | ||
| 848 | unrecov_restore: | 857 | unrecov_restore: |
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index 176bf99e01c6..32fc04f78890 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
| @@ -528,10 +528,12 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_206) | |||
| 528 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40) | 528 | KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40) |
| 529 | 529 | ||
| 530 | /* | 530 | /* |
| 531 | * An interrupt came in while soft-disabled. We set paca->irq_happened, | 531 | * An interrupt came in while soft-disabled. We set paca->irq_happened, then: |
| 532 | * then, if it was a decrementer interrupt, we bump the dec to max and | 532 | * - If it was a decrementer interrupt, we bump the dec to max and and return. |
| 533 | * and return, else we hard disable and return. This is called with | 533 | * - If it was a doorbell we return immediately since doorbells are edge |
| 534 | * r10 containing the value to OR to the paca field. | 534 | * triggered and won't automatically refire. |
| 535 | * - else we hard disable and return. | ||
| 536 | * This is called with r10 containing the value to OR to the paca field. | ||
| 535 | */ | 537 | */ |
| 536 | #define MASKED_INTERRUPT(_H) \ | 538 | #define MASKED_INTERRUPT(_H) \ |
| 537 | masked_##_H##interrupt: \ | 539 | masked_##_H##interrupt: \ |
| @@ -539,13 +541,15 @@ masked_##_H##interrupt: \ | |||
| 539 | lbz r11,PACAIRQHAPPENED(r13); \ | 541 | lbz r11,PACAIRQHAPPENED(r13); \ |
| 540 | or r11,r11,r10; \ | 542 | or r11,r11,r10; \ |
| 541 | stb r11,PACAIRQHAPPENED(r13); \ | 543 | stb r11,PACAIRQHAPPENED(r13); \ |
| 542 | andi. r10,r10,PACA_IRQ_DEC; \ | 544 | cmpwi r10,PACA_IRQ_DEC; \ |
| 543 | beq 1f; \ | 545 | bne 1f; \ |
| 544 | lis r10,0x7fff; \ | 546 | lis r10,0x7fff; \ |
| 545 | ori r10,r10,0xffff; \ | 547 | ori r10,r10,0xffff; \ |
| 546 | mtspr SPRN_DEC,r10; \ | 548 | mtspr SPRN_DEC,r10; \ |
| 547 | b 2f; \ | 549 | b 2f; \ |
| 548 | 1: mfspr r10,SPRN_##_H##SRR1; \ | 550 | 1: cmpwi r10,PACA_IRQ_DBELL; \ |
| 551 | beq 2f; \ | ||
| 552 | mfspr r10,SPRN_##_H##SRR1; \ | ||
| 549 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ | 553 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ |
| 550 | rotldi r10,r10,16; \ | 554 | rotldi r10,r10,16; \ |
| 551 | mtspr SPRN_##_H##SRR1,r10; \ | 555 | mtspr SPRN_##_H##SRR1,r10; \ |
| @@ -562,8 +566,8 @@ masked_##_H##interrupt: \ | |||
| 562 | 566 | ||
| 563 | /* | 567 | /* |
| 564 | * Called from arch_local_irq_enable when an interrupt needs | 568 | * Called from arch_local_irq_enable when an interrupt needs |
| 565 | * to be resent. r3 contains 0x500 or 0x900 to indicate which | 569 | * to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate |
| 566 | * kind of interrupt. MSR:EE is already off. We generate a | 570 | * which kind of interrupt. MSR:EE is already off. We generate a |
| 567 | * stackframe like if a real interrupt had happened. | 571 | * stackframe like if a real interrupt had happened. |
| 568 | * | 572 | * |
| 569 | * Note: While MSR:EE is off, we need to make sure that _MSR | 573 | * Note: While MSR:EE is off, we need to make sure that _MSR |
| @@ -579,9 +583,18 @@ _GLOBAL(__replay_interrupt) | |||
| 579 | mflr r11 | 583 | mflr r11 |
| 580 | mfcr r9 | 584 | mfcr r9 |
| 581 | ori r12,r12,MSR_EE | 585 | ori r12,r12,MSR_EE |
| 582 | andi. r3,r3,0x0800 | 586 | cmpwi r3,0x900 |
| 583 | bne decrementer_common | 587 | beq decrementer_common |
| 584 | b hardware_interrupt_common | 588 | cmpwi r3,0x500 |
| 589 | beq hardware_interrupt_common | ||
| 590 | BEGIN_FTR_SECTION | ||
| 591 | cmpwi r3,0xe80 | ||
| 592 | beq h_doorbell_common | ||
| 593 | FTR_SECTION_ELSE | ||
| 594 | cmpwi r3,0xa00 | ||
| 595 | beq doorbell_super_common | ||
| 596 | ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) | ||
| 597 | blr | ||
| 585 | 598 | ||
| 586 | #ifdef CONFIG_PPC_PSERIES | 599 | #ifdef CONFIG_PPC_PSERIES |
| 587 | /* | 600 | /* |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 71413f41278f..4f97fe345526 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
| @@ -122,8 +122,8 @@ static inline notrace int decrementer_check_overflow(void) | |||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | /* This is called whenever we are re-enabling interrupts | 124 | /* This is called whenever we are re-enabling interrupts |
| 125 | * and returns either 0 (nothing to do) or 500/900 if there's | 125 | * and returns either 0 (nothing to do) or 500/900/280/a00/e80 if |
| 126 | * either an EE or a DEC to generate. | 126 | * there's an EE, DEC or DBELL to generate. |
| 127 | * | 127 | * |
| 128 | * This is called in two contexts: From arch_local_irq_restore() | 128 | * This is called in two contexts: From arch_local_irq_restore() |
| 129 | * before soft-enabling interrupts, and from the exception exit | 129 | * before soft-enabling interrupts, and from the exception exit |
| @@ -182,6 +182,13 @@ notrace unsigned int __check_irq_replay(void) | |||
| 182 | local_paca->irq_happened &= ~PACA_IRQ_DBELL; | 182 | local_paca->irq_happened &= ~PACA_IRQ_DBELL; |
| 183 | if (happened & PACA_IRQ_DBELL) | 183 | if (happened & PACA_IRQ_DBELL) |
| 184 | return 0x280; | 184 | return 0x280; |
| 185 | #else | ||
| 186 | local_paca->irq_happened &= ~PACA_IRQ_DBELL; | ||
| 187 | if (happened & PACA_IRQ_DBELL) { | ||
| 188 | if (cpu_has_feature(CPU_FTR_HVMODE)) | ||
| 189 | return 0xe80; | ||
| 190 | return 0xa00; | ||
| 191 | } | ||
| 185 | #endif /* CONFIG_PPC_BOOK3E */ | 192 | #endif /* CONFIG_PPC_BOOK3E */ |
| 186 | 193 | ||
| 187 | /* There should be nothing left ! */ | 194 | /* There should be nothing left ! */ |
