Because the MSR is listed in msrs_to_save, it is exported to userspace
for both AMD and Intel processors.  However, on AMD currently getting
it will fail.

vmx_set_msr must keep the case label in order to handle the "exit
nested on reset by writing 0" case.

Signed-off-by: Paolo Bonzini <[email protected]>
---
 arch/x86/include/asm/kvm_host.h |  8 ++++++++
 arch/x86/kvm/vmx.c              | 41 ++++++++++-------------------------------
 arch/x86/kvm/x86.c              | 11 +++++++++++
 arch/x86/kvm/x86.h              |  8 ++++++++
 4 files changed, 37 insertions(+), 31 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index b771667e8e99..f77e5f5a6b01 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -486,6 +486,14 @@ struct kvm_vcpu_arch {
        u64 ia32_xss;
 
        /*
+        * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
+        * msr_ia32_feature_control. FEATURE_CONTROL_LOCKED is always included
+        * in msr_ia32_feature_control_valid_bits.
+        */
+       u64 msr_ia32_feature_control;
+       u64 msr_ia32_feature_control_valid_bits;
+
+       /*
         * Paging state of the vcpu
         *
         * If the vcpu runs in guest mode with two level paging this still saves
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 15793a4c5df0..939cd8b835c2 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -611,14 +611,6 @@ struct vcpu_vmx {
        bool guest_pkru_valid;
        u32 guest_pkru;
        u32 host_pkru;
-
-       /*
-        * Only bits masked by msr_ia32_feature_control_valid_bits can be set in
-        * msr_ia32_feature_control. FEATURE_CONTROL_LOCKED is always included
-        * in msr_ia32_feature_control_valid_bits.
-        */
-       u64 msr_ia32_feature_control;
-       u64 msr_ia32_feature_control_valid_bits;
 };
 
 enum segment_cache_field {
@@ -2932,14 +2924,6 @@ static int vmx_get_vmx_msr(struct kvm_vcpu *vcpu, u32 
msr_index, u64 *pdata)
        return 0;
 }
 
-static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
-                                                uint64_t val)
-{
-       uint64_t valid_bits = to_vmx(vcpu)->msr_ia32_feature_control_valid_bits;
-
-       return !(val & ~valid_bits);
-}
-
 /*
  * Reads an msr value (of 'msr_index') into 'pdata'.
  * Returns 0 on success, non-0 otherwise.
@@ -2983,14 +2967,11 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
                break;
        case MSR_IA32_MCG_EXT_CTL:
                if (!msr_info->host_initiated &&
-                   !(to_vmx(vcpu)->msr_ia32_feature_control &
+                   !(vcpu->arch.msr_ia32_feature_control &
                      FEATURE_CONTROL_LMCE))
                        return 1;
                msr_info->data = vcpu->arch.mcg_ext_ctl;
                break;
-       case MSR_IA32_FEATURE_CONTROL:
-               msr_info->data = to_vmx(vcpu)->msr_ia32_feature_control;
-               break;
        case MSR_IA32_VMX_BASIC ... MSR_IA32_VMX_VMFUNC:
                if (!nested_vmx_allowed(vcpu))
                        return 1;
@@ -3081,18 +3062,18 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
                break;
        case MSR_IA32_MCG_EXT_CTL:
                if ((!msr_info->host_initiated &&
-                    !(to_vmx(vcpu)->msr_ia32_feature_control &
+                    !(vcpu->arch.msr_ia32_feature_control &
                       FEATURE_CONTROL_LMCE)) ||
                    (data & ~MCG_EXT_CTL_LMCE_EN))
                        return 1;
                vcpu->arch.mcg_ext_ctl = data;
                break;
        case MSR_IA32_FEATURE_CONTROL:
-               if (!vmx_feature_control_msr_valid(vcpu, data) ||
-                   (to_vmx(vcpu)->msr_ia32_feature_control &
+               if (!feature_control_msr_valid(vcpu, data) ||
+                   (vcpu->arch.msr_ia32_feature_control &
                     FEATURE_CONTROL_LOCKED && !msr_info->host_initiated))
                        return 1;
-               vmx->msr_ia32_feature_control = data;
+               vcpu->arch.msr_ia32_feature_control = data;
                if (msr_info->host_initiated && data == 0)
                        vmx_leave_nested(vcpu);
                break;
@@ -6964,7 +6945,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
                return 1;
        }
 
-       if ((vmx->msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
+       if ((vcpu->arch.msr_ia32_feature_control & VMXON_NEEDED_FEATURES)
                        != VMXON_NEEDED_FEATURES) {
                kvm_inject_gp(vcpu, 0);
                return 1;
@@ -9081,8 +9062,6 @@ static struct kvm_vcpu *vmx_create_vcpu(struct kvm *kvm, 
unsigned int id)
                        goto free_vmcs;
        }
 
-       vmx->msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
-
        return &vmx->vcpu;
 
 free_vmcs:
@@ -9232,10 +9211,10 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
        }
 
        if (nested_vmx_allowed(vcpu))
-               to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
+               vcpu->arch.msr_ia32_feature_control_valid_bits |=
                        FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
        else
-               to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
+               vcpu->arch.msr_ia32_feature_control_valid_bits &=
                        ~FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX;
 }
 
@@ -11135,10 +11114,10 @@ out:
 static void vmx_setup_mce(struct kvm_vcpu *vcpu)
 {
        if (vcpu->arch.mcg_cap & MCG_LMCE_P)
-               to_vmx(vcpu)->msr_ia32_feature_control_valid_bits |=
+               vcpu->arch.msr_ia32_feature_control_valid_bits |=
                        FEATURE_CONTROL_LMCE;
        else
-               to_vmx(vcpu)->msr_ia32_feature_control_valid_bits &=
+               vcpu->arch.msr_ia32_feature_control_valid_bits &=
                        ~FEATURE_CONTROL_LMCE;
 }
 
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 411f786950ab..388d9ffd7551 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2097,6 +2097,13 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
        case MSR_IA32_TSCDEADLINE:
                kvm_set_lapic_tscdeadline_msr(vcpu, data);
                break;
+       case MSR_IA32_FEATURE_CONTROL:
+               if (!feature_control_msr_valid(vcpu, data) ||
+                   (vcpu->arch.msr_ia32_feature_control &
+                    FEATURE_CONTROL_LOCKED && !msr_info->host_initiated))
+                       return 1;
+               vcpu->arch.msr_ia32_feature_control = data;
+               break;
        case MSR_IA32_TSC_ADJUST:
                if (guest_cpuid_has_tsc_adjust(vcpu)) {
                        if (!msr_info->host_initiated) {
@@ -2364,6 +2371,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct 
msr_data *msr_info)
        case MSR_IA32_TSC_ADJUST:
                msr_info->data = (u64)vcpu->arch.ia32_tsc_adjust_msr;
                break;
+       case MSR_IA32_FEATURE_CONTROL:
+               msr_info->data = vcpu->arch.msr_ia32_feature_control;
+               break;
        case MSR_IA32_MISC_ENABLE:
                msr_info->data = vcpu->arch.ia32_misc_enable_msr;
                break;
@@ -7705,6 +7715,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 
        vcpu->arch.ia32_tsc_adjust_msr = 0x0;
        vcpu->arch.pv_time_enabled = false;
+       vcpu->arch.msr_ia32_feature_control_valid_bits = FEATURE_CONTROL_LOCKED;
 
        vcpu->arch.guest_supported_xcr0 = 0;
        vcpu->arch.guest_xstate_size = XSAVE_HDR_SIZE + XSAVE_HDR_OFFSET;
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 7ce3634ab5fe..a46c43aa762c 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -157,6 +157,14 @@ static inline bool kvm_check_has_quirk(struct kvm *kvm, 
u64 quirk)
        return !(kvm->arch.disabled_quirks & quirk);
 }
 
+static inline bool feature_control_msr_valid(struct kvm_vcpu *vcpu,
+                                                uint64_t val)
+{
+       uint64_t valid_bits = vcpu->arch.msr_ia32_feature_control_valid_bits;
+
+       return !(val & ~valid_bits);
+}
+
 void kvm_before_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_after_handle_nmi(struct kvm_vcpu *vcpu);
 void kvm_set_pending_timer(struct kvm_vcpu *vcpu);
-- 
1.8.3.1


Reply via email to