Skip to content

Commit 19f1031

Browse files
sean-jcbonzini
authored andcommitted
KVM: VMX: Stub out enable_evmcs static key for CONFIG_HYPERV=n
Wrap enable_evmcs in a helper and stub it out when CONFIG_HYPERV=n in order to eliminate the static branch nop placeholders. clang-14 is clever enough to elide the nop, but gcc-12 is not. Stubbing out the key reduces the size of kvm-intel.ko by ~7.5% (200KiB) when compiled with gcc-12 (there are a _lot_ of VMCS accesses throughout KVM). Reviewed-by: Vitaly Kuznetsov <vkuznets@redhat.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Message-Id: <20230211003534.564198-3-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent 68ac422 commit 19f1031

4 files changed

Lines changed: 28 additions & 23 deletions

File tree

arch/x86/kvm/vmx/hyperv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@
118118

119119
#define EVMCS1_SUPPORTED_VMFUNC (0)
120120

121-
DEFINE_STATIC_KEY_FALSE(enable_evmcs);
122-
123121
#define EVMCS1_OFFSET(x) offsetof(struct hv_enlightened_vmcs, x)
124122
#define EVMCS1_FIELD(number, name, clean_field)[ROL16(number, 6)] = \
125123
{EVMCS1_OFFSET(name), clean_field}
@@ -611,6 +609,8 @@ int nested_evmcs_check_controls(struct vmcs12 *vmcs12)
611609
}
612610

613611
#if IS_ENABLED(CONFIG_HYPERV)
612+
DEFINE_STATIC_KEY_FALSE(enable_evmcs);
613+
614614
/*
615615
* KVM on Hyper-V always uses the latest known eVMCSv1 revision, the assumption
616616
* is: in case a feature has corresponding fields in eVMCS described and it was

arch/x86/kvm/vmx/hyperv.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@
1616

1717
struct vmcs_config;
1818

19-
DECLARE_STATIC_KEY_FALSE(enable_evmcs);
20-
2119
#define current_evmcs ((struct hv_enlightened_vmcs *)this_cpu_read(current_vmcs))
2220

2321
#define KVM_EVMCS_VERSION 1
@@ -69,6 +67,13 @@ static inline u64 evmcs_read_any(struct hv_enlightened_vmcs *evmcs,
6967

7068
#if IS_ENABLED(CONFIG_HYPERV)
7169

70+
DECLARE_STATIC_KEY_FALSE(enable_evmcs);
71+
72+
static __always_inline bool kvm_is_using_evmcs(void)
73+
{
74+
return static_branch_unlikely(&enable_evmcs);
75+
}
76+
7277
static __always_inline int get_evmcs_offset(unsigned long field,
7378
u16 *clean_field)
7479
{
@@ -158,6 +163,7 @@ static inline void evmcs_load(u64 phys_addr)
158163

159164
void evmcs_sanitize_exec_ctrls(struct vmcs_config *vmcs_conf);
160165
#else /* !IS_ENABLED(CONFIG_HYPERV) */
166+
static __always_inline bool kvm_is_using_evmcs(void) { return false; }
161167
static __always_inline void evmcs_write64(unsigned long field, u64 value) {}
162168
static __always_inline void evmcs_write32(unsigned long field, u32 value) {}
163169
static __always_inline void evmcs_write16(unsigned long field, u16 value) {}

arch/x86/kvm/vmx/vmx.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ static void hv_reset_evmcs(void)
595595
{
596596
struct hv_vp_assist_page *vp_ap;
597597

598-
if (!static_branch_unlikely(&enable_evmcs))
598+
if (!kvm_is_using_evmcs())
599599
return;
600600

601601
/*
@@ -2816,8 +2816,7 @@ static int vmx_hardware_enable(void)
28162816
* This can happen if we hot-added a CPU but failed to allocate
28172817
* VP assist page for it.
28182818
*/
2819-
if (static_branch_unlikely(&enable_evmcs) &&
2820-
!hv_get_vp_assist_page(cpu))
2819+
if (kvm_is_using_evmcs() && !hv_get_vp_assist_page(cpu))
28212820
return -EFAULT;
28222821

28232822
intel_pt_handle_vmx(1);
@@ -2869,7 +2868,7 @@ struct vmcs *alloc_vmcs_cpu(bool shadow, int cpu, gfp_t flags)
28692868
memset(vmcs, 0, vmcs_config.size);
28702869

28712870
/* KVM supports Enlightened VMCS v1 only */
2872-
if (static_branch_unlikely(&enable_evmcs))
2871+
if (kvm_is_using_evmcs())
28732872
vmcs->hdr.revision_id = KVM_EVMCS_VERSION;
28742873
else
28752874
vmcs->hdr.revision_id = vmcs_config.revision_id;
@@ -2964,7 +2963,7 @@ static __init int alloc_kvm_area(void)
29642963
* still be marked with revision_id reported by
29652964
* physical CPU.
29662965
*/
2967-
if (static_branch_unlikely(&enable_evmcs))
2966+
if (kvm_is_using_evmcs())
29682967
vmcs->hdr.revision_id = vmcs_config.revision_id;
29692968

29702969
per_cpu(vmxarea, cpu) = vmcs;
@@ -3931,7 +3930,7 @@ static void vmx_msr_bitmap_l01_changed(struct vcpu_vmx *vmx)
39313930
* 'Enlightened MSR Bitmap' feature L0 needs to know that MSR
39323931
* bitmap has changed.
39333932
*/
3934-
if (IS_ENABLED(CONFIG_HYPERV) && static_branch_unlikely(&enable_evmcs)) {
3933+
if (kvm_is_using_evmcs()) {
39353934
struct hv_enlightened_vmcs *evmcs = (void *)vmx->vmcs01.vmcs;
39363935

39373936
if (evmcs->hv_enlightenments_control.msr_bitmap)
@@ -7310,7 +7309,7 @@ static fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu)
73107309
vmx_vcpu_enter_exit(vcpu, __vmx_vcpu_run_flags(vmx));
73117310

73127311
/* All fields are clean at this point */
7313-
if (static_branch_unlikely(&enable_evmcs)) {
7312+
if (kvm_is_using_evmcs()) {
73147313
current_evmcs->hv_clean_fields |=
73157314
HV_VMX_ENLIGHTENED_CLEAN_FIELD_ALL;
73167315

@@ -7440,7 +7439,7 @@ static int vmx_vcpu_create(struct kvm_vcpu *vcpu)
74407439
* feature only for vmcs01, KVM currently isn't equipped to realize any
74417440
* performance benefits from enabling it for vmcs02.
74427441
*/
7443-
if (IS_ENABLED(CONFIG_HYPERV) && static_branch_unlikely(&enable_evmcs) &&
7442+
if (kvm_is_using_evmcs() &&
74447443
(ms_hyperv.nested_features & HV_X64_NESTED_MSR_BITMAP)) {
74457444
struct hv_enlightened_vmcs *evmcs = (void *)vmx->vmcs01.vmcs;
74467445

arch/x86/kvm/vmx/vmx_ops.h

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -147,23 +147,23 @@ static __always_inline unsigned long __vmcs_readl(unsigned long field)
147147
static __always_inline u16 vmcs_read16(unsigned long field)
148148
{
149149
vmcs_check16(field);
150-
if (static_branch_unlikely(&enable_evmcs))
150+
if (kvm_is_using_evmcs())
151151
return evmcs_read16(field);
152152
return __vmcs_readl(field);
153153
}
154154

155155
static __always_inline u32 vmcs_read32(unsigned long field)
156156
{
157157
vmcs_check32(field);
158-
if (static_branch_unlikely(&enable_evmcs))
158+
if (kvm_is_using_evmcs())
159159
return evmcs_read32(field);
160160
return __vmcs_readl(field);
161161
}
162162

163163
static __always_inline u64 vmcs_read64(unsigned long field)
164164
{
165165
vmcs_check64(field);
166-
if (static_branch_unlikely(&enable_evmcs))
166+
if (kvm_is_using_evmcs())
167167
return evmcs_read64(field);
168168
#ifdef CONFIG_X86_64
169169
return __vmcs_readl(field);
@@ -175,7 +175,7 @@ static __always_inline u64 vmcs_read64(unsigned long field)
175175
static __always_inline unsigned long vmcs_readl(unsigned long field)
176176
{
177177
vmcs_checkl(field);
178-
if (static_branch_unlikely(&enable_evmcs))
178+
if (kvm_is_using_evmcs())
179179
return evmcs_read64(field);
180180
return __vmcs_readl(field);
181181
}
@@ -222,7 +222,7 @@ static __always_inline void __vmcs_writel(unsigned long field, unsigned long val
222222
static __always_inline void vmcs_write16(unsigned long field, u16 value)
223223
{
224224
vmcs_check16(field);
225-
if (static_branch_unlikely(&enable_evmcs))
225+
if (kvm_is_using_evmcs())
226226
return evmcs_write16(field, value);
227227

228228
__vmcs_writel(field, value);
@@ -231,7 +231,7 @@ static __always_inline void vmcs_write16(unsigned long field, u16 value)
231231
static __always_inline void vmcs_write32(unsigned long field, u32 value)
232232
{
233233
vmcs_check32(field);
234-
if (static_branch_unlikely(&enable_evmcs))
234+
if (kvm_is_using_evmcs())
235235
return evmcs_write32(field, value);
236236

237237
__vmcs_writel(field, value);
@@ -240,7 +240,7 @@ static __always_inline void vmcs_write32(unsigned long field, u32 value)
240240
static __always_inline void vmcs_write64(unsigned long field, u64 value)
241241
{
242242
vmcs_check64(field);
243-
if (static_branch_unlikely(&enable_evmcs))
243+
if (kvm_is_using_evmcs())
244244
return evmcs_write64(field, value);
245245

246246
__vmcs_writel(field, value);
@@ -252,7 +252,7 @@ static __always_inline void vmcs_write64(unsigned long field, u64 value)
252252
static __always_inline void vmcs_writel(unsigned long field, unsigned long value)
253253
{
254254
vmcs_checkl(field);
255-
if (static_branch_unlikely(&enable_evmcs))
255+
if (kvm_is_using_evmcs())
256256
return evmcs_write64(field, value);
257257

258258
__vmcs_writel(field, value);
@@ -262,7 +262,7 @@ static __always_inline void vmcs_clear_bits(unsigned long field, u32 mask)
262262
{
263263
BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
264264
"vmcs_clear_bits does not support 64-bit fields");
265-
if (static_branch_unlikely(&enable_evmcs))
265+
if (kvm_is_using_evmcs())
266266
return evmcs_write32(field, evmcs_read32(field) & ~mask);
267267

268268
__vmcs_writel(field, __vmcs_readl(field) & ~mask);
@@ -272,7 +272,7 @@ static __always_inline void vmcs_set_bits(unsigned long field, u32 mask)
272272
{
273273
BUILD_BUG_ON_MSG(__builtin_constant_p(field) && ((field) & 0x6000) == 0x2000,
274274
"vmcs_set_bits does not support 64-bit fields");
275-
if (static_branch_unlikely(&enable_evmcs))
275+
if (kvm_is_using_evmcs())
276276
return evmcs_write32(field, evmcs_read32(field) | mask);
277277

278278
__vmcs_writel(field, __vmcs_readl(field) | mask);
@@ -289,7 +289,7 @@ static inline void vmcs_load(struct vmcs *vmcs)
289289
{
290290
u64 phys_addr = __pa(vmcs);
291291

292-
if (static_branch_unlikely(&enable_evmcs))
292+
if (kvm_is_using_evmcs())
293293
return evmcs_load(phys_addr);
294294

295295
vmx_asm1(vmptrld, "m"(phys_addr), vmcs, phys_addr);

0 commit comments

Comments
 (0)