[PATCH v2 48/49] KVM: x86: Add a macro for features that are synthesized into boot_cpu_data

From: Sean Christopherson
Date: Fri May 17 2024 - 13:54:22 EST


Add yet another CPUID macro, this time for features that the host kernel
synthesizes into boot_cpu_data, i.e. that the kernel force sets even in
situations where the feature isn't reported by CPUID. Thanks to the
macro shenanigans of kvm_cpu_cap_init(), such features can now be handled
in the core CPUID framework, i.e. don't need to be handled out-of-band and
thus without as many guardrails.

Adding a dedicated macro also helps document what's going on, e.g. the
calls to kvm_cpu_cap_check_and_set() are very confusing unless the reader
knows exactly how kvm_cpu_cap_init() generates kvm_cpu_caps (and even
then, it's far from obvious).

Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
arch/x86/kvm/cpuid.c | 22 ++++++++++++++++------
1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 0130e0677387..0e64a6332052 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -106,6 +106,17 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted)
F(name); \
})

+/*
+ * Synthesized Feature - For features that are synthesized into boot_cpu_data,
+ * i.e. may not be present in the raw CPUID, but can still be advertised to
+ * userspace. Primarily used for mitigation related feature flags.
+ */
+#define SYN_F(name) \
+({ \
+ kvm_cpu_cap_synthesized |= 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.
@@ -727,13 +738,15 @@ 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_emulated = 0; \
+ u32 kvm_cpu_cap_synthesized = 0; \
\
if (leaf < NCAPINTS) \
kvm_cpu_caps[leaf] &= (mask); \
else \
kvm_cpu_caps[leaf] = (mask); \
\
- kvm_cpu_caps[leaf] &= raw_cpuid_get(cpuid); \
+ kvm_cpu_caps[leaf] &= (raw_cpuid_get(cpuid) | \
+ kvm_cpu_cap_synthesized); \
kvm_cpu_caps[leaf] |= kvm_cpu_cap_emulated; \
} while (0)

@@ -913,13 +926,10 @@ void kvm_set_cpu_caps(void)
kvm_cpu_cap_init(CPUID_8000_0021_EAX,
F(NO_NESTED_DATA_BP) | F(LFENCE_RDTSC) | 0 /* SmmPgCfgLock */ |
F(NULL_SEL_CLR_BASE) | F(AUTOIBRS) | 0 /* PrefetchCtlMsr */ |
- F(WRMSR_XX_BASE_NS)
+ F(WRMSR_XX_BASE_NS) | SYN_F(SBPB) | SYN_F(IBPB_BRTYPE) |
+ SYN_F(SRSO_NO)
);

- kvm_cpu_cap_check_and_set(X86_FEATURE_SBPB);
- kvm_cpu_cap_check_and_set(X86_FEATURE_IBPB_BRTYPE);
- kvm_cpu_cap_check_and_set(X86_FEATURE_SRSO_NO);
-
kvm_cpu_cap_init(CPUID_8000_0022_EAX,
F(PERFMON_V2)
);
--
2.45.0.215.g3402c0e53f-goog