KVM: selftests: Verify userspace can stuff IA32_FEATURE_CONTROL at will
authorSean Christopherson <seanjc@google.com>
Tue, 7 Jun 2022 23:23:53 +0000 (23:23 +0000)
committerSean Christopherson <seanjc@google.com>
Thu, 1 Dec 2022 00:29:54 +0000 (16:29 -0800)
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: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20220607232353.3375324-4-seanjc@google.com
tools/testing/selftests/kvm/include/x86_64/processor.h
tools/testing/selftests/kvm/x86_64/vmx_msrs_test.c

index 5d310ab..ac4590a 100644 (file)
@@ -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)
index 322d561..90720b6 100644 (file)
@@ -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);
 }