aboutsummaryrefslogtreecommitdiffstats
path: root/virt/kvm/kvm_main.c
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2009-06-04 14:08:24 -0400
committerAvi Kivity <avi@redhat.com>2009-09-10 01:32:49 -0400
commitfa40a8214bb9bcae8d49c234c19d8b4a6c1f37ff (patch)
tree6449f27072f128a1c39faaaeef1787f754345aaf /virt/kvm/kvm_main.c
parent60eead79ad8750f80384cbe48fc44edcc78a0305 (diff)
KVM: switch irq injection/acking data structures to irq_lock
Protect irq injection/acking data structures with a separate irq_lock mutex. This fixes the following deadlock: CPU A CPU B kvm_vm_ioctl_deassign_dev_irq() mutex_lock(&kvm->lock); worker_thread() -> kvm_deassign_irq() -> kvm_assigned_dev_interrupt_work_handler() -> deassign_host_irq() mutex_lock(&kvm->lock); -> cancel_work_sync() [blocked] [gleb: fix ia64 path] Reported-by: Alex Williamson <alex.williamson@hp.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com> Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Avi Kivity <avi@redhat.com>
Diffstat (limited to 'virt/kvm/kvm_main.c')
-rw-r--r--virt/kvm/kvm_main.c16
1 files changed, 9 insertions, 7 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d47e660fb709..0d481b282448 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -62,6 +62,12 @@
62MODULE_AUTHOR("Qumranet"); 62MODULE_AUTHOR("Qumranet");
63MODULE_LICENSE("GPL"); 63MODULE_LICENSE("GPL");
64 64
65/*
66 * Ordering of locks:
67 *
68 * kvm->lock --> kvm->irq_lock
69 */
70
65DEFINE_SPINLOCK(kvm_lock); 71DEFINE_SPINLOCK(kvm_lock);
66LIST_HEAD(vm_list); 72LIST_HEAD(vm_list);
67 73
@@ -126,11 +132,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
126 interrupt_work); 132 interrupt_work);
127 kvm = assigned_dev->kvm; 133 kvm = assigned_dev->kvm;
128 134
129 /* This is taken to safely inject irq inside the guest. When 135 mutex_lock(&kvm->irq_lock);
130 * the interrupt injection (or the ioapic code) uses a
131 * finer-grained lock, update this
132 */
133 mutex_lock(&kvm->lock);
134 spin_lock_irq(&assigned_dev->assigned_dev_lock); 136 spin_lock_irq(&assigned_dev->assigned_dev_lock);
135 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) { 137 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
136 struct kvm_guest_msix_entry *guest_entries = 138 struct kvm_guest_msix_entry *guest_entries =
@@ -149,7 +151,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
149 assigned_dev->guest_irq, 1); 151 assigned_dev->guest_irq, 1);
150 152
151 spin_unlock_irq(&assigned_dev->assigned_dev_lock); 153 spin_unlock_irq(&assigned_dev->assigned_dev_lock);
152 mutex_unlock(&assigned_dev->kvm->lock); 154 mutex_unlock(&assigned_dev->kvm->irq_lock);
153} 155}
154 156
155static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id) 157static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
@@ -207,7 +209,7 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
207static void deassign_guest_irq(struct kvm *kvm, 209static void deassign_guest_irq(struct kvm *kvm,
208 struct kvm_assigned_dev_kernel *assigned_dev) 210 struct kvm_assigned_dev_kernel *assigned_dev)
209{ 211{
210 kvm_unregister_irq_ack_notifier(&assigned_dev->ack_notifier); 212 kvm_unregister_irq_ack_notifier(kvm, &assigned_dev->ack_notifier);
211 assigned_dev->ack_notifier.gsi = -1; 213 assigned_dev->ack_notifier.gsi = -1;
212 214
213 if (assigned_dev->irq_source_id != -1) 215 if (assigned_dev->irq_source_id != -1)