KVM: x86: Advertise CPUID.(EAX=7,ECX=2):EDX[5:0] to userspace
authorJim Mattson <jmattson@google.com>
Tue, 24 Oct 2023 00:16:35 +0000 (17:16 -0700)
committerSean Christopherson <seanjc@google.com>
Thu, 30 Nov 2023 19:50:16 +0000 (11:50 -0800)
The low five bits {INTEL_PSFD, IPRED_CTRL, RRSBA_CTRL, DDPD_U, BHI_CTRL}
advertise the availability of specific bits in IA32_SPEC_CTRL. Since KVM
dynamically determines the legal IA32_SPEC_CTRL bits for the underlying
hardware, the hard work has already been done. Just let userspace know
that a guest can use these IA32_SPEC_CTRL bits.

The sixth bit (MCDT_NO) states that the processor does not exhibit MXCSR
Configuration Dependent Timing (MCDT) behavior. This is an inherent
property of the physical processor that is inherited by the virtual
CPU. Pass that information on to userspace.

Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: Chao Gao <chao.gao@intel.com>
Link: https://lore.kernel.org/r/20231024001636.890236-1-jmattson@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/cpuid.c
arch/x86/kvm/reverse_cpuid.h

index dda6fc4..1811a9d 100644 (file)
@@ -679,6 +679,11 @@ void kvm_set_cpu_caps(void)
                F(AMX_COMPLEX)
        );
 
+       kvm_cpu_cap_init_kvm_defined(CPUID_7_2_EDX,
+               F(INTEL_PSFD) | F(IPRED_CTRL) | F(RRSBA_CTRL) | F(DDPD_U) |
+               F(BHI_CTRL) | F(MCDT_NO)
+       );
+
        kvm_cpu_cap_mask(CPUID_D_1_EAX,
                F(XSAVEOPT) | F(XSAVEC) | F(XGETBV1) | F(XSAVES) | f_xfd
        );
@@ -960,13 +965,13 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
                break;
        /* function 7 has additional index. */
        case 7:
-               entry->eax = min(entry->eax, 1u);
+               max_idx = entry->eax = min(entry->eax, 2u);
                cpuid_entry_override(entry, CPUID_7_0_EBX);
                cpuid_entry_override(entry, CPUID_7_ECX);
                cpuid_entry_override(entry, CPUID_7_EDX);
 
-               /* KVM only supports 0x7.0 and 0x7.1, capped above via min(). */
-               if (entry->eax == 1) {
+               /* KVM only supports up to 0x7.2, capped above via min(). */
+               if (max_idx >= 1) {
                        entry = do_host_cpuid(array, function, 1);
                        if (!entry)
                                goto out;
@@ -976,6 +981,16 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
                        entry->ebx = 0;
                        entry->ecx = 0;
                }
+               if (max_idx >= 2) {
+                       entry = do_host_cpuid(array, function, 2);
+                       if (!entry)
+                               goto out;
+
+                       cpuid_entry_override(entry, CPUID_7_2_EDX);
+                       entry->ecx = 0;
+                       entry->ebx = 0;
+                       entry->eax = 0;
+               }
                break;
        case 0xa: { /* Architectural Performance Monitoring */
                union cpuid10_eax eax;
index b816506..1700701 100644 (file)
@@ -16,6 +16,7 @@ enum kvm_only_cpuid_leafs {
        CPUID_7_1_EDX,
        CPUID_8000_0007_EDX,
        CPUID_8000_0022_EAX,
+       CPUID_7_2_EDX,
        NR_KVM_CPU_CAPS,
 
        NKVMCAPINTS = NR_KVM_CPU_CAPS - NCAPINTS,
@@ -46,6 +47,14 @@ enum kvm_only_cpuid_leafs {
 #define X86_FEATURE_AMX_COMPLEX         KVM_X86_FEATURE(CPUID_7_1_EDX, 8)
 #define X86_FEATURE_PREFETCHITI         KVM_X86_FEATURE(CPUID_7_1_EDX, 14)
 
+/* Intel-defined sub-features, CPUID level 0x00000007:2 (EDX) */
+#define X86_FEATURE_INTEL_PSFD         KVM_X86_FEATURE(CPUID_7_2_EDX, 0)
+#define X86_FEATURE_IPRED_CTRL         KVM_X86_FEATURE(CPUID_7_2_EDX, 1)
+#define KVM_X86_FEATURE_RRSBA_CTRL     KVM_X86_FEATURE(CPUID_7_2_EDX, 2)
+#define X86_FEATURE_DDPD_U             KVM_X86_FEATURE(CPUID_7_2_EDX, 3)
+#define X86_FEATURE_BHI_CTRL           KVM_X86_FEATURE(CPUID_7_2_EDX, 4)
+#define X86_FEATURE_MCDT_NO            KVM_X86_FEATURE(CPUID_7_2_EDX, 5)
+
 /* CPUID level 0x80000007 (EDX). */
 #define KVM_X86_FEATURE_CONSTANT_TSC   KVM_X86_FEATURE(CPUID_8000_0007_EDX, 8)
 
@@ -80,6 +89,7 @@ static const struct cpuid_reg reverse_cpuid[] = {
        [CPUID_8000_0007_EDX] = {0x80000007, 0, CPUID_EDX},
        [CPUID_8000_0021_EAX] = {0x80000021, 0, CPUID_EAX},
        [CPUID_8000_0022_EAX] = {0x80000022, 0, CPUID_EAX},
+       [CPUID_7_2_EDX]       = {         7, 2, CPUID_EDX},
 };
 
 /*
@@ -116,6 +126,8 @@ static __always_inline u32 __feature_translate(int x86_feature)
                return KVM_X86_FEATURE_CONSTANT_TSC;
        else if (x86_feature == X86_FEATURE_PERFMON_V2)
                return KVM_X86_FEATURE_PERFMON_V2;
+       else if (x86_feature == X86_FEATURE_RRSBA_CTRL)
+               return KVM_X86_FEATURE_RRSBA_CTRL;
 
        return x86_feature;
 }