diff options
author | Eric Auger <eric.auger@linaro.org> | 2015-03-04 05:14:36 -0500 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2015-03-12 10:15:34 -0400 |
commit | 174178fed338edba66ab9580af0c5d9e1a4e5019 (patch) | |
tree | c290d6b6ae1464dd7dc72bfe63e0bb0553eac460 /virt | |
parent | 649cf73994e8ac69dfe3e7a35fba9acf051e7fe6 (diff) |
KVM: arm/arm64: add irqfd support
This patch enables irqfd on arm/arm64.
Both irqfd and resamplefd are supported. Injection is implemented
in vgic.c without routing.
This patch enables CONFIG_HAVE_KVM_EVENTFD and CONFIG_HAVE_KVM_IRQFD.
KVM_CAP_IRQFD is now advertised. KVM_CAP_IRQFD_RESAMPLE capability
automatically is advertised as soon as CONFIG_HAVE_KVM_IRQFD is set.
Irqfd injection is restricted to SPI. The rationale behind not
supporting PPI irqfd injection is that any device using a PPI would
be a private-to-the-CPU device (timer for instance), so its state
would have to be context-switched along with the VCPU and would
require in-kernel wiring anyhow. It is not a relevant use case for
irqfds.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-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/vgic.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index 897c849305db..c000e978c1fb 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
@@ -31,6 +31,7 @@ | |||
31 | #include <asm/kvm_emulate.h> | 31 | #include <asm/kvm_emulate.h> |
32 | #include <asm/kvm_arm.h> | 32 | #include <asm/kvm_arm.h> |
33 | #include <asm/kvm_mmu.h> | 33 | #include <asm/kvm_mmu.h> |
34 | #include <trace/events/kvm.h> | ||
34 | 35 | ||
35 | /* | 36 | /* |
36 | * How the whole thing works (courtesy of Christoffer Dall): | 37 | * How the whole thing works (courtesy of Christoffer Dall): |
@@ -1083,6 +1084,7 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | |||
1083 | u32 status = vgic_get_interrupt_status(vcpu); | 1084 | u32 status = vgic_get_interrupt_status(vcpu); |
1084 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; | 1085 | struct vgic_dist *dist = &vcpu->kvm->arch.vgic; |
1085 | bool level_pending = false; | 1086 | bool level_pending = false; |
1087 | struct kvm *kvm = vcpu->kvm; | ||
1086 | 1088 | ||
1087 | kvm_debug("STATUS = %08x\n", status); | 1089 | kvm_debug("STATUS = %08x\n", status); |
1088 | 1090 | ||
@@ -1118,6 +1120,17 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu) | |||
1118 | */ | 1120 | */ |
1119 | vgic_dist_irq_clear_soft_pend(vcpu, vlr.irq); | 1121 | vgic_dist_irq_clear_soft_pend(vcpu, vlr.irq); |
1120 | 1122 | ||
1123 | /* | ||
1124 | * kvm_notify_acked_irq calls kvm_set_irq() | ||
1125 | * to reset the IRQ level. Need to release the | ||
1126 | * lock for kvm_set_irq to grab it. | ||
1127 | */ | ||
1128 | spin_unlock(&dist->lock); | ||
1129 | |||
1130 | kvm_notify_acked_irq(kvm, 0, | ||
1131 | vlr.irq - VGIC_NR_PRIVATE_IRQS); | ||
1132 | spin_lock(&dist->lock); | ||
1133 | |||
1121 | /* Any additional pending interrupt? */ | 1134 | /* Any additional pending interrupt? */ |
1122 | if (vgic_dist_irq_get_level(vcpu, vlr.irq)) { | 1135 | if (vgic_dist_irq_get_level(vcpu, vlr.irq)) { |
1123 | vgic_cpu_irq_set(vcpu, vlr.irq); | 1136 | vgic_cpu_irq_set(vcpu, vlr.irq); |
@@ -1913,3 +1926,38 @@ out_free_irq: | |||
1913 | free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus()); | 1926 | free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus()); |
1914 | return ret; | 1927 | return ret; |
1915 | } | 1928 | } |
1929 | |||
1930 | int kvm_irq_map_gsi(struct kvm *kvm, | ||
1931 | struct kvm_kernel_irq_routing_entry *entries, | ||
1932 | int gsi) | ||
1933 | { | ||
1934 | return gsi; | ||
1935 | } | ||
1936 | |||
1937 | int kvm_irq_map_chip_pin(struct kvm *kvm, unsigned irqchip, unsigned pin) | ||
1938 | { | ||
1939 | return pin; | ||
1940 | } | ||
1941 | |||
1942 | int kvm_set_irq(struct kvm *kvm, int irq_source_id, | ||
1943 | u32 irq, int level, bool line_status) | ||
1944 | { | ||
1945 | unsigned int spi = irq + VGIC_NR_PRIVATE_IRQS; | ||
1946 | |||
1947 | trace_kvm_set_irq(irq, level, irq_source_id); | ||
1948 | |||
1949 | BUG_ON(!vgic_initialized(kvm)); | ||
1950 | |||
1951 | if (spi > kvm->arch.vgic.nr_irqs) | ||
1952 | return -EINVAL; | ||
1953 | return kvm_vgic_inject_irq(kvm, 0, spi, level); | ||
1954 | |||
1955 | } | ||
1956 | |||
1957 | /* MSI not implemented yet */ | ||
1958 | int kvm_set_msi(struct kvm_kernel_irq_routing_entry *e, | ||
1959 | struct kvm *kvm, int irq_source_id, | ||
1960 | int level, bool line_status) | ||
1961 | { | ||
1962 | return 0; | ||
1963 | } | ||