diff options
author | Marc Zyngier <maz@kernel.org> | 2019-03-18 06:13:01 -0400 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2019-08-18 13:38:35 -0400 |
commit | 24cab82c34aa6f3ede3de1d8621624cb5ef33feb (patch) | |
tree | f56c1700b1a3b4b1637b2fea506eec8df94910fa /virt/kvm/arm | |
parent | d45331b00ddb179e291766617259261c112db872 (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.c | 5 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-its.c | 49 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic.h | 2 |
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 | ||
141 | struct 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 | |||
1671 | void 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 | |||
1695 | void 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); | |||
307 | int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its, | 307 | int 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); |
309 | struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi); | 309 | struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi); |
310 | void vgic_lpi_translation_cache_init(struct kvm *kvm); | ||
311 | void vgic_lpi_translation_cache_destroy(struct kvm *kvm); | ||
310 | 312 | ||
311 | bool vgic_supports_direct_msis(struct kvm *kvm); | 313 | bool vgic_supports_direct_msis(struct kvm *kvm); |
312 | int vgic_v4_init(struct kvm *kvm); | 314 | int vgic_v4_init(struct kvm *kvm); |