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

KVM: selftests: Verify userspace can stuff IA32_FEATURE_CONTROL at will



Verify the KVM allows userspace to set all supported bits in the
IA32_FEATURE_CONTROL MSR irrespective of the current guest CPUID, and
that all unsupported bits are rejected.

Throw the testcase into vmx_msrs_test even though it's not technically a
VMX MSR; it's close enough, and the most frequently feature controlled by
the MSR is VMX.

Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20220607232353.3375324-4-seanjc@google.com
parent 2d6cd686
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ struct kvm_x86_cpu_feature {
#define	X86_FEATURE_XMM2		KVM_X86_CPU_FEATURE(0x1, 0, EDX, 26)
#define	X86_FEATURE_FSGSBASE		KVM_X86_CPU_FEATURE(0x7, 0, EBX, 0)
#define	X86_FEATURE_TSC_ADJUST		KVM_X86_CPU_FEATURE(0x7, 0, EBX, 1)
#define	X86_FEATURE_SGX			KVM_X86_CPU_FEATURE(0x7, 0, EBX, 2)
#define	X86_FEATURE_HLE			KVM_X86_CPU_FEATURE(0x7, 0, EBX, 4)
#define	X86_FEATURE_SMEP	        KVM_X86_CPU_FEATURE(0x7, 0, EBX, 7)
#define	X86_FEATURE_INVPCID		KVM_X86_CPU_FEATURE(0x7, 0, EBX, 10)
@@ -115,6 +116,7 @@ struct kvm_x86_cpu_feature {
#define	X86_FEATURE_PKU			KVM_X86_CPU_FEATURE(0x7, 0, ECX, 3)
#define	X86_FEATURE_LA57		KVM_X86_CPU_FEATURE(0x7, 0, ECX, 16)
#define	X86_FEATURE_RDPID		KVM_X86_CPU_FEATURE(0x7, 0, ECX, 22)
#define	X86_FEATURE_SGX_LC		KVM_X86_CPU_FEATURE(0x7, 0, ECX, 30)
#define	X86_FEATURE_SHSTK		KVM_X86_CPU_FEATURE(0x7, 0, ECX, 7)
#define	X86_FEATURE_IBT			KVM_X86_CPU_FEATURE(0x7, 0, EDX, 20)
#define	X86_FEATURE_AMX_TILE		KVM_X86_CPU_FEATURE(0x7, 0, EDX, 24)
+47 −0
Original line number Diff line number Diff line
@@ -67,6 +67,52 @@ static void vmx_save_restore_msrs_test(struct kvm_vcpu *vcpu)
	vmx_fixed1_msr_test(vcpu, MSR_IA32_VMX_VMFUNC, -1ull);
}

static void __ia32_feature_control_msr_test(struct kvm_vcpu *vcpu,
					    uint64_t msr_bit,
					    struct kvm_x86_cpu_feature feature)
{
	uint64_t val;

	vcpu_clear_cpuid_feature(vcpu, feature);

	val = vcpu_get_msr(vcpu, MSR_IA32_FEAT_CTL);
	vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, val | msr_bit | FEAT_CTL_LOCKED);
	vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, (val & ~msr_bit) | FEAT_CTL_LOCKED);
	vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, val | msr_bit | FEAT_CTL_LOCKED);
	vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, (val & ~msr_bit) | FEAT_CTL_LOCKED);
	vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, val);

	if (!kvm_cpu_has(feature))
		return;

	vcpu_set_cpuid_feature(vcpu, feature);
}

static void ia32_feature_control_msr_test(struct kvm_vcpu *vcpu)
{
	uint64_t supported_bits = 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;
	int bit, r;

	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_VMX_ENABLED_INSIDE_SMX, X86_FEATURE_SMX);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_VMX_ENABLED_INSIDE_SMX, X86_FEATURE_VMX);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX, X86_FEATURE_VMX);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_SGX_LC_ENABLED, X86_FEATURE_SGX_LC);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_SGX_LC_ENABLED, X86_FEATURE_SGX);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_SGX_ENABLED, X86_FEATURE_SGX);
	__ia32_feature_control_msr_test(vcpu, FEAT_CTL_LMCE_ENABLED, X86_FEATURE_MCE);

	for_each_clear_bit(bit, &supported_bits, 64) {
		r = _vcpu_set_msr(vcpu, MSR_IA32_FEAT_CTL, BIT(bit));
		TEST_ASSERT(r == 0,
			    "Setting reserved bit %d in IA32_FEATURE_CONTROL should fail", bit);
	}
}

int main(void)
{
	struct kvm_vcpu *vcpu;
@@ -79,6 +125,7 @@ int main(void)
	vm = vm_create_with_one_vcpu(&vcpu, NULL);

	vmx_save_restore_msrs_test(vcpu);
	ia32_feature_control_msr_test(vcpu);

	kvm_vm_free(vm);
}