diff options
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/kvm_main.c | 70 |
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 @@ | |||
64 | MODULE_AUTHOR("Qumranet"); | 64 | MODULE_AUTHOR("Qumranet"); |
65 | MODULE_LICENSE("GPL"); | 65 | MODULE_LICENSE("GPL"); |
66 | 66 | ||
67 | static int msi2intx = 1; | ||
68 | module_param(msi2intx, bool, 0); | ||
69 | |||
67 | DEFINE_SPINLOCK(kvm_lock); | 70 | DEFINE_SPINLOCK(kvm_lock); |
68 | LIST_HEAD(vm_list); | 71 | LIST_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 | ||