Skip to content

Commit 3d5689e

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/lpi-xa-cache into kvmarm-master/next
* kvm-arm64/lpi-xa-cache: : . : New and improved LPI translation cache from Oliver Upton. : : From the cover letter: : : "As discussed [*], here is the new take on the LPI translation cache, : migrating to an xarray indexed by (devid, eventid) per ITS. : : The end result is quite satisfying, as it becomes possible to rip out : other nasties such as the lpi_list_lock. To that end, patches 2-6 aren't : _directly_ related to the translation cache cleanup, but instead are : done to enable the cleanups at the end of the series. : : I changed out my test machine from the last time so the baseline has : moved a bit, but here are the results from the vgic_lpi_stress test: : : +----------------------------+------------+-------------------+ : | Configuration | v6.8-rc1 | v6.8-rc1 + series | : +----------------------------+------------+-------------------+ : | -v 1 -d 1 -e 1 -i 1000000 | 2063296.81 | 1362602.35 | : | -v 16 -d 16 -e 16 -i 10000 | 610678.33 | 5200910.01 | : | -v 16 -d 16 -e 17 -i 10000 | 678361.53 | 5890675.51 | : | -v 32 -d 32 -e 1 -i 100000 | 580918.96 | 8304552.67 | : | -v 1 -d 1 -e 17 -i 1000 | 1512443.94 | 1425953.8 | : +----------------------------+------------+-------------------+ : : Unlike last time, no dramatic regressions at any performance point. The : regression on a single interrupt stream is to be expected, as the : overheads of SRCU and two tree traversals (kvm_io_bus_get_dev(), : translation cache xarray) are likely greater than that of a linked-list : with a single node." : . KVM: selftests: Add stress test for LPI injection KVM: selftests: Use MPIDR_HWID_BITMASK from cputype.h KVM: selftests: Add helper for enabling LPIs on a redistributor KVM: selftests: Add a minimal library for interacting with an ITS KVM: selftests: Add quadword MMIO accessors KVM: selftests: Standardise layout of GIC frames KVM: selftests: Align with kernel's GIC definitions KVM: arm64: vgic-its: Get rid of the lpi_list_lock KVM: arm64: vgic-its: Rip out the global translation cache KVM: arm64: vgic-its: Use the per-ITS translation cache for injection KVM: arm64: vgic-its: Spin off helper for finding ITS by doorbell addr KVM: arm64: vgic-its: Maintain a translation cache per ITS KVM: arm64: vgic-its: Scope translation cache invalidations to an ITS KVM: arm64: vgic-its: Get rid of vgic_copy_lpi_list() KVM: arm64: vgic-debug: Use an xarray mark for debug iterator KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_cmd_handle_movall() KVM: arm64: vgic-its: Walk LPI xarray in vgic_its_invall() KVM: arm64: vgic-its: Walk LPI xarray in its_sync_lpi_pending_table() KVM: Treat the device list as an rculist Signed-off-by: Marc Zyngier <[email protected]>
2 parents 2d38f43 + 96d36ad commit 3d5689e

File tree

26 files changed

+1572
-418
lines changed

26 files changed

+1572
-418
lines changed

arch/arm64/kvm/vgic/vgic-debug.c

Lines changed: 60 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -28,27 +28,65 @@ struct vgic_state_iter {
2828
int nr_lpis;
2929
int dist_id;
3030
int vcpu_id;
31-
int intid;
31+
unsigned long intid;
3232
int lpi_idx;
33-
u32 *lpi_array;
3433
};
3534

36-
static void iter_next(struct vgic_state_iter *iter)
35+
static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter)
3736
{
37+
struct vgic_dist *dist = &kvm->arch.vgic;
38+
3839
if (iter->dist_id == 0) {
3940
iter->dist_id++;
4041
return;
4142
}
4243

44+
/*
45+
* Let the xarray drive the iterator after the last SPI, as the iterator
46+
* has exhausted the sequentially-allocated INTID space.
47+
*/
48+
if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1)) {
49+
if (iter->lpi_idx < iter->nr_lpis)
50+
xa_find_after(&dist->lpi_xa, &iter->intid,
51+
VGIC_LPI_MAX_INTID,
52+
LPI_XA_MARK_DEBUG_ITER);
53+
iter->lpi_idx++;
54+
return;
55+
}
56+
4357
iter->intid++;
4458
if (iter->intid == VGIC_NR_PRIVATE_IRQS &&
4559
++iter->vcpu_id < iter->nr_cpus)
4660
iter->intid = 0;
61+
}
4762

48-
if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS)) {
49-
if (iter->lpi_idx < iter->nr_lpis)
50-
iter->intid = iter->lpi_array[iter->lpi_idx];
51-
iter->lpi_idx++;
63+
static int iter_mark_lpis(struct kvm *kvm)
64+
{
65+
struct vgic_dist *dist = &kvm->arch.vgic;
66+
struct vgic_irq *irq;
67+
unsigned long intid;
68+
int nr_lpis = 0;
69+
70+
xa_for_each(&dist->lpi_xa, intid, irq) {
71+
if (!vgic_try_get_irq_kref(irq))
72+
continue;
73+
74+
xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);
75+
nr_lpis++;
76+
}
77+
78+
return nr_lpis;
79+
}
80+
81+
static void iter_unmark_lpis(struct kvm *kvm)
82+
{
83+
struct vgic_dist *dist = &kvm->arch.vgic;
84+
struct vgic_irq *irq;
85+
unsigned long intid;
86+
87+
xa_for_each(&dist->lpi_xa, intid, irq) {
88+
xa_clear_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);
89+
vgic_put_irq(kvm, irq);
5290
}
5391
}
5492

@@ -61,15 +99,12 @@ static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
6199

62100
iter->nr_cpus = nr_cpus;
63101
iter->nr_spis = kvm->arch.vgic.nr_spis;
64-
if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
65-
iter->nr_lpis = vgic_copy_lpi_list(kvm, NULL, &iter->lpi_array);
66-
if (iter->nr_lpis < 0)
67-
iter->nr_lpis = 0;
68-
}
102+
if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
103+
iter->nr_lpis = iter_mark_lpis(kvm);
69104

70105
/* Fast forward to the right position if needed */
71106
while (pos--)
72-
iter_next(iter);
107+
iter_next(kvm, iter);
73108
}
74109

75110
static bool end_of_vgic(struct vgic_state_iter *iter)
@@ -114,7 +149,7 @@ static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
114149
struct vgic_state_iter *iter = kvm->arch.vgic.iter;
115150

116151
++*pos;
117-
iter_next(iter);
152+
iter_next(kvm, iter);
118153
if (end_of_vgic(iter))
119154
iter = NULL;
120155
return iter;
@@ -134,13 +169,14 @@ static void vgic_debug_stop(struct seq_file *s, void *v)
134169

135170
mutex_lock(&kvm->arch.config_lock);
136171
iter = kvm->arch.vgic.iter;
137-
kfree(iter->lpi_array);
172+
iter_unmark_lpis(kvm);
138173
kfree(iter);
139174
kvm->arch.vgic.iter = NULL;
140175
mutex_unlock(&kvm->arch.config_lock);
141176
}
142177

143-
static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
178+
static void print_dist_state(struct seq_file *s, struct vgic_dist *dist,
179+
struct vgic_state_iter *iter)
144180
{
145181
bool v3 = dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3;
146182

@@ -149,7 +185,7 @@ static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
149185
seq_printf(s, "vgic_model:\t%s\n", v3 ? "GICv3" : "GICv2");
150186
seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
151187
if (v3)
152-
seq_printf(s, "nr_lpis:\t%d\n", atomic_read(&dist->lpi_count));
188+
seq_printf(s, "nr_lpis:\t%d\n", iter->nr_lpis);
153189
seq_printf(s, "enabled:\t%d\n", dist->enabled);
154190
seq_printf(s, "\n");
155191

@@ -236,7 +272,7 @@ static int vgic_debug_show(struct seq_file *s, void *v)
236272
unsigned long flags;
237273

238274
if (iter->dist_id == 0) {
239-
print_dist_state(s, &kvm->arch.vgic);
275+
print_dist_state(s, &kvm->arch.vgic, iter);
240276
return 0;
241277
}
242278

@@ -246,11 +282,13 @@ static int vgic_debug_show(struct seq_file *s, void *v)
246282
if (iter->vcpu_id < iter->nr_cpus)
247283
vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
248284

285+
/*
286+
* Expect this to succeed, as iter_mark_lpis() takes a reference on
287+
* every LPI to be visited.
288+
*/
249289
irq = vgic_get_irq(kvm, vcpu, iter->intid);
250-
if (!irq) {
251-
seq_printf(s, " LPI %4d freed\n", iter->intid);
252-
return 0;
253-
}
290+
if (WARN_ON_ONCE(!irq))
291+
return -EINVAL;
254292

255293
raw_spin_lock_irqsave(&irq->irq_lock, flags);
256294
print_irq_state(s, irq, vcpu);

arch/arm64/kvm/vgic/vgic-init.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,6 @@ void kvm_vgic_early_init(struct kvm *kvm)
5353
{
5454
struct vgic_dist *dist = &kvm->arch.vgic;
5555

56-
INIT_LIST_HEAD(&dist->lpi_translation_cache);
57-
raw_spin_lock_init(&dist->lpi_list_lock);
5856
xa_init_flags(&dist->lpi_xa, XA_FLAGS_LOCK_IRQ);
5957
}
6058

@@ -305,9 +303,6 @@ int vgic_init(struct kvm *kvm)
305303
}
306304
}
307305

308-
if (vgic_has_its(kvm))
309-
vgic_lpi_translation_cache_init(kvm);
310-
311306
/*
312307
* If we have GICv4.1 enabled, unconditionally request enable the
313308
* v4 support so that we get HW-accelerated vSGIs. Otherwise, only
@@ -361,9 +356,6 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
361356
dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
362357
}
363358

364-
if (vgic_has_its(kvm))
365-
vgic_lpi_translation_cache_destroy(kvm);
366-
367359
if (vgic_supports_direct_msis(kvm))
368360
vgic_v4_teardown(kvm);
369361

0 commit comments

Comments
 (0)