aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/kvm_host.h1
-rw-r--r--virt/kvm/kvm_main.c13
2 files changed, 13 insertions, 1 deletions
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 161816284192..aacc5449f586 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -345,6 +345,7 @@ struct kvm_assigned_dev_kernel {
345 int flags; 345 int flags;
346 struct pci_dev *dev; 346 struct pci_dev *dev;
347 struct kvm *kvm; 347 struct kvm *kvm;
348 spinlock_t assigned_dev_lock;
348}; 349};
349 350
350struct kvm_irq_mask_notifier { 351struct kvm_irq_mask_notifier {
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 29c0afb064da..687d113a3e5e 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -42,6 +42,7 @@
42#include <linux/mman.h> 42#include <linux/mman.h>
43#include <linux/swap.h> 43#include <linux/swap.h>
44#include <linux/bitops.h> 44#include <linux/bitops.h>
45#include <linux/spinlock.h>
45 46
46#include <asm/processor.h> 47#include <asm/processor.h>
47#include <asm/io.h> 48#include <asm/io.h>
@@ -130,6 +131,7 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
130 * finer-grained lock, update this 131 * finer-grained lock, update this
131 */ 132 */
132 mutex_lock(&kvm->lock); 133 mutex_lock(&kvm->lock);
134 spin_lock_irq(&assigned_dev->assigned_dev_lock);
133 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) { 135 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
134 struct kvm_guest_msix_entry *guest_entries = 136 struct kvm_guest_msix_entry *guest_entries =
135 assigned_dev->guest_msix_entries; 137 assigned_dev->guest_msix_entries;
@@ -156,18 +158,21 @@ static void kvm_assigned_dev_interrupt_work_handler(struct work_struct *work)
156 } 158 }
157 } 159 }
158 160
161 spin_unlock_irq(&assigned_dev->assigned_dev_lock);
159 mutex_unlock(&assigned_dev->kvm->lock); 162 mutex_unlock(&assigned_dev->kvm->lock);
160} 163}
161 164
162static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id) 165static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
163{ 166{
167 unsigned long flags;
164 struct kvm_assigned_dev_kernel *assigned_dev = 168 struct kvm_assigned_dev_kernel *assigned_dev =
165 (struct kvm_assigned_dev_kernel *) dev_id; 169 (struct kvm_assigned_dev_kernel *) dev_id;
166 170
171 spin_lock_irqsave(&assigned_dev->assigned_dev_lock, flags);
167 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) { 172 if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_MSIX) {
168 int index = find_index_from_host_irq(assigned_dev, irq); 173 int index = find_index_from_host_irq(assigned_dev, irq);
169 if (index < 0) 174 if (index < 0)
170 return IRQ_HANDLED; 175 goto out;
171 assigned_dev->guest_msix_entries[index].flags |= 176 assigned_dev->guest_msix_entries[index].flags |=
172 KVM_ASSIGNED_MSIX_PENDING; 177 KVM_ASSIGNED_MSIX_PENDING;
173 } 178 }
@@ -177,6 +182,8 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
177 disable_irq_nosync(irq); 182 disable_irq_nosync(irq);
178 assigned_dev->host_irq_disabled = true; 183 assigned_dev->host_irq_disabled = true;
179 184
185out:
186 spin_unlock_irqrestore(&assigned_dev->assigned_dev_lock, flags);
180 return IRQ_HANDLED; 187 return IRQ_HANDLED;
181} 188}
182 189
@@ -184,6 +191,7 @@ static irqreturn_t kvm_assigned_dev_intr(int irq, void *dev_id)
184static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian) 191static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
185{ 192{
186 struct kvm_assigned_dev_kernel *dev; 193 struct kvm_assigned_dev_kernel *dev;
194 unsigned long flags;
187 195
188 if (kian->gsi == -1) 196 if (kian->gsi == -1)
189 return; 197 return;
@@ -196,10 +204,12 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian)
196 /* The guest irq may be shared so this ack may be 204 /* The guest irq may be shared so this ack may be
197 * from another device. 205 * from another device.
198 */ 206 */
207 spin_lock_irqsave(&dev->assigned_dev_lock, flags);
199 if (dev->host_irq_disabled) { 208 if (dev->host_irq_disabled) {
200 enable_irq(dev->host_irq); 209 enable_irq(dev->host_irq);
201 dev->host_irq_disabled = false; 210 dev->host_irq_disabled = false;
202 } 211 }
212 spin_unlock_irqrestore(&dev->assigned_dev_lock, flags);
203} 213}
204 214
205static void deassign_guest_irq(struct kvm *kvm, 215static void deassign_guest_irq(struct kvm *kvm,
@@ -615,6 +625,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm,
615 match->host_devfn = assigned_dev->devfn; 625 match->host_devfn = assigned_dev->devfn;
616 match->flags = assigned_dev->flags; 626 match->flags = assigned_dev->flags;
617 match->dev = dev; 627 match->dev = dev;
628 spin_lock_init(&match->assigned_dev_lock);
618 match->irq_source_id = -1; 629 match->irq_source_id = -1;
619 match->kvm = kvm; 630 match->kvm = kvm;
620 match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq; 631 match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;