If I create a machine with more CPUs than KVM supports, but specify multiple accelerator options, QEMU will fall back to the next accelerator. This is great, because if I've explicitly specified multiple accelerators, I've told QEMU I'm fine with any of them being used to provide the machine I want.
When I create a machine with nested virtualization enabled, though, this doesn't happen. KVM often doesn't support it, but TCG always does. The nice thing to do would be for QEMU to fall back to TCG if KVM can't provide, like it does when too many CPUs are requested. This patch adjusts the behaviour to do that. This is very helpful for OS development scripts that run an OS in QEMU — I want everybody to be able to run the script, always with virtualization enabled because the OS requires it, but for it to take advantage of KVM acceleration when available. Signed-off-by: Alyssa Ross <[email protected]> --- hw/arm/virt.c | 6 ------ target/arm/kvm.c | 8 ++++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/hw/arm/virt.c b/hw/arm/virt.c index 7456614d05..0b63b2eac3 100644 --- a/hw/arm/virt.c +++ b/hw/arm/virt.c @@ -2372,12 +2372,6 @@ static void machvirt_init(MachineState *machine) exit(1); } - if (vms->virt && kvm_enabled() && !kvm_arm_el2_supported()) { - error_report("mach-virt: host kernel KVM does not support providing " - "Virtualization extensions to the guest CPU"); - exit(1); - } - if (vms->virt && !kvm_enabled() && !tcg_enabled() && !qtest_enabled()) { error_report("mach-virt: %s does not support providing " "Virtualization extensions to the guest CPU", diff --git a/target/arm/kvm.c b/target/arm/kvm.c index d4a68874b8..20dcc6a820 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -615,6 +615,14 @@ int kvm_arch_init(MachineState *ms, KVMState *s) ret = -EINVAL; } + if (object_property_find(OBJECT(ms), "virtualization") && + object_property_get_bool(OBJECT(ms), "virtualization", NULL) && + !kvm_arm_el2_supported()) { + error_report("Using ARM nested virtualization with KVM requires " + "a host kernel with KVM_CAP_ARM_EL2"); + ret = -EINVAL; + } + if (kvm_check_extension(s, KVM_CAP_ARM_NISV_TO_USER)) { if (kvm_vm_enable_cap(s, KVM_CAP_ARM_NISV_TO_USER, 0)) { error_report("Failed to enable KVM_CAP_ARM_NISV_TO_USER cap"); base-commit: ae56950eac7b61b1abf42003329ee0f3ce111711 -- 2.53.0
