kvm_vm_ioctl_deassign_dev_irq() would potentially recursively get kvm->lock, because it called kvm_deassigned_irq() which implicit hold kvm->lock by calling deassign_host_irq(). Fix it by move kvm_deassign_irq() out of critial region. And add the missing lock for deassign_guest_irq(). Reported-by: Alex Williamson <alex.williamson@xxxxxx> Signed-off-by: Sheng Yang <sheng@xxxxxxxxxxxxxxx> --- virt/kvm/kvm_main.c | 14 +++++++------- 1 files changed, 7 insertions(+), 7 deletions(-) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 4d00942..3c69655 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -215,6 +215,8 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian) static void deassign_guest_irq(struct kvm *kvm, struct kvm_assigned_dev_kernel *assigned_dev) { + mutex_lock(&kvm->lock); + kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier); assigned_dev->ack_notifier.gsi = -1; @@ -222,6 +224,8 @@ static void deassign_guest_irq(struct kvm *kvm, kvm_free_irq_source_id(kvm, assigned_dev->irq_source_id); assigned_dev->irq_source_id = -1; assigned_dev->irq_requested_type &= ~(KVM_DEV_IRQ_GUEST_MASK); + + mutex_unlock(&kvm->lock); } /* The function implicit hold kvm->lock mutex due to cancel_work_sync() */ @@ -558,20 +562,16 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm, struct kvm_assigned_irq *assigned_irq) { - int r = -ENODEV; struct kvm_assigned_dev_kernel *match; mutex_lock(&kvm->lock); - match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head, assigned_irq->assigned_dev_id); + mutex_unlock(&kvm->lock); if (!match) - goto out; + return -ENODEV; - r = kvm_deassign_irq(kvm, match, assigned_irq->flags); -out: - mutex_unlock(&kvm->lock); - return r; + return kvm_deassign_irq(kvm, match, assigned_irq->flags); } static int kvm_vm_ioctl_assign_device(struct kvm *kvm, -- 1.5.4.5 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html