KVM: SVM: Check that the current CPU supports SVM in kvm_is_svm_supported()
authorSean Christopherson <seanjc@google.com>
Fri, 21 Jul 2023 20:18:54 +0000 (13:18 -0700)
committerSean Christopherson <seanjc@google.com>
Thu, 3 Aug 2023 22:37:15 +0000 (15:37 -0700)
Check "this" CPU instead of the boot CPU when querying SVM support so that
the per-CPU checks done during hardware enabling actually function as
intended, i.e. will detect issues where SVM isn't support on all CPUs.

Disable migration for the use from svm_init() mostly so that the standard
accessors for the per-CPU data can be used without getting yelled at by
CONFIG_DEBUG_PREEMPT=y sanity checks.  Preventing the "disabled by BIOS"
error message from reporting the wrong CPU is largely a bonus, as ensuring
a stable CPU during module load is a non-goal for KVM.

Link: https://lore.kernel.org/all/ZAdxNgv0M6P63odE@google.com
Cc: Kai Huang <kai.huang@intel.com>
Cc: Chao Gao <chao.gao@intel.com>
Reviewed-by: Kai Huang <kai.huang@intel.com>
Link: https://lore.kernel.org/r/20230721201859.2307736-15-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/kvm/svm/svm.c

index ff6c769..9e44916 100644 (file)
@@ -518,18 +518,20 @@ static void svm_init_osvw(struct kvm_vcpu *vcpu)
                vcpu->arch.osvw.status |= 1;
 }
 
-static bool kvm_is_svm_supported(void)
+static bool __kvm_is_svm_supported(void)
 {
-       int cpu = raw_smp_processor_id();
+       int cpu = smp_processor_id();
+       struct cpuinfo_x86 *c = &cpu_data(cpu);
+
        u64 vm_cr;
 
-       if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
-           boot_cpu_data.x86_vendor != X86_VENDOR_HYGON) {
+       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 (!boot_cpu_has(X86_FEATURE_SVM)) {
+       if (!cpu_has(c, X86_FEATURE_SVM)) {
                pr_err("SVM not supported by CPU %d\n", cpu);
                return false;
        }
@@ -548,9 +550,20 @@ static bool kvm_is_svm_supported(void)
        return true;
 }
 
+static 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;