KVM: arm64: Restore GICv2-on-GICv3 functionality
authorMarc Zyngier <maz@kernel.org>
Wed, 7 Jun 2023 14:38:44 +0000 (15:38 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 28 Jun 2023 09:12:40 +0000 (11:12 +0200)
commit 1caa71a7a600f7781ce05ef1e84701c459653663 upstream.

When reworking the vgic locking, the vgic distributor registration
got simplified, which was a very good cleanup. But just a tad too
radical, as we now register the *native* vgic only, ignoring the
GICv2-on-GICv3 that allows pre-historic VMs (or so I thought)
to run.

As it turns out, QEMU still defaults to GICv2 in some cases, and
this breaks Nathan's setup!

Fix it by propagating the *requested* vgic type rather than the
host's version.

Fixes: 59112e9c390b ("KVM: arm64: vgic: Fix a circular locking issue")
Reported-by: Nathan Chancellor <nathan@kernel.org>
Tested-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Marc Zyngier <maz@kernel.org>
link: https://lore.kernel.org/r/20230606221525.GA2269598@dev-arch.thelio-3990X
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/arm64/kvm/vgic/vgic-init.c

index 37e74ca4dad8585ed710b96b150953fad444d303..f2f3bf4a04b0b2e873cfd01aa618d6a19cedca17 100644 (file)
@@ -446,6 +446,7 @@ int vgic_lazy_init(struct kvm *kvm)
 int kvm_vgic_map_resources(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
+       enum vgic_type type;
        gpa_t dist_base;
        int ret = 0;
 
@@ -460,10 +461,13 @@ int kvm_vgic_map_resources(struct kvm *kvm)
        if (!irqchip_in_kernel(kvm))
                goto out;
 
-       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2)
+       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
                ret = vgic_v2_map_resources(kvm);
-       else
+               type = VGIC_V2;
+       } else {
                ret = vgic_v3_map_resources(kvm);
+               type = VGIC_V3;
+       }
 
        if (ret) {
                __kvm_vgic_destroy(kvm);
@@ -473,8 +477,7 @@ int kvm_vgic_map_resources(struct kvm *kvm)
        dist_base = dist->vgic_dist_base;
        mutex_unlock(&kvm->arch.config_lock);
 
-       ret = vgic_register_dist_iodev(kvm, dist_base,
-                                      kvm_vgic_global_state.type);
+       ret = vgic_register_dist_iodev(kvm, dist_base, type);
        if (ret) {
                kvm_err("Unable to register VGIC dist MMIO regions\n");
                kvm_vgic_destroy(kvm);