diff options
author | Alexander Graf <agraf@suse.de> | 2008-11-25 14:17:05 -0500 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2009-03-24 05:02:46 -0400 |
commit | b286d5d8b0836e76832dafcc5a18b0e8e5a3bc5e (patch) | |
tree | 5512694ea51b5d435b81763019f3c2c61d6a6b21 /arch/x86/kvm/svm.c | |
parent | 1371d90460189d02bf1bcca19dbfe6bd10dc6031 (diff) |
KVM: SVM: Implement hsave
Implement the hsave MSR, that gives the VCPU a GPA to save the
old guest state in.
v2 allows userspace to save/restore hsave
v4 dummys out the hsave MSR, so we use a host page
v6 remembers the guest's hsave and exports the MSR
Acked-by: Joerg Roedel <joro@8bytes.org>
Signed-off-by: Alexander Graf <agraf@suse.de>
Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'arch/x86/kvm/svm.c')
-rw-r--r-- | arch/x86/kvm/svm.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index 79cc06bfe57c..59aaff1c9597 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -626,6 +626,7 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
626 | struct vcpu_svm *svm; | 626 | struct vcpu_svm *svm; |
627 | struct page *page; | 627 | struct page *page; |
628 | struct page *msrpm_pages; | 628 | struct page *msrpm_pages; |
629 | struct page *hsave_page; | ||
629 | int err; | 630 | int err; |
630 | 631 | ||
631 | svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); | 632 | svm = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); |
@@ -651,6 +652,11 @@ static struct kvm_vcpu *svm_create_vcpu(struct kvm *kvm, unsigned int id) | |||
651 | svm->msrpm = page_address(msrpm_pages); | 652 | svm->msrpm = page_address(msrpm_pages); |
652 | svm_vcpu_init_msrpm(svm->msrpm); | 653 | svm_vcpu_init_msrpm(svm->msrpm); |
653 | 654 | ||
655 | hsave_page = alloc_page(GFP_KERNEL); | ||
656 | if (!hsave_page) | ||
657 | goto uninit; | ||
658 | svm->hsave = page_address(hsave_page); | ||
659 | |||
654 | svm->vmcb = page_address(page); | 660 | svm->vmcb = page_address(page); |
655 | clear_page(svm->vmcb); | 661 | clear_page(svm->vmcb); |
656 | svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; | 662 | svm->vmcb_pa = page_to_pfn(page) << PAGE_SHIFT; |
@@ -680,6 +686,7 @@ static void svm_free_vcpu(struct kvm_vcpu *vcpu) | |||
680 | 686 | ||
681 | __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); | 687 | __free_page(pfn_to_page(svm->vmcb_pa >> PAGE_SHIFT)); |
682 | __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); | 688 | __free_pages(virt_to_page(svm->msrpm), MSRPM_ALLOC_ORDER); |
689 | __free_page(virt_to_page(svm->hsave)); | ||
683 | kvm_vcpu_uninit(vcpu); | 690 | kvm_vcpu_uninit(vcpu); |
684 | kmem_cache_free(kvm_vcpu_cache, svm); | 691 | kmem_cache_free(kvm_vcpu_cache, svm); |
685 | } | 692 | } |
@@ -1377,6 +1384,9 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 *data) | |||
1377 | case MSR_IA32_LASTINTTOIP: | 1384 | case MSR_IA32_LASTINTTOIP: |
1378 | *data = svm->vmcb->save.last_excp_to; | 1385 | *data = svm->vmcb->save.last_excp_to; |
1379 | break; | 1386 | break; |
1387 | case MSR_VM_HSAVE_PA: | ||
1388 | *data = svm->hsave_msr; | ||
1389 | break; | ||
1380 | default: | 1390 | default: |
1381 | return kvm_get_msr_common(vcpu, ecx, data); | 1391 | return kvm_get_msr_common(vcpu, ecx, data); |
1382 | } | 1392 | } |
@@ -1471,6 +1481,9 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, unsigned ecx, u64 data) | |||
1471 | pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", ecx, data); | 1481 | pr_unimpl(vcpu, "unimplemented perfctr wrmsr: 0x%x data 0x%llx\n", ecx, data); |
1472 | 1482 | ||
1473 | break; | 1483 | break; |
1484 | case MSR_VM_HSAVE_PA: | ||
1485 | svm->hsave_msr = data; | ||
1486 | break; | ||
1474 | default: | 1487 | default: |
1475 | return kvm_set_msr_common(vcpu, ecx, data); | 1488 | return kvm_set_msr_common(vcpu, ecx, data); |
1476 | } | 1489 | } |