mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-09-04 20:19:47 +08:00
KVM: arm64: Fix circular locking dependency
The rule inside kvm enforces that the vcpu->mutex is taken *inside* kvm->lock. The rule is violated by the pkvm_create_hyp_vm() which acquires the kvm->lock while already holding the vcpu->mutex lock from kvm_vcpu_ioctl(). Avoid the circular locking dependency altogether by protecting the hyp vm handle with the config_lock, much like we already do for other forms of VM-scoped data. Signed-off-by: Sebastian Ene <sebastianene@google.com> Cc: stable@vger.kernel.org Reviewed-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20240124091027.1477174-2-sebastianene@google.com
This commit is contained in:
parent
6613476e22
commit
10c02aad11
@ -101,6 +101,17 @@ void __init kvm_hyp_reserve(void)
|
|||||||
hyp_mem_base);
|
hyp_mem_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void __pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
||||||
|
{
|
||||||
|
if (host_kvm->arch.pkvm.handle) {
|
||||||
|
WARN_ON(kvm_call_hyp_nvhe(__pkvm_teardown_vm,
|
||||||
|
host_kvm->arch.pkvm.handle));
|
||||||
|
}
|
||||||
|
|
||||||
|
host_kvm->arch.pkvm.handle = 0;
|
||||||
|
free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Allocates and donates memory for hypervisor VM structs at EL2.
|
* Allocates and donates memory for hypervisor VM structs at EL2.
|
||||||
*
|
*
|
||||||
@ -181,7 +192,7 @@ static int __pkvm_create_hyp_vm(struct kvm *host_kvm)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
destroy_vm:
|
destroy_vm:
|
||||||
pkvm_destroy_hyp_vm(host_kvm);
|
__pkvm_destroy_hyp_vm(host_kvm);
|
||||||
return ret;
|
return ret;
|
||||||
free_vm:
|
free_vm:
|
||||||
free_pages_exact(hyp_vm, hyp_vm_sz);
|
free_pages_exact(hyp_vm, hyp_vm_sz);
|
||||||
@ -194,23 +205,19 @@ int pkvm_create_hyp_vm(struct kvm *host_kvm)
|
|||||||
{
|
{
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&host_kvm->lock);
|
mutex_lock(&host_kvm->arch.config_lock);
|
||||||
if (!host_kvm->arch.pkvm.handle)
|
if (!host_kvm->arch.pkvm.handle)
|
||||||
ret = __pkvm_create_hyp_vm(host_kvm);
|
ret = __pkvm_create_hyp_vm(host_kvm);
|
||||||
mutex_unlock(&host_kvm->lock);
|
mutex_unlock(&host_kvm->arch.config_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
void pkvm_destroy_hyp_vm(struct kvm *host_kvm)
|
||||||
{
|
{
|
||||||
if (host_kvm->arch.pkvm.handle) {
|
mutex_lock(&host_kvm->arch.config_lock);
|
||||||
WARN_ON(kvm_call_hyp_nvhe(__pkvm_teardown_vm,
|
__pkvm_destroy_hyp_vm(host_kvm);
|
||||||
host_kvm->arch.pkvm.handle));
|
mutex_unlock(&host_kvm->arch.config_lock);
|
||||||
}
|
|
||||||
|
|
||||||
host_kvm->arch.pkvm.handle = 0;
|
|
||||||
free_hyp_memcache(&host_kvm->arch.pkvm.teardown_mc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pkvm_init_host_vm(struct kvm *host_kvm)
|
int pkvm_init_host_vm(struct kvm *host_kvm)
|
||||||
|
Loading…
Reference in New Issue
Block a user