Skip to content

Commit b4886fa

Browse files
sean-jcbonzini
authored andcommitted
KVM: Add a module param to allow enabling virtualization when KVM is loaded
Add an on-by-default module param, enable_virt_at_load, to let userspace force virtualization to be enabled in hardware when KVM is initialized, i.e. just before /dev/kvm is exposed to userspace. Enabling virtualization during KVM initialization allows userspace to avoid the additional latency when creating/destroying the first/last VM (or more specifically, on the 0=>1 and 1=>0 edges of creation/destruction). Now that KVM uses the cpuhp framework to do per-CPU enabling, the latency could be non-trivial as the cpuhup bringup/teardown is serialized across CPUs, e.g. the latency could be problematic for use case that need to spin up VMs quickly. Prior to commit 10474ae ("KVM: Activate Virtualization On Demand"), KVM _unconditionally_ enabled virtualization during load, i.e. there's no fundamental reason KVM needs to dynamically toggle virtualization. These days, the only known argument for not enabling virtualization is to allow KVM to be autoloaded without blocking other out-of-tree hypervisors, and such use cases can simply change the module param, e.g. via command line. Note, the aforementioned commit also mentioned that enabling SVM (AMD's virtualization extensions) can result in "using invalid TLB entries". It's not clear whether the changelog was referring to a KVM bug, a CPU bug, or something else entirely. Regardless, leaving virtualization off by default is not a robust "fix", as any protection provided is lost the instant userspace creates the first VM. Reviewed-by: Chao Gao <[email protected]> Acked-by: Kai Huang <[email protected]> Reviewed-by: Kai Huang <[email protected]> Tested-by: Farrah Chen <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 0617a76 commit b4886fa

File tree

2 files changed

+52
-0
lines changed

2 files changed

+52
-0
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2648,6 +2648,23 @@
26482648

26492649
Default is Y (on).
26502650

2651+
kvm.enable_virt_at_load=[KVM,ARM64,LOONGARCH,MIPS,RISCV,X86]
2652+
If enabled, KVM will enable virtualization in hardware
2653+
when KVM is loaded, and disable virtualization when KVM
2654+
is unloaded (if KVM is built as a module).
2655+
2656+
If disabled, KVM will dynamically enable and disable
2657+
virtualization on-demand when creating and destroying
2658+
VMs, i.e. on the 0=>1 and 1=>0 transitions of the
2659+
number of VMs.
2660+
2661+
Enabling virtualization at module lode avoids potential
2662+
latency for creation of the 0=>1 VM, as KVM serializes
2663+
virtualization enabling across all online CPUs. The
2664+
"cost" of enabling virtualization when KVM is loaded,
2665+
is that doing so may interfere with using out-of-tree
2666+
hypervisors that want to "own" virtualization hardware.
2667+
26512668
kvm.enable_vmware_backdoor=[KVM] Support VMware backdoor PV interface.
26522669
Default is false (don't support).
26532670

virt/kvm/kvm_main.c

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5571,6 +5571,9 @@ static struct miscdevice kvm_dev = {
55715571
};
55725572

55735573
#ifdef CONFIG_KVM_GENERIC_HARDWARE_ENABLING
5574+
static bool enable_virt_at_load = true;
5575+
module_param(enable_virt_at_load, bool, 0444);
5576+
55745577
__visible bool kvm_rebooting;
55755578
EXPORT_SYMBOL_GPL(kvm_rebooting);
55765579

@@ -5721,15 +5724,39 @@ static void kvm_disable_virtualization(void)
57215724
unregister_syscore_ops(&kvm_syscore_ops);
57225725
cpuhp_remove_state(CPUHP_AP_KVM_ONLINE);
57235726
}
5727+
5728+
static int kvm_init_virtualization(void)
5729+
{
5730+
if (enable_virt_at_load)
5731+
return kvm_enable_virtualization();
5732+
5733+
return 0;
5734+
}
5735+
5736+
static void kvm_uninit_virtualization(void)
5737+
{
5738+
if (enable_virt_at_load)
5739+
kvm_disable_virtualization();
5740+
}
57245741
#else /* CONFIG_KVM_GENERIC_HARDWARE_ENABLING */
57255742
static int kvm_enable_virtualization(void)
57265743
{
57275744
return 0;
57285745
}
57295746

5747+
static int kvm_init_virtualization(void)
5748+
{
5749+
return 0;
5750+
}
5751+
57305752
static void kvm_disable_virtualization(void)
57315753
{
57325754

5755+
}
5756+
5757+
static void kvm_uninit_virtualization(void)
5758+
{
5759+
57335760
}
57345761
#endif /* CONFIG_KVM_GENERIC_HARDWARE_ENABLING */
57355762

@@ -6474,6 +6501,10 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
64746501

64756502
kvm_gmem_init(module);
64766503

6504+
r = kvm_init_virtualization();
6505+
if (r)
6506+
goto err_virt;
6507+
64776508
/*
64786509
* Registration _must_ be the very last thing done, as this exposes
64796510
* /dev/kvm to userspace, i.e. all infrastructure must be setup!
@@ -6487,6 +6518,8 @@ int kvm_init(unsigned vcpu_size, unsigned vcpu_align, struct module *module)
64876518
return 0;
64886519

64896520
err_register:
6521+
kvm_uninit_virtualization();
6522+
err_virt:
64906523
kvm_vfio_ops_exit();
64916524
err_vfio:
64926525
kvm_async_pf_deinit();
@@ -6512,6 +6545,8 @@ void kvm_exit(void)
65126545
*/
65136546
misc_deregister(&kvm_dev);
65146547

6548+
kvm_uninit_virtualization();
6549+
65156550
debugfs_remove_recursive(kvm_debugfs_dir);
65166551
for_each_possible_cpu(cpu)
65176552
free_cpumask_var(per_cpu(cpu_kick_mask, cpu));

0 commit comments

Comments
 (0)