Skip to content

Commit 8b3405e

Browse files
Suzuki K PouloseChristoffer Dall
authored andcommitted
kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd
In kvm_free_stage2_pgd() we don't hold the kvm->mmu_lock while calling unmap_stage2_range() on the entire memory range for the guest. This could cause problems with other callers (e.g, munmap on a memslot) trying to unmap a range. And since we have to unmap the entire Guest memory range holding a spinlock, make sure we yield the lock if necessary, after we unmap each PUD range. Fixes: commit d5d8184 ("KVM: ARM: Memory virtualization setup") Cc: [email protected] # v3.10+ Cc: Paolo Bonzini <[email protected]> Cc: Marc Zyngier <[email protected]> Cc: Christoffer Dall <[email protected]> Cc: Mark Rutland <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> [ Avoid vCPU starvation and lockup detector warnings ] Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Suzuki K Poulose <[email protected]> Signed-off-by: Christoffer Dall <[email protected]>
1 parent 72f3104 commit 8b3405e

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

arch/arm/kvm/mmu.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,11 +292,18 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
292292
phys_addr_t addr = start, end = start + size;
293293
phys_addr_t next;
294294

295+
assert_spin_locked(&kvm->mmu_lock);
295296
pgd = kvm->arch.pgd + stage2_pgd_index(addr);
296297
do {
297298
next = stage2_pgd_addr_end(addr, end);
298299
if (!stage2_pgd_none(*pgd))
299300
unmap_stage2_puds(kvm, pgd, addr, next);
301+
/*
302+
* If the range is too large, release the kvm->mmu_lock
303+
* to prevent starvation and lockup detector warnings.
304+
*/
305+
if (next != end)
306+
cond_resched_lock(&kvm->mmu_lock);
300307
} while (pgd++, addr = next, addr != end);
301308
}
302309

@@ -831,7 +838,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
831838
if (kvm->arch.pgd == NULL)
832839
return;
833840

841+
spin_lock(&kvm->mmu_lock);
834842
unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
843+
spin_unlock(&kvm->mmu_lock);
844+
835845
/* Free the HW pgd, one page at a time */
836846
free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
837847
kvm->arch.pgd = NULL;

0 commit comments

Comments
 (0)