aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/vmx.c140
1 files changed, 57 insertions, 83 deletions
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 880f371705bc..9b4b5d6dcd34 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -6914,97 +6914,21 @@ static int get_vmx_mem_address(struct kvm_vcpu *vcpu,
6914 return 0; 6914 return 0;
6915} 6915}
6916 6916
6917/* 6917static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer)
6918 * This function performs the various checks including
6919 * - if it's 4KB aligned
6920 * - No bits beyond the physical address width are set
6921 * - Returns 0 on success or else 1
6922 * (Intel SDM Section 30.3)
6923 */
6924static int nested_vmx_check_vmptr(struct kvm_vcpu *vcpu, int exit_reason,
6925 gpa_t *vmpointer)
6926{ 6918{
6927 gva_t gva; 6919 gva_t gva;
6928 gpa_t vmptr;
6929 struct x86_exception e; 6920 struct x86_exception e;
6930 struct page *page;
6931 struct vcpu_vmx *vmx = to_vmx(vcpu);
6932 int maxphyaddr = cpuid_maxphyaddr(vcpu);
6933 6921
6934 if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION), 6922 if (get_vmx_mem_address(vcpu, vmcs_readl(EXIT_QUALIFICATION),
6935 vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva)) 6923 vmcs_read32(VMX_INSTRUCTION_INFO), false, &gva))
6936 return 1; 6924 return 1;
6937 6925
6938 if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, &vmptr, 6926 if (kvm_read_guest_virt(&vcpu->arch.emulate_ctxt, gva, vmpointer,
6939 sizeof(vmptr), &e)) { 6927 sizeof(*vmpointer), &e)) {
6940 kvm_inject_page_fault(vcpu, &e); 6928 kvm_inject_page_fault(vcpu, &e);
6941 return 1; 6929 return 1;
6942 } 6930 }
6943 6931
6944 switch (exit_reason) {
6945 case EXIT_REASON_VMON:
6946 /*
6947 * SDM 3: 24.11.5
6948 * The first 4 bytes of VMXON region contain the supported
6949 * VMCS revision identifier
6950 *
6951 * Note - IA32_VMX_BASIC[48] will never be 1
6952 * for the nested case;
6953 * which replaces physical address width with 32
6954 *
6955 */
6956 if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
6957 nested_vmx_failInvalid(vcpu);
6958 return kvm_skip_emulated_instruction(vcpu);
6959 }
6960
6961 page = nested_get_page(vcpu, vmptr);
6962 if (page == NULL) {
6963 nested_vmx_failInvalid(vcpu);
6964 return kvm_skip_emulated_instruction(vcpu);
6965 }
6966 if (*(u32 *)kmap(page) != VMCS12_REVISION) {
6967 kunmap(page);
6968 nested_release_page_clean(page);
6969 nested_vmx_failInvalid(vcpu);
6970 return kvm_skip_emulated_instruction(vcpu);
6971 }
6972 kunmap(page);
6973 nested_release_page_clean(page);
6974 vmx->nested.vmxon_ptr = vmptr;
6975 break;
6976 case EXIT_REASON_VMCLEAR:
6977 if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
6978 nested_vmx_failValid(vcpu,
6979 VMXERR_VMCLEAR_INVALID_ADDRESS);
6980 return kvm_skip_emulated_instruction(vcpu);
6981 }
6982
6983 if (vmptr == vmx->nested.vmxon_ptr) {
6984 nested_vmx_failValid(vcpu,
6985 VMXERR_VMCLEAR_VMXON_POINTER);
6986 return kvm_skip_emulated_instruction(vcpu);
6987 }
6988 break;
6989 case EXIT_REASON_VMPTRLD:
6990 if (!PAGE_ALIGNED(vmptr) || (vmptr >> maxphyaddr)) {
6991 nested_vmx_failValid(vcpu,
6992 VMXERR_VMPTRLD_INVALID_ADDRESS);
6993 return kvm_skip_emulated_instruction(vcpu);
6994 }
6995
6996 if (vmptr == vmx->nested.vmxon_ptr) {
6997 nested_vmx_failValid(vcpu,
6998 VMXERR_VMPTRLD_VMXON_POINTER);
6999 return kvm_skip_emulated_instruction(vcpu);
7000 }
7001 break;
7002 default:
7003 return 1; /* shouldn't happen */
7004 }
7005
7006 if (vmpointer)
7007 *vmpointer = vmptr;
7008 return 0; 6932 return 0;
7009} 6933}
7010 6934
@@ -7066,6 +6990,8 @@ out_msr_bitmap:
7066static int handle_vmon(struct kvm_vcpu *vcpu) 6990static int handle_vmon(struct kvm_vcpu *vcpu)
7067{ 6991{
7068 int ret; 6992 int ret;
6993 gpa_t vmptr;
6994 struct page *page;
7069 struct vcpu_vmx *vmx = to_vmx(vcpu); 6995 struct vcpu_vmx *vmx = to_vmx(vcpu);
7070 const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED 6996 const u64 VMXON_NEEDED_FEATURES = FEATURE_CONTROL_LOCKED
7071 | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX; 6997 | FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
@@ -7095,9 +7021,37 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
7095 return 1; 7021 return 1;
7096 } 7022 }
7097 7023
7098 if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMON, NULL)) 7024 if (nested_vmx_get_vmptr(vcpu, &vmptr))
7099 return 1; 7025 return 1;
7100 7026
7027 /*
7028 * SDM 3: 24.11.5
7029 * The first 4 bytes of VMXON region contain the supported
7030 * VMCS revision identifier
7031 *
7032 * Note - IA32_VMX_BASIC[48] will never be 1 for the nested case;
7033 * which replaces physical address width with 32
7034 */
7035 if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
7036 nested_vmx_failInvalid(vcpu);
7037 return kvm_skip_emulated_instruction(vcpu);
7038 }
7039
7040 page = nested_get_page(vcpu, vmptr);
7041 if (page == NULL) {
7042 nested_vmx_failInvalid(vcpu);
7043 return kvm_skip_emulated_instruction(vcpu);
7044 }
7045 if (*(u32 *)kmap(page) != VMCS12_REVISION) {
7046 kunmap(page);
7047 nested_release_page_clean(page);
7048 nested_vmx_failInvalid(vcpu);
7049 return kvm_skip_emulated_instruction(vcpu);
7050 }
7051 kunmap(page);
7052 nested_release_page_clean(page);
7053
7054 vmx->nested.vmxon_ptr = vmptr;
7101 ret = enter_vmx_operation(vcpu); 7055 ret = enter_vmx_operation(vcpu);
7102 if (ret) 7056 if (ret)
7103 return ret; 7057 return ret;
@@ -7213,9 +7167,19 @@ static int handle_vmclear(struct kvm_vcpu *vcpu)
7213 if (!nested_vmx_check_permission(vcpu)) 7167 if (!nested_vmx_check_permission(vcpu))
7214 return 1; 7168 return 1;
7215 7169
7216 if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMCLEAR, &vmptr)) 7170 if (nested_vmx_get_vmptr(vcpu, &vmptr))
7217 return 1; 7171 return 1;
7218 7172
7173 if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
7174 nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_INVALID_ADDRESS);
7175 return kvm_skip_emulated_instruction(vcpu);
7176 }
7177
7178 if (vmptr == vmx->nested.vmxon_ptr) {
7179 nested_vmx_failValid(vcpu, VMXERR_VMCLEAR_VMXON_POINTER);
7180 return kvm_skip_emulated_instruction(vcpu);
7181 }
7182
7219 if (vmptr == vmx->nested.current_vmptr) 7183 if (vmptr == vmx->nested.current_vmptr)
7220 nested_release_vmcs12(vmx); 7184 nested_release_vmcs12(vmx);
7221 7185
@@ -7545,9 +7509,19 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
7545 if (!nested_vmx_check_permission(vcpu)) 7509 if (!nested_vmx_check_permission(vcpu))
7546 return 1; 7510 return 1;
7547 7511
7548 if (nested_vmx_check_vmptr(vcpu, EXIT_REASON_VMPTRLD, &vmptr)) 7512 if (nested_vmx_get_vmptr(vcpu, &vmptr))
7549 return 1; 7513 return 1;
7550 7514
7515 if (!PAGE_ALIGNED(vmptr) || (vmptr >> cpuid_maxphyaddr(vcpu))) {
7516 nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_INVALID_ADDRESS);
7517 return kvm_skip_emulated_instruction(vcpu);
7518 }
7519
7520 if (vmptr == vmx->nested.vmxon_ptr) {
7521 nested_vmx_failValid(vcpu, VMXERR_VMPTRLD_VMXON_POINTER);
7522 return kvm_skip_emulated_instruction(vcpu);
7523 }
7524
7551 if (vmx->nested.current_vmptr != vmptr) { 7525 if (vmx->nested.current_vmptr != vmptr) {
7552 struct vmcs12 *new_vmcs12; 7526 struct vmcs12 *new_vmcs12;
7553 struct page *page; 7527 struct page *page;