On Wed, Feb 09, 2022, Chao Gao wrote: > At init time, KVM does compatibility checks to ensure that all online > CPUs support hardware virtualization and a common set of features. But > KVM uses hotplugged CPUs without such compatibility checks. On Intel > CPUs, this leads to #GP if the hotplugged CPU doesn't support VMX or > vmentry failure if the hotplugged CPU doesn't meet minimal feature > requirements. > > Do compatibility checks when onlining a CPU and abort the online process > if the hotplugged CPU is incompatible with online CPUs. > > CPU hotplug is disabled during hardware_enable_all() to prevent the corner > case as shown below. A hotplugged CPU marks itself online in > cpu_online_mask (1) and enables interrupt (2) before invoking callbacks > registered in ONLINE section (3). So, if hardware_enable_all() is invoked > on another CPU right after (2), then on_each_cpu() in hardware_enable_all() > invokes hardware_enable_nolock() on the hotplugged CPU before > kvm_online_cpu() is called. This makes the CPU escape from compatibility > checks, which is risky. > > start_secondary { ... > set_cpu_online(smp_processor_id(), true); <- 1 > ... > local_irq_enable(); <- 2 > ... > cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); <- 3 > } > > Keep compatibility checks at KVM init time. It can help to find > incompatibility issues earlier and refuse to load arch KVM module > (e.g., kvm-intel). > > Loosen the WARN_ON in kvm_arch_check_processor_compat so that it > can be invoked from KVM's CPU hotplug callback (i.e., kvm_online_cpu). > > Opportunistically, add a pr_err() for setup_vmcs_config() path in > vmx_check_processor_compatibility() so that each possible error path has > its own error message. Convert printk(KERN_ERR ... to pr_err to please > checkpatch.pl > > Signed-off-by: Chao Gao <chao.gao@xxxxxxxxx> > --- Reviewed-by: Sean Christopherson <seanjc@xxxxxxxxxx>