diff options
author | Eric Auger <eric.auger@redhat.com> | 2016-07-22 12:20:42 -0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-07-22 13:52:03 -0400 |
commit | 995a0ee9809b6948bb7bfea77f129fe1d5157cc1 (patch) | |
tree | aa87eb8de3f3e111b9dcc4b470a24a660cd6bb8a | |
parent | 180ae7b1182344ca617d8b5200306b02a6b5075d (diff) |
KVM: arm/arm64: Enable MSI routing
Up to now, only irqchip routing entries could be set. This patch
adds the capability to insert MSI routing entries.
For ARM64, let's also increase KVM_MAX_IRQ_ROUTES to 4096: this
include SPI irqchip routes plus MSI routes. In the future this
might be extended.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Reviewed-by: Andre Przywara <andre.przywara@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
-rw-r--r-- | Documentation/virtual/kvm/api.txt | 3 | ||||
-rw-r--r-- | include/linux/kvm_host.h | 2 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-irqfd.c | 8 | ||||
-rw-r--r-- | virt/kvm/irqchip.c | 24 |
4 files changed, 28 insertions, 9 deletions
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt index 7e5f9afcc693..7a04216d7278 100644 --- a/Documentation/virtual/kvm/api.txt +++ b/Documentation/virtual/kvm/api.txt | |||
@@ -2381,6 +2381,9 @@ On arm/arm64, gsi routing being supported, the following can happen: | |||
2381 | - in case no routing entry is associated to this gsi, injection fails | 2381 | - in case no routing entry is associated to this gsi, injection fails |
2382 | - in case the gsi is associated to an irqchip routing entry, | 2382 | - in case the gsi is associated to an irqchip routing entry, |
2383 | irqchip.pin + 32 corresponds to the injected SPI ID. | 2383 | irqchip.pin + 32 corresponds to the injected SPI ID. |
2384 | - in case the gsi is associated to an MSI routing entry, the MSI | ||
2385 | message and device ID are translated into an LPI (support restricted | ||
2386 | to GICv3 ITS in-kernel emulation). | ||
2384 | 2387 | ||
2385 | 4.76 KVM_PPC_ALLOCATE_HTAB | 2388 | 4.76 KVM_PPC_ALLOCATE_HTAB |
2386 | 2389 | ||
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index a7eb5c48251e..a318c3b21608 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h | |||
@@ -1048,6 +1048,8 @@ static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) | |||
1048 | 1048 | ||
1049 | #ifdef CONFIG_S390 | 1049 | #ifdef CONFIG_S390 |
1050 | #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... | 1050 | #define KVM_MAX_IRQ_ROUTES 4096 //FIXME: we can have more than that... |
1051 | #elif defined(CONFIG_ARM64) | ||
1052 | #define KVM_MAX_IRQ_ROUTES 4096 | ||
1051 | #else | 1053 | #else |
1052 | #define KVM_MAX_IRQ_ROUTES 1024 | 1054 | #define KVM_MAX_IRQ_ROUTES 1024 |
1053 | #endif | 1055 | #endif |
diff --git a/virt/kvm/arm/vgic/vgic-irqfd.c b/virt/kvm/arm/vgic/vgic-irqfd.c index 6e84d530d9f7..683a589711b0 100644 --- a/virt/kvm/arm/vgic/vgic-irqfd.c +++ b/virt/kvm/arm/vgic/vgic-irqfd.c | |||
@@ -59,6 +59,14 @@ int kvm_set_routing_entry(struct kvm_kernel_irq_routing_entry *e, | |||
59 | (e->irqchip.irqchip >= KVM_NR_IRQCHIPS)) | 59 | (e->irqchip.irqchip >= KVM_NR_IRQCHIPS)) |
60 | goto out; | 60 | goto out; |
61 | break; | 61 | break; |
62 | case KVM_IRQ_ROUTING_MSI: | ||
63 | e->set = kvm_set_msi; | ||
64 | e->msi.address_lo = ue->u.msi.address_lo; | ||
65 | e->msi.address_hi = ue->u.msi.address_hi; | ||
66 | e->msi.data = ue->u.msi.data; | ||
67 | e->msi.flags = ue->flags; | ||
68 | e->msi.devid = ue->u.msi.devid; | ||
69 | break; | ||
62 | default: | 70 | default: |
63 | goto out; | 71 | goto out; |
64 | } | 72 | } |
diff --git a/virt/kvm/irqchip.c b/virt/kvm/irqchip.c index 0c000546aedc..c6202199e505 100644 --- a/virt/kvm/irqchip.c +++ b/virt/kvm/irqchip.c | |||
@@ -178,6 +178,7 @@ int kvm_set_irq_routing(struct kvm *kvm, | |||
178 | unsigned flags) | 178 | unsigned flags) |
179 | { | 179 | { |
180 | struct kvm_irq_routing_table *new, *old; | 180 | struct kvm_irq_routing_table *new, *old; |
181 | struct kvm_kernel_irq_routing_entry *e; | ||
181 | u32 i, j, nr_rt_entries = 0; | 182 | u32 i, j, nr_rt_entries = 0; |
182 | int r; | 183 | int r; |
183 | 184 | ||
@@ -201,23 +202,25 @@ int kvm_set_irq_routing(struct kvm *kvm, | |||
201 | new->chip[i][j] = -1; | 202 | new->chip[i][j] = -1; |
202 | 203 | ||
203 | for (i = 0; i < nr; ++i) { | 204 | for (i = 0; i < nr; ++i) { |
204 | struct kvm_kernel_irq_routing_entry *e; | ||
205 | |||
206 | r = -ENOMEM; | 205 | r = -ENOMEM; |
207 | e = kzalloc(sizeof(*e), GFP_KERNEL); | 206 | e = kzalloc(sizeof(*e), GFP_KERNEL); |
208 | if (!e) | 207 | if (!e) |
209 | goto out; | 208 | goto out; |
210 | 209 | ||
211 | r = -EINVAL; | 210 | r = -EINVAL; |
212 | if (ue->flags) { | 211 | switch (ue->type) { |
213 | kfree(e); | 212 | case KVM_IRQ_ROUTING_MSI: |
214 | goto out; | 213 | if (ue->flags & ~KVM_MSI_VALID_DEVID) |
214 | goto free_entry; | ||
215 | break; | ||
216 | default: | ||
217 | if (ue->flags) | ||
218 | goto free_entry; | ||
219 | break; | ||
215 | } | 220 | } |
216 | r = setup_routing_entry(new, e, ue); | 221 | r = setup_routing_entry(new, e, ue); |
217 | if (r) { | 222 | if (r) |
218 | kfree(e); | 223 | goto free_entry; |
219 | goto out; | ||
220 | } | ||
221 | ++ue; | 224 | ++ue; |
222 | } | 225 | } |
223 | 226 | ||
@@ -234,7 +237,10 @@ int kvm_set_irq_routing(struct kvm *kvm, | |||
234 | 237 | ||
235 | new = old; | 238 | new = old; |
236 | r = 0; | 239 | r = 0; |
240 | goto out; | ||
237 | 241 | ||
242 | free_entry: | ||
243 | kfree(e); | ||
238 | out: | 244 | out: |
239 | free_irq_routing_table(new); | 245 | free_irq_routing_table(new); |
240 | 246 | ||