KVM: arm/arm64: vgic: Add LPI translation cache definition
authorMarc Zyngier <maz@kernel.org>
Mon, 18 Mar 2019 10:13:01 +0000 (10:13 +0000)
committerMarc Zyngier <maz@kernel.org>
Sun, 18 Aug 2019 17:38:35 +0000 (18:38 +0100)
Add the basic data structure that expresses an MSI to LPI
translation as well as the allocation/release hooks.

The size of the cache is arbitrarily defined as 16*nr_vcpus.

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

index 7a30524a80ee8793b446d745c225c5864f50cdc7..ded50a30e2d5135e6afd9968a45e0583b25ace50 100644 (file)
@@ -249,6 +249,9 @@ struct vgic_dist {
        struct list_head        lpi_list_head;
        int                     lpi_list_count;
 
+       /* LPI translation cache */
+       struct list_head        lpi_translation_cache;
+
        /* used by vgic-debug */
        struct vgic_state_iter *iter;
 
index bdbc297d06fb4676559dab05137a03d916d58273..80127ca9269f4a687b5e2e7efff9efd9cabcb719 100644 (file)
@@ -53,6 +53,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
 
        INIT_LIST_HEAD(&dist->lpi_list_head);
+       INIT_LIST_HEAD(&dist->lpi_translation_cache);
        raw_spin_lock_init(&dist->lpi_list_lock);
 }
 
@@ -294,6 +295,7 @@ int vgic_init(struct kvm *kvm)
        }
 
        if (vgic_has_its(kvm)) {
+               vgic_lpi_translation_cache_init(kvm);
                ret = vgic_v4_init(kvm);
                if (ret)
                        goto out;
@@ -335,6 +337,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
                INIT_LIST_HEAD(&dist->rd_regions);
        }
 
+       if (vgic_has_its(kvm))
+               vgic_lpi_translation_cache_destroy(kvm);
+
        if (vgic_supports_direct_msis(kvm))
                vgic_v4_teardown(kvm);
 }
index 482036612adfe1bdadda51e86946c3276456ccdb..0e5c1519bbe2e0c7c61cc903236d7c1f826a69dc 100644 (file)
@@ -138,6 +138,14 @@ struct its_ite {
        u32 event_id;
 };
 
+struct vgic_translation_cache_entry {
+       struct list_head        entry;
+       phys_addr_t             db;
+       u32                     devid;
+       u32                     eventid;
+       struct vgic_irq         *irq;
+};
+
 /**
  * struct vgic_its_abi - ITS abi ops and settings
  * @cte_esz: collection table entry size
@@ -1657,6 +1665,45 @@ out:
        return ret;
 }
 
+/* Default is 16 cached LPIs per vcpu */
+#define LPI_DEFAULT_PCPU_CACHE_SIZE    16
+
+void vgic_lpi_translation_cache_init(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       unsigned int sz;
+       int i;
+
+       if (!list_empty(&dist->lpi_translation_cache))
+               return;
+
+       sz = atomic_read(&kvm->online_vcpus) * LPI_DEFAULT_PCPU_CACHE_SIZE;
+
+       for (i = 0; i < sz; i++) {
+               struct vgic_translation_cache_entry *cte;
+
+               /* An allocation failure is not fatal */
+               cte = kzalloc(sizeof(*cte), GFP_KERNEL);
+               if (WARN_ON(!cte))
+                       break;
+
+               INIT_LIST_HEAD(&cte->entry);
+               list_add(&cte->entry, &dist->lpi_translation_cache);
+       }
+}
+
+void vgic_lpi_translation_cache_destroy(struct kvm *kvm)
+{
+       struct vgic_dist *dist = &kvm->arch.vgic;
+       struct vgic_translation_cache_entry *cte, *tmp;
+
+       list_for_each_entry_safe(cte, tmp,
+                                &dist->lpi_translation_cache, entry) {
+               list_del(&cte->entry);
+               kfree(cte);
+       }
+}
+
 #define INITIAL_BASER_VALUE                                              \
        (GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb)                | \
         GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner)         | \
@@ -1685,6 +1732,8 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
                        kfree(its);
                        return ret;
                }
+
+               vgic_lpi_translation_cache_init(dev->kvm);
        }
 
        mutex_init(&its->its_lock);
index 797e05004d807a1041b4711488913f78f98636bb..a25b790ffa4ec76bd163456d913204f49dfbd018 100644 (file)
@@ -307,6 +307,8 @@ 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);
+void vgic_lpi_translation_cache_init(struct kvm *kvm);
+void vgic_lpi_translation_cache_destroy(struct kvm *kvm);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);