kvm: arm/arm64: Fix locking for kvm_free_stage2_pgd
commit 8b3405e345b5a098101b0c31b264c812bba045d9 upstream. 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 d5d8184d35c9 ("KVM: ARM: Memory virtualization setup") Cc: Paolo Bonzini <pbonzin@redhat.com> Cc: Marc Zyngier <marc.zyngier@arm.com> Cc: Christoffer Dall <christoffer.dall@linaro.org> Cc: Mark Rutland <mark.rutland@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> [ Avoid vCPU starvation and lockup detector warnings ] Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> Signed-off-by: Christoffer Dall <cdall@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
e2587fba99
commit
2a60bb6352
@ -300,6 +300,14 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
|
||||
next = kvm_pgd_addr_end(addr, end);
|
||||
if (!pgd_none(*pgd))
|
||||
unmap_puds(kvm, pgd, addr, next);
|
||||
/*
|
||||
* If we are dealing with a large range in
|
||||
* stage2 table, release the kvm->mmu_lock
|
||||
* to prevent starvation and lockup detector
|
||||
* warnings.
|
||||
*/
|
||||
if (kvm && (next != end))
|
||||
cond_resched_lock(&kvm->mmu_lock);
|
||||
} while (pgd++, addr = next, addr != end);
|
||||
}
|
||||
|
||||
@ -738,6 +746,7 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
|
||||
*/
|
||||
static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
|
||||
{
|
||||
assert_spin_locked(&kvm->mmu_lock);
|
||||
unmap_range(kvm, kvm->arch.pgd, start, size);
|
||||
}
|
||||
|
||||
@ -824,7 +833,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
|
||||
if (kvm->arch.pgd == NULL)
|
||||
return;
|
||||
|
||||
spin_lock(&kvm->mmu_lock);
|
||||
unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
|
||||
spin_unlock(&kvm->mmu_lock);
|
||||
|
||||
kvm_free_hwpgd(kvm_get_hwpgd(kvm));
|
||||
if (KVM_PREALLOC_LEVEL > 0)
|
||||
kfree(kvm->arch.pgd);
|
||||
|
Loading…
x
Reference in New Issue
Block a user