Skip to content

Commit bebfd2a

Browse files
Marc Zyngierchazy
authored andcommitted
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 <[email protected]> Reviewed-by: Eric Auger <[email protected]> Signed-off-by: Marc Zyngier <[email protected]> Signed-off-by: Christoffer Dall <[email protected]>
1 parent b2c9a85 commit bebfd2a

File tree

2 files changed

+58
-41
lines changed

2 files changed

+58
-41
lines changed

virt/kvm/arm/vgic/vgic-its.c

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -505,19 +505,11 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
505505
return 0;
506506
}
507507

508-
/*
509-
* Find the target VCPU and the LPI number for a given devid/eventid pair
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-
*/
515-
static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
516-
u32 devid, u32 eventid)
508+
int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
509+
u32 devid, u32 eventid, struct vgic_irq **irq)
517510
{
518511
struct kvm_vcpu *vcpu;
519512
struct its_ite *ite;
520-
unsigned long flags;
521513

522514
if (!its->enabled)
523515
return -EBUSY;
@@ -533,26 +525,61 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
533525
if (!vcpu->arch.vgic_cpu.lpis_enabled)
534526
return -EBUSY;
535527

536-
spin_lock_irqsave(&ite->irq->irq_lock, flags);
537-
ite->irq->pending_latch = true;
538-
vgic_queue_irq_unlock(kvm, ite->irq, flags);
539-
528+
*irq = ite->irq;
540529
return 0;
541530
}
542531

543-
static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
532+
struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi)
544533
{
534+
u64 address;
535+
struct kvm_io_device *kvm_io_dev;
545536
struct vgic_io_device *iodev;
546537

547-
if (dev->ops != &kvm_io_gic_ops)
548-
return NULL;
538+
if (!vgic_has_its(kvm))
539+
return ERR_PTR(-ENODEV);
549540

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);
551549

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);
552554
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+
*/
567+
static 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;
554577

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;
556583
}
557584

558585
/*
@@ -563,30 +590,16 @@ static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
563590
*/
564591
int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
565592
{
566-
u64 address;
567-
struct kvm_io_device *kvm_io_dev;
568-
struct vgic_io_device *iodev;
593+
struct vgic_its *its;
569594
int ret;
570595

571-
if (!vgic_has_its(kvm))
572-
return -ENODEV;
573-
574-
if (!(msi->flags & KVM_MSI_VALID_DEVID))
575-
return -EINVAL;
576-
577-
address = (u64)msi->address_hi << 32 | msi->address_lo;
596+
its = vgic_msi_to_its(kvm, msi);
597+
if (IS_ERR(its))
598+
return PTR_ERR(its);
578599

579-
kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
580-
if (!kvm_io_dev)
581-
return -EINVAL;
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);
600+
mutex_lock(&its->its_lock);
601+
ret = vgic_its_trigger_msi(kvm, its, msi->devid, msi->data);
602+
mutex_unlock(&its->its_lock);
590603

591604
if (ret < 0)
592605
return ret;

virt/kvm/arm/vgic/vgic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,4 +237,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
237237
}
238238
}
239239

240+
int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
241+
u32 devid, u32 eventid, struct vgic_irq **irq);
242+
struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
243+
240244
#endif

0 commit comments

Comments
 (0)