KVM: SVM: Check that the current CPU supports SVM in kvm_is_svm_supported()

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>
This commit is contained in:
Sean Christopherson 2023-07-21 13:18:54 -07:00
parent 85fd29dd5f
commit c4db4f20f3

View 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;