diff options
| -rw-r--r-- | arch/powerpc/include/asm/hw_irq.h | 2 | ||||
| -rw-r--r-- | arch/powerpc/kvm/booke.c | 21 | ||||
| -rw-r--r-- | arch/powerpc/kvm/booke_emulate.c | 25 | ||||
| -rw-r--r-- | arch/powerpc/kvm/booke_interrupts.S | 55 | ||||
| -rw-r--r-- | arch/powerpc/kvm/bookehv_interrupts.S | 2 | ||||
| -rw-r--r-- | arch/powerpc/kvm/e500mc.c | 8 | ||||
| -rw-r--r-- | arch/powerpc/kvm/emulate.c | 16 |
7 files changed, 98 insertions, 31 deletions
diff --git a/arch/powerpc/include/asm/hw_irq.h b/arch/powerpc/include/asm/hw_irq.h index c9aac24b02e2..2aadb47efaec 100644 --- a/arch/powerpc/include/asm/hw_irq.h +++ b/arch/powerpc/include/asm/hw_irq.h | |||
| @@ -34,6 +34,8 @@ extern void __replay_interrupt(unsigned int vector); | |||
| 34 | 34 | ||
| 35 | extern void timer_interrupt(struct pt_regs *); | 35 | extern void timer_interrupt(struct pt_regs *); |
| 36 | extern void performance_monitor_exception(struct pt_regs *regs); | 36 | extern void performance_monitor_exception(struct pt_regs *regs); |
| 37 | extern void WatchdogException(struct pt_regs *regs); | ||
| 38 | extern void unknown_exception(struct pt_regs *regs); | ||
| 37 | 39 | ||
| 38 | #ifdef CONFIG_PPC64 | 40 | #ifdef CONFIG_PPC64 |
| 39 | #include <asm/paca.h> | 41 | #include <asm/paca.h> |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 86681eec60b1..d25a097c852b 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
| @@ -612,6 +612,12 @@ static void kvmppc_fill_pt_regs(struct pt_regs *regs) | |||
| 612 | regs->link = lr; | 612 | regs->link = lr; |
| 613 | } | 613 | } |
| 614 | 614 | ||
| 615 | /* | ||
| 616 | * For interrupts needed to be handled by host interrupt handlers, | ||
| 617 | * corresponding host handler are called from here in similar way | ||
| 618 | * (but not exact) as they are called from low level handler | ||
| 619 | * (such as from arch/powerpc/kernel/head_fsl_booke.S). | ||
| 620 | */ | ||
| 615 | static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, | 621 | static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, |
| 616 | unsigned int exit_nr) | 622 | unsigned int exit_nr) |
| 617 | { | 623 | { |
| @@ -639,6 +645,17 @@ static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, | |||
| 639 | kvmppc_fill_pt_regs(®s); | 645 | kvmppc_fill_pt_regs(®s); |
| 640 | performance_monitor_exception(®s); | 646 | performance_monitor_exception(®s); |
| 641 | break; | 647 | break; |
| 648 | case BOOKE_INTERRUPT_WATCHDOG: | ||
| 649 | kvmppc_fill_pt_regs(®s); | ||
| 650 | #ifdef CONFIG_BOOKE_WDT | ||
| 651 | WatchdogException(®s); | ||
| 652 | #else | ||
| 653 | unknown_exception(®s); | ||
| 654 | #endif | ||
| 655 | break; | ||
| 656 | case BOOKE_INTERRUPT_CRITICAL: | ||
| 657 | unknown_exception(®s); | ||
| 658 | break; | ||
| 642 | } | 659 | } |
| 643 | } | 660 | } |
| 644 | 661 | ||
| @@ -683,6 +700,10 @@ int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 683 | r = RESUME_GUEST; | 700 | r = RESUME_GUEST; |
| 684 | break; | 701 | break; |
| 685 | 702 | ||
| 703 | case BOOKE_INTERRUPT_WATCHDOG: | ||
| 704 | r = RESUME_GUEST; | ||
| 705 | break; | ||
| 706 | |||
| 686 | case BOOKE_INTERRUPT_DOORBELL: | 707 | case BOOKE_INTERRUPT_DOORBELL: |
| 687 | kvmppc_account_exit(vcpu, DBELL_EXITS); | 708 | kvmppc_account_exit(vcpu, DBELL_EXITS); |
| 688 | r = RESUME_GUEST; | 709 | r = RESUME_GUEST; |
diff --git a/arch/powerpc/kvm/booke_emulate.c b/arch/powerpc/kvm/booke_emulate.c index 9eb9809eb13e..12834bb608ab 100644 --- a/arch/powerpc/kvm/booke_emulate.c +++ b/arch/powerpc/kvm/booke_emulate.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "booke.h" | 24 | #include "booke.h" |
| 25 | 25 | ||
| 26 | #define OP_19_XOP_RFI 50 | 26 | #define OP_19_XOP_RFI 50 |
| 27 | #define OP_19_XOP_RFCI 51 | ||
| 27 | 28 | ||
| 28 | #define OP_31_XOP_MFMSR 83 | 29 | #define OP_31_XOP_MFMSR 83 |
| 29 | #define OP_31_XOP_WRTEE 131 | 30 | #define OP_31_XOP_WRTEE 131 |
| @@ -36,6 +37,12 @@ static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) | |||
| 36 | kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); | 37 | kvmppc_set_msr(vcpu, vcpu->arch.shared->srr1); |
| 37 | } | 38 | } |
| 38 | 39 | ||
| 40 | static void kvmppc_emul_rfci(struct kvm_vcpu *vcpu) | ||
| 41 | { | ||
| 42 | vcpu->arch.pc = vcpu->arch.csrr0; | ||
| 43 | kvmppc_set_msr(vcpu, vcpu->arch.csrr1); | ||
| 44 | } | ||
| 45 | |||
| 39 | int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | 46 | int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, |
| 40 | unsigned int inst, int *advance) | 47 | unsigned int inst, int *advance) |
| 41 | { | 48 | { |
| @@ -52,6 +59,12 @@ int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, | |||
| 52 | *advance = 0; | 59 | *advance = 0; |
| 53 | break; | 60 | break; |
| 54 | 61 | ||
| 62 | case OP_19_XOP_RFCI: | ||
| 63 | kvmppc_emul_rfci(vcpu); | ||
| 64 | kvmppc_set_exit_type(vcpu, EMULATED_RFCI_EXITS); | ||
| 65 | *advance = 0; | ||
| 66 | break; | ||
| 67 | |||
| 55 | default: | 68 | default: |
| 56 | emulated = EMULATE_FAIL; | 69 | emulated = EMULATE_FAIL; |
| 57 | break; | 70 | break; |
| @@ -113,6 +126,12 @@ int kvmppc_booke_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) | |||
| 113 | case SPRN_ESR: | 126 | case SPRN_ESR: |
| 114 | vcpu->arch.shared->esr = spr_val; | 127 | vcpu->arch.shared->esr = spr_val; |
| 115 | break; | 128 | break; |
| 129 | case SPRN_CSRR0: | ||
| 130 | vcpu->arch.csrr0 = spr_val; | ||
| 131 | break; | ||
| 132 | case SPRN_CSRR1: | ||
| 133 | vcpu->arch.csrr1 = spr_val; | ||
| 134 | break; | ||
| 116 | case SPRN_DBCR0: | 135 | case SPRN_DBCR0: |
| 117 | vcpu->arch.dbcr0 = spr_val; | 136 | vcpu->arch.dbcr0 = spr_val; |
| 118 | break; | 137 | break; |
| @@ -232,6 +251,12 @@ int kvmppc_booke_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) | |||
| 232 | case SPRN_ESR: | 251 | case SPRN_ESR: |
| 233 | *spr_val = vcpu->arch.shared->esr; | 252 | *spr_val = vcpu->arch.shared->esr; |
| 234 | break; | 253 | break; |
| 254 | case SPRN_CSRR0: | ||
| 255 | *spr_val = vcpu->arch.csrr0; | ||
| 256 | break; | ||
| 257 | case SPRN_CSRR1: | ||
| 258 | *spr_val = vcpu->arch.csrr1; | ||
| 259 | break; | ||
| 235 | case SPRN_DBCR0: | 260 | case SPRN_DBCR0: |
| 236 | *spr_val = vcpu->arch.dbcr0; | 261 | *spr_val = vcpu->arch.dbcr0; |
| 237 | break; | 262 | break; |
diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S index 8feec2ff3928..09456c4719f3 100644 --- a/arch/powerpc/kvm/booke_interrupts.S +++ b/arch/powerpc/kvm/booke_interrupts.S | |||
| @@ -53,16 +53,21 @@ | |||
| 53 | (1<<BOOKE_INTERRUPT_PROGRAM) | \ | 53 | (1<<BOOKE_INTERRUPT_PROGRAM) | \ |
| 54 | (1<<BOOKE_INTERRUPT_DTLB_MISS)) | 54 | (1<<BOOKE_INTERRUPT_DTLB_MISS)) |
| 55 | 55 | ||
| 56 | .macro KVM_HANDLER ivor_nr | 56 | .macro KVM_HANDLER ivor_nr scratch srr0 |
| 57 | _GLOBAL(kvmppc_handler_\ivor_nr) | 57 | _GLOBAL(kvmppc_handler_\ivor_nr) |
| 58 | /* Get pointer to vcpu and record exit number. */ | 58 | /* Get pointer to vcpu and record exit number. */ |
| 59 | mtspr SPRN_SPRG_WSCRATCH0, r4 | 59 | mtspr \scratch , r4 |
| 60 | mfspr r4, SPRN_SPRG_RVCPU | 60 | mfspr r4, SPRN_SPRG_RVCPU |
| 61 | stw r3, VCPU_GPR(r3)(r4) | ||
| 61 | stw r5, VCPU_GPR(r5)(r4) | 62 | stw r5, VCPU_GPR(r5)(r4) |
| 62 | stw r6, VCPU_GPR(r6)(r4) | 63 | stw r6, VCPU_GPR(r6)(r4) |
| 64 | mfspr r3, \scratch | ||
| 63 | mfctr r5 | 65 | mfctr r5 |
| 64 | lis r6, kvmppc_resume_host@h | 66 | stw r3, VCPU_GPR(r4)(r4) |
| 65 | stw r5, VCPU_CTR(r4) | 67 | stw r5, VCPU_CTR(r4) |
| 68 | mfspr r3, \srr0 | ||
| 69 | lis r6, kvmppc_resume_host@h | ||
| 70 | stw r3, VCPU_PC(r4) | ||
| 66 | li r5, \ivor_nr | 71 | li r5, \ivor_nr |
| 67 | ori r6, r6, kvmppc_resume_host@l | 72 | ori r6, r6, kvmppc_resume_host@l |
| 68 | mtctr r6 | 73 | mtctr r6 |
| @@ -70,37 +75,35 @@ _GLOBAL(kvmppc_handler_\ivor_nr) | |||
| 70 | .endm | 75 | .endm |
| 71 | 76 | ||
| 72 | _GLOBAL(kvmppc_handlers_start) | 77 | _GLOBAL(kvmppc_handlers_start) |
| 73 | KVM_HANDLER BOOKE_INTERRUPT_CRITICAL | 78 | KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0 |
| 74 | KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK | 79 | KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0 |
| 75 | KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE | 80 | KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE SPRN_SPRG_RSCRATCH0 SPRN_SRR0 |
| 76 | KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE | 81 | KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE SPRN_SPRG_RSCRATCH0 SPRN_SRR0 |
| 77 | KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL | 82 | KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL SPRN_SPRG_RSCRATCH0 SPRN_SRR0 |
| 78 | KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT | 83 | KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT SPRN_SPRG_RSCRATCH0 SPRN_SRR0 |
