@@ -610,12 +610,14 @@ static __always_inline u32 raw_cpuid_get(struct cpuid_reg cpuid)
do { \
const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32); \
const u32 __maybe_unused kvm_cpu_cap_init_in_progress = leaf; \
+ u32 kvm_cpu_cap_passthrough = 0; \
\
if (leaf < NCAPINTS) \
kvm_cpu_caps[leaf] &= (mask); \
else \
kvm_cpu_caps[leaf] = (mask); \
\
+ kvm_cpu_caps[leaf] |= kvm_cpu_cap_passthrough; \
kvm_cpu_caps[leaf] &= raw_cpuid_get(cpuid); \
} while (0)
@@ -652,6 +654,18 @@ do { \
(IS_ENABLED(CONFIG_X86_64) ? F(name) : 0); \
})
+/*
+ * Passthrough Feature - For features that KVM supports based purely on raw
+ * hardware CPUID, i.e. that KVM virtualizes even if the host kernel doesn't
+ * use the feature. Simply force set the feature in KVM's capabilities, raw
+ * CPUID support will be factored in by kvm_cpu_cap_mask().
+ */
+#define PASSTHROUGH_F(name) \
+({ \
+ kvm_cpu_cap_passthrough |= F(name); \
+ F(name); \
+})
+
/*
* Aliased Features - For features in 0x8000_0001.EDX that are duplicates of
* identical 0x1.EDX features, and thus are aliased from 0x1 to 0x8000_0001.
@@ -777,7 +791,7 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_init(CPUID_7_ECX,
F(AVX512VBMI) |
- F(LA57) |
+ PASSTHROUGH_F(LA57) |
F(PKU) |
0 /*OSPKE*/ |
F(RDPID) |
@@ -796,9 +810,6 @@ void kvm_set_cpu_caps(void)
F(SGX_LC) |
F(BUS_LOCK_DETECT)
);
- /* Set LA57 based on hardware capability. */
- if (cpuid_ecx(7) & feature_bit(LA57))
- kvm_cpu_cap_set(X86_FEATURE_LA57);
/*
* PKU not yet implemented for shadow paging and requires OSPKE
@@ -1076,6 +1087,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cpu_caps);
#undef F
#undef SF
#undef X86_64_F
+#undef PASSTHROUGH_F
#undef ALIASED_1_EDX_F
struct kvm_cpuid_array {
Add a macro for use in kvm_set_cpu_caps() to automagically initialize features that KVM wants to support based solely on the CPU's capabilities, e.g. KVM advertises LA57 support if it's available in hardware, even if the host kernel isn't utilizing 57-bit virtual addresses. Track a features that are passed through to userspace (from hardware) in a local variable, and simply OR them in *after* adjusting the capabilities that came from boot_cpu_data. Note, eliminating the open-coded call to cpuid_ecx() also fixes a largely benign bug where KVM could incorrectly report LA57 support on Intel CPUs whose max supported CPUID is less than 7, i.e. if the max supported leaf (<7) happened to have bit 16 set. In practice, barring a funky virtual machine setup, the bug is benign as all known CPUs that support VMX also support leaf 7. Signed-off-by: Sean Christopherson <seanjc@google.com> --- arch/x86/kvm/cpuid.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-)