[RFC PATCH 12/14] KVM: x86: Move VMX and SVM support checks into VAC

From: Anish Ghulati
Date: Tue Nov 07 2023 - 15:29:55 EST


kvm_is_***_supported checks to see if VMX and SVM are supported on the
host. Move this to VAC because it needs to be called before each h/w
enable and disable call.

Signed-off-by: Anish Ghulati <aghulati@xxxxxxxxxx>
---
arch/x86/kvm/svm/svm.c | 45 +-----------------------------------------
arch/x86/kvm/svm/vac.c | 43 ++++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/vac.h | 4 ++++
arch/x86/kvm/vmx/vac.c | 29 +++++++++++++++++++++++++++
arch/x86/kvm/vmx/vmx.c | 31 +----------------------------
arch/x86/kvm/x86.h | 6 ------
6 files changed, 78 insertions(+), 80 deletions(-)

diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 752f769c0333..df5673c98e7b 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -515,52 +515,9 @@ static void svm_init_osvw(struct kvm_vcpu *vcpu)
vcpu->arch.osvw.status |= 1;
}

-static bool __kvm_is_svm_supported(void)
-{
- int cpu = smp_processor_id();
- struct cpuinfo_x86 *c = &cpu_data(cpu);
-
- u64 vm_cr;
-
- if (c->x86_vendor != X86_VENDOR_AMD &&
- c->x86_vendor != X86_VENDOR_HYGON) {
- pr_err("CPU %d isn't AMD or Hygon\n", cpu);
- return false;
- }
-
- if (!cpu_has(c, X86_FEATURE_SVM)) {
- pr_err("SVM not supported by CPU %d\n", cpu);
- return false;
- }
-
- if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
- pr_info("KVM is unsupported when running as an SEV guest\n");
- return false;
- }
-
- rdmsrl(MSR_VM_CR, vm_cr);
- if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) {
- pr_err("SVM disabled (by BIOS) in MSR_VM_CR on CPU %d\n", cpu);
- return false;
- }
-
- return true;
-}
-
-bool kvm_is_svm_supported(void)
-{
- bool supported;
-
- migrate_disable();
- supported = __kvm_is_svm_supported();
- migrate_enable();
-
- return supported;
-}
-
static int svm_check_processor_compat(void)
{
- if (!__kvm_is_svm_supported())
+ if (!kvm_is_svm_supported())
return -EIO;

return 0;
diff --git a/arch/x86/kvm/svm/vac.c b/arch/x86/kvm/svm/vac.c
index 2dd1c763f7d6..7c4db99ca7d5 100644
--- a/arch/x86/kvm/svm/vac.c
+++ b/arch/x86/kvm/svm/vac.c
@@ -10,6 +10,49 @@
DEFINE_PER_CPU(struct svm_cpu_data, svm_data);
unsigned int max_sev_asid;

+static bool __kvm_is_svm_supported(void)
+{
+ int cpu = smp_processor_id();
+ struct cpuinfo_x86 *c = &cpu_data(cpu);
+
+ u64 vm_cr;
+
+ if (c->x86_vendor != X86_VENDOR_AMD &&
+ c->x86_vendor != X86_VENDOR_HYGON) {
+ pr_err("CPU %d isn't AMD or Hygon\n", cpu);
+ return false;
+ }
+
+ if (!cpu_has(c, X86_FEATURE_SVM)) {
+ pr_err("SVM not supported by CPU %d\n", cpu);
+ return false;
+ }
+
+ if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
+ pr_info("KVM is unsupported when running as an SEV guest\n");
+ return false;
+ }
+
+ rdmsrl(MSR_VM_CR, vm_cr);
+ if (vm_cr & (1 << SVM_VM_CR_SVM_DISABLE)) {
+ pr_err("SVM disabled (by BIOS) in MSR_VM_CR on CPU %d\n", cpu);
+ return false;
+ }
+
+ return true;
+}
+
+bool kvm_is_svm_supported(void)
+{
+ bool supported;
+
+ migrate_disable();
+ supported = __kvm_is_svm_supported();
+ migrate_enable();
+
+ return supported;
+}
+
static inline void kvm_cpu_svm_disable(void)
{
uint64_t efer;
diff --git a/arch/x86/kvm/vac.h b/arch/x86/kvm/vac.h
index 6c0a480ee9e3..5be30cce5a1c 100644
--- a/arch/x86/kvm/vac.h
+++ b/arch/x86/kvm/vac.h
@@ -9,9 +9,11 @@ int __init vac_init(void);
void vac_exit(void);

#ifdef CONFIG_KVM_INTEL
+bool kvm_is_vmx_supported(void);
int __init vac_vmx_init(void);
void vac_vmx_exit(void);
#else
+bool kvm_is_vmx_supported(void) { return false }
int __init vac_vmx_init(void)
{
return 0;
@@ -20,9 +22,11 @@ void vac_vmx_exit(void) {}
#endif

#ifdef CONFIG_KVM_AMD
+bool kvm_is_svm_supported(void);
int __init vac_svm_init(void);
void vac_svm_exit(void);
#else
+bool kvm_is_svm_supported(void) { return false }
int __init vac_svm_init(void)
{
return 0;
diff --git a/arch/x86/kvm/vmx/vac.c b/arch/x86/kvm/vmx/vac.c
index 202686ccbaec..cdfdeb67a719 100644
--- a/arch/x86/kvm/vmx/vac.c
+++ b/arch/x86/kvm/vmx/vac.c
@@ -31,6 +31,35 @@ struct vmcs *vac_get_vmxarea(int cpu)
static DECLARE_BITMAP(vmx_vpid_bitmap, VMX_NR_VPIDS);
static DEFINE_SPINLOCK(vmx_vpid_lock);

+static bool __kvm_is_vmx_supported(void)
+{
+ int cpu = smp_processor_id();
+
+ if (!(cpuid_ecx(1) & feature_bit(VMX))) {
+ pr_err("VMX not supported by CPU %d\n", cpu);
+ return false;
+ }
+
+ if (!this_cpu_has(X86_FEATURE_MSR_IA32_FEAT_CTL) ||
+ !this_cpu_has(X86_FEATURE_VMX)) {
+ pr_err("VMX not enabled (by BIOS) in MSR_IA32_FEAT_CTL on CPU %d\n", cpu);
+ return false;
+ }
+
+ return true;
+}
+
+bool kvm_is_vmx_supported(void)
+{
+ bool supported;
+
+ migrate_disable();
+ supported = __kvm_is_vmx_supported();
+ migrate_enable();
+
+ return supported;
+}
+
int allocate_vpid(void)
{
int vpid;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 46e2d5c69d1d..6301b49e0e80 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -2625,42 +2625,13 @@ static int setup_vmcs_config(struct vmcs_config *vmcs_conf,
return 0;
}

-static bool __kvm_is_vmx_supported(void)
-{
- int cpu = smp_processor_id();
-
- if (!(cpuid_ecx(1) & feature_bit(VMX))) {
- pr_err("VMX not supported by CPU %d\n", cpu);
- return false;
- }
-
- if (!this_cpu_has(X86_FEATURE_MSR_IA32_FEAT_CTL) ||
- !this_cpu_has(X86_FEATURE_VMX)) {
- pr_err("VMX not enabled (by BIOS) in MSR_IA32_FEAT_CTL on CPU %d\n", cpu);
- return false;
- }
-
- return true;
-}
-
-bool kvm_is_vmx_supported(void)
-{
- bool supported;
-
- migrate_disable();
- supported = __kvm_is_vmx_supported();
- migrate_enable();
-
- return supported;
-}
-
static int vmx_check_processor_compat(void)
{
int cpu = raw_smp_processor_id();
struct vmcs_config vmcs_conf;
struct vmx_capability vmx_cap;

- if (!__kvm_is_vmx_supported())
+ if (!kvm_is_vmx_supported())
return -EIO;

if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0) {
diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h
index 322be05e6c5b..1da8efcd3e9c 100644
--- a/arch/x86/kvm/x86.h
+++ b/arch/x86/kvm/x86.h
@@ -10,18 +10,12 @@
#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 {
--
2.42.0.869.gea05f2083d-goog