Skip to content

Commit 140768a

Browse files
committed
KVM: Acquire SCRU lock outside of irqfds.lock during assignment
Acquire SRCU outside of irqfds.lock so that the locking is symmetrical, and add a comment explaining why on earth KVM holds SRCU for so long. Tested-by: K Prateek Nayak <kprateek.nayak@amd.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/r/20250522235223.3178519-3-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 283ed50 commit 140768a

1 file changed

Lines changed: 16 additions & 3 deletions

File tree

virt/kvm/eventfd.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -394,6 +394,18 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
394394
*/
395395
init_waitqueue_func_entry(&irqfd->wait, irqfd_wakeup);
396396

397+
/*
398+
* Set the irqfd routing and add it to KVM's list before registering
399+
* the irqfd with the eventfd, so that the routing information is valid
400+
* and stays valid, e.g. if there are GSI routing changes, prior to
401+
* making the irqfd visible, i.e. before it might be signaled.
402+
*
403+
* Note, holding SRCU ensures a stable read of routing information, and
404+
* also prevents irqfd_shutdown() from freeing the irqfd before it's
405+
* fully initialized.
406+
*/
407+
idx = srcu_read_lock(&kvm->irq_srcu);
408+
397409
spin_lock_irq(&kvm->irqfds.lock);
398410

399411
ret = 0;
@@ -402,11 +414,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
402414
continue;
403415
/* This fd is used for another irq already. */
404416
ret = -EBUSY;
405-
spin_unlock_irq(&kvm->irqfds.lock);
406-
goto fail;
417+
goto fail_duplicate;
407418
}
408419

409-
idx = srcu_read_lock(&kvm->irq_srcu);
410420
irqfd_update(kvm, irqfd);
411421

412422
list_add_tail(&irqfd->list, &kvm->irqfds.items);
@@ -441,6 +451,9 @@ kvm_irqfd_assign(struct kvm *kvm, struct kvm_irqfd *args)
441451
srcu_read_unlock(&kvm->irq_srcu, idx);
442452
return 0;
443453

454+
fail_duplicate:
455+
spin_unlock_irq(&kvm->irqfds.lock);
456+
srcu_read_unlock(&kvm->irq_srcu, idx);
444457
fail:
445458
if (irqfd->resampler)
446459
irqfd_resampler_shutdown(irqfd);

0 commit comments

Comments
 (0)