diff options
Diffstat (limited to 'virt/kvm/irq_comm.c')
-rw-r--r-- | virt/kvm/irq_comm.c | 76 |
1 files changed, 3 insertions, 73 deletions
diff --git a/virt/kvm/irq_comm.c b/virt/kvm/irq_comm.c index d5008f4aade7..e2e6b4473a96 100644 --- a/virt/kvm/irq_comm.c +++ b/virt/kvm/irq_comm.c | |||
@@ -271,27 +271,14 @@ void kvm_fire_mask_notifiers(struct kvm *kvm, unsigned irqchip, unsigned pin, | |||
271 | rcu_read_unlock(); | 271 | rcu_read_unlock(); |
272 | } | 272 | } |
273 | 273 | ||
274 | static int setup_routing_entry(struct kvm_irq_routing_table *rt, | 274 | int kvm_set_routing_entry(struct kvm_irq_routing_table *rt, |
275 | struct kvm_kernel_irq_routing_entry *e, | 275 | struct kvm_kernel_irq_routing_entry *e, |
276 | const struct kvm_irq_routing_entry *ue) | 276 | const struct kvm_irq_routing_entry *ue) |
277 | { | 277 | { |
278 | int r = -EINVAL; | 278 | int r = -EINVAL; |
279 | int delta; | 279 | int delta; |
280 | unsigned max_pin; | 280 | unsigned max_pin; |
281 | struct kvm_kernel_irq_routing_entry *ei; | ||
282 | 281 | ||
283 | /* | ||
284 | * Do not allow GSI to be mapped to the same irqchip more than once. | ||
285 | * Allow only one to one mapping between GSI and MSI. | ||
286 | */ | ||
287 | hlist_for_each_entry(ei, &rt->map[ue->gsi], link) | ||
288 | if (ei->type == KVM_IRQ_ROUTING_MSI || | ||
289 | ue->type == KVM_IRQ_ROUTING_MSI || | ||
290 | ue->u.irqchip.irqchip == ei->irqchip.irqchip) | ||
291 | return r; | ||
292 | |||
293 | e->gsi = ue->gsi; | ||
294 | e->type = ue->type; | ||
295 | switch (ue->type) { | 282 | switch (ue->type) { |
296 | case KVM_IRQ_ROUTING_IRQCHIP: | 283 | case KVM_IRQ_ROUTING_IRQCHIP: |
297 | delta = 0; | 284 | delta = 0; |
@@ -328,68 +315,11 @@ static int setup_routing_entry(struct kvm_irq_routing_table *rt, | |||
328 | goto out; | 315 | goto out; |
329 | } | 316 | } |
330 | 317 | ||
331 | hlist_add_head(&e->link, &rt->map[e->gsi]); | ||
332 | r = 0; | 318 | r = 0; |
333 | out: | 319 | out: |
334 | return r; | 320 | return r; |
335 | } | 321 | } |
336 | 322 | ||
337 | int kvm_set_irq_routing(struct kvm *kvm, | ||
338 | const struct kvm_irq_routing_entry *ue, | ||
339 | unsigned nr, | ||
340 | unsigned flags) | ||
341 | { | ||
342 | struct kvm_irq_routing_table *new, *old; | ||
343 | u32 i, j, nr_rt_entries = 0; | ||
344 | int r; | ||
345 | |||
346 | for (i = 0; i < nr; ++i) { | ||
347 | if (ue[i].gsi >= KVM_MAX_IRQ_ROUTES) | ||
348 | return -EINVAL; | ||
349 | nr_rt_entries = max(nr_rt_entries, ue[i].gsi); | ||
350 | } | ||
351 | |||
352 | nr_rt_entries += 1; | ||
353 | |||
354 | new = kzalloc(sizeof(*new) + (nr_rt_entries * sizeof(struct hlist_head)) | ||
355 | + (nr * sizeof(struct kvm_kernel_irq_routing_entry)), | ||
356 | GFP_KERNEL); | ||
357 | |||
358 | if (!new) | ||
359 | return -ENOMEM; | ||
360 | |||
361 | new->rt_entries = (void *)&new->map[nr_rt_entries]; | ||
362 | |||
363 | new->nr_rt_entries = nr_rt_entries; | ||
364 | for (i = 0; i < 3; i++) | ||
365 | for (j = 0; j < KVM_IRQCHIP_NUM_PINS; j++) | ||
366 | new->chip[i][j] = -1; | ||
367 | |||
368 | for (i = 0; i < nr; ++i) { | ||
369 | r = -EINVAL; | ||
370 | if (ue->flags) | ||
371 | goto out; | ||
372 | r = setup_routing_entry(new, &new->rt_entries[i], ue); | ||
373 | if (r) | ||
374 | goto out; | ||
375 | ++ue; | ||
376 | } | ||
377 | |||
378 | mutex_lock(&kvm->irq_lock); | ||
379 | old = kvm->irq_routing; | ||
380 | kvm_irq_routing_update(kvm, new); | ||
381 | mutex_unlock(&kvm->irq_lock); | ||
382 | |||
383 | synchronize_rcu(); | ||
384 | |||
385 | new = old; | ||
386 | r = 0; | ||
387 | |||
388 | out: | ||
389 | kfree(new); | ||
390 | return r; | ||
391 | } | ||
392 | |||
393 | #define IOAPIC_ROUTING_ENTRY(irq) \ | 323 | #define IOAPIC_ROUTING_ENTRY(irq) \ |
394 | { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ | 324 | { .gsi = irq, .type = KVM_IRQ_ROUTING_IRQCHIP, \ |
395 | .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) } | 325 | .u.irqchip.irqchip = KVM_IRQCHIP_IOAPIC, .u.irqchip.pin = (irq) } |