Skip to content

Commit f1fb088

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86: Take irqfds.lock when adding/deleting IRQ bypass producer
Take irqfds.lock when adding/deleting an IRQ bypass producer to ensure irqfd->producer isn't modified while kvm_irq_routing_update() is running. The only lock held when a producer is added/removed is irqbypass's mutex. Fixes: 8727688 ("KVM: x86: select IRQ_BYPASS_MANAGER") Cc: [email protected] Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent bcda70c commit f1fb088

File tree

1 file changed

+15
-2
lines changed

1 file changed

+15
-2
lines changed

arch/x86/kvm/x86.c

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13561,15 +13561,22 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
1356113561
{
1356213562
struct kvm_kernel_irqfd *irqfd =
1356313563
container_of(cons, struct kvm_kernel_irqfd, consumer);
13564+
struct kvm *kvm = irqfd->kvm;
1356413565
int ret;
1356513566

13566-
irqfd->producer = prod;
1356713567
kvm_arch_start_assignment(irqfd->kvm);
13568+
13569+
spin_lock_irq(&kvm->irqfds.lock);
13570+
irqfd->producer = prod;
13571+
1356813572
ret = kvm_x86_call(pi_update_irte)(irqfd->kvm,
1356913573
prod->irq, irqfd->gsi, 1);
1357013574
if (ret)
1357113575
kvm_arch_end_assignment(irqfd->kvm);
1357213576

13577+
spin_unlock_irq(&kvm->irqfds.lock);
13578+
13579+
1357313580
return ret;
1357413581
}
1357513582

@@ -13579,22 +13586,28 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
1357913586
int ret;
1358013587
struct kvm_kernel_irqfd *irqfd =
1358113588
container_of(cons, struct kvm_kernel_irqfd, consumer);
13589+
struct kvm *kvm = irqfd->kvm;
1358213590

1358313591
WARN_ON(irqfd->producer != prod);
13584-
irqfd->producer = NULL;
1358513592

1358613593
/*
1358713594
* When producer of consumer is unregistered, we change back to
1358813595
* remapped mode, so we can re-use the current implementation
1358913596
* when the irq is masked/disabled or the consumer side (KVM
1359013597
* int this case doesn't want to receive the interrupts.
1359113598
*/
13599+
spin_lock_irq(&kvm->irqfds.lock);
13600+
irqfd->producer = NULL;
13601+
1359213602
ret = kvm_x86_call(pi_update_irte)(irqfd->kvm,
1359313603
prod->irq, irqfd->gsi, 0);
1359413604
if (ret)
1359513605
printk(KERN_INFO "irq bypass consumer (token %p) unregistration"
1359613606
" fails: %d\n", irqfd->consumer.token, ret);
1359713607

13608+
spin_unlock_irq(&kvm->irqfds.lock);
13609+
13610+
1359813611
kvm_arch_end_assignment(irqfd->kvm);
1359913612
}
1360013613

0 commit comments

Comments
 (0)