On Wed, 11 Mar 2026 at 09:54, Alyssa Ross <[email protected]> wrote: > > 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; > + }
Looking a bit closer at this, it's a bit awkward that we're looking at a machine property in generic target/arm code. There is no guarantee that the machine is "virt" or that every KVM-supporting machine has a "virtualization" property, and the target/ code isn't really supposed to do board-specific stuff. The board-independent way to say "are we trying to enable EL2" is to look at the CPU property has_el2. But the CPU isn't created at this point, so it's too early to do that here. Similar things where the early accelerator code wants information from the board we have handled with a method in MachineClass, like get_physical_address_range. We could do that here, but maybe it's a bit over-engineered? IDK. There are other cases also where the virt board will error out for "KVM and some config we could do with TCG": * KVM + EL2 + GICv2 * KVM + EL2 + kernel-irqchip=off * KVM + GICv2 but host hardware doesn't support GICv2 emulation * KVM + GICv3 but host hardware doesn't support GICv3 emulation * KVM + MTE but host hardware/kernel doesn't support MTE The first two are "always fails", but if we're going to have a mechanism for "figure out in kvm_arch_init what KVM features the board is going to want to enable" then it might be nice to also be able to use it for the last 3. -- PMM
