summaryrefslogtreecommitdiffstats
path: root/virt/kvm/arm
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2019-03-18 06:13:01 -0400
committerMarc Zyngier <maz@kernel.org>2019-08-18 13:38:35 -0400
commit24cab82c34aa6f3ede3de1d8621624cb5ef33feb (patch)
treef56c1700b1a3b4b1637b2fea506eec8df94910fa /virt/kvm/arm
parentd45331b00ddb179e291766617259261c112db872 (diff)
KVM: arm/arm64: vgic: Add LPI translation cache definition
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>
Diffstat (limited to 'virt/kvm/arm')
-rw-r--r--virt/kvm/arm/vgic/vgic-init.c5
-rw-r--r--virt/kvm/arm/vgic/vgic-its.c49
-rw-r--r--virt/kvm/arm/vgic/vgic.h2
3 files changed, 56 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index bdbc297d06fb..80127ca9269f 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -53,6 +53,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
53 struct vgic_dist *dist = &kvm->arch.vgic; 53 struct vgic_dist *dist = &kvm->arch.vgic;
54 54
55 INIT_LIST_HEAD(&dist->lpi_list_head); 55 INIT_LIST_HEAD(&dist->lpi_list_head);
56 INIT_LIST_HEAD(&dist->lpi_translation_cache);
56 raw_spin_lock_init(&dist->lpi_list_lock); 57 raw_spin_lock_init(&dist->lpi_list_lock);
57} 58}
58 59
@@ -294,6 +295,7 @@ int vgic_init(struct kvm *kvm)
294 } 295 }
295 296
296 if (vgic_has_its(kvm)) { 297 if (vgic_has_its(kvm)) {
298 vgic_lpi_translation_cache_init(kvm);
297 ret = vgic_v4_init(kvm); 299 ret = vgic_v4_init(kvm);
298 if (ret) 300 if (ret)
299 goto out; 301 goto out;
@@ -335,6 +337,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
335 INIT_LIST_HEAD(&dist->rd_regions); 337 INIT_LIST_HEAD(&dist->rd_regions);
336 } 338 }
337 339
340 if (vgic_has_its(kvm))
341 vgic_lpi_translation_cache_destroy(kvm);
342
338 if (vgic_supports_direct_msis(kvm)) 343 if (vgic_supports_direct_msis(kvm))
339 vgic_v4_teardown(kvm); 344 vgic_v4_teardown(kvm);
340} 345}
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 482036612adf..0e5c1519bbe2 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -138,6 +138,14 @@ struct its_ite {
138 u32 event_id; 138 u32 event_id;
139}; 139};
140 140
141struct vgic_translation_cache_entry {
142 struct list_head entry;
143 phys_addr_t db;
144 u32 devid;
145 u32 eventid;
146 struct vgic_irq *irq;
147};
148
141/** 149/**
142 * struct vgic_its_abi - ITS abi ops and settings 150 * struct vgic_its_abi - ITS abi ops and settings
143 * @cte_esz: collection table entry size 151 * @cte_esz: collection table entry size
@@ -1657,6 +1665,45 @@ out:
1657 return ret; 1665 return ret;
1658} 1666}
1659 1667
1668/* Default is 16 cached LPIs per vcpu */
1669#define LPI_DEFAULT_PCPU_CACHE_SIZE 16
1670
1671void vgic_lpi_translation_cache_init(struct kvm *kvm)
1672{
1673 struct vgic_dist *dist = &kvm->arch.vgic;
1674 unsigned int sz;
1675 int i;
1676
1677 if (!list_empty(&dist->lpi_translation_cache))
1678 return;
1679
1680 sz = atomic_read(&kvm->online_vcpus) * LPI_DEFAULT_PCPU_CACHE_SIZE;
1681
1682 for (i = 0; i < sz; i++) {
1683 struct vgic_translation_cache_entry *cte;
1684
1685 /* An allocation failure is not fatal */
1686 cte = kzalloc(sizeof(*cte), GFP_KERNEL);
1687 if (WARN_ON(!cte))
1688 break;
1689
1690 INIT_LIST_HEAD(&cte->entry);
1691 list_add(&cte->entry, &dist->lpi_translation_cache);
1692 }
1693}
1694
1695void vgic_lpi_translation_cache_destroy(struct kvm *kvm)
1696{
1697 struct vgic_dist *dist = &kvm->arch.vgic;
1698 struct vgic_translation_cache_entry *cte, *tmp;
1699
1700 list_for_each_entry_safe(cte, tmp,
1701 &dist->lpi_translation_cache, entry) {
1702 list_del(&cte->entry);
1703 kfree(cte);
1704 }
1705}
1706
1660#define INITIAL_BASER_VALUE \ 1707#define INITIAL_BASER_VALUE \
1661 (GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb) | \ 1708 (GIC_BASER_CACHEABILITY(GITS_BASER, INNER, RaWb) | \
1662 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner) | \ 1709 GIC_BASER_CACHEABILITY(GITS_BASER, OUTER, SameAsInner) | \
@@ -1685,6 +1732,8 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
1685 kfree(its); 1732 kfree(its);
1686 return ret; 1733 return ret;
1687 } 1734 }
1735
1736 vgic_lpi_translation_cache_init(dev->kvm);
1688 } 1737 }
1689 1738
1690 mutex_init(&its->its_lock); 1739 mutex_init(&its->its_lock);
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 797e05004d80..a25b790ffa4e 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -307,6 +307,8 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr);
307int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its, 307int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
308 u32 devid, u32 eventid, struct vgic_irq **irq); 308 u32 devid, u32 eventid, struct vgic_irq **irq);
309struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi); 309struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
310void vgic_lpi_translation_cache_init(struct kvm *kvm);
311void vgic_lpi_translation_cache_destroy(struct kvm *kvm);
310 312
311bool vgic_supports_direct_msis(struct kvm *kvm); 313bool vgic_supports_direct_msis(struct kvm *kvm);
312int vgic_v4_init(struct kvm *kvm); 314int vgic_v4_init(struct kvm *kvm);