Skip to content

Commit

Permalink
KVM: arm64: Move double-checked lock to kvm_vgic_map_resources()
Browse files Browse the repository at this point in the history
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
  • Loading branch information
Alexandru Elisei authored and Marc Zyngier committed Dec 23, 2020
1 parent f16570b commit 1c91f06
Show file tree
Hide file tree
Showing 4 changed files with 9 additions and 11 deletions.
8 changes: 3 additions & 5 deletions arch/arm64/kvm/arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions arch/arm64/kvm/vgic/vgic-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
3 changes: 0 additions & 3 deletions arch/arm64/kvm/vgic/vgic-v2.c
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
3 changes: 0 additions & 3 deletions arch/arm64/kvm/vgic/vgic-v3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down

0 comments on commit 1c91f06

Please sign in to comment.