diff options
-rw-r--r-- | arch/powerpc/include/asm/exception-64s.h | 2 | ||||
-rw-r--r-- | arch/powerpc/include/asm/hardirq.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/hw_irq.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_asm.h | 1 | ||||
-rw-r--r-- | arch/powerpc/include/asm/machdep.h | 4 | ||||
-rw-r--r-- | arch/powerpc/include/asm/opal.h | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/entry_64.S | 5 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 66 | ||||
-rw-r--r-- | arch/powerpc/kernel/irq.c | 14 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 24 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s_hv_rmhandlers.S | 6 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 14 | ||||
-rw-r--r-- | arch/powerpc/platforms/powernv/setup.c | 2 |
13 files changed, 139 insertions, 3 deletions
diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h index 13a63379e496..77f52b26dad6 100644 --- a/arch/powerpc/include/asm/exception-64s.h +++ b/arch/powerpc/include/asm/exception-64s.h | |||
@@ -425,6 +425,8 @@ label##_relon_hv: \ | |||
425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL | 425 | #define SOFTEN_VALUE_0xa00 PACA_IRQ_DBELL |
426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL | 426 | #define SOFTEN_VALUE_0xe80 PACA_IRQ_DBELL |
427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL | 427 | #define SOFTEN_VALUE_0xe82 PACA_IRQ_DBELL |
428 | #define SOFTEN_VALUE_0xe60 PACA_IRQ_HMI | ||
429 | #define SOFTEN_VALUE_0xe62 PACA_IRQ_HMI | ||
428 | 430 | ||
429 | #define __SOFTEN_TEST(h, vec) \ | 431 | #define __SOFTEN_TEST(h, vec) \ |
430 | lbz r10,PACASOFTIRQEN(r13); \ | 432 | lbz r10,PACASOFTIRQEN(r13); \ |
diff --git a/arch/powerpc/include/asm/hardirq.h b/arch/powerpc/include/asm/hardirq.h index 418fb654370d..1bbb3013d6aa 100644 --- a/arch/powerpc/include/asm/hardirq.h +++ b/arch/powerpc/include/asm/hardirq.h | |||
@@ -11,6 +11,7 @@ typedef struct { | |||
11 | unsigned int pmu_irqs; | 11 | unsigned int pmu_irqs; |
12 | unsigned int mce_exceptions; | 12 | unsigned int mce_exceptions; |
13 | unsigned int spurious_irqs; | 13 | unsigned int spurious_irqs; |
14 | unsigned int hmi_exceptions; | ||
14 | #ifdef CONFIG_PPC_DOORBELL | 15 | #ifdef CONFIG_PPC_DOORBELL |
15 | unsigned int doorbell_irqs; | 16 | unsigned int doorbell_irqs; |
16 | #endif | 17 | #endif |
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index 10be1dd01c6b..b59ac27a6b7d 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
@@ -25,6 +25,7 @@ | |||
25 | #define PACA_IRQ_EE 0x04 | 25 | #define PACA_IRQ_EE 0x04 |
26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ | 26 | #define PACA_IRQ_DEC 0x08 /* Or FIT */ |
27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ | 27 | #define PACA_IRQ_EE_EDGE 0x10 /* BookE only */ |
28 | #define PACA_IRQ_HMI 0x20 | ||
28 | 29 | ||
29 | #endif /* CONFIG_PPC64 */ | 30 | #endif /* CONFIG_PPC64 */ |
30 | 31 | ||
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h index 9601741080e5..ecf7e133a4f2 100644 --- a/arch/powerpc/include/asm/kvm_asm.h +++ b/arch/powerpc/include/asm/kvm_asm.h | |||
@@ -98,6 +98,7 @@ | |||
98 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 | 98 | #define BOOK3S_INTERRUPT_H_DATA_STORAGE 0xe00 |
99 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 | 99 | #define BOOK3S_INTERRUPT_H_INST_STORAGE 0xe20 |
100 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 | 100 | #define BOOK3S_INTERRUPT_H_EMUL_ASSIST 0xe40 |
101 | #define BOOK3S_INTERRUPT_HMI 0xe60 | ||
101 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 | 102 | #define BOOK3S_INTERRUPT_H_DOORBELL 0xe80 |
102 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 | 103 | #define BOOK3S_INTERRUPT_PERFMON 0xf00 |
103 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 | 104 | #define BOOK3S_INTERRUPT_ALTIVEC 0xf20 |
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 5c7e74ddee4c..44e90516519b 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h | |||
@@ -174,6 +174,10 @@ struct machdep_calls { | |||
174 | /* Exception handlers */ | 174 | /* Exception handlers */ |
175 | int (*system_reset_exception)(struct pt_regs *regs); | 175 | int (*system_reset_exception)(struct pt_regs *regs); |
176 | int (*machine_check_exception)(struct pt_regs *regs); | 176 | int (*machine_check_exception)(struct pt_regs *regs); |
177 | int (*handle_hmi_exception)(struct pt_regs *regs); | ||
178 | |||
179 | /* Early exception handlers called in realmode */ | ||
180 | int (*hmi_exception_early)(struct pt_regs *regs); | ||
177 | 181 | ||
178 | /* Called during machine check exception to retrive fixup address. */ | 182 | /* Called during machine check exception to retrive fixup address. */ |
179 | bool (*mce_check_early_recovery)(struct pt_regs *regs); | 183 | bool (*mce_check_early_recovery)(struct pt_regs *regs); |
diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h index 7f5fd5396261..efc16c37b959 100644 --- a/arch/powerpc/include/asm/opal.h +++ b/arch/powerpc/include/asm/opal.h | |||
@@ -915,6 +915,8 @@ extern void opal_msglog_init(void); | |||
915 | 915 | ||
916 | extern int opal_machine_check(struct pt_regs *regs); | 916 | extern int opal_machine_check(struct pt_regs *regs); |
917 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); | 917 | extern bool opal_mce_check_early_recovery(struct pt_regs *regs); |
918 | extern int opal_hmi_exception_early(struct pt_regs *regs); | ||
919 | extern int opal_handle_hmi_exception(struct pt_regs *regs); | ||
918 | 920 | ||
919 | extern void opal_shutdown(void); | 921 | extern void opal_shutdown(void); |
920 | extern int opal_resync_timebase(void); | 922 | extern int opal_resync_timebase(void); |
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index d6b22e8c8ee1..5bbd1bc8c3b0 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S | |||
@@ -915,6 +915,11 @@ restore_check_irq_replay: | |||
915 | addi r3,r1,STACK_FRAME_OVERHEAD; | 915 | addi r3,r1,STACK_FRAME_OVERHEAD; |
916 | bl do_IRQ | 916 | bl do_IRQ |
917 | b ret_from_except | 917 | b ret_from_except |
918 | 1: cmpwi cr0,r3,0xe60 | ||
919 | bne 1f | ||
920 | addi r3,r1,STACK_FRAME_OVERHEAD; | ||
921 | bl handle_hmi_exception | ||
922 | b ret_from_except | ||
918 | 1: cmpwi cr0,r3,0x900 | 923 | 1: cmpwi cr0,r3,0x900 |
919 | bne 1f | 924 | bne 1f |
920 | addi r3,r1,STACK_FRAME_OVERHEAD; | 925 | addi r3,r1,STACK_FRAME_OVERHEAD; |
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 |
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c index 248ee7e5bebd..4c5891de162e 100644 --- a/arch/powerpc/kernel/irq.c +++ b/arch/powerpc/kernel/irq.c | |||
@@ -189,6 +189,11 @@ notrace unsigned int __check_irq_replay(void) | |||
189 | } | 189 | } |
190 | #endif /* CONFIG_PPC_BOOK3E */ | 190 | #endif /* CONFIG_PPC_BOOK3E */ |
191 | 191 | ||
192 | /* Check if an hypervisor Maintenance interrupt happened */ | ||
193 | local_paca->irq_happened &= ~PACA_IRQ_HMI; | ||
194 | if (happened & PACA_IRQ_HMI) | ||
195 | return 0xe60; | ||
196 | |||
192 | /* There should be nothing left ! */ | 197 | /* There should be nothing left ! */ |
193 | BUG_ON(local_paca->irq_happened != 0); | 198 | BUG_ON(local_paca->irq_happened != 0); |
194 | 199 | ||
@@ -377,6 +382,14 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
377 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); | 382 | seq_printf(p, "%10u ", per_cpu(irq_stat, j).mce_exceptions); |
378 | seq_printf(p, " Machine check exceptions\n"); | 383 | seq_printf(p, " Machine check exceptions\n"); |
379 | 384 | ||
385 | if (cpu_has_feature(CPU_FTR_HVMODE)) { | ||
386 | seq_printf(p, "%*s: ", prec, "HMI"); | ||
387 | for_each_online_cpu(j) | ||
388 | seq_printf(p, "%10u ", | ||
389 | per_cpu(irq_stat, j).hmi_exceptions); | ||
390 | seq_printf(p, " Hypervisor Maintenance Interrupts\n"); | ||
391 | } | ||
392 | |||
380 | #ifdef CONFIG_PPC_DOORBELL | 393 | #ifdef CONFIG_PPC_DOORBELL |
381 | if (cpu_has_feature(CPU_FTR_DBELL)) { | 394 | if (cpu_has_feature(CPU_FTR_DBELL)) { |
382 | seq_printf(p, "%*s: ", prec, "DBL"); | 395 | seq_printf(p, "%*s: ", prec, "DBL"); |
@@ -400,6 +413,7 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
400 | sum += per_cpu(irq_stat, cpu).mce_exceptions; | 413 | sum += per_cpu(irq_stat, cpu).mce_exceptions; |
401 | sum += per_cpu(irq_stat, cpu).spurious_irqs; | 414 | sum += per_cpu(irq_stat, cpu).spurious_irqs; |
402 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; | 415 | sum += per_cpu(irq_stat, cpu).timer_irqs_others; |
416 | sum += per_cpu(irq_stat, cpu).hmi_exceptions; | ||
403 | #ifdef CONFIG_PPC_DOORBELL | 417 | #ifdef CONFIG_PPC_DOORBELL |
404 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; | 418 | sum += per_cpu(irq_stat, cpu).doorbell_irqs; |
405 | #endif | 419 | #endif |
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index cb9cfe448ee8..0dc43f9932cf 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -302,6 +302,16 @@ long machine_check_early(struct pt_regs *regs) | |||
302 | return handled; | 302 | return handled; |
303 | } | 303 | } |
304 | 304 | ||
305 | long hmi_exception_realmode(struct pt_regs *regs) | ||
306 | { | ||
307 | __get_cpu_var(irq_stat).hmi_exceptions++; | ||
308 | |||
309 | if (ppc_md.hmi_exception_early) | ||
310 | ppc_md.hmi_exception_early(regs); | ||
311 | |||
312 | return 0; | ||
313 | } | ||
314 | |||
305 | #endif | 315 | #endif |
306 | 316 | ||
307 | /* | 317 | /* |
@@ -738,6 +748,20 @@ void SMIException(struct pt_regs *regs) | |||
738 | die("System Management Interrupt", regs, SIGABRT); | 748 | die("System Management Interrupt", regs, SIGABRT); |
739 | } | 749 | } |
740 | 750 | ||
751 | void handle_hmi_exception(struct pt_regs *regs) | ||
752 | { | ||
753 | struct pt_regs *old_regs; | ||
754 | |||
755 | old_regs = set_irq_regs(regs); | ||
756 | irq_enter(); | ||
757 | |||
758 | if (ppc_md.handle_hmi_exception) | ||
759 | ppc_md.handle_hmi_exception(regs); | ||
760 | |||
761 | irq_exit(); | ||
762 | set_irq_regs(old_regs); | ||
763 | } | ||
764 | |||
741 | void unknown_exception(struct pt_regs *regs) | 765 | void unknown_exception(struct pt_regs *regs) |
742 | { | 766 | { |
743 | enum ctx_state prev_state = exception_enter(); | 767 | enum ctx_state prev_state = exception_enter(); |
diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S index 868347ef09fd..0de9309b9a55 100644 --- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S +++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S | |||
@@ -159,6 +159,8 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S) | |||
159 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL | 159 | cmpwi r12, BOOK3S_INTERRUPT_EXTERNAL |
160 | BEGIN_FTR_SECTION | 160 | BEGIN_FTR_SECTION |
161 | beq 11f | 161 | beq 11f |
162 | cmpwi cr2, r12, BOOK3S_INTERRUPT_HMI | ||
163 | beq cr2, 14f /* HMI check */ | ||
162 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | 164 | END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) |
163 | 165 | ||
164 | /* RFI into the highmem handler, or branch to interrupt handler */ | 166 | /* RFI into the highmem handler, or branch to interrupt handler */ |
@@ -179,6 +181,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_206) | |||
179 | 181 | ||
180 | 13: b machine_check_fwnmi | 182 | 13: b machine_check_fwnmi |
181 | 183 | ||
184 | 14: mtspr SPRN_HSRR0, r8 | ||
185 | mtspr SPRN_HSRR1, r7 | ||
186 | b hmi_exception_after_realmode | ||
187 | |||
182 | kvmppc_primary_no_guest: | 188 | kvmppc_primary_no_guest: |
183 | /* We handle this much like a ceded vcpu */ | 189 | /* We handle this much like a ceded vcpu */ |
184 | /* set our bit in napping_threads */ | 190 | /* set our bit in napping_threads */ |
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 6ef2e5c5bc64..d20d69921376 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -514,6 +514,20 @@ int opal_machine_check(struct pt_regs *regs) | |||
514 | return 0; | 514 | return 0; |
515 | } | 515 | } |
516 | 516 | ||
517 | /* Early hmi handler called in real mode. */ | ||
518 | int opal_hmi_exception_early(struct pt_regs *regs) | ||
519 | { | ||
520 | /* TODO: Call opal hmi handler. */ | ||
521 | return 0; | ||
522 | } | ||
523 | |||
524 | /* HMI exception handler called in virtual mode during check_irq_replay. */ | ||
525 | int opal_handle_hmi_exception(struct pt_regs *regs) | ||
526 | { | ||
527 | /* TODO: Retrive and print HMI event from OPAL. */ | ||
528 | return 0; | ||
529 | } | ||
530 | |||
517 | static uint64_t find_recovery_address(uint64_t nip) | 531 | static uint64_t find_recovery_address(uint64_t nip) |
518 | { | 532 | { |
519 | int i; | 533 | int i; |
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c index d9b88fa7c5a3..5a0e2dc6de5f 100644 --- a/arch/powerpc/platforms/powernv/setup.c +++ b/arch/powerpc/platforms/powernv/setup.c | |||
@@ -264,6 +264,8 @@ static void __init pnv_setup_machdep_opal(void) | |||
264 | ppc_md.halt = pnv_halt; | 264 | ppc_md.halt = pnv_halt; |
265 | ppc_md.machine_check_exception = opal_machine_check; | 265 | ppc_md.machine_check_exception = opal_machine_check; |
266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; | 266 | ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery; |
267 | ppc_md.hmi_exception_early = opal_hmi_exception_early; | ||
268 | ppc_md.handle_hmi_exception = opal_handle_hmi_exception; | ||
267 | } | 269 | } |
268 | 270 | ||
269 | #ifdef CONFIG_PPC_POWERNV_RTAS | 271 | #ifdef CONFIG_PPC_POWERNV_RTAS |