aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/include/asm/kvm_asm.h6
-rw-r--r--arch/powerpc/kvm/book3s_64_rmhandlers.S39
-rw-r--r--arch/powerpc/kvm/book3s_64_slb.S16
-rw-r--r--arch/powerpc/kvm/emulate.c4
4 files changed, 59 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/kvm_asm.h b/arch/powerpc/include/asm/kvm_asm.h
index af2abe74f544..aadf2dd6f84e 100644
--- a/arch/powerpc/include/asm/kvm_asm.h
+++ b/arch/powerpc/include/asm/kvm_asm.h
@@ -97,4 +97,10 @@
97#define RESUME_HOST RESUME_FLAG_HOST 97#define RESUME_HOST RESUME_FLAG_HOST
98#define RESUME_HOST_NV (RESUME_FLAG_HOST|RESUME_FLAG_NV) 98#define RESUME_HOST_NV (RESUME_FLAG_HOST|RESUME_FLAG_NV)
99 99
100#define KVM_GUEST_MODE_NONE 0
101#define KVM_GUEST_MODE_GUEST 1
102#define KVM_GUEST_MODE_SKIP 2
103
104#define KVM_INST_FETCH_FAILED -1
105
100#endif /* __POWERPC_KVM_ASM_H__ */ 106#endif /* __POWERPC_KVM_ASM_H__ */
diff --git a/arch/powerpc/kvm/book3s_64_rmhandlers.S b/arch/powerpc/kvm/book3s_64_rmhandlers.S
index cd9f0b609e48..9ad1c2645d6f 100644
--- a/arch/powerpc/kvm/book3s_64_rmhandlers.S
+++ b/arch/powerpc/kvm/book3s_64_rmhandlers.S
@@ -49,7 +49,7 @@ kvmppc_trampoline_\intno:
49 mfcr r12 49 mfcr r12
50 stw r12, PACA_KVM_SCRATCH1(r13) 50 stw r12, PACA_KVM_SCRATCH1(r13)
51 lbz r12, PACA_KVM_IN_GUEST(r13) 51 lbz r12, PACA_KVM_IN_GUEST(r13)
52 cmpwi r12, 0 52 cmpwi r12, KVM_GUEST_MODE_NONE
53 bne ..kvmppc_handler_hasmagic_\intno 53 bne ..kvmppc_handler_hasmagic_\intno
54 /* No KVM guest? Then jump back to the Linux handler! */ 54 /* No KVM guest? Then jump back to the Linux handler! */
55 lwz r12, PACA_KVM_SCRATCH1(r13) 55 lwz r12, PACA_KVM_SCRATCH1(r13)
@@ -60,6 +60,11 @@ kvmppc_trampoline_\intno:
60 60
61 /* Now we know we're handling a KVM guest */ 61 /* Now we know we're handling a KVM guest */
62..kvmppc_handler_hasmagic_\intno: 62..kvmppc_handler_hasmagic_\intno:
63
64 /* Should we just skip the faulting instruction? */
65 cmpwi r12, KVM_GUEST_MODE_SKIP
66 beq kvmppc_handler_skip_ins
67
63 /* Let's store which interrupt we're handling */ 68 /* Let's store which interrupt we're handling */
64 li r12, \intno 69 li r12, \intno
65 70
@@ -86,6 +91,38 @@ INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_ALTIVEC
86INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX 91INTERRUPT_TRAMPOLINE BOOK3S_INTERRUPT_VSX
87 92
88/* 93/*
94 * Bring us back to the faulting code, but skip the
95 * faulting instruction.
96 *
97 * This is a generic exit path from the interrupt
98 * trampolines above.
99 *
100 * Input Registers:
101 *
102 * R12 = free
103 * R13 = PACA
104 * PACA.KVM.SCRATCH0 = guest R12
105 * PACA.KVM.SCRATCH1 = guest CR
106 * SPRG_SCRATCH0 = guest R13
107 *
108 */
109kvmppc_handler_skip_ins:
110
111 /* Patch the IP to the next instruction */
112 mfsrr0 r12
113 addi r12, r12, 4
114 mtsrr0 r12
115
116 /* Clean up all state */
117 lwz r12, PACA_KVM_SCRATCH1(r13)
118 mtcr r12
119 ld r12, PACA_KVM_SCRATCH0(r13)
120 mfspr r13, SPRN_SPRG_SCRATCH0
121
122 /* And get back into the code */
123 RFI
124
125/*
89 * This trampoline brings us back to a real mode handler 126 * This trampoline brings us back to a real mode handler
90 * 127 *
91 * Input Registers: 128 * Input Registers:
diff --git a/arch/powerpc/kvm/book3s_64_slb.S b/arch/powerpc/kvm/book3s_64_slb.S
index 7188c11ed7d1..d07b88617b2c 100644
--- a/arch/powerpc/kvm/book3s_64_slb.S
+++ b/arch/powerpc/kvm/book3s_64_slb.S
@@ -212,10 +212,6 @@ kvmppc_handler_trampoline_exit:
212 mfdar r5 212 mfdar r5
213 mfdsisr r6 213 mfdsisr r6
214 214
215 /* Unset guest state */
216 li r9, 0
217 stb r9, PACA_KVM_IN_GUEST(r13)
218
219 /* 215 /*
220 * In order for us to easily get the last instruction, 216 * In order for us to easily get the last instruction,
221 * we got the #vmexit at, we exploit the fact that the 217 * we got the #vmexit at, we exploit the fact that the
@@ -233,18 +229,28 @@ kvmppc_handler_trampoline_exit:
233 229
234ld_last_inst: 230ld_last_inst:
235 /* Save off the guest instruction we're at */ 231 /* Save off the guest instruction we're at */
232
233 /* Set guest mode to 'jump over instruction' so if lwz faults
234 * we'll just continue at the next IP. */
235 li r9, KVM_GUEST_MODE_SKIP
236 stb r9, PACA_KVM_IN_GUEST(r13)
237
236 /* 1) enable paging for data */ 238 /* 1) enable paging for data */
237 mfmsr r9 239 mfmsr r9
238 ori r11, r9, MSR_DR /* Enable paging for data */ 240 ori r11, r9, MSR_DR /* Enable paging for data */
239 mtmsr r11 241 mtmsr r11
240 /* 2) fetch the instruction */ 242 /* 2) fetch the instruction */
241 /* XXX implement PACA_KVM_IN_GUEST=2 path to safely jump over this */ 243 li r0, KVM_INST_FETCH_FAILED /* In case lwz faults */
242 lwz r0, 0(r3) 244 lwz r0, 0(r3)
243 /* 3) disable paging again */ 245 /* 3) disable paging again */
244 mtmsr r9 246 mtmsr r9
245 247
246no_ld_last_inst: 248no_ld_last_inst:
247 249
250 /* Unset guest mode */
251 li r9, KVM_GUEST_MODE_NONE
252 stb r9, PACA_KVM_IN_GUEST(r13)
253
248 /* Restore bolted entries from the shadow and fix it along the way */ 254 /* Restore bolted entries from the shadow and fix it along the way */
249 255
250 /* We don't store anything in entry 0, so we don't need to take care of it */ 256 /* We don't store anything in entry 0, so we don't need to take care of it */
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 38219af0cd0e..04e317c1bbee 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -143,6 +143,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
143 143
144 pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst)); 144 pr_debug(KERN_INFO "Emulating opcode %d / %d\n", get_op(inst), get_xop(inst));
145 145
146 /* Try again next time */
147 if (inst == KVM_INST_FETCH_FAILED)
148 return EMULATE_DONE;
149
146 switch (get_op(inst)) { 150 switch (get_op(inst)) {
147 case OP_TRAP: 151 case OP_TRAP:
148#ifdef CONFIG_PPC64 152#ifdef CONFIG_PPC64