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 | |
| 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>
| -rw-r--r-- | arch/x86/kvm/kvm_svm.h | 2 | ||||
| -rw-r--r-- | arch/x86/kvm/svm.c | 13 | ||||
| -rw-r--r-- | arch/x86/kvm/x86.c | 2 |
3 files changed, 16 insertions, 1 deletions
diff --git a/arch/x86/kvm/kvm_svm.h b/arch/x86/kvm/kvm_svm.h index 8e5ee99551f6..a0877cac7b9c 100644 --- a/arch/x86/kvm/kvm_svm.h +++ b/arch/x86/kvm/kvm_svm.h | |||
| @@ -41,6 +41,8 @@ struct vcpu_svm { | |||
| 41 | unsigned long host_dr7; | 41 | unsigned long host_dr7; |
| 42 | 42 | ||
| 43 | u32 *msrpm; | 43 | u32 *msrpm; |
| 44 | struct vmcb *hsave; | ||
| 45 | u64 hsave_msr; | ||
| 44 | }; | 46 | }; |
| 45 | 47 | ||
| 46 | #endif | 48 | #endif |
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 | } |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 758b7a155ae9..99165a961f08 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
| @@ -456,7 +456,7 @@ static u32 msrs_to_save[] = { | |||
| 456 | MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, | 456 | MSR_CSTAR, MSR_KERNEL_GS_BASE, MSR_SYSCALL_MASK, MSR_LSTAR, |
| 457 | #endif | 457 | #endif |
| 458 | MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, | 458 | MSR_IA32_TIME_STAMP_COUNTER, MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK, |
| 459 | MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT | 459 | MSR_IA32_PERF_STATUS, MSR_IA32_CR_PAT, MSR_VM_HSAVE_PA |
| 460 | }; | 460 | }; |
| 461 | 461 | ||
| 462 | static unsigned num_msrs_to_save; | 462 | static unsigned num_msrs_to_save; |
