aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2010-06-13 05:29:39 -0400
committerAvi Kivity <avi@redhat.com>2010-08-01 03:46:37 -0400
commit2d5b5a665508c60577c1088e0405850a965b6795 (patch)
tree3549325770a39b0c7fd2b7f81aa6fa42295803e2 /arch/x86/kvm/x86.c
parent69b61833f7ce6e61e196c8a724e4d1278b24ac02 (diff)
KVM: x86: XSAVE/XRSTOR live migration support
This patch enable save/restore of xsave state. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r--arch/x86/kvm/x86.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 795999e1ac19..0c8dc9614e7d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1680,6 +1680,7 @@ int kvm_dev_ioctl_check_extension(long ext)
1680 case KVM_CAP_PCI_SEGMENT: 1680 case KVM_CAP_PCI_SEGMENT:
1681 case KVM_CAP_DEBUGREGS: 1681 case KVM_CAP_DEBUGREGS:
1682 case KVM_CAP_X86_ROBUST_SINGLESTEP: 1682 case KVM_CAP_X86_ROBUST_SINGLESTEP:
1683 case KVM_CAP_XSAVE:
1683 r = 1; 1684 r = 1;
1684 break; 1685 break;
1685 case KVM_CAP_COALESCED_MMIO: 1686 case KVM_CAP_COALESCED_MMIO:
@@ -1703,6 +1704,9 @@ int kvm_dev_ioctl_check_extension(long ext)
1703 case KVM_CAP_MCE: 1704 case KVM_CAP_MCE:
1704 r = KVM_MAX_MCE_BANKS; 1705 r = KVM_MAX_MCE_BANKS;
1705 break; 1706 break;
1707 case KVM_CAP_XCRS:
1708 r = cpu_has_xsave;
1709 break;
1706 default: 1710 default:
1707 r = 0; 1711 r = 0;
1708 break; 1712 break;
@@ -2355,6 +2359,77 @@ static int kvm_vcpu_ioctl_x86_set_debugregs(struct kvm_vcpu *vcpu,
2355 return 0; 2359 return 0;
2356} 2360}
2357 2361
2362static void kvm_vcpu_ioctl_x86_get_xsave(struct kvm_vcpu *vcpu,
2363 struct kvm_xsave *guest_xsave)
2364{
2365 if (cpu_has_xsave)
2366 memcpy(guest_xsave->region,
2367 &vcpu->arch.guest_fpu.state->xsave,
2368 sizeof(struct xsave_struct));
2369 else {
2370 memcpy(guest_xsave->region,
2371 &vcpu->arch.guest_fpu.state->fxsave,
2372 sizeof(struct i387_fxsave_struct));
2373 *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)] =
2374 XSTATE_FPSSE;
2375 }
2376}
2377
2378static int kvm_vcpu_ioctl_x86_set_xsave(struct kvm_vcpu *vcpu,
2379 struct kvm_xsave *guest_xsave)
2380{
2381 u64 xstate_bv =
2382 *(u64 *)&guest_xsave->region[XSAVE_HDR_OFFSET / sizeof(u32)];
2383
2384 if (cpu_has_xsave)
2385 memcpy(&vcpu->arch.guest_fpu.state->xsave,
2386 guest_xsave->region, sizeof(struct xsave_struct));
2387 else {
2388 if (xstate_bv & ~XSTATE_FPSSE)
2389 return -EINVAL;
2390 memcpy(&vcpu->arch.guest_fpu.state->fxsave,
2391 guest_xsave->region, sizeof(struct i387_fxsave_struct));
2392 }
2393 return 0;
2394}
2395
2396static void kvm_vcpu_ioctl_x86_get_xcrs(struct kvm_vcpu *vcpu,
2397 struct kvm_xcrs *guest_xcrs)
2398{
2399 if (!cpu_has_xsave) {
2400 guest_xcrs->nr_xcrs = 0;
2401 return;
2402 }
2403
2404 guest_xcrs->nr_xcrs = 1;
2405 guest_xcrs->flags = 0;
2406 guest_xcrs->xcrs[0].xcr = XCR_XFEATURE_ENABLED_MASK;
2407 guest_xcrs->xcrs[0].value = vcpu->arch.xcr0;
2408}
2409
2410static int kvm_vcpu_ioctl_x86_set_xcrs(struct kvm_vcpu *vcpu,
2411 struct kvm_xcrs *guest_xcrs)
2412{
2413 int i, r = 0;
2414
2415 if (!cpu_has_xsave)
2416 return -EINVAL;
2417
2418 if (guest_xcrs->nr_xcrs > KVM_MAX_XCRS || guest_xcrs->flags)
2419 return -EINVAL;
2420
2421 for (i = 0; i < guest_xcrs->nr_xcrs; i++)
2422 /* Only support XCR0 currently */
2423 if (guest_xcrs->xcrs[0].xcr == XCR_XFEATURE_ENABLED_MASK) {
2424 r = __kvm_set_xcr(vcpu, XCR_XFEATURE_ENABLED_MASK,
2425 guest_xcrs->xcrs[0].value);
2426 break;
2427 }
2428 if (r)
2429 r = -EINVAL;
2430 return r;
2431}
2432
2358long kvm_arch_vcpu_ioctl(struct file *filp, 2433long kvm_arch_vcpu_ioctl(struct file *filp,
2359 unsigned int ioctl, unsigned long arg) 2434 unsigned int ioctl, unsigned long arg)
2360{ 2435{
@@ -2556,6 +2631,70 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
2556 r = kvm_vcpu_ioctl_x86_set_debugregs(vcpu, &dbgregs); 2631 r = kvm_vcpu_ioctl_x86_set_debugregs(vcpu, &dbgregs);
2557 break; 2632 break;
2558 } 2633 }
2634 case KVM_GET_XSAVE: {
2635 struct kvm_xsave *xsave;
2636
2637 xsave = kzalloc(sizeof(struct kvm_xsave), GFP_KERNEL);
2638 r = -ENOMEM;
2639 if (!xsave)
2640 break;
2641
2642 kvm_vcpu_ioctl_x86_get_xsave(vcpu, xsave);
2643
2644 r = -EFAULT;
2645 if (copy_to_user(argp, xsave, sizeof(struct kvm_xsave)))
2646 break;
2647 r = 0;
2648 break;
2649 }
2650 case KVM_SET_XSAVE: {
2651 struct kvm_xsave *xsave;
2652
2653 xsave = kzalloc(sizeof(struct kvm_xsave), GFP_KERNEL);
2654 r = -ENOMEM;
2655 if (!xsave)
2656 break;
2657
2658 r = -EFAULT;
2659 if (copy_from_user(xsave, argp, sizeof(struct kvm_xsave)))
2660 break;
2661
2662 r = kvm_vcpu_ioctl_x86_set_xsave(vcpu, xsave);
2663 break;
2664 }
2665 case KVM_GET_XCRS: {
2666 struct kvm_xcrs *xcrs;
2667
2668 xcrs = kzalloc(sizeof(struct kvm_xcrs), GFP_KERNEL);
2669 r = -ENOMEM;
2670 if (!xcrs)
2671 break;
2672
2673 kvm_vcpu_ioctl_x86_get_xcrs(vcpu, xcrs);
2674
2675 r = -EFAULT;
2676 if (copy_to_user(argp, xcrs,
2677 sizeof(struct kvm_xcrs)))
2678 break;
2679 r = 0;
2680 break;
2681 }
2682 case KVM_SET_XCRS: {
2683 struct kvm_xcrs *xcrs;
2684
2685 xcrs = kzalloc(sizeof(struct kvm_xcrs), GFP_KERNEL);
2686 r = -ENOMEM;
2687 if (!xcrs)
2688 break;
2689
2690 r = -EFAULT;
2691 if (copy_from_user(xcrs, argp,
2692 sizeof(struct kvm_xcrs)))
2693 break;
2694
2695 r = kvm_vcpu_ioctl_x86_set_xcrs(vcpu, xcrs);
2696 break;
2697 }
2559 default: 2698 default:
2560 r = -EINVAL; 2699 r = -EINVAL;
2561 } 2700 }