aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/booke.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r--arch/powerpc/kvm/booke.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 75dbaeb2efa3..0b77be187cf7 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -457,6 +457,11 @@ void kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu)
457int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) 457int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
458{ 458{
459 int ret; 459 int ret;
460#ifdef CONFIG_PPC_FPU
461 unsigned int fpscr;
462 int fpexc_mode;
463 u64 fpr[32];
464#endif
460 465
461 if (!vcpu->arch.sane) { 466 if (!vcpu->arch.sane) {
462 kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR; 467 kvm_run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
@@ -479,7 +484,46 @@ int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu)
479 } 484 }
480 485
481 kvm_guest_enter(); 486 kvm_guest_enter();
487
488#ifdef CONFIG_PPC_FPU
489 /* Save userspace FPU state in stack */
490 enable_kernel_fp();
491 memcpy(fpr, current->thread.fpr, sizeof(current->thread.fpr));
492 fpscr = current->thread.fpscr.val;
493 fpexc_mode = current->thread.fpexc_mode;
494
495 /* Restore guest FPU state to thread */
496 memcpy(current->thread.fpr, vcpu->arch.fpr, sizeof(vcpu->arch.fpr));
497 current->thread.fpscr.val = vcpu->arch.fpscr;
498
499 /*
500 * Since we can't trap on MSR_FP in GS-mode, we consider the guest
501 * as always using the FPU. Kernel usage of FP (via
502 * enable_kernel_fp()) in this thread must not occur while
503 * vcpu->fpu_active is set.
504 */
505 vcpu->fpu_active = 1;
506
507 kvmppc_load_guest_fp(vcpu);
508#endif
509
482 ret = __kvmppc_vcpu_run(kvm_run, vcpu); 510 ret = __kvmppc_vcpu_run(kvm_run, vcpu);
511
512#ifdef CONFIG_PPC_FPU
513 kvmppc_save_guest_fp(vcpu);
514
515 vcpu->fpu_active = 0;
516
517 /* Save guest FPU state from thread */
518 memcpy(vcpu->arch.fpr, current->thread.fpr, sizeof(vcpu->arch.fpr));
519 vcpu->arch.fpscr = current->thread.fpscr.val;
520
521 /* Restore userspace FPU state from stack */
522 memcpy(current->thread.fpr, fpr, sizeof(current->thread.fpr));
523 current->thread.fpscr.val = fpscr;
524 current->thread.fpexc_mode = fpexc_mode;
525#endif
526
483 kvm_guest_exit(); 527 kvm_guest_exit();
484 528
485out: 529out: