diff options
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64s.S')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index f521b2dac051..6144d5a6bfe7 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -335,7 +335,7 @@ emulation_assist_trampoline: | |||
335 | hv_exception_trampoline: | 335 | hv_exception_trampoline: |
336 | SET_SCRATCH0(r13) | 336 | SET_SCRATCH0(r13) |
337 | EXCEPTION_PROLOG_0(PACA_EXGEN) | 337 | EXCEPTION_PROLOG_0(PACA_EXGEN) |
338 | b hmi_exception_hv | 338 | b hmi_exception_early |
339 | 339 | ||
340 | . = 0xe80 | 340 | . = 0xe80 |
341 | hv_doorbell_trampoline: | 341 | hv_doorbell_trampoline: |
@@ -589,8 +589,64 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
589 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) | 589 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe22) |
590 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) | 590 | STD_EXCEPTION_HV_OOL(0xe42, emulation_assist) |
591 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) | 591 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe42) |
592 | STD_EXCEPTION_HV_OOL(0xe62, hmi_exception) /* need to flush cache ? */ | 592 | MASKABLE_EXCEPTION_HV_OOL(0xe62, hmi_exception) |
593 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) | 593 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe62) |
594 | |||
595 | .globl hmi_exception_early | ||
596 | hmi_exception_early: | ||
597 | EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, 0xe60) | ||
598 | mr r10,r1 /* Save r1 */ | ||
599 | ld r1,PACAEMERGSP(r13) /* Use emergency stack */ | ||
600 | subi r1,r1,INT_FRAME_SIZE /* alloc stack frame */ | ||
601 | std r9,_CCR(r1) /* save CR in stackframe */ | ||
602 | mfspr r11,SPRN_HSRR0 /* Save HSRR0 */ | ||
603 | std r11,_NIP(r1) /* save HSRR0 in stackframe */ | ||
604 | mfspr r12,SPRN_HSRR1 /* Save SRR1 */ | ||
605 | std r12,_MSR(r1) /* save SRR1 in stackframe */ | ||
606 | std r10,0(r1) /* make stack chain pointer */ | ||
607 | std r0,GPR0(r1) /* save r0 in stackframe */ | ||
608 | std r10,GPR1(r1) /* save r1 in stackframe */ | ||
609 | EXCEPTION_PROLOG_COMMON_2(PACA_EXGEN) | ||
610 | EXCEPTION_PROLOG_COMMON_3(0xe60) | ||
611 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
612 | bl hmi_exception_realmode | ||
613 | /* Windup the stack. */ | ||
614 | /* Clear MSR_RI before setting SRR0 and SRR1. */ | ||
615 | li r0,MSR_RI | ||
616 | mfmsr r9 /* get MSR value */ | ||
617 | andc r9,r9,r0 | ||
618 | mtmsrd r9,1 /* Clear MSR_RI */ | ||
619 | /* Move original HSRR0 and HSRR1 into the respective regs */ | ||
620 | ld r9,_MSR(r1) | ||
621 | mtspr SPRN_HSRR1,r9 | ||
622 | ld r3,_NIP(r1) | ||
623 | mtspr SPRN_HSRR0,r3 | ||
624 | ld r9,_CTR(r1) | ||
625 | mtctr r9 | ||
626 | ld r9,_XER(r1) | ||
627 | mtxer r9 | ||
628 | ld r9,_LINK(r1) | ||
629 | mtlr r9 | ||
630 | REST_GPR(0, r1) | ||
631 | REST_8GPRS(2, r1) | ||
632 | REST_GPR(10, r1) | ||
633 | ld r11,_CCR(r1) | ||
634 | mtcr r11 | ||
635 | REST_GPR(11, r1) | ||
636 | REST_2GPRS(12, r1) | ||
637 | /* restore original r1. */ | ||
638 | ld r1,GPR1(r1) | ||
639 | |||
640 | /* | ||
641 | * Go to virtual mode and pull the HMI event information from | ||
642 | * firmware. | ||
643 | */ | ||
644 | .globl hmi_exception_after_realmode | ||
645 | hmi_exception_after_realmode: | ||
646 | SET_SCRATCH0(r13) | ||
647 | EXCEPTION_PROLOG_0(PACA_EXGEN) | ||
648 | b hmi_exception_hv | ||
649 | |||
594 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) | 650 | MASKABLE_EXCEPTION_HV_OOL(0xe82, h_doorbell) |
595 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) | 651 | KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe82) |
596 | 652 | ||
@@ -611,6 +667,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_CFAR) | |||
611 | * - If it was a decrementer interrupt, we bump the dec to max and and return. | 667 | * - If it was a decrementer interrupt, we bump the dec to max and and return. |
612 | * - If it was a doorbell we return immediately since doorbells are edge | 668 | * - If it was a doorbell we return immediately since doorbells are edge |
613 | * triggered and won't automatically refire. | 669 | * triggered and won't automatically refire. |
670 | * - If it was a HMI we return immediately since we handled it in realmode | ||
671 | * and it won't refire. | ||
614 | * - else we hard disable and return. | 672 | * - else we hard disable and return. |
615 | * This is called with r10 containing the value to OR to the paca field. | 673 | * This is called with r10 containing the value to OR to the paca field. |
616 | */ | 674 | */ |
@@ -628,6 +686,8 @@ masked_##_H##interrupt: \ | |||
628 | b 2f; \ | 686 | b 2f; \ |
629 | 1: cmpwi r10,PACA_IRQ_DBELL; \ | 687 | 1: cmpwi r10,PACA_IRQ_DBELL; \ |
630 | beq 2f; \ | 688 | beq 2f; \ |
689 | cmpwi r10,PACA_IRQ_HMI; \ | ||
690 | beq 2f; \ | ||
631 | mfspr r10,SPRN_##_H##SRR1; \ | 691 | mfspr r10,SPRN_##_H##SRR1; \ |
632 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ | 692 | rldicl r10,r10,48,1; /* clear MSR_EE */ \ |
633 | rotldi r10,r10,16; \ | 693 | rotldi r10,r10,16; \ |
@@ -767,7 +827,7 @@ kvmppc_skip_Hinterrupt: | |||
767 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) | 827 | STD_EXCEPTION_COMMON(0xd00, single_step, single_step_exception) |
768 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) | 828 | STD_EXCEPTION_COMMON(0xe00, trap_0e, unknown_exception) |
769 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) | 829 | STD_EXCEPTION_COMMON(0xe40, emulation_assist, emulation_assist_interrupt) |
770 | STD_EXCEPTION_COMMON(0xe60, hmi_exception, unknown_exception) | 830 | STD_EXCEPTION_COMMON_ASYNC(0xe60, hmi_exception, handle_hmi_exception) |
771 | #ifdef CONFIG_PPC_DOORBELL | 831 | #ifdef CONFIG_PPC_DOORBELL |
772 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) | 832 | STD_EXCEPTION_COMMON_ASYNC(0xe80, h_doorbell, doorbell_exception) |
773 | #else | 833 | #else |