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 | |
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>
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 6 | ||||
-rw-r--r-- | arch/arm/include/uapi/asm/kvm.h | 3 | ||||
-rw-r--r-- | arch/arm/kvm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm/kvm/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/kvm/arm.c | 1 | ||||
-rw-r--r-- | arch/arm64/include/uapi/asm/kvm.h | 3 | ||||
-rw-r--r-- | arch/arm64/kvm/Kconfig | 2 | ||||
-rw-r--r-- | arch/arm64/kvm/Makefile | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic.c | 48 |
9 files changed, 66 insertions, 3 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index b112efc816f1..b265d8e50be0 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -2234,7 +2234,7 @@ into the hash PTE second double word). | |||
2234 | 4.75 KVM_IRQFD | 2234 | 4.75 KVM_IRQFD |
2235 | 2235 | ||
2236 | Capability: KVM_CAP_IRQFD | 2236 | Capability: KVM_CAP_IRQFD |
2237 | Architectures: x86 s390 | 2237 | Architectures: x86 s390 arm arm64 |
2238 | Type: vm ioctl | 2238 | Type: vm ioctl |
2239 | Parameters: struct kvm_irqfd (in) | 2239 | Parameters: struct kvm_irqfd (in) |
2240 | Returns: 0 on success, -1 on error | 2240 | Returns: 0 on success, -1 on error |
@@ -2260,6 +2260,10 @@ Note that closing the resamplefd is not sufficient to disable the | |||
2260 | irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment | 2260 | irqfd. The KVM_IRQFD_FLAG_RESAMPLE is only necessary on assignment |
2261 | and need not be specified with KVM_IRQFD_FLAG_DEASSIGN. | 2261 | and need not be specified with KVM_IRQFD_FLAG_DEASSIGN. |
2262 | 2262 | ||
2263 | On ARM/ARM64, the gsi field in the kvm_irqfd struct specifies the Shared | ||
2264 | Peripheral Interrupt (SPI) index, such that the GIC interrupt ID is | ||
2265 | given by gsi + 32. | ||
2266 | |||
2263 | 4.76 KVM_PPC_ALLOCATE_HTAB | 2267 | 4.76 KVM_PPC_ALLOCATE_HTAB |
2264 | 2268 | ||
2265 | Capability: KVM_CAP_PPC_ALLOC_HTAB | 2269 | Capability: KVM_CAP_PPC_ALLOC_HTAB |
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 0db25bc32864..2499867dd0d8 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h | |||
@@ -198,6 +198,9 @@ struct kvm_arch_memory_slot { | |||
198 | /* Highest supported SPI, from VGIC_NR_IRQS */ | 198 | /* Highest supported SPI, from VGIC_NR_IRQS */ |
199 | #define KVM_ARM_IRQ_GIC_MAX 127 | 199 | #define KVM_ARM_IRQ_GIC_MAX 127 |
200 | 200 | ||
201 | /* One single KVM irqchip, ie. the VGIC */ | ||
202 | #define KVM_NR_IRQCHIPS 1 | ||
203 | |||
201 | /* PSCI interface */ | 204 | /* PSCI interface */ |
202 | #define KVM_PSCI_FN_BASE 0x95c1ba5e | 205 | #define KVM_PSCI_FN_BASE 0x95c1ba5e |
203 | #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) | 206 | #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) |
diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig index 83a448e8192b..f1f79d104309 100644 --- a/arch/arm/kvm/Kconfig +++ b/arch/arm/kvm/Kconfig | |||
@@ -28,6 +28,8 @@ config KVM | |||
28 | select KVM_GENERIC_DIRTYLOG_READ_PROTECT | 28 | select KVM_GENERIC_DIRTYLOG_READ_PROTECT |
29 | select SRCU | 29 | select SRCU |
30 | select MMU_NOTIFIER | 30 | select MMU_NOTIFIER |
31 | select HAVE_KVM_EVENTFD | ||
32 | select HAVE_KVM_IRQFD | ||
31 | depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER | 33 | depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER |
32 | ---help--- | 34 | ---help--- |
33 | Support hosting virtualized guest machines. | 35 | Support hosting virtualized guest machines. |
diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile index 60be7be4c824..a093bf125ca8 100644 --- a/arch/arm/kvm/Makefile +++ b/arch/arm/kvm/Makefile | |||
@@ -15,7 +15,7 @@ AFLAGS_init.o := -Wa,-march=armv7-a$(plus_virt) | |||
15 | AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt) | 15 | AFLAGS_interrupts.o := -Wa,-march=armv7-a$(plus_virt) |
16 | 16 | ||
17 | KVM := ../../../virt/kvm | 17 | KVM := ../../../virt/kvm |
18 | kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o | 18 | kvm-arm-y = $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o |
19 | 19 | ||
20 | obj-y += kvm-arm.o init.o interrupts.o | 20 | obj-y += kvm-arm.o init.o interrupts.o |
21 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o | 21 | obj-y += arm.o handle_exit.o guest.o mmu.o emulate.o reset.o |
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 5e893ebb9de7..cc96619f10a4 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c | |||
@@ -171,6 +171,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) | |||
171 | int r; | 171 | int r; |
172 | switch (ext) { | 172 | switch (ext) { |
173 | case KVM_CAP_IRQCHIP: | 173 | case KVM_CAP_IRQCHIP: |
174 | case KVM_CAP_IRQFD: | ||
174 | case KVM_CAP_DEVICE_CTRL: | 175 | case KVM_CAP_DEVICE_CTRL: |
175 | case KVM_CAP_USER_MEMORY: | 176 | case KVM_CAP_USER_MEMORY: |
176 | case KVM_CAP_SYNC_MMU: | 177 | case KVM_CAP_SYNC_MMU: |
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index 3ef77a466018..c154c0b7eb60 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h | |||
@@ -191,6 +191,9 @@ struct kvm_arch_memory_slot { | |||
191 | /* Highest supported SPI, from VGIC_NR_IRQS */ | 191 | /* Highest supported SPI, from VGIC_NR_IRQS */ |
192 | #define KVM_ARM_IRQ_GIC_MAX 127 | 192 | #define KVM_ARM_IRQ_GIC_MAX 127 |
193 | 193 | ||
194 | /* One single KVM irqchip, ie. the VGIC */ | ||
195 | #define KVM_NR_IRQCHIPS 1 | ||
196 | |||
194 | /* PSCI interface */ | 197 | /* PSCI interface */ |
195 | #define KVM_PSCI_FN_BASE 0x95c1ba5e | 198 | #define KVM_PSCI_FN_BASE 0x95c1ba5e |
196 | #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) | 199 | #define KVM_PSCI_FN(n) (KVM_PSCI_FN_BASE + (n)) |
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig index 05f56ce6ee70..5105e297ed5f 100644 --- a/arch/arm64/kvm/Kconfig +++ b/arch/arm64/kvm/Kconfig | |||
@@ -28,6 +28,8 @@ config KVM | |||
28 | select KVM_ARM_HOST | 28 | select KVM_ARM_HOST |
29 | select KVM_GENERIC_DIRTYLOG_READ_PROTECT | 29 | select KVM_GENERIC_DIRTYLOG_READ_PROTECT |
30 | select SRCU | 30 | select SRCU |
31 | select HAVE_KVM_EVENTFD | ||
32 | select HAVE_KVM_IRQFD | ||
31 | ---help--- | 33 | ---help--- |
32 | Support hosting virtualized guest machines. | 34 | Support hosting virtualized guest machines. |
33 | 35 | ||
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile index c92b26abc691..b22c6360a324 100644 --- a/arch/arm64/kvm/Makefile +++ b/arch/arm64/kvm/Makefile | |||
@@ -11,7 +11,7 @@ ARM=../../../arch/arm/kvm | |||
11 | 11 | ||
12 | obj-$(CONFIG_KVM_ARM_HOST) += kvm.o | 12 | obj-$(CONFIG_KVM_ARM_HOST) += kvm.o |
13 | 13 | ||
14 | kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o | 14 | kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o $(KVM)/eventfd.o |
15 | kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o | 15 | kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/arm.o $(ARM)/mmu.o $(ARM)/mmio.o |
16 | kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o | 16 | kvm-$(CONFIG_KVM_ARM_HOST) += $(ARM)/psci.o $(ARM)/perf.o |
17 | 17 | ||
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 | } | ||