diff options
Diffstat (limited to 'arch/powerpc/kvm/emulate.c')
-rw-r--r-- | arch/powerpc/kvm/emulate.c | 223 |
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 | ||
135 | static 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 | |||
187 | static 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 |