diff options
Diffstat (limited to 'arch/powerpc/kvm/booke.c')
-rw-r--r-- | arch/powerpc/kvm/booke.c | 44 |
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) | |||
457 | int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu) | 457 | int 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 | ||
485 | out: | 529 | out: |