Skip to content

Commit 75c489e

Browse files
committed
KVM: x86: Add a macro for features that are synthesized into boot_cpu_data
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). Link: https://lore.kernel.org/r/20241128013424.4096668-53-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent cbdeea0 commit 75c489e

File tree

1 file changed

+30
-19
lines changed

1 file changed

+30
-19
lines changed

arch/x86/kvm/cpuid.c

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,7 @@ do { \
686686
const struct cpuid_reg cpuid = x86_feature_cpuid(leaf * 32); \
687687
const u32 __maybe_unused kvm_cpu_cap_init_in_progress = leaf; \
688688
u32 kvm_cpu_cap_passthrough = 0; \
689+
u32 kvm_cpu_cap_synthesized = 0; \
689690
u32 kvm_cpu_cap_emulated = 0; \
690691
\
691692
if (leaf < NCAPINTS) \
@@ -694,7 +695,8 @@ do { \
694695
kvm_cpu_caps[leaf] = (mask); \
695696
\
696697
kvm_cpu_caps[leaf] |= kvm_cpu_cap_passthrough; \
697-
kvm_cpu_caps[leaf] &= raw_cpuid_get(cpuid); \
698+
kvm_cpu_caps[leaf] &= (raw_cpuid_get(cpuid) | \
699+
kvm_cpu_cap_synthesized); \
698700
kvm_cpu_caps[leaf] |= kvm_cpu_cap_emulated; \
699701
} while (0)
700702

@@ -741,6 +743,17 @@ do { \
741743
F(name); \
742744
})
743745

746+
/*
747+
* Synthesized Feature - For features that are synthesized into boot_cpu_data,
748+
* i.e. may not be present in the raw CPUID, but can still be advertised to
749+
* userspace. Primarily used for mitigation related feature flags.
750+
*/
751+
#define SYNTHESIZED_F(name) \
752+
({ \
753+
kvm_cpu_cap_synthesized |= F(name); \
754+
F(name); \
755+
})
756+
744757
/*
745758
* Passthrough Feature - For features that KVM supports based purely on raw
746759
* hardware CPUID, i.e. that KVM virtualizes even if the host kernel doesn't
@@ -1105,35 +1118,32 @@ void kvm_set_cpu_caps(void)
11051118

11061119
kvm_cpu_cap_init(CPUID_8000_0021_EAX,
11071120
F(NO_NESTED_DATA_BP) |
1108-
F(LFENCE_RDTSC) |
1121+
/*
1122+
* Synthesize "LFENCE is serializing" into the AMD-defined entry
1123+
* in KVM's supported CPUID, i.e. if the feature is reported as
1124+
* supported by the kernel. LFENCE_RDTSC was a Linux-defined
1125+
* synthetic feature long before AMD joined the bandwagon, e.g.
1126+
* LFENCE is serializing on most CPUs that support SSE2. On
1127+
* CPUs that don't support AMD's leaf, ANDing with the raw host
1128+
* CPUID will drop the flags, and reporting support in AMD's
1129+
* leaf can make it easier for userspace to detect the feature.
1130+
*/
1131+
SYNTHESIZED_F(LFENCE_RDTSC) |
11091132
0 /* SmmPgCfgLock */ |
11101133
F(NULL_SEL_CLR_BASE) |
11111134
F(AUTOIBRS) |
11121135
EMULATED_F(NO_SMM_CTL_MSR) |
11131136
0 /* PrefetchCtlMsr */ |
1114-
F(WRMSR_XX_BASE_NS)
1137+
F(WRMSR_XX_BASE_NS) |
1138+
SYNTHESIZED_F(SBPB) |
1139+
SYNTHESIZED_F(IBPB_BRTYPE) |
1140+
SYNTHESIZED_F(SRSO_NO)
11151141
);
11161142

1117-
kvm_cpu_cap_check_and_set(X86_FEATURE_SBPB);
1118-
kvm_cpu_cap_check_and_set(X86_FEATURE_IBPB_BRTYPE);
1119-
kvm_cpu_cap_check_and_set(X86_FEATURE_SRSO_NO);
1120-
11211143
kvm_cpu_cap_init(CPUID_8000_0022_EAX,
11221144
F(PERFMON_V2)
11231145
);
11241146

1125-
/*
1126-
* Synthesize "LFENCE is serializing" into the AMD-defined entry in
1127-
* KVM's supported CPUID if the feature is reported as supported by the
1128-
* kernel. LFENCE_RDTSC was a Linux-defined synthetic feature long
1129-
* before AMD joined the bandwagon, e.g. LFENCE is serializing on most
1130-
* CPUs that support SSE2. On CPUs that don't support AMD's leaf,
1131-
* kvm_cpu_cap_init() will unfortunately drop the flag due to ANDing
1132-
* the mask with the raw host CPUID, and reporting support in AMD's
1133-
* leaf can make it easier for userspace to detect the feature.
1134-
*/
1135-
if (cpu_feature_enabled(X86_FEATURE_LFENCE_RDTSC))
1136-
kvm_cpu_cap_set(X86_FEATURE_LFENCE_RDTSC);
11371147
if (!static_cpu_has_bug(X86_BUG_NULL_SEG))
11381148
kvm_cpu_cap_set(X86_FEATURE_NULL_SEL_CLR_BASE);
11391149

@@ -1171,6 +1181,7 @@ EXPORT_SYMBOL_GPL(kvm_set_cpu_caps);
11711181
#undef SF
11721182
#undef X86_64_F
11731183
#undef EMULATED_F
1184+
#undef SYNTHESIZED_F
11741185
#undef PASSTHROUGH_F
11751186
#undef ALIASED_1_EDX_F
11761187

0 commit comments

Comments
 (0)