aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/emulate.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/emulate.c')
-rw-r--r--arch/powerpc/kvm/emulate.c223
1 files changed, 123 insertions, 100 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index ee04abaefe23..9d9cddc5b346 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -39,6 +39,7 @@
39#define OP_31_XOP_TRAP 4 39#define OP_31_XOP_TRAP 4
40#define OP_31_XOP_LWZX 23 40#define OP_31_XOP_LWZX 23
41#define OP_31_XOP_TRAP_64 68 41#define OP_31_XOP_TRAP_64 68
42#define OP_31_XOP_DCBF 86
42#define OP_31_XOP_LBZX 87 43#define OP_31_XOP_LBZX 87
43#define OP_31_XOP_STWX 151 44#define OP_31_XOP_STWX 151
44#define OP_31_XOP_STBX 215 45#define OP_31_XOP_STBX 215
@@ -131,6 +132,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb)
131 return vcpu->arch.dec - jd; 132 return vcpu->arch.dec - jd;
132} 133}
133 134
135static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
136{
137 enum emulation_result emulated = EMULATE_DONE;
138 ulong spr_val = kvmppc_get_gpr(vcpu, rs);
139
140 switch (sprn) {
141 case SPRN_SRR0:
142 vcpu->arch.shared->srr0 = spr_val;
143 break;
144 case SPRN_SRR1:
145 vcpu->arch.shared->srr1 = spr_val;
146 break;
147
148 /* XXX We need to context-switch the timebase for
149 * watchdog and FIT. */
150 case SPRN_TBWL: break;
151 case SPRN_TBWU: break;
152
153 case SPRN_MSSSR0: break;
154
155 case SPRN_DEC:
156 vcpu->arch.dec = spr_val;
157 kvmppc_emulate_dec(vcpu);
158 break;
159
160 case SPRN_SPRG0:
161 vcpu->arch.shared->sprg0 = spr_val;
162 break;
163 case SPRN_SPRG1:
164 vcpu->arch.shared->sprg1 = spr_val;
165 break;
166 case SPRN_SPRG2:
167 vcpu->arch.shared->sprg2 = spr_val;
168 break;
169 case SPRN_SPRG3:
170 vcpu->arch.shared->sprg3 = spr_val;
171 break;
172
173 default:
174 emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
175 spr_val);
176 if (emulated == EMULATE_FAIL)
177 printk(KERN_INFO "mtspr: unknown spr "
178 "0x%x\n", sprn);
179 break;
180 }
181
182 kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
183
184 return emulated;
185}
186
187static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
188{
189 enum emulation_result emulated = EMULATE_DONE;
190 ulong spr_val = 0;
191
192 switch (sprn) {
193 case SPRN_SRR0:
194 spr_val = vcpu->arch.shared->srr0;
195 break;
196 case SPRN_SRR1:
197 spr_val = vcpu->arch.shared->srr1;
198 break;
199 case SPRN_PVR:
200 spr_val = vcpu->arch.pvr;
201 break;
202 case SPRN_PIR:
203 spr_val = vcpu->vcpu_id;
204 break;
205 case SPRN_MSSSR0:
206 spr_val = 0;
207 break;
208
209 /* Note: mftb and TBRL/TBWL are user-accessible, so
210 * the guest can always access the real TB anyways.
211 * In fact, we probably will never see these traps. */
212 case SPRN_TBWL:
213 spr_val = get_tb() >> 32;
214 break;
215 case SPRN_TBWU:
216 spr_val = get_tb();
217 break;
218
219 case SPRN_SPRG0:
220 spr_val = vcpu->arch.shared->sprg0;
221 break;
222 case SPRN_SPRG1:
223 spr_val = vcpu->arch.shared->sprg1;
224 break;
225 case SPRN_SPRG2:
226 spr_val = vcpu->arch.shared->sprg2;
227 break;
228 case SPRN_SPRG3:
229 spr_val = vcpu->arch.shared->sprg3;
230 break;
231 /* Note: SPRG4-7 are user-readable, so we don't get
232 * a trap. */
233
234 case SPRN_DEC:
235 spr_val = kvmppc_get_dec(vcpu, get_tb());
236 break;
237 default:
238 emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
239 &spr_val);
240 if (unlikely(emulated == EMULATE_FAIL)) {
241 printk(KERN_INFO "mfspr: unknown spr "
242 "0x%x\n", sprn);
243 }
244 break;
245 }
246
247 if (emulated == EMULATE_DONE)
248 kvmppc_set_gpr(vcpu, rt, spr_val);
249 kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
250
251 return emulated;
252}
253
134/* XXX to do: 254/* XXX to do:
135 * lhax 255 * lhax
136 * lhaux 256 * lhaux
@@ -156,7 +276,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
156 int sprn = get_sprn(inst); 276 int sprn = get_sprn(inst);
157 enum emulation_result emulated = EMULATE_DONE; 277 enum emulation_result emulated = EMULATE_DONE;
158 int advance = 1; 278 int advance = 1;
159 ulong spr_val = 0;
160 279
161 /* this default type might be overwritten by subcategories */ 280 /* this default type might be overwritten by subcategories */
162 kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); 281 kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS);
@@ -236,62 +355,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
236 break; 355 break;
237 356
238 case OP_31_XOP_MFSPR: 357 case OP_31_XOP_MFSPR:
239 switch (sprn) { 358 emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
240 case SPRN_SRR0:
241 spr_val = vcpu->arch.shared->srr0;
242 break;
243 case SPRN_SRR1:
244 spr_val = vcpu->arch.shared->srr1;
245 break;
246 case SPRN_PVR:
247 spr_val = vcpu->arch.pvr;
248 break;
249 case SPRN_PIR:
250 spr_val = vcpu->vcpu_id;
251 break;
252 case SPRN_MSSSR0:
253 spr_val = 0;
254 break;
255
256 /* Note: mftb and TBRL/TBWL are user-accessible, so
257 * the guest can always access the real TB anyways.
258 * In fact, we probably will never see these traps. */
259 case SPRN_TBWL:
260 spr_val = get_tb() >> 32;
261 break;
262 case SPRN_TBWU:
263 spr_val = get_tb();
264 break;
265
266 case SPRN_SPRG0:
267 spr_val = vcpu->arch.shared->sprg0;
268 break;
269 case SPRN_SPRG1:
270 spr_val = vcpu->arch.shared->sprg1;
271 break;
272 case SPRN_SPRG2:
273 spr_val = vcpu->arch.shared->sprg2;
274 break;
275 case SPRN_SPRG3:
276 spr_val = vcpu->arch.shared->sprg3;
277 break;
278 /* Note: SPRG4-7 are user-readable, so we don't get
279 * a trap. */
280
281 case SPRN_DEC:
282 spr_val = kvmppc_get_dec(vcpu, get_tb());
283 break;
284 default:
285 emulated = kvmppc_core_emulate_mfspr(vcpu, sprn,
286 &spr_val);
287 if (unlikely(emulated == EMULATE_FAIL)) {
288 printk(KERN_INFO "mfspr: unknown spr "
289 "0x%x\n", sprn);
290 }
291 break;
292 }
293 kvmppc_set_gpr(vcpu, rt, spr_val);
294 kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS);
295 break; 359 break;
296 360
297 case OP_31_XOP_STHX: 361 case OP_31_XOP_STHX:
@@ -308,51 +372,10 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
308 break; 372 break;
309 373
310 case OP_31_XOP_MTSPR: 374 case OP_31_XOP_MTSPR:
311 spr_val = kvmppc_get_gpr(vcpu, rs); 375 emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
312 switch (sprn) {
313 case SPRN_SRR0:
314 vcpu->arch.shared->srr0 = spr_val;
315 break;
316 case SPRN_SRR1:
317 vcpu->arch.shared->srr1 = spr_val;
318 break;
319
320 /* XXX We need to context-switch the timebase for
321 * watchdog and FIT. */
322 case SPRN_TBWL: break;
323 case SPRN_TBWU: break;
324
325 case SPRN_MSSSR0: break;
326
327 case SPRN_DEC:
328 vcpu->arch.dec = spr_val;
329 kvmppc_emulate_dec(vcpu);
330 break;
331
332 case SPRN_SPRG0:
333 vcpu->arch.shared->sprg0 = spr_val;
334 break;
335 case SPRN_SPRG1:
336 vcpu->arch.shared->sprg1 = spr_val;
337 break;
338 case SPRN_SPRG2:
339 vcpu->arch.shared->sprg2 = spr_val;
340 break;
341 case SPRN_SPRG3:
342 vcpu->arch.shared->sprg3 = spr_val;
343 break;
344
345 default:
346 emulated = kvmppc_core_emulate_mtspr(vcpu, sprn,
347 spr_val);
348 if (emulated == EMULATE_FAIL)
349 printk(KERN_INFO "mtspr: unknown spr "
350 "0x%x\n", sprn);
351 break;
352 }
353 kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS);
354 break; 376 break;
355 377
378 case OP_31_XOP_DCBF:
356 case OP_31_XOP_DCBI: 379 case OP_31_XOP_DCBI:
357 /* Do nothing. The guest is performing dcbi because 380 /* Do nothing. The guest is performing dcbi because
358 * hardware DMA is not snooped by the dcache, but 381 * hardware DMA is not snooped by the dcache, but