|
17 | 17 | #include <linux/kvm.h>
|
18 | 18 | #include <linux/kvm_host.h>
|
19 | 19 | #include <linux/list_sort.h>
|
| 20 | +#include <linux/interrupt.h> |
| 21 | +#include <linux/irq.h> |
20 | 22 |
|
21 | 23 | #include "vgic.h"
|
22 | 24 |
|
@@ -409,40 +411,68 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
|
409 | 411 | return 0;
|
410 | 412 | }
|
411 | 413 |
|
412 |
| -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq) |
| 414 | +/* @irq->irq_lock must be held */ |
| 415 | +static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq, |
| 416 | + unsigned int host_irq) |
413 | 417 | {
|
414 |
| - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); |
| 418 | + struct irq_desc *desc; |
| 419 | + struct irq_data *data; |
| 420 | + |
| 421 | + /* |
| 422 | + * Find the physical IRQ number corresponding to @host_irq |
| 423 | + */ |
| 424 | + desc = irq_to_desc(host_irq); |
| 425 | + if (!desc) { |
| 426 | + kvm_err("%s: no interrupt descriptor\n", __func__); |
| 427 | + return -EINVAL; |
| 428 | + } |
| 429 | + data = irq_desc_get_irq_data(desc); |
| 430 | + while (data->parent_data) |
| 431 | + data = data->parent_data; |
| 432 | + |
| 433 | + irq->hw = true; |
| 434 | + irq->host_irq = host_irq; |
| 435 | + irq->hwintid = data->hwirq; |
| 436 | + return 0; |
| 437 | +} |
| 438 | + |
| 439 | +/* @irq->irq_lock must be held */ |
| 440 | +static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq) |
| 441 | +{ |
| 442 | + irq->hw = false; |
| 443 | + irq->hwintid = 0; |
| 444 | +} |
| 445 | + |
| 446 | +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq, |
| 447 | + u32 vintid) |
| 448 | +{ |
| 449 | + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); |
415 | 450 | unsigned long flags;
|
| 451 | + int ret; |
416 | 452 |
|
417 | 453 | BUG_ON(!irq);
|
418 | 454 |
|
419 | 455 | spin_lock_irqsave(&irq->irq_lock, flags);
|
420 |
| - |
421 |
| - irq->hw = true; |
422 |
| - irq->hwintid = phys_irq; |
423 |
| - |
| 456 | + ret = kvm_vgic_map_irq(vcpu, irq, host_irq); |
424 | 457 | spin_unlock_irqrestore(&irq->irq_lock, flags);
|
425 | 458 | vgic_put_irq(vcpu->kvm, irq);
|
426 | 459 |
|
427 |
| - return 0; |
| 460 | + return ret; |
428 | 461 | }
|
429 | 462 |
|
430 |
| -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq) |
| 463 | +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid) |
431 | 464 | {
|
432 | 465 | struct vgic_irq *irq;
|
433 | 466 | unsigned long flags;
|
434 | 467 |
|
435 | 468 | if (!vgic_initialized(vcpu->kvm))
|
436 | 469 | return -EAGAIN;
|
437 | 470 |
|
438 |
| - irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); |
| 471 | + irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); |
439 | 472 | BUG_ON(!irq);
|
440 | 473 |
|
441 | 474 | spin_lock_irqsave(&irq->irq_lock, flags);
|
442 |
| - |
443 |
| - irq->hw = false; |
444 |
| - irq->hwintid = 0; |
445 |
| - |
| 475 | + kvm_vgic_unmap_irq(irq); |
446 | 476 | spin_unlock_irqrestore(&irq->irq_lock, flags);
|
447 | 477 | vgic_put_irq(vcpu->kvm, irq);
|
448 | 478 |
|
@@ -784,9 +814,9 @@ void vgic_kick_vcpus(struct kvm *kvm)
|
784 | 814 | }
|
785 | 815 | }
|
786 | 816 |
|
787 |
| -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq) |
| 817 | +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid) |
788 | 818 | {
|
789 |
| - struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq); |
| 819 | + struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid); |
790 | 820 | bool map_is_active;
|
791 | 821 | unsigned long flags;
|
792 | 822 |
|
|
0 commit comments