diff options
author | Alexander Graf <agraf@suse.de> | 2012-10-06 17:19:01 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2012-10-30 05:54:51 -0400 |
commit | 388cf9ee3c751c3a4cf8776987143354d6d8c797 (patch) | |
tree | e86e275ddbb34fdd7cd0d9ecd5390be2bbfb7963 /arch/powerpc/kvm/emulate.c | |
parent | 686de182a217d315e50fef74ba5e7bcd7ea6c246 (diff) |
KVM: PPC: Move mtspr/mfspr emulation into own functions
The mtspr/mfspr emulation code became quite big over time. Move it
into its own function so things stay more readable.
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm/emulate.c')
-rw-r--r-- | arch/powerpc/kvm/emulate.c | 221 |
1 files changed, 121 insertions, 100 deletions
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c index ee04abaefe23..b0855e5d8905 100644 --- a/arch/powerpc/kvm/emulate.c +++ b/arch/powerpc/kvm/emulate.c | |||
@@ -131,6 +131,125 @@ u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb) | |||
131 | return vcpu->arch.dec - jd; | 131 | return vcpu->arch.dec - jd; |
132 | } | 132 | } |
133 | 133 | ||
134 | static int kvmppc_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs) | ||
135 | { | ||
136 | enum emulation_result emulated = EMULATE_DONE; | ||
137 | ulong spr_val = kvmppc_get_gpr(vcpu, rs); | ||
138 | |||
139 | switch (sprn) { | ||
140 | case SPRN_SRR0: | ||
141 | vcpu->arch.shared->srr0 = spr_val; | ||
142 | break; | ||
143 | case SPRN_SRR1: | ||
144 | vcpu->arch.shared->srr1 = spr_val; | ||
145 | break; | ||
146 | |||
147 | /* XXX We need to context-switch the timebase for | ||
148 | * watchdog and FIT. */ | ||
149 | case SPRN_TBWL: break; | ||
150 | case SPRN_TBWU: break; | ||
151 | |||
152 | case SPRN_MSSSR0: break; | ||
153 | |||
154 | case SPRN_DEC: | ||
155 | vcpu->arch.dec = spr_val; | ||
156 | kvmppc_emulate_dec(vcpu); | ||
157 | break; | ||
158 | |||
159 | case SPRN_SPRG0: | ||
160 | vcpu->arch.shared->sprg0 = spr_val; | ||
161 | break; | ||
162 | case SPRN_SPRG1: | ||
163 | vcpu->arch.shared->sprg1 = spr_val; | ||
164 | break; | ||
165 | case SPRN_SPRG2: | ||
166 | vcpu->arch.shared->sprg2 = spr_val; | ||
167 | break; | ||
168 | case SPRN_SPRG3: | ||
169 | vcpu->arch.shared->sprg3 = spr_val; | ||
170 | break; | ||
171 | |||
172 | default: | ||
173 | emulated = kvmppc_core_emulate_mtspr(vcpu, sprn, | ||
174 | spr_val); | ||
175 | if (emulated == EMULATE_FAIL) | ||
176 | printk(KERN_INFO "mtspr: unknown spr " | ||
177 | "0x%x\n", sprn); | ||
178 | break; | ||
179 | } | ||
180 | |||
181 | kvmppc_set_exit_type(vcpu, EMULATED_MTSPR_EXITS); | ||
182 | |||
183 | return emulated; | ||
184 | } | ||
185 | |||
186 | static int kvmppc_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt) | ||
187 | { | ||
188 | enum emulation_result emulated = EMULATE_DONE; | ||
189 | ulong spr_val = 0; | ||
190 | |||
191 | switch (sprn) { | ||
192 | case SPRN_SRR0: | ||
193 | spr_val = vcpu->arch.shared->srr0; | ||
194 | break; | ||
195 | case SPRN_SRR1: | ||
196 | spr_val = vcpu->arch.shared->srr1; | ||
197 | break; | ||
198 | case SPRN_PVR: | ||
199 | spr_val = vcpu->arch.pvr; | ||
200 | break; | ||
201 | case SPRN_PIR: | ||
202 | spr_val = vcpu->vcpu_id; | ||
203 | break; | ||
204 | case SPRN_MSSSR0: | ||
205 | spr_val = 0; | ||
206 | break; | ||
207 | |||
208 | /* Note: mftb and TBRL/TBWL are user-accessible, so | ||
209 | * the guest can always access the real TB anyways. | ||
210 | * In fact, we probably will never see these traps. */ | ||
211 | case SPRN_TBWL: | ||
212 | spr_val = get_tb() >> 32; | ||
213 | break; | ||
214 | case SPRN_TBWU: | ||
215 | spr_val = get_tb(); | ||
216 | break; | ||
217 | |||
218 | case SPRN_SPRG0: | ||
219 | spr_val = vcpu->arch.shared->sprg0; | ||
220 | break; | ||
221 | case SPRN_SPRG1: | ||
222 | spr_val = vcpu->arch.shared->sprg1; | ||
223 | break; | ||
224 | case SPRN_SPRG2: | ||
225 | spr_val = vcpu->arch.shared->sprg2; | ||
226 | break; | ||
227 | case SPRN_SPRG3: | ||
228 | spr_val = vcpu->arch.shared->sprg3; | ||
229 | break; | ||
230 | /* Note: SPRG4-7 are user-readable, so we don't get | ||
231 | * a trap. */ | ||
232 | |||
233 | case SPRN_DEC: | ||
234 | spr_val = kvmppc_get_dec(vcpu, get_tb()); | ||
235 | break; | ||
236 | default: | ||
237 | emulated = kvmppc_core_emulate_mfspr(vcpu, sprn, | ||
238 | &spr_val); | ||
239 | if (unlikely(emulated == EMULATE_FAIL)) { | ||
240 | printk(KERN_INFO "mfspr: unknown spr " | ||
241 | "0x%x\n", sprn); | ||
242 | } | ||
243 | break; | ||
244 | } | ||
245 | |||
246 | if (emulated == EMULATE_DONE) | ||
247 | kvmppc_set_gpr(vcpu, rt, spr_val); | ||
248 | kvmppc_set_exit_type(vcpu, EMULATED_MFSPR_EXITS); | ||
249 | |||
250 | return emulated; | ||
251 | } | ||
252 | |||
134 | /* XXX to do: | 253 | /* XXX to do: |
135 | * lhax | 254 | * lhax |
136 | * lhaux | 255 | * lhaux |
@@ -156,7 +275,6 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
156 | int sprn = get_sprn(inst); | 275 | int sprn = get_sprn(inst); |
157 | enum emulation_result emulated = EMULATE_DONE; | 276 | enum emulation_result emulated = EMULATE_DONE; |
158 | int advance = 1; | 277 | int advance = 1; |
159 | ulong spr_val = 0; | ||
160 | 278 | ||
161 | /* this default type might be overwritten by subcategories */ | 279 | /* this default type might be overwritten by subcategories */ |
162 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); | 280 | kvmppc_set_exit_type(vcpu, EMULATED_INST_EXITS); |
@@ -236,62 +354,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
236 | break; | 354 | break; |
237 | 355 | ||
238 | case OP_31_XOP_MFSPR: | 356 | case OP_31_XOP_MFSPR: |
239 | switch (sprn) { | 357 | 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; | 358 | break; |
296 | 359 | ||
297 | case OP_31_XOP_STHX: | 360 | case OP_31_XOP_STHX: |
@@ -308,49 +371,7 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) | |||
308 | break; | 371 | break; |
309 | 372 | ||
310 | case OP_31_XOP_MTSPR: | 373 | case OP_31_XOP_MTSPR: |
311 | spr_val = kvmppc_get_gpr(vcpu, rs); | 374 | 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; | 375 | break; |
355 | 376 | ||
356 | case OP_31_XOP_DCBI: | 377 | case OP_31_XOP_DCBI: |