mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
synced 2025-10-16 00:03:34 +10:00
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: 8727688006
("KVM: x86: select IRQ_BYPASS_MANAGER")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-ID: <20250404193923.1413163-5-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
bcda70c56f
commit
f1fb088d9c
@ -13561,15 +13561,22 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
|
||||
{
|
||||
struct kvm_kernel_irqfd *irqfd =
|
||||
container_of(cons, struct kvm_kernel_irqfd, consumer);
|
||||
struct kvm *kvm = irqfd->kvm;
|
||||
int ret;
|
||||
|
||||
irqfd->producer = prod;
|
||||
kvm_arch_start_assignment(irqfd->kvm);
|
||||
|
||||
spin_lock_irq(&kvm->irqfds.lock);
|
||||
irqfd->producer = prod;
|
||||
|
||||
ret = kvm_x86_call(pi_update_irte)(irqfd->kvm,
|
||||
prod->irq, irqfd->gsi, 1);
|
||||
if (ret)
|
||||
kvm_arch_end_assignment(irqfd->kvm);
|
||||
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -13579,9 +13586,9 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
|
||||
int ret;
|
||||
struct kvm_kernel_irqfd *irqfd =
|
||||
container_of(cons, struct kvm_kernel_irqfd, consumer);
|
||||
struct kvm *kvm = irqfd->kvm;
|
||||
|
||||
WARN_ON(irqfd->producer != prod);
|
||||
irqfd->producer = NULL;
|
||||
|
||||
/*
|
||||
* When producer of consumer is unregistered, we change back to
|
||||
@ -13589,12 +13596,18 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
|
||||
* when the irq is masked/disabled or the consumer side (KVM
|
||||
* int this case doesn't want to receive the interrupts.
|
||||
*/
|
||||
spin_lock_irq(&kvm->irqfds.lock);
|
||||
irqfd->producer = NULL;
|
||||
|
||||
ret = kvm_x86_call(pi_update_irte)(irqfd->kvm,
|
||||
prod->irq, irqfd->gsi, 0);
|
||||
if (ret)
|
||||
printk(KERN_INFO "irq bypass consumer (token %p) unregistration"
|
||||
" fails: %d\n", irqfd->consumer.token, ret);
|
||||
|
||||
spin_unlock_irq(&kvm->irqfds.lock);
|
||||
|
||||
|
||||
kvm_arch_end_assignment(irqfd->kvm);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user