aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/svm.c
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2008-11-25 14:17:05 -0500
committerAvi Kivity <avi@redhat.com>2009-03-24 05:02:46 -0400
commitb286d5d8b0836e76832dafcc5a18b0e8e5a3bc5e (patch)
tree5512694ea51b5d435b81763019f3c2c61d6a6b21 /arch/x86/kvm/svm.c
parent1371d90460189d02bf1bcca19dbfe6bd10dc6031 (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.c13
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 }