aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSheng Yang <sheng@linux.intel.com>2008-11-24 01:32:57 -0500
committerAvi Kivity <avi@redhat.com>2008-12-31 09:55:02 -0500
commit5319c662522db8995ff9276ba9d80549c64b294a (patch)
tree9091de707ff40ec148fde7e06dae461a4b5c29de
parent6b9cc7fd469869bed38831c5adac3f59dc25eaf5 (diff)
KVM: MSI to INTx translate
Now we use MSI as default one, and translate MSI to INTx when guest need INTx rather than MSI. For legacy device, we provide support for non-sharing host IRQ. Provide a parameter msi2intx for this method. The value is true by default in x86 architecture. We can't guarantee this mode can work on every device, but for most of us tested, it works. If your device encounter some trouble with this mode, you can try set msi2intx modules parameter to 0. If the device is OK with msi2intx=0, then please report it to KVM mailing list or me. We may prepare a blacklist for the device that can't work in this mode. Signed-off-by: Sheng Yang <sheng@linux.intel.com> Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--virt/kvm/kvm_main.c70
1 files changed, 54 insertions, 16 deletions
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index bf36ae9ae7df..54d25e6f6d2d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -64,6 +64,9 @@
64MODULE_AUTHOR("Qumranet"); 64MODULE_AUTHOR("Qumranet");
65MODULE_LICENSE("GPL"); 65MODULE_LICENSE("GPL");
66 66
67static int msi2intx = 1;
68module_param(msi2intx, bool, 0);
69
67DEFINE_SPINLOCK(kvm_lock); 70DEFINE_SPINLOCK(kvm_lock);
68LIST_HEAD(vm_list); 71LIST_HEAD(vm_list);
69 72
@@ -250,7 +253,8 @@ static int assigned_device_update_intx(struct kvm *kvm,
250 return 0; 253 return 0;
251 254
252 if (irqchip_in_kernel(kvm)) { 255 if (irqchip_in_kernel(kvm)) {
253 if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) { 256 if (!msi2intx &&
257 adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) {
254 free_irq(adev->host_irq, (void *)kvm); 258 free_irq(adev->host_irq, (void *)kvm);
255 pci_disable_msi(adev->dev); 259 pci_disable_msi(adev->dev);
256 } 260 }
@@ -285,21 +289,33 @@ static int assigned_device_update_msi(struct kvm *kvm,
285{ 289{
286 int r; 290 int r;
287 291
288 /* x86 don't care upper address of guest msi message addr */ 292 if (airq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) {
289 adev->guest_msi.address_lo = airq->guest_msi.addr_lo; 293 /* x86 don't care upper address of guest msi message addr */
290 adev->guest_msi.data = airq->guest_msi.data; 294 adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_MSI;
291 adev->ack_notifier.gsi = -1; 295 adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_INTX;
296 adev->guest_msi.address_lo = airq->guest_msi.addr_lo;
297 adev->guest_msi.data = airq->guest_msi.data;
298 adev->ack_notifier.gsi = -1;
299 } else if (msi2intx) {
300 adev->irq_requested_type |= KVM_ASSIGNED_DEV_GUEST_INTX;
301 adev->irq_requested_type &= ~KVM_ASSIGNED_DEV_GUEST_MSI;
302 adev->guest_irq = airq->guest_irq;
303 adev->ack_notifier.gsi = airq->guest_irq;
304 }
292 305
293 if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI) 306 if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_MSI)
294 return 0; 307 return 0;
295 308
296 if (irqchip_in_kernel(kvm)) { 309 if (irqchip_in_kernel(kvm)) {
297 if (adev->irq_requested_type & KVM_ASSIGNED_DEV_HOST_INTX) 310 if (!msi2intx) {
298 free_irq(adev->host_irq, (void *)adev); 311 if (adev->irq_requested_type &
299 312 KVM_ASSIGNED_DEV_HOST_INTX)
300 r = pci_enable_msi(adev->dev); 313 free_irq(adev->host_irq, (void *)adev);
301 if (r) 314
302 return r; 315 r = pci_enable_msi(adev->dev);
316 if (r)
317 return r;
318 }
303 319
304 adev->host_irq = adev->dev->irq; 320 adev->host_irq = adev->dev->irq;
305 if (request_irq(adev->host_irq, kvm_assigned_dev_intr, 0, 321 if (request_irq(adev->host_irq, kvm_assigned_dev_intr, 0,
@@ -307,8 +323,10 @@ static int assigned_device_update_msi(struct kvm *kvm,
307 return -EIO; 323 return -EIO;
308 } 324 }
309 325
310 adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI | 326 if (!msi2intx)
311 KVM_ASSIGNED_DEV_HOST_MSI; 327 adev->irq_requested_type = KVM_ASSIGNED_DEV_GUEST_MSI;
328
329 adev->irq_requested_type |= KVM_ASSIGNED_DEV_HOST_MSI;
312 return 0; 330 return 0;
313} 331}
314#endif 332#endif
@@ -346,10 +364,19 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
346 goto out_release; 364 goto out_release;
347 else 365 else
348 match->irq_source_id = r; 366 match->irq_source_id = r;
367
368#ifdef CONFIG_X86
369 /* Determine host device irq type, we can know the
370 * result from dev->msi_enabled */
371 if (msi2intx)
372 pci_enable_msi(match->dev);
373#endif
349 } 374 }
350 } 375 }
351 376
352 if (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI) { 377 if ((!msi2intx &&
378 (assigned_irq->flags & KVM_DEV_IRQ_ASSIGN_ENABLE_MSI)) ||
379 (msi2intx && match->dev->msi_enabled)) {
353#ifdef CONFIG_X86 380#ifdef CONFIG_X86
354 r = assigned_device_update_msi(kvm, match, assigned_irq); 381 r = assigned_device_update_msi(kvm, match, assigned_irq);
355 if (r) { 382 if (r) {
@@ -362,8 +389,16 @@ static int kvm_vm_ioctl_assign_irq(struct kvm *kvm,
362#endif 389#endif
363 } else if (assigned_irq->host_irq == 0 && match->dev->irq == 0) { 390 } else if (assigned_irq->host_irq == 0 && match->dev->irq == 0) {
364 /* Host device IRQ 0 means don't support INTx */ 391 /* Host device IRQ 0 means don't support INTx */
365 printk(KERN_WARNING "kvm: wait device to enable MSI!\n"); 392 if (!msi2intx) {
366 r = 0; 393 printk(KERN_WARNING
394 "kvm: wait device to enable MSI!\n");
395 r = 0;
396 } else {
397 printk(KERN_WARNING
398 "kvm: failed to enable MSI device!\n");
399 r = -ENOTTY;
400 goto out_release;
401 }
367 } else { 402 } else {
368 /* Non-sharing INTx mode */ 403 /* Non-sharing INTx mode */
369 r = assigned_device_update_intx(kvm, match, assigned_irq); 404 r = assigned_device_update_intx(kvm, match, assigned_irq);
@@ -2209,6 +2244,9 @@ int kvm_init(void *opaque, unsigned int vcpu_size,
2209 2244
2210 kvm_preempt_ops.sched_in = kvm_sched_in; 2245 kvm_preempt_ops.sched_in = kvm_sched_in;
2211 kvm_preempt_ops.sched_out = kvm_sched_out; 2246 kvm_preempt_ops.sched_out = kvm_sched_out;
2247#ifndef CONFIG_X86
2248 msi2intx = 0;
2249#endif
2212 2250
2213 return 0; 2251 return 0;
2214 2252