Skip to content

Commit d2a00af

Browse files
committed
KVM: VMX: Allow userspace to set all supported FEATURE_CONTROL bits
Allow userspace to set all supported bits in MSR IA32_FEATURE_CONTROL irrespective of the guest CPUID model, e.g. via KVM_SET_MSRS. KVM's ABI is that userspace is allowed to set MSRs before CPUID, i.e. can set MSRs to values that would fault according to the guest CPUID model. Signed-off-by: Sean Christopherson <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 0b5e7a1 commit d2a00af

File tree

1 file changed

+31
-5
lines changed

1 file changed

+31
-5
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1836,12 +1836,38 @@ bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
18361836
return nested && guest_cpuid_has(vcpu, X86_FEATURE_VMX);
18371837
}
18381838

1839-
static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
1840-
uint64_t val)
1839+
/*
1840+
* Userspace is allowed to set any supported IA32_FEATURE_CONTROL regardless of
1841+
* guest CPUID. Note, KVM allows userspace to set "VMX in SMX" to maintain
1842+
* backwards compatibility even though KVM doesn't support emulating SMX. And
1843+
* because userspace set "VMX in SMX", the guest must also be allowed to set it,
1844+
* e.g. if the MSR is left unlocked and the guest does a RMW operation.
1845+
*/
1846+
#define KVM_SUPPORTED_FEATURE_CONTROL (FEAT_CTL_LOCKED | \
1847+
FEAT_CTL_VMX_ENABLED_INSIDE_SMX | \
1848+
FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX | \
1849+
FEAT_CTL_SGX_LC_ENABLED | \
1850+
FEAT_CTL_SGX_ENABLED | \
1851+
FEAT_CTL_LMCE_ENABLED)
1852+
1853+
static inline bool vmx_feature_control_msr_valid(struct vcpu_vmx *vmx,
1854+
struct msr_data *msr)
18411855
{
1842-
uint64_t valid_bits = to_vmx(vcpu)->msr_ia32_feature_control_valid_bits;
1856+
uint64_t valid_bits;
1857+
1858+
/*
1859+
* Ensure KVM_SUPPORTED_FEATURE_CONTROL is updated when new bits are
1860+
* exposed to the guest.
1861+
*/
1862+
WARN_ON_ONCE(vmx->msr_ia32_feature_control_valid_bits &
1863+
~KVM_SUPPORTED_FEATURE_CONTROL);
1864+
1865+
if (msr->host_initiated)
1866+
valid_bits = KVM_SUPPORTED_FEATURE_CONTROL;
1867+
else
1868+
valid_bits = vmx->msr_ia32_feature_control_valid_bits;
18431869

1844-
return !(val & ~valid_bits);
1870+
return !(msr->data & ~valid_bits);
18451871
}
18461872

18471873
static int vmx_get_msr_feature(struct kvm_msr_entry *msr)
@@ -2240,7 +2266,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
22402266
vcpu->arch.mcg_ext_ctl = data;
22412267
break;
22422268
case MSR_IA32_FEAT_CTL:
2243-
if (!vmx_feature_control_msr_valid(vcpu, data) ||
2269+
if (!vmx_feature_control_msr_valid(vmx, msr_info) ||
22442270
(to_vmx(vcpu)->msr_ia32_feature_control &
22452271
FEAT_CTL_LOCKED && !msr_info->host_initiated))
22462272
return 1;

0 commit comments

Comments
 (0)