diff options
author | Eric Auger <eric.auger@redhat.com> | 2017-10-27 10:28:32 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2017-11-06 11:20:19 -0500 |
commit | 47bbd31f740c4e693d01766f367ad3366fb49a6d (patch) | |
tree | 54bcec5711d5dd778f654e00949cf685b4148fc0 /virt | |
parent | 2412405b3141cfe943d05a28a2160187d45f1c9a (diff) |
KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
We want to reuse the core of the map/unmap functions for IRQ
forwarding. Let's move the computation of the hwirq in
kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
the host_irq is added to struct vgic_irq.
We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
handle as a parameter.
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/arch_timer.c | 24 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.c | 60 |
2 files changed, 46 insertions, 38 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index 4db54ff08d9e..4151250ce8da 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
@@ -817,9 +817,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) | |||
817 | { | 817 | { |
818 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; | 818 | struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu; |
819 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); | 819 | struct arch_timer_context *vtimer = vcpu_vtimer(vcpu); |
820 | struct irq_desc *desc; | ||
821 | struct irq_data *data; | ||
822 | int phys_irq; | ||
823 | int ret; | 820 | int ret; |
824 | 821 | ||
825 | if (timer->enabled) | 822 | if (timer->enabled) |
@@ -837,26 +834,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu) | |||
837 | return -EINVAL; | 834 | return -EINVAL; |
838 | } | 835 | } |
839 | 836 | ||
840 | /* | 837 | ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq); |
841 | * Find the physical IRQ number corresponding to the host_vtimer_irq | ||
842 | */ | ||
843 | desc = irq_to_desc(host_vtimer_irq); | ||
844 | if (!desc) { | ||
845 | kvm_err("%s: no interrupt descriptor\n", __func__); | ||
846 | return -EINVAL; | ||
847 | } | ||
848 | |||
849 | data = irq_desc_get_irq_data(desc); | ||
850 | while (data->parent_data) | ||
851 | data = data->parent_data; | ||
852 | |||
853 | phys_irq = data->hwirq; | ||
854 | |||
855 | /* | ||
856 | * Tell the VGIC that the virtual interrupt is tied to a | ||
857 | * physical interrupt. We do that once per VCPU. | ||
858 | */ | ||
859 | ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq); | ||
860 | if (ret) | 838 | if (ret) |
861 | return ret; | 839 | return ret; |
862 | 840 | ||
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c index e54ef2fdf73d..a05a5700910b 100644 --- a/virt/kvm/arm/vgic/vgic.c +++ b/virt/kvm/arm/vgic/vgic.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/kvm.h> | 17 | #include <linux/kvm.h> |
18 | #include <linux/kvm_host.h> | 18 | #include <linux/kvm_host.h> |
19 | #include <linux/list_sort.h> | 19 | #include <linux/list_sort.h> |
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/irq.h> | ||
20 | 22 | ||
21 | #include "vgic.h" | 23 | #include "vgic.h" |
22 | 24 | ||
@@ -409,25 +411,56 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid, | |||
409 | return 0; | 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 | unsigned long flags; | 450 | unsigned long flags; |
451 | int ret; | ||
416 | 452 | ||
417 | BUG_ON(!irq); | 453 | BUG_ON(!irq); |
418 | 454 | ||
419 | spin_lock_irqsave(&irq->irq_lock, flags); | 455 | spin_lock_irqsave(&irq->irq_lock, flags); |
420 | 456 | ret = kvm_vgic_map_irq(vcpu, irq, host_irq); | |
421 | irq->hw = true; | ||
422 | irq->hwintid = phys_irq; | ||
423 | |||
424 | spin_unlock_irqrestore(&irq->irq_lock, flags); | 457 | spin_unlock_irqrestore(&irq->irq_lock, flags); |
425 | vgic_put_irq(vcpu->kvm, irq); | 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 | struct vgic_irq *irq; | 465 | struct vgic_irq *irq; |
433 | unsigned long flags; | 466 | unsigned long flags; |
@@ -435,14 +468,11 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq) | |||
435 | if (!vgic_initialized(vcpu->kvm)) | 468 | if (!vgic_initialized(vcpu->kvm)) |
436 | return -EAGAIN; | 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 | BUG_ON(!irq); | 472 | BUG_ON(!irq); |
440 | 473 | ||
441 | spin_lock_irqsave(&irq->irq_lock, flags); | 474 | spin_lock_irqsave(&irq->irq_lock, flags); |
442 | 475 | kvm_vgic_unmap_irq(irq); | |
443 | irq->hw = false; | ||
444 | irq->hwintid = 0; | ||
445 | |||
446 | spin_unlock_irqrestore(&irq->irq_lock, flags); | 476 | spin_unlock_irqrestore(&irq->irq_lock, flags); |
447 | vgic_put_irq(vcpu->kvm, irq); | 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 | bool map_is_active; | 820 | bool map_is_active; |
791 | unsigned long flags; | 821 | unsigned long flags; |
792 | 822 | ||