]> git.proxmox.com Git - mirror_ubuntu-hirsute-kernel.git/commitdiff
KVM: arm64: Move double-checked lock to kvm_vgic_map_resources()
authorAlexandru Elisei <alexandru.elisei@arm.com>
Tue, 1 Dec 2020 15:01:55 +0000 (15:01 +0000)
committerMarc Zyngier <maz@kernel.org>
Wed, 23 Dec 2020 16:43:43 +0000 (16:43 +0000)
kvm_vgic_map_resources() is called when a VCPU if first run and it maps all
the VGIC MMIO regions. To prevent double-initialization, the VGIC uses the
ready variable to keep track of the state of resources and the global KVM
mutex to protect against concurrent accesses. After the lock is taken, the
variable is checked again in case another VCPU took the lock between the
current VCPU reading ready equals false and taking the lock.

The double-checked lock pattern is spread across four different functions:
in kvm_vcpu_first_run_init(), in kvm_vgic_map_resource() and in
vgic_{v2,v3}_map_resources(), which makes it hard to reason about and
introduces minor code duplication. Consolidate the checks in
kvm_vgic_map_resources(), where the lock is taken.

No functional change intended.

Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20201201150157.223625-4-alexandru.elisei@arm.com
arch/arm64/kvm/arm.c
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-v2.c
arch/arm64/kvm/vgic/vgic-v3.c

index e207e4541f55200703bf07644c90359db73b054a..ab782c480e9a56a58efc865bc9bd4cb6df6ba251 100644 (file)
@@ -580,11 +580,9 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
                 * Map the VGIC hardware resources before running a vcpu the
                 * first time on this VM.
                 */
-               if (unlikely(!vgic_ready(kvm))) {
-                       ret = kvm_vgic_map_resources(kvm);
-                       if (ret)
-                               return ret;
-               }
+               ret = kvm_vgic_map_resources(kvm);
+               if (ret)
+                       return ret;
        } else {
                /*
                 * Tell the rest of the code that there are userspace irqchip
index 32e32d67a127f0e7a3b59a4e5b36d1c9c124d7b9..a2f4d1c85f001cbd23f3951dc9204b2e14120851 100644 (file)
@@ -428,7 +428,13 @@ int kvm_vgic_map_resources(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
        int ret = 0;
 
+       if (likely(vgic_ready(kvm)))
+               return 0;
+
        mutex_lock(&kvm->lock);
+       if (vgic_ready(kvm))
+               goto out;
+
        if (!irqchip_in_kernel(kvm))
                goto out;
 
index ebf53a4e129630fef87b018021eb5f393baca16a..7f38c1a9363957048c2c91af7f2d37da587b1216 100644 (file)
@@ -306,9 +306,6 @@ int vgic_v2_map_resources(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
        int ret = 0;
 
-       if (vgic_ready(kvm))
-               goto out;
-
        if (IS_VGIC_ADDR_UNDEF(dist->vgic_dist_base) ||
            IS_VGIC_ADDR_UNDEF(dist->vgic_cpu_base)) {
                kvm_err("Need to set vgic cpu and dist addresses first\n");
index 9cdf39a94a635697257f15b727e8b2886547f15c..35029c5cb0f125a62aad210f321186eb6f33f110 100644 (file)
@@ -500,9 +500,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
        int ret = 0;
        int c;
 
-       if (vgic_ready(kvm))
-               goto out;
-
        kvm_for_each_vcpu(c, vcpu, kvm) {
                struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;