Skip to content

Commit 3ef5ba6

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/debugfs-fixes into kvmarm-master/next
* kvm-arm64/debugfs-fixes: : . : Cleanup of the debugfs iterator, which are way more complicated : than they ought to be, courtesy of Fuad Tabba. From the cover letter: : : "This series refactors the debugfs implementations for `idregs` and : `vgic-state` to use standard `seq_file` iterator patterns. : : The existing implementations relied on storing iterator state within : global VM structures (`kvm_arch` and `vgic_dist`). This approach : prevented concurrent reads of the debugfs files (returning -EBUSY) and : created improper dependencies between transient file operations and : long-lived VM state." : . KVM: arm64: Use standard seq_file iterator for vgic-debug debugfs KVM: arm64: Reimplement vgic-debug XArray iteration KVM: arm64: Use standard seq_file iterator for idregs debugfs Signed-off-by: Marc Zyngier <maz@kernel.org>
2 parents 47e89fe + fb21cb0 commit 3ef5ba6

4 files changed

Lines changed: 40 additions & 125 deletions

File tree

arch/arm64/include/asm/kvm_host.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,6 @@ struct kvm_arch {
373373
/* Maximum number of counters for the guest */
374374
u8 nr_pmu_counters;
375375

376-
/* Iterator for idreg debugfs */
377-
u8 idreg_debugfs_iter;
378-
379376
/* Hypercall features firmware registers' descriptor */
380377
struct kvm_smccc_features smccc_feat;
381378
struct maple_tree smccc_filter;

arch/arm64/kvm/sys_regs.c

Lines changed: 8 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -4993,7 +4993,7 @@ static bool emulate_sys_reg(struct kvm_vcpu *vcpu,
49934993
return false;
49944994
}
49954995

4996-
static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
4996+
static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, loff_t pos)
49974997
{
49984998
unsigned long i, idreg_idx = 0;
49994999

@@ -5003,10 +5003,8 @@ static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
50035003
if (!is_vm_ftr_id_reg(reg_to_encoding(r)))
50045004
continue;
50055005

5006-
if (idreg_idx == pos)
5006+
if (idreg_idx++ == pos)
50075007
return r;
5008-
5009-
idreg_idx++;
50105008
}
50115009

50125010
return NULL;
@@ -5015,23 +5013,11 @@ static const struct sys_reg_desc *idregs_debug_find(struct kvm *kvm, u8 pos)
50155013
static void *idregs_debug_start(struct seq_file *s, loff_t *pos)
50165014
{
50175015
struct kvm *kvm = s->private;
5018-
u8 *iter;
5019-
5020-
mutex_lock(&kvm->arch.config_lock);
5021-
5022-
iter = &kvm->arch.idreg_debugfs_iter;
5023-
if (test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags) &&
5024-
*iter == (u8)~0) {
5025-
*iter = *pos;
5026-
if (!idregs_debug_find(kvm, *iter))
5027-
iter = NULL;
5028-
} else {
5029-
iter = ERR_PTR(-EBUSY);
5030-
}
50315016

5032-
mutex_unlock(&kvm->arch.config_lock);
5017+
if (!test_bit(KVM_ARCH_FLAG_ID_REGS_INITIALIZED, &kvm->arch.flags))
5018+
return NULL;
50335019

5034-
return iter;
5020+
return (void *)idregs_debug_find(kvm, *pos);
50355021
}
50365022

50375023
static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos)
@@ -5040,37 +5026,19 @@ static void *idregs_debug_next(struct seq_file *s, void *v, loff_t *pos)
50405026

50415027
(*pos)++;
50425028

5043-
if (idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter + 1)) {
5044-
kvm->arch.idreg_debugfs_iter++;
5045-
5046-
return &kvm->arch.idreg_debugfs_iter;
5047-
}
5048-
5049-
return NULL;
5029+
return (void *)idregs_debug_find(kvm, *pos);
50505030
}
50515031

50525032
static void idregs_debug_stop(struct seq_file *s, void *v)
50535033
{
5054-
struct kvm *kvm = s->private;
5055-
5056-
if (IS_ERR(v))
5057-
return;
5058-
5059-
mutex_lock(&kvm->arch.config_lock);
5060-
5061-
kvm->arch.idreg_debugfs_iter = ~0;
5062-
5063-
mutex_unlock(&kvm->arch.config_lock);
50645034
}
50655035

50665036
static int idregs_debug_show(struct seq_file *s, void *v)
50675037
{
5068-
const struct sys_reg_desc *desc;
5038+
const struct sys_reg_desc *desc = v;
50695039
struct kvm *kvm = s->private;
50705040

5071-
desc = idregs_debug_find(kvm, kvm->arch.idreg_debugfs_iter);
5072-
5073-
if (!desc->name)
5041+
if (!desc)
50745042
return 0;
50755043

50765044
seq_printf(s, "%20s:\t%016llx\n",
@@ -5090,8 +5058,6 @@ DEFINE_SEQ_ATTRIBUTE(idregs_debug);
50905058

50915059
void kvm_sys_regs_create_debugfs(struct kvm *kvm)
50925060
{
5093-
kvm->arch.idreg_debugfs_iter = ~0;
5094-
50955061
debugfs_create_file("idregs", 0444, kvm->debugfs_dentry, kvm,
50965062
&idregs_debug_fops);
50975063
}

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

Lines changed: 32 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,9 @@
2525
struct vgic_state_iter {
2626
int nr_cpus;
2727
int nr_spis;
28-
int nr_lpis;
2928
int dist_id;
3029
int vcpu_id;
3130
unsigned long intid;
32-
int lpi_idx;
3331
};
3432

3533
static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter)
@@ -45,13 +43,15 @@ static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter)
4543
* Let the xarray drive the iterator after the last SPI, as the iterator
4644
* has exhausted the sequentially-allocated INTID space.
4745
*/
48-
if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1) &&
49-
iter->nr_lpis) {
50-
if (iter->lpi_idx < iter->nr_lpis)
51-
xa_find_after(&dist->lpi_xa, &iter->intid,
52-
VGIC_LPI_MAX_INTID,
53-
LPI_XA_MARK_DEBUG_ITER);
54-
iter->lpi_idx++;
46+
if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS - 1)) {
47+
if (iter->intid == VGIC_LPI_MAX_INTID + 1)
48+
return;
49+
50+
rcu_read_lock();
51+
if (!xa_find_after(&dist->lpi_xa, &iter->intid,
52+
VGIC_LPI_MAX_INTID, XA_PRESENT))
53+
iter->intid = VGIC_LPI_MAX_INTID + 1;
54+
rcu_read_unlock();
5555
return;
5656
}
5757

@@ -61,44 +61,21 @@ static void iter_next(struct kvm *kvm, struct vgic_state_iter *iter)
6161
iter->intid = 0;
6262
}
6363

64-
static int iter_mark_lpis(struct kvm *kvm)
64+
static int vgic_count_lpis(struct kvm *kvm)
6565
{
6666
struct vgic_dist *dist = &kvm->arch.vgic;
67-
unsigned long intid, flags;
6867
struct vgic_irq *irq;
68+
unsigned long intid;
6969
int nr_lpis = 0;
7070

71-
xa_lock_irqsave(&dist->lpi_xa, flags);
72-
73-
xa_for_each(&dist->lpi_xa, intid, irq) {
74-
if (!vgic_try_get_irq_ref(irq))
75-
continue;
76-
77-
__xa_set_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);
71+
rcu_read_lock();
72+
xa_for_each(&dist->lpi_xa, intid, irq)
7873
nr_lpis++;
79-
}
80-
81-
xa_unlock_irqrestore(&dist->lpi_xa, flags);
74+
rcu_read_unlock();
8275

8376
return nr_lpis;
8477
}
8578

86-
static void iter_unmark_lpis(struct kvm *kvm)
87-
{
88-
struct vgic_dist *dist = &kvm->arch.vgic;
89-
unsigned long intid, flags;
90-
struct vgic_irq *irq;
91-
92-
xa_for_each_marked(&dist->lpi_xa, intid, irq, LPI_XA_MARK_DEBUG_ITER) {
93-
xa_lock_irqsave(&dist->lpi_xa, flags);
94-
__xa_clear_mark(&dist->lpi_xa, intid, LPI_XA_MARK_DEBUG_ITER);
95-
xa_unlock_irqrestore(&dist->lpi_xa, flags);
96-
97-
/* vgic_put_irq() expects to be called outside of the xa_lock */
98-
vgic_put_irq(kvm, irq);
99-
}
100-
}
101-
10279
static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
10380
loff_t pos)
10481
{
@@ -108,8 +85,6 @@ static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
10885

10986
iter->nr_cpus = nr_cpus;
11087
iter->nr_spis = kvm->arch.vgic.nr_spis;
111-
if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
112-
iter->nr_lpis = iter_mark_lpis(kvm);
11388

11489
/* Fast forward to the right position if needed */
11590
while (pos--)
@@ -121,80 +96,64 @@ static bool end_of_vgic(struct vgic_state_iter *iter)
12196
return iter->dist_id > 0 &&
12297
iter->vcpu_id == iter->nr_cpus &&
12398
iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS) &&
124-
(!iter->nr_lpis || iter->lpi_idx > iter->nr_lpis);
99+
iter->intid > VGIC_LPI_MAX_INTID;
125100
}
126101

127102
static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
128103
{
129104
struct kvm *kvm = s->private;
130105
struct vgic_state_iter *iter;
131106

132-
mutex_lock(&kvm->arch.config_lock);
133-
iter = kvm->arch.vgic.iter;
134-
if (iter) {
135-
iter = ERR_PTR(-EBUSY);
136-
goto out;
137-
}
138-
139107
iter = kmalloc(sizeof(*iter), GFP_KERNEL);
140-
if (!iter) {
141-
iter = ERR_PTR(-ENOMEM);
142-
goto out;
143-
}
108+
if (!iter)
109+
return ERR_PTR(-ENOMEM);
144110

145111
iter_init(kvm, iter, *pos);
146-
kvm->arch.vgic.iter = iter;
147112

148-
if (end_of_vgic(iter))
113+
if (end_of_vgic(iter)) {
114+
kfree(iter);
149115
iter = NULL;
150-
out:
151-
mutex_unlock(&kvm->arch.config_lock);
116+
}
117+
152118
return iter;
153119
}
154120

155121
static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
156122
{
157123
struct kvm *kvm = s->private;
158-
struct vgic_state_iter *iter = kvm->arch.vgic.iter;
124+
struct vgic_state_iter *iter = v;
159125

160126
++*pos;
161127
iter_next(kvm, iter);
162-
if (end_of_vgic(iter))
128+
if (end_of_vgic(iter)) {
129+
kfree(iter);
163130
iter = NULL;
131+
}
164132
return iter;
165133
}
166134

167135
static void vgic_debug_stop(struct seq_file *s, void *v)
168136
{
169-
struct kvm *kvm = s->private;
170-
struct vgic_state_iter *iter;
137+
struct vgic_state_iter *iter = v;
171138

172-
/*
173-
* If the seq file wasn't properly opened, there's nothing to clearn
174-
* up.
175-
*/
176-
if (IS_ERR(v))
139+
if (IS_ERR_OR_NULL(v))
177140
return;
178141

179-
mutex_lock(&kvm->arch.config_lock);
180-
iter = kvm->arch.vgic.iter;
181-
iter_unmark_lpis(kvm);
182142
kfree(iter);
183-
kvm->arch.vgic.iter = NULL;
184-
mutex_unlock(&kvm->arch.config_lock);
185143
}
186144

187145
static void print_dist_state(struct seq_file *s, struct vgic_dist *dist,
188146
struct vgic_state_iter *iter)
189147
{
190148
bool v3 = dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3;
149+
struct kvm *kvm = s->private;
191150

192151
seq_printf(s, "Distributor\n");
193152
seq_printf(s, "===========\n");
194153
seq_printf(s, "vgic_model:\t%s\n", v3 ? "GICv3" : "GICv2");
195154
seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
196155
if (v3)
197-
seq_printf(s, "nr_lpis:\t%d\n", iter->nr_lpis);
156+
seq_printf(s, "nr_lpis:\t%d\n", vgic_count_lpis(kvm));
198157
seq_printf(s, "enabled:\t%d\n", dist->enabled);
199158
seq_printf(s, "\n");
200159

@@ -291,16 +250,13 @@ static int vgic_debug_show(struct seq_file *s, void *v)
291250
if (iter->vcpu_id < iter->nr_cpus)
292251
vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
293252

294-
/*
295-
* Expect this to succeed, as iter_mark_lpis() takes a reference on
296-
* every LPI to be visited.
297-
*/
298253
if (iter->intid < VGIC_NR_PRIVATE_IRQS)
299254
irq = vgic_get_vcpu_irq(vcpu, iter->intid);
300255
else
301256
irq = vgic_get_irq(kvm, iter->intid);
302-
if (WARN_ON_ONCE(!irq))
303-
return -EINVAL;
257+
258+
if (!irq)
259+
return 0;
304260

305261
raw_spin_lock_irqsave(&irq->irq_lock, flags);
306262
print_irq_state(s, irq, vcpu);

include/kvm/arm_vgic.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -300,12 +300,8 @@ struct vgic_dist {
300300
*/
301301
u64 propbaser;
302302

303-
#define LPI_XA_MARK_DEBUG_ITER XA_MARK_0
304303
struct xarray lpi_xa;
305304

306-
/* used by vgic-debug */
307-
struct vgic_state_iter *iter;
308-
309305
/*
310306
* GICv4 ITS per-VM data, containing the IRQ domain, the VPE
311307
* array, the property table pointer as well as allocation

0 commit comments

Comments
 (0)