Commit b4f69df0 authored by Vitaly Kuznetsov's avatar Vitaly Kuznetsov Committed by Sean Christopherson
Browse files

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: default avatarVitaly Kuznetsov <vkuznets@redhat.com>
Reviewed-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Tested-by: default avatarJeremi Piotrowski <jpiotrowski@linux.microsoft.com>
Link: https://lore.kernel.org/r/20231205103630.1391318-13-vkuznets@redhat.com


Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
parent f9731462
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -937,8 +937,10 @@ struct kvm_vcpu_arch {
	/* used for guest single stepping over the given code position */
	unsigned long singlestep_rip;

#ifdef CONFIG_KVM_HYPERV
	bool hyperv_enabled;
	struct kvm_vcpu_hv *hyperv;
#endif
#ifdef CONFIG_KVM_XEN
	struct kvm_vcpu_xen xen;
#endif
@@ -1095,6 +1097,7 @@ enum hv_tsc_page_status {
	HV_TSC_PAGE_BROKEN,
};

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

	struct kvm_hv_syndbg hv_syndbg;
};
#endif

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

#ifdef CONFIG_KVM_HYPERV
	struct kvm_hv hyperv;
#endif

#ifdef CONFIG_KVM_XEN
	struct kvm_xen xen;
+14 −0
Original line number Diff line number Diff line
@@ -141,6 +141,20 @@ config KVM_SMM

	  If unsure, say Y.

config KVM_HYPERV
	bool "Support for Microsoft Hyper-V emulation"
	depends on KVM
	default y
	help
	  Provides KVM support for emulating Microsoft Hyper-V.  This allows KVM
	  to expose a subset of the paravirtualized interfaces defined in the
	  Hyper-V Hypervisor Top-Level Functional Specification (TLFS):
	  https://docs.microsoft.com/en-us/virtualization/hyper-v-on-windows/reference/tlfs
	  These interfaces are required for the correct and performant functioning
	  of Windows and Hyper-V guests on KVM.

	  If unsure, say "Y".

config KVM_XEN
	bool "Support for Xen hypercall interface"
	depends on KVM
+9 −11
Original line number Diff line number Diff line
@@ -11,29 +11,27 @@ include $(srctree)/virt/kvm/Makefile.kvm

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

ifdef CONFIG_HYPERV
kvm-y			+= kvm_onhyperv.o
endif

kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.o
kvm-$(CONFIG_KVM_HYPERV) += hyperv.o
kvm-$(CONFIG_KVM_XEN)	+= xen.o
kvm-$(CONFIG_KVM_SMM)	+= smm.o

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

ifdef CONFIG_HYPERV
kvm-intel-y		+= vmx/vmx_onhyperv.o
endif
kvm-intel-$(CONFIG_X86_SGX_KVM)	+= vmx/sgx.o
kvm-intel-$(CONFIG_KVM_HYPERV)	+= vmx/hyperv.o vmx/hyperv_evmcs.o

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

ifdef CONFIG_HYPERV
kvm-y			+= kvm_onhyperv.o
kvm-intel-y		+= vmx/vmx_onhyperv.o vmx/hyperv_evmcs.o
kvm-amd-y		+= svm/svm_onhyperv.o
endif

+6 −0
Original line number Diff line number Diff line
@@ -314,11 +314,15 @@ EXPORT_SYMBOL_GPL(kvm_update_cpuid_runtime);

static bool kvm_cpuid_has_hyperv(struct kvm_cpuid_entry2 *entries, int nent)
{
#ifdef CONFIG_KVM_HYPERV
	struct kvm_cpuid_entry2 *entry;

	entry = cpuid_entry2_find(entries, nent, HYPERV_CPUID_INTERFACE,
				  KVM_CPUID_INDEX_NOT_SIGNIFICANT);
	return entry && entry->eax == HYPERV_CPUID_SIGNATURE_EAX;
#else
	return false;
#endif
}

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,
		return 0;
	}

#ifdef CONFIG_KVM_HYPERV
	if (kvm_cpuid_has_hyperv(e2, nent)) {
		r = kvm_hv_vcpu_init(vcpu);
		if (r)
			return r;
	}
#endif

	r = kvm_check_cpuid(vcpu, e2, nent);
	if (r)
+60 −1
Original line number Diff line number Diff line
@@ -24,6 +24,8 @@
#include <linux/kvm_host.h>
#include "x86.h"

#ifdef CONFIG_KVM_HYPERV

/* "Hv#1" signature */
#define HYPERV_CPUID_SIGNATURE_EAX 0x31237648

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

int kvm_hv_vcpu_flush_tlb(struct kvm_vcpu *vcpu);
#else /* CONFIG_KVM_HYPERV */
static inline void kvm_hv_setup_tsc_page(struct kvm *kvm,
					 struct pvclock_vcpu_time_info *hv_clock) {}
static inline void kvm_hv_request_tsc_page_update(struct kvm *kvm) {}
static inline void kvm_hv_init_vm(struct kvm *kvm) {}
static inline void kvm_hv_destroy_vm(struct kvm *kvm) {}
static inline int kvm_hv_vcpu_init(struct kvm_vcpu *vcpu)
{
	return 0;
}
static inline void kvm_hv_vcpu_uninit(struct kvm_vcpu *vcpu) {}
static inline bool kvm_hv_hypercall_enabled(struct kvm_vcpu *vcpu)
{
	return false;
}
static inline int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
{
	return HV_STATUS_ACCESS_DENIED;
}
static inline void kvm_hv_vcpu_purge_flush_tlb(struct kvm_vcpu *vcpu) {}
static inline void kvm_hv_free_pa_page(struct kvm *kvm) {}
static inline bool kvm_hv_synic_has_vector(struct kvm_vcpu *vcpu, int vector)
{
	return false;
}
static inline bool kvm_hv_synic_auto_eoi_set(struct kvm_vcpu *vcpu, int vector)
{
	return false;
}
static inline void kvm_hv_synic_send_eoi(struct kvm_vcpu *vcpu, int vector) {}
static inline bool kvm_hv_invtsc_suppressed(struct kvm_vcpu *vcpu)
{
	return false;
}
static inline void kvm_hv_set_cpuid(struct kvm_vcpu *vcpu, bool hyperv_enabled) {}
static inline bool kvm_hv_has_stimer_pending(struct kvm_vcpu *vcpu)
{
	return false;
}
static inline bool kvm_hv_is_tlb_flush_hcall(struct kvm_vcpu *vcpu)
{
	return false;
}
static inline bool guest_hv_cpuid_has_l2_tlb_flush(struct kvm_vcpu *vcpu)
{
	return false;
}
static inline int kvm_hv_verify_vp_assist(struct kvm_vcpu *vcpu)
{
	return 0;
}
static inline u32 kvm_hv_get_vpindex(struct kvm_vcpu *vcpu)
{
	return vcpu->vcpu_idx;
}
static inline void kvm_hv_nested_transtion_tlb_flush(struct kvm_vcpu *vcpu, bool tdp_enabled) {}
#endif /* CONFIG_KVM_HYPERV */

#endif
#endif /* __ARCH_X86_KVM_HYPERV_H__ */
Loading