Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

powerpc: Add code to handle soft-disabled doorbells on server

This patch adds the logic to properly handle doorbells that come in when
interrupts have been soft disabled and to replay them when interrupts
are re-enabled:

- masked_##_H##interrupt is modified to leave interrupts enabled when a
doorbell has come in since doorbells are edge sensitive and as such
won't be automatically re-raised.

- __check_irq_replay now tests if a doorbell happened on book3s, and
returns either 0xe80 or 0xa00 depending on whether we are the
hypervisor or not.

- restore_check_irq_replay now tests for the two possible server
doorbell vector numbers to replay.

- __replay_interrupt also adds tests for the two server doorbell vector
numbers, and is modified to use a compare instruction rather than an
andi. on the single bit difference between 0x500 and 0x900.

The last two use a CPU feature section to avoid needlessly testing
against the hypervisor vector if it is not the hypervisor, and vice
versa.

Signed-off-by: Ian Munsie <imunsie@au1.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

authored by

Ian Munsie and committed by
Benjamin Herrenschmidt
fe9e1d54 919ca868

+45 -16
+11 -2
arch/powerpc/kernel/entry_64.S
··· 836 836 addi r3,r1,STACK_FRAME_OVERHEAD; 837 837 bl .timer_interrupt 838 838 b .ret_from_except 839 + #ifdef CONFIG_PPC_DOORBELL 840 + 1: 839 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 850 bne 1f 842 851 addi r3,r1,STACK_FRAME_OVERHEAD; 843 852 bl .doorbell_exception 844 853 b .ret_from_except 845 - #endif /* CONFIG_PPC_BOOK3E */ 854 + #endif /* CONFIG_PPC_DOORBELL */ 846 855 1: b .ret_from_except /* What else to do here ? */ 847 856 848 857 unrecov_restore:
+25 -12
arch/powerpc/kernel/exceptions-64s.S
··· 528 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, 532 - * then, if it was a decrementer interrupt, we bump the dec to max and 533 - * and return, else we hard disable and return. This is called with 534 - * r10 containing the value to OR to the paca field. 531 + * An interrupt came in while soft-disabled. We set paca->irq_happened, then: 532 + * - If it was a decrementer interrupt, we bump the dec to max and and return. 533 + * - If it was a doorbell we return immediately since doorbells are edge 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 538 #define MASKED_INTERRUPT(_H) \ 537 539 masked_##_H##interrupt: \ ··· 541 539 lbz r11,PACAIRQHAPPENED(r13); \ 542 540 or r11,r11,r10; \ 543 541 stb r11,PACAIRQHAPPENED(r13); \ 544 - andi. r10,r10,PACA_IRQ_DEC; \ 545 - beq 1f; \ 542 + cmpwi r10,PACA_IRQ_DEC; \ 543 + bne 1f; \ 546 544 lis r10,0x7fff; \ 547 545 ori r10,r10,0xffff; \ 548 546 mtspr SPRN_DEC,r10; \ 549 547 b 2f; \ 550 - 1: mfspr r10,SPRN_##_H##SRR1; \ 548 + 1: cmpwi r10,PACA_IRQ_DBELL; \ 549 + beq 2f; \ 550 + mfspr r10,SPRN_##_H##SRR1; \ 551 551 rldicl r10,r10,48,1; /* clear MSR_EE */ \ 552 552 rotldi r10,r10,16; \ 553 553 mtspr SPRN_##_H##SRR1,r10; \ ··· 566 562 567 563 /* 568 564 * Called from arch_local_irq_enable when an interrupt needs 569 - * to be resent. r3 contains 0x500 or 0x900 to indicate which 570 - * kind of interrupt. MSR:EE is already off. We generate a 565 + * to be resent. r3 contains 0x500, 0x900, 0xa00 or 0xe80 to indicate 566 + * which kind of interrupt. MSR:EE is already off. We generate a 571 567 * stackframe like if a real interrupt had happened. 572 568 * 573 569 * Note: While MSR:EE is off, we need to make sure that _MSR ··· 583 579 mflr r11 584 580 mfcr r9 585 581 ori r12,r12,MSR_EE 586 - andi. r3,r3,0x0800 587 - bne decrementer_common 588 - b hardware_interrupt_common 582 + cmpwi r3,0x900 583 + beq decrementer_common 584 + cmpwi r3,0x500 585 + beq hardware_interrupt_common 586 + BEGIN_FTR_SECTION 587 + cmpwi r3,0xe80 588 + beq h_doorbell_common 589 + FTR_SECTION_ELSE 590 + cmpwi r3,0xa00 591 + beq doorbell_super_common 592 + ALT_FTR_SECTION_END_IFSET(CPU_FTR_HVMODE) 593 + blr 589 594 590 595 #ifdef CONFIG_PPC_PSERIES 591 596 /*
+9 -2
arch/powerpc/kernel/irq.c
··· 122 122 } 123 123 124 124 /* This is called whenever we are re-enabling interrupts 125 - * and returns either 0 (nothing to do) or 500/900 if there's 126 - * either an EE or a DEC to generate. 125 + * and returns either 0 (nothing to do) or 500/900/280/a00/e80 if 126 + * there's an EE, DEC or DBELL to generate. 127 127 * 128 128 * This is called in two contexts: From arch_local_irq_restore() 129 129 * before soft-enabling interrupts, and from the exception exit ··· 182 182 local_paca->irq_happened &= ~PACA_IRQ_DBELL; 183 183 if (happened & PACA_IRQ_DBELL) 184 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 192 #endif /* CONFIG_PPC_BOOK3E */ 186 193 187 194 /* There should be nothing left ! */