History

KVM: Allow host IRQ sharing for assigned PCI 2.3 devices

PCI 2.3 allows to generically disable IRQ sources at device level. This enables us to share legacy IRQs of such devices with other host devices when passing them to a guest. The new IRQ sharing feature introduced here is optional, user space has to request it explicitly. Moreover, user space can inform us about its view of PCI_COMMAND_INTX_DISABLE so that we can avoid unmasking the interrupt and signaling it if the guest masked it via the virtualized PCI config space.

Jan Kiszka committed 14 years ago

Commit 07700a91 parent 3e515705 files · +230 −29Browse files

Showing the changes to virt (1 of 5 files). Show all

Unified · Split

virt/kvm/assigned-dev.c+180−29
@@ -55,22 +55,66 @@ static int find_index_from_host_irq(struct kvm_assigned_dev_kernel · 54 unmodified lines
5555 return index;
5656 }
5757
58−static irqreturn_t kvm_assigned_dev_thread(int irq, void *dev_id)
58+static irqreturn_t kvm_assigned_dev_intx(int irq, void *dev_id)
5959 {
6060 struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
61+ int ret;
6162
62− if (assigned_dev->irq_requested_type & KVM_DEV_IRQ_HOST_INTX) {
63− spin_lock(&assigned_dev->intx_lock);
63+ spin_lock(&assigned_dev->intx_lock);
64+ if (pci_check_and_mask_intx(assigned_dev->dev)) {
65+ assigned_dev->host_irq_disabled = true;
66+ ret = IRQ_WAKE_THREAD;
67+ } else
68+ ret = IRQ_NONE;
69+ spin_unlock(&assigned_dev->intx_lock);
70+
71+ return ret;
72+}
73+
74+static void
75+kvm_assigned_dev_raise_guest_irq(struct kvm_assigned_dev_kernel *assigned_dev,
76+ int vector)
77+{
78+ if (unlikely(assigned_dev->irq_requested_type &
79+ KVM_DEV_IRQ_GUEST_INTX)) {
80+ mutex_lock(&assigned_dev->intx_mask_lock);
81+ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX))
82+ kvm_set_irq(assigned_dev->kvm,
83+ assigned_dev->irq_source_id, vector, 1);
84+ mutex_unlock(&assigned_dev->intx_mask_lock);
85+ } else
86+ kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
87+ vector, 1);
88+}
89+
90+static irqreturn_t kvm_assigned_dev_thread_intx(int irq, void *dev_id)
91+{
92+ struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
93+
94+ if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
95+ spin_lock_irq(&assigned_dev->intx_lock);
6496 disable_irq_nosync(irq);
6597 assigned_dev->host_irq_disabled = true;
66− spin_unlock(&assigned_dev->intx_lock);
98+ spin_unlock_irq(&assigned_dev->intx_lock);
6799 }
68100
69− kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
70− assigned_dev->guest_irq, 1);
101+ kvm_assigned_dev_raise_guest_irq(assigned_dev,
102+ assigned_dev->guest_irq);
103+
104+ return IRQ_HANDLED;
105+}
106+
107+#ifdef __KVM_HAVE_MSI
108+static irqreturn_t kvm_assigned_dev_thread_msi(int irq, void *dev_id)
109+{
110+ struct kvm_assigned_dev_kernel *assigned_dev = dev_id;
111+
112+ kvm_assigned_dev_raise_guest_irq(assigned_dev,
113+ assigned_dev->guest_irq);
71114
72115 return IRQ_HANDLED;
73116 }
117+#endif
74118
75119 #ifdef __KVM_HAVE_MSIX
76120 static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id)
@@ -81,8 +125,7 @@ static irqreturn_t kvm_assigned_dev_thread_msix(int irq, void *dev_id) · 4 unmodified lines
81125
82126 if (index >= 0) {
83127 vector = assigned_dev->guest_msix_entries[index].vector;
84− kvm_set_irq(assigned_dev->kvm, assigned_dev->irq_source_id,
85− vector, 1);
128+ kvm_assigned_dev_raise_guest_irq(assigned_dev, vector);
86129 }
87130
88131 return IRQ_HANDLED;
@@ -98,15 +141,31 @@ static void kvm_assigned_dev_ack_irq(struct kvm_irq_ack_notifier *kian) · 9 unmodified lines
98141
99142 kvm_set_irq(dev->kvm, dev->irq_source_id, dev->guest_irq, 0);
100143
101− /* The guest irq may be shared so this ack may be
102− * from another device.
103− */
104− spin_lock(&dev->intx_lock);
105− if (dev->host_irq_disabled) {
106− enable_irq(dev->host_irq);
107− dev->host_irq_disabled = false;
144+ mutex_lock(&dev->intx_mask_lock);
145+
146+ if (!(dev->flags & KVM_DEV_ASSIGN_MASK_INTX)) {
147+ bool reassert = false;
148+
149+ spin_lock_irq(&dev->intx_lock);
150+ /*
151+ * The guest IRQ may be shared so this ack can come from an
152+ * IRQ for another guest device.
153+ */
154+ if (dev->host_irq_disabled) {
155+ if (!(dev->flags & KVM_DEV_ASSIGN_PCI_2_3))
156+ enable_irq(dev->host_irq);
157+ else if (!pci_check_and_unmask_intx(dev->dev))
158+ reassert = true;
159+ dev->host_irq_disabled = reassert;
160+ }
161+ spin_unlock_irq(&dev->intx_lock);
162+
163+ if (reassert)
164+ kvm_set_irq(dev->kvm, dev->irq_source_id,
165+ dev->guest_irq, 1);
108166 }
109− spin_unlock(&dev->intx_lock);
167+
168+ mutex_unlock(&dev->intx_mask_lock);
110169 }
111170
112171 static void deassign_guest_irq(struct kvm *kvm,
@@ -154,7 +213,15 @@ static void deassign_host_irq(struct kvm *kvm, · 41 unmodified lines
154213 pci_disable_msix(assigned_dev->dev);
155214 } else {
156215 /* Deal with MSI and INTx */
157− disable_irq(assigned_dev->host_irq);
216+ if ((assigned_dev->irq_requested_type &
217+ KVM_DEV_IRQ_HOST_INTX) &&
218+ (assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
219+ spin_lock_irq(&assigned_dev->intx_lock);
220+ pci_intx(assigned_dev->dev, false);
221+ spin_unlock_irq(&assigned_dev->intx_lock);
222+ synchronize_irq(assigned_dev->host_irq);
223+ } else
224+ disable_irq(assigned_dev->host_irq);
158225
159226 free_irq(assigned_dev->host_irq, assigned_dev);
160227
@@ -235,15 +302,34 @@ void kvm_free_all_assigned_devices(struct kvm *kvm) · 74 unmodified lines
235302 static int assigned_device_enable_host_intx(struct kvm *kvm,
236303 struct kvm_assigned_dev_kernel *dev)
237304 {
305+ irq_handler_t irq_handler;
306+ unsigned long flags;
307+
238308 dev->host_irq = dev->dev->irq;
239− /* Even though this is PCI, we don't want to use shared
240− * interrupts. Sharing host devices with guest-assigned devices
241− * on the same interrupt line is not a happy situation: there
242− * are going to be long delays in accepting, acking, etc.
309+
310+ /*
311+ * We can only share the IRQ line with other host devices if we are
312+ * able to disable the IRQ source at device-level - independently of
313+ * the guest driver. Otherwise host devices may suffer from unbounded
314+ * IRQ latencies when the guest keeps the line asserted.
243315 */
244− if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
245− IRQF_ONESHOT, dev->irq_name, dev))
316+ if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
317+ irq_handler = kvm_assigned_dev_intx;
318+ flags = IRQF_SHARED;
319+ } else {
320+ irq_handler = NULL;
321+ flags = IRQF_ONESHOT;
322+ }
323+ if (request_threaded_irq(dev->host_irq, irq_handler,
324+ kvm_assigned_dev_thread_intx, flags,
325+ dev->irq_name, dev))
246326 return -EIO;
327+
328+ if (dev->flags & KVM_DEV_ASSIGN_PCI_2_3) {
329+ spin_lock_irq(&dev->intx_lock);
330+ pci_intx(dev->dev, true);
331+ spin_unlock_irq(&dev->intx_lock);
332+ }
247333 return 0;
248334 }
249335
@@ -260,8 +346,9 @@ static int assigned_device_enable_host_msi(struct kvm *kvm, · 10 unmodified lines
260346 }
261347
262348 dev->host_irq = dev->dev->irq;
263− if (request_threaded_irq(dev->host_irq, NULL, kvm_assigned_dev_thread,
264− 0, dev->irq_name, dev)) {
349+ if (request_threaded_irq(dev->host_irq, NULL,
350+ kvm_assigned_dev_thread_msi, 0,
351+ dev->irq_name, dev)) {
265352 pci_disable_msi(dev->dev);
266353 return -EIO;
267354 }
@@ -319,7 +406,6 @@ static int assigned_device_enable_guest_msi(struct kvm *kvm, · 51 unmodified lines
319406 {
320407 dev->guest_irq = irq->guest_irq;
321408 dev->ack_notifier.gsi = -1;
322− dev->host_irq_disabled = false;
323409 return 0;
324410 }
325411 #endif
@@ -331,7 +417,6 @@ static int assigned_device_enable_guest_msix(struct kvm *kvm, · 5 unmodified lines
331417 {
332418 dev->guest_irq = irq->guest_irq;
333419 dev->ack_notifier.gsi = -1;
334− dev->host_irq_disabled = false;
335420 return 0;
336421 }
337422 #endif
@@ -365,6 +450,7 @@ static int assign_host_irq(struct kvm *kvm, · 27 unmodified lines
365450 default:
366451 r = -EINVAL;
367452 }
453+ dev->host_irq_disabled = false;
368454
369455 if (!r)
370456 dev->irq_requested_type |= host_irq_type;
@@ -466,6 +552,7 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm, · 95 unmodified lines
466552 {
467553 int r = -ENODEV;
468554 struct kvm_assigned_dev_kernel *match;
555+ unsigned long irq_type;
469556
470557 mutex_lock(&kvm->lock);
471558
@@ -474,7 +561,9 @@ static int kvm_vm_ioctl_deassign_dev_irq(struct kvm *kvm, · 2 unmodified lines
474561 if (!match)
475562 goto out;
476563
477− r = kvm_deassign_irq(kvm, match, assigned_irq->flags);
564+ irq_type = assigned_irq->flags & (KVM_DEV_IRQ_HOST_MASK |
565+ KVM_DEV_IRQ_GUEST_MASK);
566+ r = kvm_deassign_irq(kvm, match, irq_type);
478567 out:
479568 mutex_unlock(&kvm->lock);
480569 return r;
@@ -607,6 +696,10 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, · 126 unmodified lines
607696 if (!match->pci_saved_state)
608697 printk(KERN_DEBUG "%s: Couldn't store %s saved state\n",
609698 __func__, dev_name(&dev->dev));
699+
700+ if (!pci_intx_mask_supported(dev))
701+ assigned_dev->flags &= ~KVM_DEV_ASSIGN_PCI_2_3;
702+
610703 match->assigned_dev_id = assigned_dev->assigned_dev_id;
611704 match->host_segnr = assigned_dev->segnr;
612705 match->host_busnr = assigned_dev->busnr;
@@ -614,6 +707,7 @@ static int kvm_vm_ioctl_assign_device(struct kvm *kvm, · 1 unmodified line
614707 match->flags = assigned_dev->flags;
615708 match->dev = dev;
616709 spin_lock_init(&match->intx_lock);
710+ mutex_init(&match->intx_mask_lock);
617711 match->irq_source_id = -1;
618712 match->kvm = kvm;
619713 match->ack_notifier.irq_acked = kvm_assigned_dev_ack_irq;
@@ -759,6 +853,55 @@ msix_entry_out: · 139 unmodified lines
759853 }
760854 #endif
761855
856+static int kvm_vm_ioctl_set_pci_irq_mask(struct kvm *kvm,
857+ struct kvm_assigned_pci_dev *assigned_dev)
858+{
859+ int r = 0;
860+ struct kvm_assigned_dev_kernel *match;
861+
862+ mutex_lock(&kvm->lock);
863+
864+ match = kvm_find_assigned_dev(&kvm->arch.assigned_dev_head,
865+ assigned_dev->assigned_dev_id);
866+ if (!match) {
867+ r = -ENODEV;
868+ goto out;
869+ }
870+
871+ mutex_lock(&match->intx_mask_lock);
872+
873+ match->flags &= ~KVM_DEV_ASSIGN_MASK_INTX;
874+ match->flags |= assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX;
875+
876+ if (match->irq_requested_type & KVM_DEV_IRQ_GUEST_INTX) {
877+ if (assigned_dev->flags & KVM_DEV_ASSIGN_MASK_INTX) {
878+ kvm_set_irq(match->kvm, match->irq_source_id,
879+ match->guest_irq, 0);
880+ /*
881+ * Masking at hardware-level is performed on demand,
882+ * i.e. when an IRQ actually arrives at the host.
883+ */
884+ } else if (!(assigned_dev->flags & KVM_DEV_ASSIGN_PCI_2_3)) {
885+ /*
886+ * Unmask the IRQ line if required. Unmasking at
887+ * device level will be performed by user space.
888+ */
889+ spin_lock_irq(&match->intx_lock);
890+ if (match->host_irq_disabled) {
891+ enable_irq(match->host_irq);
892+ match->host_irq_disabled = false;
893+ }
894+ spin_unlock_irq(&match->intx_lock);
895+ }
896+ }
897+
898+ mutex_unlock(&match->intx_mask_lock);
899+
900+out:
901+ mutex_unlock(&kvm->lock);
902+ return r;
903+}
904+
762905 long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl,
763906 unsigned long arg)
764907 {
@@ -866,6 +1009,15 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, · 101 unmodified lines
8661009 break;
8671010 }
8681011 #endif
1012+ case KVM_ASSIGN_SET_INTX_MASK: {
1013+ struct kvm_assigned_pci_dev assigned_dev;
1014+
1015+ r = -EFAULT;
1016+ if (copy_from_user(&assigned_dev, argp, sizeof assigned_dev))
1017+ goto out;
1018+ r = kvm_vm_ioctl_set_pci_irq_mask(kvm, &assigned_dev);
1019+ break;
1020+ }
8691021 default:
8701022 r = -ENOTTY;
8711023 break;
@@ -873,4 +1025,3 @@ long kvm_vm_ioctl_assigned_device(struct kvm *kvm, unsigned ioctl, · 1 unmodified line
8731025 out:
8741026 return r;
8751027 }
876−

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t