aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-07-15 05:41:47 -0400
committerAvi Kivity <avi@redhat.com>2012-07-15 05:41:47 -0400
commit64604e09ec3389cfc9668136a9302a3832cf0095 (patch)
tree0eecb2833d8279f634aaff436e97c79837f48cbd
parentad756a1603c5fac207758faaac7f01c34c9d0b7b (diff)
parent0c1fc3c3c496f8719fbea7fd3668491413ad420e (diff)
Merge branch 'for-upstream' of git://github.com/agraf/linux-2.6 into next
ppc queue from Alex Graf: * Prepare some of the booke code for 64 bit support * BookE: Fix ESR flag in DSI * BookE: Add rfci emulation * 'for-upstream' of git://github.com/agraf/linux-2.6: KVM: PPC: Critical interrupt emulation support KVM: PPC: e500mc: Fix tlbilx emulation for 64-bit guests KVM: PPC64: booke: Set interrupt computation mode for 64-bit host KVM: PPC: bookehv: Add ESR flag to Data Storage Interrupt KVM: PPC: bookehv64: Add support for std/ld emulation. booke: Added crit/mc exception handler for e500v2 booke/bookehv: Add host crit-watchdog exception support Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/powerpc/include/asm/hw_irq.h2
-rw-r--r--arch/powerpc/kvm/booke.c21
-rw-r--r--arch/powerpc/kvm/booke_emulate.c25
-rw-r--r--arch/powerpc/kvm/booke_interrupts.S55
-rw-r--r--arch/powerpc/kvm/bookehv_interrupts.S2
-rw-r--r--arch/powerpc/kvm/e500mc.c8
-rw-r--r--arch/powerpc/kvm/emulate.c16
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
35extern void timer_interrupt(struct pt_regs *); 35extern void timer_interrupt(struct pt_regs *);
36extern void performance_monitor_exception(struct pt_regs *regs); 36extern void performance_monitor_exception(struct pt_regs *regs);
37extern void WatchdogException(struct pt_regs *regs);
38extern 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 */
615static void kvmppc_restart_interrupt(struct kvm_vcpu *vcpu, 621static 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(&regs); 645 kvmppc_fill_pt_regs(&regs);
640 performance_monitor_exception(&regs); 646 performance_monitor_exception(&regs);
641 break; 647 break;
648 case BOOKE_INTERRUPT_WATCHDOG:
649 kvmppc_fill_pt_regs(&regs);
650#ifdef CONFIG_BOOKE_WDT
651 WatchdogException(&regs);
652#else
653 unknown_exception(&regs);
654#endif
655 break;
656 case BOOKE_INTERRUPT_CRITICAL:
657 unknown_exception(&regs);
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
40static 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
39int kvmppc_booke_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 46int 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)
73KVM_HANDLER BOOKE_INTERRUPT_CRITICAL 78KVM_HANDLER BOOKE_INTERRUPT_CRITICAL SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
74KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK 79KVM_HANDLER BOOKE_INTERRUPT_MACHINE_CHECK SPRN_SPRG_RSCRATCH_MC SPRN_MCSRR0
75KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE 80KVM_HANDLER BOOKE_INTERRUPT_DATA_STORAGE SPRN_SPRG_RSCRATCH0 SPRN_SRR0
76KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE 81KVM_HANDLER BOOKE_INTERRUPT_INST_STORAGE SPRN_SPRG_RSCRATCH0 SPRN_SRR0
77KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL 82KVM_HANDLER BOOKE_INTERRUPT_EXTERNAL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
78KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT 83KVM_HANDLER BOOKE_INTERRUPT_ALIGNMENT SPRN_SPRG_RSCRATCH0 SPRN_SRR0
79KVM_HANDLER BOOKE_INTERRUPT_PROGRAM 84KVM_HANDLER BOOKE_INTERRUPT_PROGRAM SPRN_SPRG_RSCRATCH0 SPRN_SRR0
80KVM_HANDLER BOOKE_INTERRUPT_FP_UNAVAIL 85KVM_HANDLER BOOKE_INTERRUPT_FP_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
81KVM_HANDLER BOOKE_INTERRUPT_SYSCALL 86KVM_HANDLER BOOKE_INTERRUPT_SYSCALL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
82KVM_HANDLER BOOKE_INTERRUPT_AP_UNAVAIL 87KVM_HANDLER BOOKE_INTERRUPT_AP_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
83KVM_HANDLER BOOKE_INTERRUPT_DECREMENTER 88KVM_HANDLER BOOKE_INTERRUPT_DECREMENTER SPRN_SPRG_RSCRATCH0 SPRN_SRR0
84KVM_HANDLER BOOKE_INTERRUPT_FIT 89KVM_HANDLER BOOKE_INTERRUPT_FIT SPRN_SPRG_RSCRATCH0 SPRN_SRR0
85KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG 90KVM_HANDLER BOOKE_INTERRUPT_WATCHDOG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
86KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS 91KVM_HANDLER BOOKE_INTERRUPT_DTLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
87KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS 92KVM_HANDLER BOOKE_INTERRUPT_ITLB_MISS SPRN_SPRG_RSCRATCH0 SPRN_SRR0
88KVM_HANDLER BOOKE_INTERRUPT_DEBUG 93KVM_HANDLER BOOKE_INTERRUPT_DEBUG SPRN_SPRG_RSCRATCH_CRIT SPRN_CSRR0
89KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL 94KVM_HANDLER BOOKE_INTERRUPT_SPE_UNAVAIL SPRN_SPRG_RSCRATCH0 SPRN_SRR0
90KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA 95KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_DATA SPRN_SPRG_RSCRATCH0 SPRN_SRR0
91KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND 96KVM_HANDLER BOOKE_INTERRUPT_SPE_FP_ROUND SPRN_SPRG_RSCRATCH0 SPRN_SRR0
92 97
93_GLOBAL(kvmppc_handler_len) 98_GLOBAL(kvmppc_handler_len)
94 .long kvmppc_handler_1 - kvmppc_handler_0 99 .long kvmppc_handler_1 - kvmppc_handler_0
95 100
96
97/* Registers: 101/* Registers:
98 * SPRG_SCRATCH0: guest r4 102 * SPRG_SCRATCH0: guest r4
99 * r4: vcpu pointer 103 * r4: vcpu pointer
100 * r5: KVM exit number 104 * r5: KVM exit number
101 */ 105 */
102_GLOBAL(kvmppc_resume_host) 106_GLOBAL(kvmppc_resume_host)
103 stw r3, VCPU_GPR(r3)(r4)
104 mfcr r3 107 mfcr r3
105 stw r3, VCPU_CR(r4) 108 stw r3, VCPU_CR(r4)
106 stw r7, VCPU_GPR(r7)(r4) 109 stw r7, VCPU_GPR(r7)(r4)
@@ -181,10 +184,6 @@ _GLOBAL(kvmppc_resume_host)
181 stw r3, VCPU_LR(r4) 184 stw r3, VCPU_LR(r4)
182 mfxer r3 185 mfxer r3
183 stw r3, VCPU_XER(r4) 186 stw r3, VCPU_XER(r4)
184 mfspr r3, SPRN_SPRG_RSCRATCH0
185 stw r3, VCPU_GPR(r4)(r4)
186 mfspr r3, SPRN_SRR0
187 stw r3, VCPU_PC(r4)
188 187
189 /* Restore host stack pointer and PID before IVPR, since the host 188 /* Restore host stack pointer and PID before IVPR, since the host
190 * exception handlers use them. */ 189 * exception handlers use them. */
diff --git a/arch/powerpc/kvm/bookehv_interrupts.S b/arch/powerpc/kvm/bookehv_interrupts.S
index 6048a00515d7..0fa2ef7df036 100644
--- a/arch/powerpc/kvm/bookehv_interrupts.S
+++ b/arch/powerpc/kvm/bookehv_interrupts.S
@@ -267,7 +267,7 @@ kvm_lvl_handler BOOKE_INTERRUPT_CRITICAL, \
267kvm_lvl_handler BOOKE_INTERRUPT_MACHINE_CHECK, \ 267kvm_lvl_handler BOOKE_INTERRUPT_MACHINE_CHECK, \
268 SPRN_SPRG_RSCRATCH_MC, SPRN_MCSRR0, SPRN_MCSRR1, 0 268 SPRN_SPRG_RSCRATCH_MC, SPRN_MCSRR0, SPRN_MCSRR1, 0
269kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, \ 269kvm_handler BOOKE_INTERRUPT_DATA_STORAGE, \
270 SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR) 270 SPRN_SRR0, SPRN_SRR1, (NEED_EMU | NEED_DEAR | NEED_ESR)
271kvm_handler BOOKE_INTERRUPT_INST_STORAGE, SPRN_SRR0, SPRN_SRR1, NEED_ESR 271kvm_handler BOOKE_INTERRUPT_INST_STORAGE, SPRN_SRR0, SPRN_SRR1, NEED_ESR
272kvm_handler BOOKE_INTERRUPT_EXTERNAL, SPRN_SRR0, SPRN_SRR1, 0 272kvm_handler BOOKE_INTERRUPT_EXTERNAL, SPRN_SRR0, SPRN_SRR1, 0
273kvm_handler BOOKE_INTERRUPT_ALIGNMENT, \ 273kvm_handler BOOKE_INTERRUPT_ALIGNMENT, \
diff --git a/arch/powerpc/kvm/e500mc.c b/arch/powerpc/kvm/e500mc.c
index fe6c1de6b701..1f89d26e65fb 100644
--- a/arch/powerpc/kvm/e500mc.c
+++ b/arch/powerpc/kvm/e500mc.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (C) 2010 Freescale Semiconductor, Inc. All rights reserved. 2 * Copyright (C) 2010,2012 Freescale Semiconductor, Inc. All rights reserved.
3 * 3 *
4 * Author: Varun Sethi, <varun.sethi@freescale.com> 4 * Author: Varun Sethi, <varun.sethi@freescale.com>
5 * 5 *
@@ -57,7 +57,8 @@ void kvmppc_e500_tlbil_one(struct kvmppc_vcpu_e500 *vcpu_e500,
57 struct kvm_book3e_206_tlb_entry *gtlbe) 57 struct kvm_book3e_206_tlb_entry *gtlbe)
58{ 58{
59 unsigned int tid, ts; 59 unsigned int tid, ts;
60 u32 val, eaddr, lpid; 60 gva_t eaddr;
61 u32 val, lpid;
61 unsigned long flags; 62 unsigned long flags;
62 63
63 ts = get_tlb_ts(gtlbe); 64 ts = get_tlb_ts(gtlbe);
@@ -183,6 +184,9 @@ int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu)
183 184
184 vcpu->arch.shadow_epcr = SPRN_EPCR_DSIGS | SPRN_EPCR_DGTMI | \ 185 vcpu->arch.shadow_epcr = SPRN_EPCR_DSIGS | SPRN_EPCR_DGTMI | \
185 SPRN_EPCR_DUVD; 186 SPRN_EPCR_DUVD;
187#ifdef CONFIG_64BIT
188 vcpu->arch.shadow_epcr |= SPRN_EPCR_ICM;
189#endif
186 vcpu->arch.shadow_msrp = MSRP_UCLEP | MSRP_DEP | MSRP_PMMP; 190 vcpu->arch.shadow_msrp = MSRP_UCLEP | MSRP_DEP | MSRP_PMMP;
187 vcpu->arch.eplc = EPC_EGS | (vcpu->kvm->arch.lpid << EPC_ELPID_SHIFT); 191 vcpu->arch.eplc = EPC_EGS | (vcpu->kvm->arch.lpid << EPC_ELPID_SHIFT);
188 vcpu->arch.epsc = vcpu->arch.eplc; 192 vcpu->arch.epsc = vcpu->arch.eplc;
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index f90e86dea7a2..ee04abaefe23 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -59,11 +59,13 @@
59#define OP_31_XOP_STHBRX 918 59#define OP_31_XOP_STHBRX 918
60 60
61#define OP_LWZ 32 61#define OP_LWZ 32
62#define OP_LD 58
62#define OP_LWZU 33 63#define OP_LWZU 33
63#define OP_LBZ 34 64#define OP_LBZ 34
64#define OP_LBZU 35 65#define OP_LBZU 35
65#define OP_STW 36 66#define OP_STW 36
66#define OP_STWU 37 67#define OP_STWU 37
68#define OP_STD 62
67#define OP_STB 38 69#define OP_STB 38
68#define OP_STBU 39 70#define OP_STBU 39
69#define OP_LHZ 40 71#define OP_LHZ 40
@@ -392,6 +394,12 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
392 emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); 394 emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
393 break; 395 break;
394 396
397 /* TBD: Add support for other 64 bit load variants like ldu, ldux, ldx etc. */
398 case OP_LD:
399 rt = get_rt(inst);
400 emulated = kvmppc_handle_load(run, vcpu, rt, 8, 1);
401 break;
402
395 case OP_LWZU: 403 case OP_LWZU:
396 emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); 404 emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1);
397 kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed); 405 kvmppc_set_gpr(vcpu, ra, vcpu->arch.vaddr_accessed);
@@ -412,6 +420,14 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
412 4, 1); 420 4, 1);
413 break; 421 break;
414 422
423 /* TBD: Add support for other 64 bit store variants like stdu, stdux, stdx etc. */
424 case OP_STD:
425 rs = get_rs(inst);
426 emulated = kvmppc_handle_store(run, vcpu,
427 kvmppc_get_gpr(vcpu, rs),
428 8, 1);
429 break;
430
415 case OP_STWU: 431 case OP_STWU:
416 emulated = kvmppc_handle_store(run, vcpu, 432 emulated = kvmppc_handle_store(run, vcpu,
417 kvmppc_get_gpr(vcpu, rs), 433 kvmppc_get_gpr(vcpu, rs),