KVM: arm/arm64: vgic-its: Check the LPI translation cache on MSI injection
authorMarc Zyngier <maz@kernel.org>
Mon, 18 Mar 2019 10:29:30 +0000 (10:29 +0000)
committerMarc Zyngier <maz@kernel.org>
Sun, 18 Aug 2019 17:38:53 +0000 (18:38 +0100)
When performing an MSI injection, let's first check if the translation
is already in the cache. If so, let's inject it quickly without
going through the whole translation process.

Tested-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
virt/kvm/arm/vgic/vgic-its.c
virt/kvm/arm/vgic/vgic.h

index e61d3ea..2be6b66 100644 (file)
@@ -566,6 +566,20 @@ static struct vgic_irq *__vgic_its_check_cache(struct vgic_dist *dist,
        return NULL;
 }
 
+static struct vgic_irq *vgic_its_check_cache(struct kvm *kvm, phys_addr_t db,
+                                            u32 devid, u32 eventid)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       struct vgic_irq *irq;
+       unsigned long flags;
+
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       irq = __vgic_its_check_cache(dist, db, devid, eventid);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+
+       return irq;
+}
+
 static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
                                       u32 devid, u32 eventid,
                                       struct vgic_irq *irq)
@@ -725,6 +739,25 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
        return 0;
 }
 
+int vgic_its_inject_cached_translation(struct kvm *kvm, struct kvm_msi *msi)
+{
+       struct vgic_irq *irq;
+       unsigned long flags;
+       phys_addr_t db;
+
+       db = (u64)msi->address_hi << 32 | msi->address_lo;
+       irq = vgic_its_check_cache(kvm, db, msi->devid, msi->data);
+
+       if (!irq)
+               return -1;
+
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
+       irq->pending_latch = true;
+       vgic_queue_irq_unlock(kvm, irq, flags);
+
+       return 0;
+}
+
 /*
  * Queries the KVM IO bus framework to get the ITS pointer from the given
  * doorbell address.
@@ -736,6 +769,9 @@ int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
        struct vgic_its *its;
        int ret;
 
+       if (!vgic_its_inject_cached_translation(kvm, msi))
+               return 1;
+
        its = vgic_msi_to_its(kvm, msi);
        if (IS_ERR(its))
                return PTR_ERR(its);
index c7fb4da..83066a8 100644 (file)
@@ -308,6 +308,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr);
 int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
                         u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+int vgic_its_inject_cached_translation(struct kvm *kvm, struct kvm_msi *msi);
 void vgic_lpi_translation_cache_init(struct kvm *kvm);
 void vgic_lpi_translation_cache_destroy(struct kvm *kvm);
 void vgic_its_invalidate_cache(struct kvm *kvm);