Collapse x86 vendor modules, i.e. kvm_intel and kvm_amd into kvm.ko. Add a new vendor_exit function to kvm_x86_ops so that KVM knows which exit function to call when exiting. Since the vendor modules no longer exist the vendor_exit function call does not have to go through a static call. Expose vendor init/exit/supported functions so that they can be called from vendor neutral KVM locations. Signed-off-by: Anish Ghulati <aghulati@xxxxxxxxxx> --- arch/x86/include/asm/kvm-x86-ops.h | 1 + arch/x86/include/asm/kvm_host.h | 2 + arch/x86/kernel/nmi.c | 2 +- arch/x86/kvm/Kconfig | 12 ++---- arch/x86/kvm/Makefile | 10 ++--- arch/x86/kvm/svm/svm.c | 38 +++++++---------- arch/x86/kvm/vmx/vmx.c | 66 +++++++++++++----------------- arch/x86/kvm/x86.c | 18 +++++--- arch/x86/kvm/x86.h | 15 +++++++ 9 files changed, 82 insertions(+), 82 deletions(-) diff --git a/arch/x86/include/asm/kvm-x86-ops.h b/arch/x86/include/asm/kvm-x86-ops.h index e3054e3e46d5..764be4a26a0c 100644 --- a/arch/x86/include/asm/kvm-x86-ops.h +++ b/arch/x86/include/asm/kvm-x86-ops.h @@ -14,6 +14,7 @@ BUILD_BUG_ON(1) * to make a definition optional, but in this case the default will * be __static_call_return0. */ +KVM_X86_OP(vendor_exit) KVM_X86_OP(check_processor_compatibility) KVM_X86_OP(hardware_enable) KVM_X86_OP(hardware_disable) diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h index eda45a937666..e01d1aa3628c 100644 --- a/arch/x86/include/asm/kvm_host.h +++ b/arch/x86/include/asm/kvm_host.h @@ -1546,6 +1546,8 @@ static inline u16 kvm_lapic_irq_dest_mode(bool dest_mode_logical) struct kvm_x86_ops { const char *name; + void (*vendor_exit)(void); + int (*check_processor_compatibility)(void); int (*hardware_enable)(void); diff --git a/arch/x86/kernel/nmi.c b/arch/x86/kernel/nmi.c index a0c551846b35..8f2ac7598912 100644 --- a/arch/x86/kernel/nmi.c +++ b/arch/x86/kernel/nmi.c @@ -565,7 +565,7 @@ DEFINE_IDTENTRY_RAW(exc_nmi_kvm_vmx) { exc_nmi(regs); } -#if IS_MODULE(CONFIG_KVM_INTEL) +#if IS_MODULE(CONFIG_KVM) && IS_ENABLED(CONFIG_KVM_INTEL) EXPORT_SYMBOL_GPL(asm_exc_nmi_kvm_vmx); #endif #endif diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig index 8c5fb7f57b4c..adfa57d59643 100644 --- a/arch/x86/kvm/Kconfig +++ b/arch/x86/kvm/Kconfig @@ -75,15 +75,12 @@ config KVM_WERROR If in doubt, say "N". config KVM_INTEL - tristate "KVM for Intel (and compatible) processors support" + bool "KVM for Intel (and compatible) processors support" depends on KVM && IA32_FEAT_CTL help Provides support for KVM on processors equipped with Intel's VT extensions, a.k.a. Virtual Machine Extensions (VMX). - To compile this as a module, choose M here: the module - will be called kvm-intel. - config X86_SGX_KVM bool "Software Guard eXtensions (SGX) Virtualization" depends on X86_SGX && KVM_INTEL @@ -97,20 +94,17 @@ config X86_SGX_KVM If unsure, say N. config KVM_AMD - tristate "KVM for AMD processors support" + bool "KVM for AMD processors support" depends on KVM && (CPU_SUP_AMD || CPU_SUP_HYGON) help Provides support for KVM on AMD processors equipped with the AMD-V (SVM) extensions. - To compile this as a module, choose M here: the module - will be called kvm-amd. - config KVM_AMD_SEV def_bool y bool "AMD Secure Encrypted Virtualization (SEV) support" depends on KVM_AMD && X86_64 - depends on CRYPTO_DEV_SP_PSP && !(KVM_AMD=y && CRYPTO_DEV_CCP_DD=m) + depends on CRYPTO_DEV_SP_PSP && !(KVM=y && CRYPTO_DEV_CCP_DD=m) help Provides support for launching Encrypted VMs (SEV) and Encrypted VMs with Encrypted State (SEV-ES) on AMD processors. diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index d13f1a7b7b3d..3e965c90e065 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -21,20 +21,18 @@ kvm-$(CONFIG_X86_64) += mmu/tdp_iter.o mmu/tdp_mmu.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 \ +kvm-$(CONFIG_KVM_INTEL) += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \ vmx/hyperv.o vmx/nested.o vmx/posted_intr.o -kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o +kvm-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o -kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \ +kvm-$(CONFIG_KVM_AMD) += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o \ svm/sev.o svm/hyperv.o ifdef CONFIG_HYPERV -kvm-amd-y += svm/svm_onhyperv.o +kvm-$(CONFIG_KVM_AMD) += svm/svm_onhyperv.o endif obj-$(CONFIG_KVM) += kvm.o -obj-$(CONFIG_KVM_INTEL) += kvm-intel.o -obj-$(CONFIG_KVM_AMD) += kvm-amd.o AFLAGS_svm/vmenter.o := -iquote $(obj) $(obj)/svm/vmenter.o: $(obj)/kvm-asm-offsets.h diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index 3d44e42f4f22..7fe9d11db8a6 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -52,9 +52,6 @@ #include "kvm_onhyperv.h" #include "svm_onhyperv.h" -MODULE_AUTHOR("Qumranet"); -MODULE_LICENSE("GPL"); - #ifdef MODULE static const struct x86_cpu_id svm_cpu_id[] = { X86_MATCH_FEATURE(X86_FEATURE_SVM, NULL), @@ -551,7 +548,7 @@ static bool __kvm_is_svm_supported(void) return true; } -static bool kvm_is_svm_supported(void) +bool kvm_is_svm_supported(void) { bool supported; @@ -4873,9 +4870,21 @@ static int svm_vm_init(struct kvm *kvm) return 0; } +static void __svm_exit(void) +{ + cpu_emergency_unregister_virt_callback(svm_emergency_disable); +} + +void svm_module_exit(void) +{ + __svm_exit(); +} + static struct kvm_x86_ops svm_x86_ops __initdata = { .name = KBUILD_MODNAME, + .vendor_exit = svm_module_exit, + .check_processor_compatibility = svm_check_processor_compat, .hardware_unsetup = svm_hardware_unsetup, @@ -5298,22 +5307,12 @@ static struct kvm_x86_init_ops svm_init_ops __initdata = { .pmu_ops = &amd_pmu_ops, }; -static void __svm_exit(void) -{ - kvm_x86_vendor_exit(); - - cpu_emergency_unregister_virt_callback(svm_emergency_disable); -} - -static int __init svm_init(void) +int __init svm_init(void) { int r; __unused_size_checks(); - if (!kvm_is_svm_supported()) - return -EOPNOTSUPP; - r = kvm_x86_vendor_init(&svm_init_ops); if (r) return r; @@ -5335,12 +5334,3 @@ static int __init svm_init(void) __svm_exit(); return r; } - -static void __exit svm_exit(void) -{ - kvm_exit(); - __svm_exit(); -} - -module_init(svm_init) -module_exit(svm_exit) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 65d59de3cc63..629e662b131e 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -66,9 +66,6 @@ #include "x86.h" #include "smm.h" -MODULE_AUTHOR("Qumranet"); -MODULE_LICENSE("GPL"); - #ifdef MODULE static const struct x86_cpu_id vmx_cpu_id[] = { X86_MATCH_FEATURE(X86_FEATURE_VMX, NULL), @@ -2738,7 +2735,7 @@ static bool __kvm_is_vmx_supported(void) return true; } -static bool kvm_is_vmx_supported(void) +bool kvm_is_vmx_supported(void) { bool supported; @@ -8199,9 +8196,35 @@ static void vmx_vm_destroy(struct kvm *kvm) free_pages((unsigned long)kvm_vmx->pid_table, vmx_get_pid_table_order(kvm)); } +static void vmx_cleanup_l1d_flush(void) +{ + if (vmx_l1d_flush_pages) { + free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER); + vmx_l1d_flush_pages = NULL; + } + /* Restore state so sysfs ignores VMX */ + l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; +} + +static void __vmx_exit(void) +{ + allow_smaller_maxphyaddr = false; + + cpu_emergency_unregister_virt_callback(vmx_emergency_disable); + + vmx_cleanup_l1d_flush(); +} + +void vmx_module_exit(void) +{ + __vmx_exit(); +} + static struct kvm_x86_ops vmx_x86_ops __initdata = { .name = KBUILD_MODNAME, + .vendor_exit = vmx_module_exit, + .check_processor_compatibility = vmx_check_processor_compat, .hardware_unsetup = vmx_hardware_unsetup, @@ -8608,41 +8631,10 @@ static struct kvm_x86_init_ops vmx_init_ops __initdata = { .pmu_ops = &intel_pmu_ops, }; -static void vmx_cleanup_l1d_flush(void) -{ - if (vmx_l1d_flush_pages) { - free_pages((unsigned long)vmx_l1d_flush_pages, L1D_CACHE_ORDER); - vmx_l1d_flush_pages = NULL; - } - /* Restore state so sysfs ignores VMX */ - l1tf_vmx_mitigation = VMENTER_L1D_FLUSH_AUTO; -} - -static void __vmx_exit(void) -{ - allow_smaller_maxphyaddr = false; - - cpu_emergency_unregister_virt_callback(vmx_emergency_disable); - - vmx_cleanup_l1d_flush(); -} - -static void vmx_exit(void) -{ - kvm_exit(); - kvm_x86_vendor_exit(); - - __vmx_exit(); -} -module_exit(vmx_exit); - -static int __init vmx_init(void) +int __init vmx_init(void) { int r, cpu; - if (!kvm_is_vmx_supported()) - return -EOPNOTSUPP; - /* * Note, hv_init_evmcs() touches only VMX knobs, i.e. there's nothing * to unwind if a later step fails. @@ -8691,6 +8683,7 @@ static int __init vmx_init(void) if (r) goto err_kvm_init; + return 0; err_kvm_init: @@ -8699,4 +8692,3 @@ static int __init vmx_init(void) kvm_x86_vendor_exit(); return r; } -module_init(vmx_init); diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 6b7f89fd2d47..e62daa2c3017 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -15,6 +15,7 @@ * Amit Shah <amit.shah@xxxxxxxxxxxx> * Ben-Ami Yassour <benami@xxxxxxxxxx> */ +#include <asm-generic/errno.h> #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt #include <linux/kvm_host.h> @@ -13678,15 +13679,22 @@ static int __init kvm_x86_init(void) { kvm_mmu_x86_module_init(); mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible(); - return 0; + + if (kvm_is_svm_supported()) + return svm_init(); + else if (kvm_is_vmx_supported()) + return vmx_init(); + + pr_err_ratelimited("kvm: no hardware support for SVM or VMX\n"); + return -EOPNOTSUPP; } module_init(kvm_x86_init); static void __exit kvm_x86_exit(void) { - /* - * If module_init() is implemented, module_exit() must also be - * implemented to allow module unload. - */ + kvm_exit(); + kvm_x86_vendor_exit(); + kvm_x86_ops.vendor_exit(); + } module_exit(kvm_x86_exit); diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 6b5490319d1b..322be05e6c5b 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -9,6 +9,21 @@ #include "kvm_cache_regs.h" #include "kvm_emulate.h" +#ifdef CONFIG_KVM_AMD +bool kvm_is_svm_supported(void); +int __init svm_init(void); +void svm_module_exit(void); +#else +bool kvm_is_svm_supported(void) { return false; } +#endif +#ifdef CONFIG_KVM_INTEL +bool kvm_is_vmx_supported(void); +int __init vmx_init(void); +void vmx_module_exit(void); +#else +bool kvm_is_vmx_supported(void) { return false; } +#endif + struct kvm_caps { /* control of guest tsc rate supported? */ bool has_tsc_control; -- 2.42.0.869.gea05f2083d-goog