diff options
author | Nadav Har'El <nyh@il.ibm.com> | 2011-05-25 16:07:29 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-07-12 04:45:12 -0400 |
commit | 63846663eac783eabbc1ab7c325e41a3627d986f (patch) | |
tree | 2ff22aa2b03951943373a035254bc231ff5d774e /arch/x86/kvm/vmx.c | |
parent | 27d6c865211662721e6cf305706e4a3da35f12b4 (diff) |
KVM: nVMX: Implement VMPTRLD
This patch implements the VMPTRLD instruction.
Signed-off-by: Nadav Har'El <nyh@il.ibm.com>
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/vmx.c')
-rw-r--r-- | arch/x86/kvm/vmx.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index c7600009dacb..54866f538c6f 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -4877,6 +4877,66 @@ static int handle_vmclear(struct kvm_vcpu *vcpu) | |||
4877 | return 1; | 4877 | return 1; |
4878 | } | 4878 | } |
4879 | 4879 | ||
4880 | /* Emulate the VMPTRLD instruction */ | ||
4881 | static int handle_vmptrld(struct kvm_vcpu *vcpu) | ||
4882 | { | ||
4883 | struct vcpu_vmx *vmx = to_vmx(vcpu); | ||
4884 | gva_t gva; | ||
4885 | gpa_t vmptr; | ||
4886 | struct x86_exception e; | ||
4887 | |||
4888 | if (!nested_vmx_check_permission(vcpu)) | ||
4889 | return 1; | ||
4890 | |||
4891 | if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION), | ||
4892 | vmcs_read32(VMX_INSTRUCTION_INFO), &gva)) | ||
4893 | return 1; | ||
4894 | |||
4895 | if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr, | ||
4896 | sizeof(vmptr), &e)) { | ||
4897 | kvm_inject_page_fault(vcpu, &e); | ||
4898 | return 1; | ||
4899 | } | ||
4900 | |||
4901 | if (!IS_ALIGNED(vmptr, PAGE_SIZE)) { | ||
4902 | nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS); | ||
4903 | skip_emulated_instruction(vcpu); | ||
4904 | return 1; | ||
4905 | } | ||
4906 | |||
4907 | if (vmx->nested.current_vmptr != vmptr) { | ||
4908 | struct vmcs12 *new_vmcs12; | ||
4909 | struct page *page; | ||
4910 | page = nested_get_page(vcpu, vmptr); | ||
4911 | if (page == NULL) { | ||
4912 | nested_vmx_failInvalid(vcpu); | ||
4913 | skip_emulated_instruction(vcpu); | ||
4914 | return 1; | ||
4915 | } | ||
4916 | new_vmcs12 = kmap(page); | ||
4917 | if (new_vmcs12->revision_id != VMCS12_REVISION) { | ||
4918 | kunmap(page); | ||
4919 | nested_release_page_clean(page); | ||
4920 | nested_vmx_failValid(vcpu, | ||
4921 | VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID); | ||
4922 | skip_emulated_instruction(vcpu); | ||
4923 | return 1; | ||
4924 | } | ||
4925 | if (vmx->nested.current_vmptr != -1ull) { | ||
4926 | kunmap(vmx->nested.current_vmcs12_page); | ||
4927 | nested_release_page(vmx->nested.current_vmcs12_page); | ||
4928 | } | ||
4929 | |||
4930 | vmx->nested.current_vmptr = vmptr; | ||
4931 | vmx->nested.current_vmcs12 = new_vmcs12; | ||
4932 | vmx->nested.current_vmcs12_page = page; | ||
4933 | } | ||
4934 | |||
4935 | nested_vmx_succeed(vcpu); | ||
4936 | skip_emulated_instruction(vcpu); | ||
4937 | return 1; | ||
4938 | } | ||
4939 | |||
4880 | /* | 4940 | /* |
4881 | * The exit handlers return 1 if the exit was handled fully and guest execution | 4941 | * The exit handlers return 1 if the exit was handled fully and guest execution |
4882 | * may resume. Otherwise they set the kvm_run parameter to indicate what needs | 4942 | * may resume. Otherwise they set the kvm_run parameter to indicate what needs |
@@ -4900,7 +4960,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu) = { | |||
4900 | [EXIT_REASON_VMCALL] = handle_vmcall, | 4960 | [EXIT_REASON_VMCALL] = handle_vmcall, |
4901 | [EXIT_REASON_VMCLEAR] = handle_vmclear, | 4961 | [EXIT_REASON_VMCLEAR] = handle_vmclear, |
4902 | [EXIT_REASON_VMLAUNCH] = handle_vmx_insn, | 4962 | [EXIT_REASON_VMLAUNCH] = handle_vmx_insn, |
4903 | [EXIT_REASON_VMPTRLD] = handle_vmx_insn, | 4963 | [EXIT_REASON_VMPTRLD] = handle_vmptrld, |
4904 | [EXIT_REASON_VMPTRST] = handle_vmx_insn, | 4964 | [EXIT_REASON_VMPTRST] = handle_vmx_insn, |
4905 | [EXIT_REASON_VMREAD] = handle_vmx_insn, | 4965 | [EXIT_REASON_VMREAD] = handle_vmx_insn, |
4906 | [EXIT_REASON_VMRESUME] = handle_vmx_insn, | 4966 | [EXIT_REASON_VMRESUME] = handle_vmx_insn, |