KVM: x86: Move vendor CR4 validity check to dedicated kvm_x86_ops hook
[linux-2.6-microblaze.git] / arch / x86 / kvm / vmx / vmx.c
index d14c94d..3327964 100644 (file)
@@ -2560,8 +2560,10 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
        vmcs_conf->vmexit_ctrl         = _vmexit_control;
        vmcs_conf->vmentry_ctrl        = _vmentry_control;
 
-       if (static_branch_unlikely(&enable_evmcs))
+#if IS_ENABLED(CONFIG_HYPERV)
+       if (enlightened_vmcs)
                evmcs_sanitize_exec_ctrls(vmcs_conf);
+#endif
 
        return 0;
 }
@@ -3093,7 +3095,23 @@ static void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd,
                vmcs_writel(GUEST_CR3, guest_cr3);
 }
 
-int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+static bool vmx_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+{
+       /*
+        * We operate under the default treatment of SMM, so VMX cannot be
+        * enabled under SMM.  Note, whether or not VMXE is allowed at all is
+        * handled by kvm_valid_cr4().
+        */
+       if ((cr4 & X86_CR4_VMXE) && is_smm(vcpu))
+               return false;
+
+       if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
+               return false;
+
+       return true;
+}
+
+void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
        /*
@@ -3121,21 +3139,6 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
                }
        }
 
-       if (cr4 & X86_CR4_VMXE) {
-               /*
-                * To use VMXON (and later other VMX instructions), a guest
-                * must first be able to turn on cr4.VMXE (see handle_vmon()).
-                * So basically the check on whether to allow nested VMX
-                * is here.  We operate under the default treatment of SMM,
-                * so VMX cannot be enabled under SMM.
-                */
-               if (!nested_vmx_allowed(vcpu) || is_smm(vcpu))
-                       return 1;
-       }
-
-       if (vmx->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
-               return 1;
-
        vcpu->arch.cr4 = cr4;
        kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
 
@@ -3166,7 +3169,6 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 
        vmcs_writel(CR4_READ_SHADOW, cr4);
        vmcs_writel(GUEST_CR4, hw_cr4);
-       return 0;
 }
 
 void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
@@ -6834,7 +6836,6 @@ static void vmx_free_vcpu(struct kvm_vcpu *vcpu)
 static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
 {
        struct vcpu_vmx *vmx;
-       unsigned long *msr_bitmap;
        int i, cpu, err;
 
        BUILD_BUG_ON(offsetof(struct vcpu_vmx, vcpu) != 0);
@@ -6894,7 +6895,6 @@ static int vmx_create_vcpu(struct kvm_vcpu *vcpu)
        bitmap_fill(vmx->shadow_msr_intercept.read, MAX_POSSIBLE_PASSTHROUGH_MSRS);
        bitmap_fill(vmx->shadow_msr_intercept.write, MAX_POSSIBLE_PASSTHROUGH_MSRS);
 
-       msr_bitmap = vmx->vmcs01.msr_bitmap;
        vmx_disable_intercept_for_msr(vcpu, MSR_IA32_TSC, MSR_TYPE_R);
        vmx_disable_intercept_for_msr(vcpu, MSR_FS_BASE, MSR_TYPE_RW);
        vmx_disable_intercept_for_msr(vcpu, MSR_GS_BASE, MSR_TYPE_RW);
@@ -7616,6 +7616,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
        .get_cpl = vmx_get_cpl,
        .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
        .set_cr0 = vmx_set_cr0,
+       .is_valid_cr4 = vmx_is_valid_cr4,
        .set_cr4 = vmx_set_cr4,
        .set_efer = vmx_set_efer,
        .get_idt = vmx_get_idt,