Skip to content

Commit b4f69df

Browse files
vittyvksean-jc
authored andcommitted
KVM: x86: Make Hyper-V emulation optional
Hyper-V emulation in KVM is a fairly big chunk and in some cases it may be desirable to not compile it in to reduce module sizes as well as the attack surface. Introduce CONFIG_KVM_HYPERV option to make it possible. Note, there's room for further nVMX/nSVM code optimizations when !CONFIG_KVM_HYPERV, this will be done in follow-up patches. Reorganize Makefile a bit so all CONFIG_HYPERV and CONFIG_KVM_HYPERV files are grouped together. Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com> Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com> Tested-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com> Link: https://lore.kernel.org/r/20231205103630.1391318-13-vkuznets@redhat.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent f973146 commit b4f69df

11 files changed

Lines changed: 201 additions & 35 deletions

File tree

arch/x86/include/asm/kvm_host.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -937,8 +937,10 @@ struct kvm_vcpu_arch {
937937
/* used for guest single stepping over the given code position */
938938
unsigned long singlestep_rip;
939939

940+
#ifdef CONFIG_KVM_HYPERV
940941
bool hyperv_enabled;
941942
struct kvm_vcpu_hv *hyperv;
943+
#endif
942944
#ifdef CONFIG_KVM_XEN
943945
struct kvm_vcpu_xen xen;
944946
#endif
@@ -1095,6 +1097,7 @@ enum hv_tsc_page_status {
10951097
HV_TSC_PAGE_BROKEN,
10961098
};
10971099

1100+
#ifdef CONFIG_KVM_HYPERV
10981101
/* Hyper-V emulation context */
10991102
struct kvm_hv {
11001103
struct mutex hv_lock;
@@ -1127,6 +1130,7 @@ struct kvm_hv {
11271130

11281131
struct kvm_hv_syndbg hv_syndbg;
11291132
};
1133+
#endif
11301134

11311135
struct msr_bitmap_range {
11321136
u32 flags;
@@ -1349,7 +1353,9 @@ struct kvm_arch {
13491353
/* reads protected by irq_srcu, writes by irq_lock */
13501354
struct hlist_head mask_notifier_list;
13511355

1356+
#ifdef CONFIG_KVM_HYPERV
13521357
struct kvm_hv hyperv;
1358+
#endif
13531359

13541360
#ifdef CONFIG_KVM_XEN
13551361
struct kvm_xen xen;

arch/x86/kvm/Kconfig

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,20 @@ config KVM_SMM
141141

142142
If unsure, say Y.
143143

144+
config KVM_HYPERV
145+
bool "Support for Microsoft Hyper-V emulation"
146+
depends on KVM
147+
default y
148+
help
149+
Provides KVM support for emulating Microsoft Hyper-V. This allows KVM
150+
to expose a subset of the paravirtualized interfaces defined in the
151+
Hyper-V Hypervisor Top-Level Functional Specification (TLFS):
152+
https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
153+
These interfaces are required for the correct and performant functioning
154+
of Windows and Hyper-V guests on KVM.
155+
156+
If unsure, say "Y".
157+
144158
config KVM_XEN
145159
bool "Support for Xen hypercall interface"
146160
depends on KVM

arch/x86/kvm/Makefile

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,29 +11,27 @@ include $(srctree)/virt/kvm/Makefile.kvm
1111

1212
kvm-y += x86.o emulate.o i8259.o irq.o lapic.o \
1313
i8254.o ioapic.o irq_comm.o cpuid.o pmu.o mtrr.o \
14-
hyperv.o debugfs.o mmu/mmu.o mmu/page_track.o \
14+
debugfs.o mmu/mmu.o mmu/page_track.o \
1515
mmu/spte.o
1616

17-
ifdef CONFIG_HYPERV
18-
kvm-y += kvm_onhyperv.o
19-
endif
20-
2117
kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o
18+
kvm-$(CONFIG_KVM_HYPERV) += hyperv.o
2219
kvm-$(CONFIG_KVM_XEN) += xen.o
2320
kvm-$(CONFIG_KVM_SMM) += smm.o
2421

2522
kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
26-
vmx/hyperv.o vmx/hyperv_evmcs.o vmx/nested.o vmx/posted_intr.o
27-
kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
23+
vmx/nested.o vmx/posted_intr.o
2824

29-
ifdef CONFIG_HYPERV
30-
kvm-intel-y += vmx/vmx_onhyperv.o
31-
endif
25+
kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
26+
kvm-intel-$(CONFIG_KVM_HYPERV) += vmx/hyperv.o vmx/hyperv_evmcs.o
3227

3328
kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \
34-
svm/sev.o svm/hyperv.o
29+
svm/sev.o
30+
kvm-amd-$(CONFIG_KVM_HYPERV) += svm/hyperv.o
3531

3632
ifdef CONFIG_HYPERV
33+
kvm-y += kvm_onhyperv.o
34+
kvm-intel-y += vmx/vmx_onhyperv.o vmx/hyperv_evmcs.o
3735
kvm-amd-y += svm/svm_onhyperv.o
3836
endif
3937

arch/x86/kvm/cpuid.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,11 +314,15 @@ EXPORT_SYMBOL_GPL(kvm_update_cpuid_runtime);
314314

315315
static bool kvm_cpuid_has_hyperv(struct kvm_cpuid_entry2 *entries, int nent)
316316
{
317+
#ifdef CONFIG_KVM_HYPERV
317318
struct kvm_cpuid_entry2 *entry;
318319

319320
entry = cpuid_entry2_find(entries, nent, HYPERV_CPUID_INTERFACE,
320321
KVM_CPUID_INDEX_NOT_SIGNIFICANT);
321322
return entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX;
323+
#else
324+
return false;
325+
#endif
322326
}
323327

324328
static void kvm_vcpu_after_set_cpuid(struct kvm_vcpu *vcpu)
@@ -433,11 +437,13 @@ static int kvm_set_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid_entry2 *e2,
433437
return 0;
434438
}
435439

440+
#ifdef CONFIG_KVM_HYPERV
436441
if (kvm_cpuid_has_hyperv(e2, nent)) {
437442
r = kvm_hv_vcpu_init(vcpu);
438443
if (r)
439444
return r;
440445
}
446+
#endif
441447

442448
r = kvm_check_cpuid(vcpu, e2, nent);
443449
if (r)

arch/x86/kvm/hyperv.h

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
#include <linux/kvm_host.h>
2525
#include "x86.h"
2626

27+
#ifdef CONFIG_KVM_HYPERV
28+
2729
/* "Hv#1" signature */
2830
#define HYPERV_CPUID_SIGNATURE_EAX 0x31237648
2931

@@ -261,5 +263,62 @@ static inline void kvm_hv_nested_transtion_tlb_flush(struct kvm_vcpu *vcpu,
261263
}
262264

263265
int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu);
266+
#else /* CONFIG_KVM_HYPERV */
267+
static inline void kvm_hv_setup_tsc_page(struct kvm *kvm,
268+
struct pvclock_vcpu_time_info *hv_clock) {}
269+
static inline void kvm_hv_request_tsc_page_update(struct kvm *kvm) {}
270+
static inline void kvm_hv_init_vm(struct kvm *kvm) {}
271+
static inline void kvm_hv_destroy_vm(struct kvm *kvm) {}
272+
static inline int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
273+
{
274+
return 0;
275+
}
276+
static inline void kvm_hv_vcpu_uninit(struct kvm_vcpu *vcpu) {}
277+
static inline bool kvm_hv_hypercall_enabled(struct kvm_vcpu *vcpu)
278+
{
279+
return false;
280+
}
281+
static inline int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
282+
{
283+
return HV_STATUS_ACCESS_DENIED;
284+
}
285+
static inline void kvm_hv_vcpu_purge_flush_tlb(struct kvm_vcpu *vcpu) {}
286+
static inline void kvm_hv_free_pa_page(struct kvm *kvm) {}
287+
static inline bool kvm_hv_synic_has_vector(struct kvm_vcpu *vcpu, int vector)
288+
{
289+
return false;
290+
}
291+
static inline bool kvm_hv_synic_auto_eoi_set(struct kvm_vcpu *vcpu, int vector)
292+
{
293+
return false;
294+
}
295+
static inline void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector) {}
296+
static inline bool kvm_hv_invtsc_suppressed(struct kvm_vcpu *vcpu)
297+
{
298+
return false;
299+
}
300+
static inline void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu, bool hyperv_enabled) {}
301+
static inline bool kvm_hv_has_stimer_pending(struct kvm_vcpu *vcpu)
302+
{
303+
return false;
304+
}
305+
static inline bool kvm_hv_is_tlb_flush_hcall(struct kvm_vcpu *vcpu)
306+
{
307+
return false;
308+
}
309+
static inline bool guest_hv_cpuid_has_l2_tlb_flush(struct kvm_vcpu *vcpu)
310+
{
311+
return false;
312+
}
313+
static inline int kvm_hv_verify_vp_assist(struct kvm_vcpu *vcpu)
314+
{
315+
return 0;
316+
}
317+
static inline u32 kvm_hv_get_vpindex(struct kvm_vcpu *vcpu)
318+
{
319+
return vcpu->vcpu_idx;
320+
}
321+
static inline void kvm_hv_nested_transtion_tlb_flush(struct kvm_vcpu *vcpu, bool tdp_enabled) {}
322+
#endif /* CONFIG_KVM_HYPERV */
264323

265-
#endif
324+
#endif /* __ARCH_X86_KVM_HYPERV_H__ */

arch/x86/kvm/irq_comm.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e,
144144
return kvm_irq_delivery_to_apic(kvm, NULL, &irq, NULL);
145145
}
146146

147-
147+
#ifdef CONFIG_KVM_HYPERV
148148
static int kvm_hv_set_sint(struct kvm_kernel_irq_routing_entry *e,
149149
struct kvm *kvm, int irq_source_id, int level,
150150
bool line_status)
@@ -154,6 +154,7 @@ static int kvm_hv_set_sint(struct kvm_kernel_irq_routing_entry *e,
154154

155155
return kvm_hv_synic_set_irq(kvm, e->hv_sint.vcpu, e->hv_sint.sint);
156156
}
157+
#endif
157158

158159
int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
159160
struct kvm *kvm, int irq_source_id, int level,
@@ -163,9 +164,11 @@ int kvm_arch_set_irq_inatomic(struct kvm_kernel_irq_routing_entry *e,
163164
int r;
164165

165166
switch (e->type) {
167+
#ifdef CONFIG_KVM_HYPERV
166168
case KVM_IRQ_ROUTING_HV_SINT:
167169
return kvm_hv_set_sint(e, kvm, irq_source_id, level,
168170
line_status);
171+
#endif
169172

170173
case KVM_IRQ_ROUTING_MSI:
171174
if (kvm_msi_route_invalid(kvm, e))
@@ -314,11 +317,13 @@ int kvm_set_routing_entry(struct kvm *kvm,
314317
if (kvm_msi_route_invalid(kvm, e))
315318
return -EINVAL;
316319
break;
320+
#ifdef CONFIG_KVM_HYPERV
317321
case KVM_IRQ_ROUTING_HV_SINT:
318322
e->set = kvm_hv_set_sint;
319323
e->hv_sint.vcpu = ue->u.hv_sint.vcpu;
320324
e->hv_sint.sint = ue->u.hv_sint.sint;
321325
break;
326+
#endif
322327
#ifdef CONFIG_KVM_XEN
323328
case KVM_IRQ_ROUTING_XEN_EVTCHN:
324329
return kvm_xen_setup_evtchn(kvm, e, ue);
@@ -438,5 +443,7 @@ void kvm_scan_ioapic_routes(struct kvm_vcpu *vcpu,
438443

439444
void kvm_arch_irq_routing_update(struct kvm *kvm)
440445
{
446+
#ifdef CONFIG_KVM_HYPERV
441447
kvm_hv_irq_routing_update(kvm);
448+
#endif
442449
}

arch/x86/kvm/svm/hyperv.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include "../hyperv.h"
1212
#include "svm.h"
1313

14+
#ifdef CONFIG_KVM_HYPERV
1415
static inline void nested_svm_hv_update_vm_vp_ids(struct kvm_vcpu *vcpu)
1516
{
1617
struct vcpu_svm *svm = to_svm(vcpu);
@@ -41,5 +42,13 @@ static inline bool nested_svm_l2_tlb_flush_enabled(struct kvm_vcpu *vcpu)
4142
}
4243

4344
void svm_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu);
45+
#else /* CONFIG_KVM_HYPERV */
46+
static inline void nested_svm_hv_update_vm_vp_ids(struct kvm_vcpu *vcpu) {}
47+
static inline bool nested_svm_l2_tlb_flush_enabled(struct kvm_vcpu *vcpu)
48+
{
49+
return false;
50+
}
51+
static inline void svm_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu) {}
52+
#endif /* CONFIG_KVM_HYPERV */
4453

4554
#endif /* __ARCH_X86_KVM_SVM_HYPERV_H__ */

arch/x86/kvm/vmx/hyperv.h

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@
99
#define EVMPTR_INVALID (-1ULL)
1010
#define EVMPTR_MAP_PENDING (-2ULL)
1111

12-
static inline bool evmptr_is_valid(u64 evmptr)
13-
{
14-
return evmptr != EVMPTR_INVALID && evmptr != EVMPTR_MAP_PENDING;
15-
}
16-
1712
enum nested_evmptrld_status {
1813
EVMPTRLD_DISABLED,
1914
EVMPTRLD_SUCCEEDED,
2015
EVMPTRLD_VMFAIL,
2116
EVMPTRLD_ERROR,
2217
};
2318

19+
#ifdef CONFIG_KVM_HYPERV
20+
static inline bool evmptr_is_valid(u64 evmptr)
21+
{
22+
return evmptr != EVMPTR_INVALID && evmptr != EVMPTR_MAP_PENDING;
23+
}
24+
2425
static inline bool guest_cpuid_has_evmcs(struct kvm_vcpu *vcpu)
2526
{
2627
/*
@@ -39,5 +40,11 @@ void nested_evmcs_filter_control_msr(struct kvm_vcpu *vcpu, u32 msr_index, u64 *
3940
int nested_evmcs_check_controls(struct vmcs12 *vmcs12);
4041
bool nested_evmcs_l2_tlb_flush_enabled(struct kvm_vcpu *vcpu);
4142
void vmx_hv_inject_synthetic_vmexit_post_tlb_flush(struct kvm_vcpu *vcpu);
43+
#else
44+
static inline bool evmptr_is_valid(u64 evmptr)
45+
{
46+
return false;
47+
}
48+
#endif
4249

4350
#endif /* __KVM_X86_VMX_HYPERV_H */

0 commit comments

Comments
 (0)