Commit d2a00af2 authored by Sean Christopherson's avatar Sean Christopherson
Browse files

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: default avatarSean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20220607232353.3375324-2-seanjc@google.com
parent 0b5e7a16
Loading
Loading
Loading
Loading
+31 −5
Original line number Diff line number Diff line
@@ -1836,12 +1836,38 @@ bool nested_vmx_allowed(struct kvm_vcpu *vcpu)
	return nested && guest_cpuid_has(vcpu, X86_FEATURE_VMX);
}

static inline bool vmx_feature_control_msr_valid(struct kvm_vcpu *vcpu,
						 uint64_t val)
/*
 * Userspace is allowed to set any supported IA32_FEATURE_CONTROL regardless of
 * guest CPUID.  Note, KVM allows userspace to set "VMX in SMX" to maintain
 * backwards compatibility even though KVM doesn't support emulating SMX.  And
 * because userspace set "VMX in SMX", the guest must also be allowed to set it,
 * e.g. if the MSR is left unlocked and the guest does a RMW operation.
 */
#define KVM_SUPPORTED_FEATURE_CONTROL  (FEAT_CTL_LOCKED			 | \
					FEAT_CTL_VMX_ENABLED_INSIDE_SMX	 | \
					FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX | \
					FEAT_CTL_SGX_LC_ENABLED		 | \
					FEAT_CTL_SGX_ENABLED		 | \
					FEAT_CTL_LMCE_ENABLED)

static inline bool vmx_feature_control_msr_valid(struct vcpu_vmx *vmx,
						 struct msr_data *msr)
{
	uint64_t valid_bits = to_vmx(vcpu)->msr_ia32_feature_control_valid_bits;
	uint64_t valid_bits;

	/*
	 * Ensure KVM_SUPPORTED_FEATURE_CONTROL is updated when new bits are
	 * exposed to the guest.
	 */
	WARN_ON_ONCE(vmx->msr_ia32_feature_control_valid_bits &
		     ~KVM_SUPPORTED_FEATURE_CONTROL);

	if (msr->host_initiated)
		valid_bits = KVM_SUPPORTED_FEATURE_CONTROL;
	else
		valid_bits = vmx->msr_ia32_feature_control_valid_bits;

	return !(val & ~valid_bits);
	return !(msr->data & ~valid_bits);
}

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)
		vcpu->arch.mcg_ext_ctl = data;
		break;
	case MSR_IA32_FEAT_CTL:
		if (!vmx_feature_control_msr_valid(vcpu, data) ||
		if (!vmx_feature_control_msr_valid(vmx, msr_info) ||
		    (to_vmx(vcpu)->msr_ia32_feature_control &
		     FEAT_CTL_LOCKED && !msr_info->host_initiated))
			return 1;