summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2017-10-27 10:28:35 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2017-11-10 02:51:15 -0500
commitbebfd2a203736a42510ecf48ae82c9d7e801eeb0 (patch)
tree18fdd89d96e933c9098287b64ecc0d6fee485587 /virt
parentb2c9a85dd75a8cfa18da94b19e84eb0199011187 (diff)
KVM: arm/arm64: vITS: Add MSI translation helpers
The whole MSI injection process is fairly monolithic. An MSI write gets turned into an injected LPI in one swift go. But this is actually a more fine-grained process: - First, a virtual ITS gets selected using the doorbell address - Then the DevID/EventID pair gets translated into an LPI - Finally the LPI is injected Since the GICv4 code needs the first two steps in order to match an IRQ routing entry to an LPI, let's expose them as helpers, and refactor the existing code to use them Reviewed-by: Christoffer Dall <cdall@linaro.org> Reviewed-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/vgic/vgic-its.c95
-rw-r--r--virt/kvm/arm/vgic/vgic.h4
2 files changed, 58 insertions, 41 deletions
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 40791c121710..1de4e68ef1b6 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -505,19 +505,11 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
505 return 0; 505 return 0;
506} 506}
507 507
508/* 508int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
509 * Find the target VCPU and the LPI number for a given devid/eventid pair 509 u32 devid, u32 eventid, struct vgic_irq **irq)
510 * and make this IRQ pending, possibly injecting it.
511 * Must be called with the its_lock mutex held.
512 * Returns 0 on success, a positive error value for any ITS mapping
513 * related errors and negative error values for generic errors.
514 */
515static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
516 u32 devid, u32 eventid)
517{ 510{
518 struct kvm_vcpu *vcpu; 511 struct kvm_vcpu *vcpu;
519 struct its_ite *ite; 512 struct its_ite *ite;
520 unsigned long flags;
521 513
522 if (!its->enabled) 514 if (!its->enabled)
523 return -EBUSY; 515 return -EBUSY;
@@ -533,26 +525,61 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
533 if (!vcpu->arch.vgic_cpu.lpis_enabled) 525 if (!vcpu->arch.vgic_cpu.lpis_enabled)
534 return -EBUSY; 526 return -EBUSY;
535 527
536 spin_lock_irqsave(&ite->irq->irq_lock, flags); 528 *irq = ite->irq;
537 ite->irq->pending_latch = true;
538 vgic_queue_irq_unlock(kvm, ite->irq, flags);
539
540 return 0; 529 return 0;
541} 530}
542 531
543static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev) 532struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi)
544{ 533{
534 u64 address;
535 struct kvm_io_device *kvm_io_dev;
545 struct vgic_io_device *iodev; 536 struct vgic_io_device *iodev;
546 537
547 if (dev->ops != &kvm_io_gic_ops) 538 if (!vgic_has_its(kvm))
548 return NULL; 539 return ERR_PTR(-ENODEV);
549 540
550 iodev = container_of(dev, struct vgic_io_device, dev); 541 if (!(msi->flags & KVM_MSI_VALID_DEVID))
542 return ERR_PTR(-EINVAL);
543
544 address = (u64)msi->address_hi << 32 | msi->address_lo;
545
546 kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
547 if (!kvm_io_dev)
548 return ERR_PTR(-EINVAL);
551 549
550 if (kvm_io_dev->ops != &kvm_io_gic_ops)
551 return ERR_PTR(-EINVAL);
552
553 iodev = container_of(kvm_io_dev, struct vgic_io_device, dev);
552 if (iodev->iodev_type != IODEV_ITS) 554 if (iodev->iodev_type != IODEV_ITS)
553 return NULL; 555 return ERR_PTR(-EINVAL);
556
557 return iodev->its;
558}
559
560/*
561 * Find the target VCPU and the LPI number for a given devid/eventid pair
562 * and make this IRQ pending, possibly injecting it.
563 * Must be called with the its_lock mutex held.
564 * Returns 0 on success, a positive error value for any ITS mapping
565 * related errors and negative error values for generic errors.
566 */
567static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
568 u32 devid, u32 eventid)
569{
570 struct vgic_irq *irq = NULL;
571 unsigned long flags;
572 int err;
573
574 err = vgic_its_resolve_lpi(kvm, its, devid, eventid, &irq);
575 if (err)
576 return err;
554 577
555 return iodev; 578 spin_lock_irqsave(&irq->irq_lock, flags);
579 irq->pending_latch = true;
580 vgic_queue_irq_unlock(kvm, irq, flags);
581
582 return 0;
556} 583}
557 584
558/* 585/*
@@ -563,30 +590,16 @@ static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
563 */ 590 */
564int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi) 591int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
565{ 592{
566 u64 address; 593 struct vgic_its *its;
567 struct kvm_io_device *kvm_io_dev;
568 struct vgic_io_device *iodev;
569 int ret; 594 int ret;
570 595
571 if (!vgic_has_its(kvm)) 596 its = vgic_msi_to_its(kvm, msi);
572 return -ENODEV; 597 if (IS_ERR(its))
573 598 return PTR_ERR(its);
574 if (!(msi->flags & KVM_MSI_VALID_DEVID))
575 return -EINVAL;
576
577 address = (u64)msi->address_hi << 32 | msi->address_lo;
578 599
579 kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address); 600 mutex_lock(&its->its_lock);
580 if (!kvm_io_dev) 601 ret = vgic_its_trigger_msi(kvm, its, msi->devid, msi->data);
581 return -EINVAL; 602 mutex_unlock(&its->its_lock);
582
583 iodev = vgic_get_its_iodev(kvm_io_dev);
584 if (!iodev)
585 return -EINVAL;
586
587 mutex_lock(&iodev->its->its_lock);
588 ret = vgic_its_trigger_msi(kvm, iodev->its, msi->devid, msi->data);
589 mutex_unlock(&iodev->its->its_lock);
590 603
591 if (ret < 0) 604 if (ret < 0)
592 return ret; 605 return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 4f8aecb07ae6..0ac85045c0c7 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -237,4 +237,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
237 } 237 }
238} 238}
239 239
240int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
241 u32 devid, u32 eventid, struct vgic_irq **irq);
242struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
243
240#endif 244#endif