Skip to content

Commit f003277

Browse files
ouptonMarc Zyngier
authored andcommitted
KVM: arm64: Use config_lock to protect vgic state
Almost all of the vgic state is VM-scoped but accessed from the context of a vCPU. These accesses were serialized on the kvm->lock which cannot be nested within a vcpu->mutex critical section. Move over the vgic state to using the config_lock. Tweak the lock ordering where necessary to ensure that the config_lock is acquired after the vcpu->mutex. Acquire the config_lock in kvm_vgic_create() to avoid a race between the converted flows and GIC creation. Where necessary, continue to acquire kvm->lock to avoid a race with vCPU creation (i.e. flows that use lock_all_vcpus()). Finally, promote the locking expectations in comments to lockdep assertions and update the locking documentation for the config_lock as well as vcpu->mutex. Cc: stable@vger.kernel.org Signed-off-by: Oliver Upton <oliver.upton@linux.dev> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20230327164747.2466958-5-oliver.upton@linux.dev
1 parent 4bba7f7 commit f003277

8 files changed

Lines changed: 88 additions & 60 deletions

File tree

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
8585
struct kvm *kvm = s->private;
8686
struct vgic_state_iter *iter;
8787

88-
mutex_lock(&kvm->lock);
88+
mutex_lock(&kvm->arch.config_lock);
8989
iter = kvm->arch.vgic.iter;
9090
if (iter) {
9191
iter = ERR_PTR(-EBUSY);
@@ -104,7 +104,7 @@ static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
104104
if (end_of_vgic(iter))
105105
iter = NULL;
106106
out:
107-
mutex_unlock(&kvm->lock);
107+
mutex_unlock(&kvm->arch.config_lock);
108108
return iter;
109109
}
110110

@@ -132,12 +132,12 @@ static void vgic_debug_stop(struct seq_file *s, void *v)
132132
if (IS_ERR(v))
133133
return;
134134

135-
mutex_lock(&kvm->lock);
135+
mutex_lock(&kvm->arch.config_lock);
136136
iter = kvm->arch.vgic.iter;
137137
kfree(iter->lpi_array);
138138
kfree(iter);
139139
kvm->arch.vgic.iter = NULL;
140-
mutex_unlock(&kvm->lock);
140+
mutex_unlock(&kvm->arch.config_lock);
141141
}
142142

143143
static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)

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

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
7474
unsigned long i;
7575
int ret;
7676

77-
if (irqchip_in_kernel(kvm))
78-
return -EEXIST;
79-
8077
/*
8178
* This function is also called by the KVM_CREATE_IRQCHIP handler,
8279
* which had no chance yet to check the availability of the GICv2
@@ -87,10 +84,20 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
8784
!kvm_vgic_global_state.can_emulate_gicv2)
8885
return -ENODEV;
8986

87+
/* Must be held to avoid race with vCPU creation */
88+
lockdep_assert_held(&kvm->lock);
89+
9090
ret = -EBUSY;
9191
if (!lock_all_vcpus(kvm))
9292
return ret;
9393

94+
mutex_lock(&kvm->arch.config_lock);
95+
96+
if (irqchip_in_kernel(kvm)) {
97+
ret = -EEXIST;
98+
goto out_unlock;
99+
}
100+
94101
kvm_for_each_vcpu(i, vcpu, kvm) {
95102
if (vcpu_has_run_once(vcpu))
96103
goto out_unlock;
@@ -118,6 +125,7 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
118125
INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
119126

120127
out_unlock:
128+
mutex_unlock(&kvm->arch.config_lock);
121129
unlock_all_vcpus(kvm);
122130
return ret;
123131
}
@@ -227,9 +235,9 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
227235
* KVM io device for the redistributor that belongs to this VCPU.
228236
*/
229237
if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
230-
mutex_lock(&vcpu->kvm->lock);
238+
mutex_lock(&vcpu->kvm->arch.config_lock);
231239
ret = vgic_register_redist_iodev(vcpu);
232-
mutex_unlock(&vcpu->kvm->lock);
240+
mutex_unlock(&vcpu->kvm->arch.config_lock);
233241
}
234242
return ret;
235243
}
@@ -250,7 +258,6 @@ static void kvm_vgic_vcpu_enable(struct kvm_vcpu *vcpu)
250258
* The function is generally called when nr_spis has been explicitly set
251259
* by the guest through the KVM DEVICE API. If not nr_spis is set to 256.
252260
* vgic_initialized() returns true when this function has succeeded.
253-
* Must be called with kvm->lock held!
254261
*/
255262
int vgic_init(struct kvm *kvm)
256263
{
@@ -259,6 +266,8 @@ int vgic_init(struct kvm *kvm)
259266
int ret = 0, i;
260267
unsigned long idx;
261268

269+
lockdep_assert_held(&kvm->arch.config_lock);
270+
262271
if (vgic_initialized(kvm))
263272
return 0;
264273

@@ -373,12 +382,13 @@ void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
373382
vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF;
374383
}
375384

376-
/* To be called with kvm->lock held */
377385
static void __kvm_vgic_destroy(struct kvm *kvm)
378386
{
379387
struct kvm_vcpu *vcpu;
380388
unsigned long i;
381389

390+
lockdep_assert_held(&kvm->arch.config_lock);
391+
382392
vgic_debug_destroy(kvm);
383393

384394
kvm_for_each_vcpu(i, vcpu, kvm)
@@ -389,9 +399,9 @@ static void __kvm_vgic_destroy(struct kvm *kvm)
389399

390400
void kvm_vgic_destroy(struct kvm *kvm)
391401
{
392-
mutex_lock(&kvm->lock);
402+
mutex_lock(&kvm->arch.config_lock);
393403
__kvm_vgic_destroy(kvm);
394-
mutex_unlock(&kvm->lock);
404+
mutex_unlock(&kvm->arch.config_lock);
395405
}
396406

397407
/**
@@ -414,9 +424,9 @@ int vgic_lazy_init(struct kvm *kvm)
414424
if (kvm->arch.vgic.vgic_model != KVM_DEV_TYPE_ARM_VGIC_V2)
415425
return -EBUSY;
416426

417-
mutex_lock(&kvm->lock);
427+
mutex_lock(&kvm->arch.config_lock);
418428
ret = vgic_init(kvm);
419-
mutex_unlock(&kvm->lock);
429+
mutex_unlock(&kvm->arch.config_lock);
420430
}
421431

422432
return ret;
@@ -441,7 +451,7 @@ int kvm_vgic_map_resources(struct kvm *kvm)
441451
if (likely(vgic_ready(kvm)))
442452
return 0;
443453

444-
mutex_lock(&kvm->lock);
454+
mutex_lock(&kvm->arch.config_lock);
445455
if (vgic_ready(kvm))
446456
goto out;
447457

@@ -459,7 +469,7 @@ int kvm_vgic_map_resources(struct kvm *kvm)
459469
dist->ready = true;
460470

461471
out:
462-
mutex_unlock(&kvm->lock);
472+
mutex_unlock(&kvm->arch.config_lock);
463473
return ret;
464474
}
465475

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2045,6 +2045,13 @@ static int vgic_its_attr_regs_access(struct kvm_device *dev,
20452045

20462046
mutex_lock(&dev->kvm->lock);
20472047

2048+
if (!lock_all_vcpus(dev->kvm)) {
2049+
mutex_unlock(&dev->kvm->lock);
2050+
return -EBUSY;
2051+
}
2052+
2053+
mutex_lock(&dev->kvm->arch.config_lock);
2054+
20482055
if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base)) {
20492056
ret = -ENXIO;
20502057
goto out;
@@ -2058,11 +2065,6 @@ static int vgic_its_attr_regs_access(struct kvm_device *dev,
20582065
goto out;
20592066
}
20602067

2061-
if (!lock_all_vcpus(dev->kvm)) {
2062-
ret = -EBUSY;
2063-
goto out;
2064-
}
2065-
20662068
addr = its->vgic_its_base + offset;
20672069

20682070
len = region->access_flags & VGIC_ACCESS_64bit ? 8 : 4;
@@ -2076,8 +2078,9 @@ static int vgic_its_attr_regs_access(struct kvm_device *dev,
20762078
} else {
20772079
*reg = region->its_read(dev->kvm, its, addr, len);
20782080
}
2079-
unlock_all_vcpus(dev->kvm);
20802081
out:
2082+
mutex_unlock(&dev->kvm->arch.config_lock);
2083+
unlock_all_vcpus(dev->kvm);
20812084
mutex_unlock(&dev->kvm->lock);
20822085
return ret;
20832086
}
@@ -2757,6 +2760,8 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
27572760
return -EBUSY;
27582761
}
27592762

2763+
mutex_lock(&kvm->arch.config_lock);
2764+
27602765
switch (attr) {
27612766
case KVM_DEV_ARM_ITS_CTRL_RESET:
27622767
vgic_its_reset(kvm, its);
@@ -2769,6 +2774,7 @@ static int vgic_its_ctrl(struct kvm *kvm, struct vgic_its *its, u64 attr)
27692774
break;
27702775
}
27712776

2777+
mutex_unlock(&kvm->arch.config_lock);
27722778
unlock_all_vcpus(kvm);
27732779
mutex_unlock(&its->its_lock);
27742780
mutex_unlock(&kvm->lock);

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

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
4646
struct vgic_dist *vgic = &kvm->arch.vgic;
4747
int r;
4848

49-
mutex_lock(&kvm->lock);
49+
mutex_lock(&kvm->arch.config_lock);
5050
switch (FIELD_GET(KVM_ARM_DEVICE_TYPE_MASK, dev_addr->id)) {
5151
case KVM_VGIC_V2_ADDR_TYPE_DIST:
5252
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
@@ -68,7 +68,7 @@ int kvm_set_legacy_vgic_v2_addr(struct kvm *kvm, struct kvm_arm_device_addr *dev
6868
r = -ENODEV;
6969
}
7070

71-
mutex_unlock(&kvm->lock);
71+
mutex_unlock(&kvm->arch.config_lock);
7272

7373
return r;
7474
}
@@ -102,7 +102,7 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
102102
if (get_user(addr, uaddr))
103103
return -EFAULT;
104104

105-
mutex_lock(&kvm->lock);
105+
mutex_lock(&kvm->arch.config_lock);
106106
switch (attr->attr) {
107107
case KVM_VGIC_V2_ADDR_TYPE_DIST:
108108
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
@@ -191,7 +191,7 @@ static int kvm_vgic_addr(struct kvm *kvm, struct kvm_device_attr *attr, bool wri
191191
}
192192

193193
out:
194-
mutex_unlock(&kvm->lock);
194+
mutex_unlock(&kvm->arch.config_lock);
195195

196196
if (!r && !write)
197197
r = put_user(addr, uaddr);
@@ -227,24 +227,24 @@ static int vgic_set_common_attr(struct kvm_device *dev,
227227
(val & 31))
228228
return -EINVAL;
229229

230-
mutex_lock(&dev->kvm->lock);
230+
mutex_lock(&dev->kvm->arch.config_lock);
231231

232232
if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
233233
ret = -EBUSY;
234234
else
235235
dev->kvm->arch.vgic.nr_spis =
236236
val - VGIC_NR_PRIVATE_IRQS;
237237

238-
mutex_unlock(&dev->kvm->lock);
238+
mutex_unlock(&dev->kvm->arch.config_lock);
239239

240240
return ret;
241241
}
242242
case KVM_DEV_ARM_VGIC_GRP_CTRL: {
243243
switch (attr->attr) {
244244
case KVM_DEV_ARM_VGIC_CTRL_INIT:
245-
mutex_lock(&dev->kvm->lock);
245+
mutex_lock(&dev->kvm->arch.config_lock);
246246
r = vgic_init(dev->kvm);
247-
mutex_unlock(&dev->kvm->lock);
247+
mutex_unlock(&dev->kvm->arch.config_lock);
248248
return r;
249249
case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES:
250250
/*
@@ -260,7 +260,10 @@ static int vgic_set_common_attr(struct kvm_device *dev,
260260
mutex_unlock(&dev->kvm->lock);
261261
return -EBUSY;
262262
}
263+
264+
mutex_lock(&dev->kvm->arch.config_lock);
263265
r = vgic_v3_save_pending_tables(dev->kvm);
266+
mutex_unlock(&dev->kvm->arch.config_lock);
264267
unlock_all_vcpus(dev->kvm);
265268
mutex_unlock(&dev->kvm->lock);
266269
return r;
@@ -411,15 +414,17 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
411414

412415
mutex_lock(&dev->kvm->lock);
413416

417+
if (!lock_all_vcpus(dev->kvm)) {
418+
mutex_unlock(&dev->kvm->lock);
419+
return -EBUSY;
420+
}
421+
422+
mutex_lock(&dev->kvm->arch.config_lock);
423+
414424
ret = vgic_init(dev->kvm);
415425
if (ret)
416426
goto out;
417427

418-
if (!lock_all_vcpus(dev->kvm)) {
419-
ret = -EBUSY;
420-
goto out;
421-
}
422-
423428
switch (attr->group) {
424429
case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
425430
ret = vgic_v2_cpuif_uaccess(vcpu, is_write, addr, &val);
@@ -432,8 +437,9 @@ static int vgic_v2_attr_regs_access(struct kvm_device *dev,
432437
break;
433438
}
434439

435-
unlock_all_vcpus(dev->kvm);
436440
out:
441+
mutex_unlock(&dev->kvm->arch.config_lock);
442+
unlock_all_vcpus(dev->kvm);
437443
mutex_unlock(&dev->kvm->lock);
438444

439445
if (!ret && !is_write)
@@ -569,12 +575,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
569575

570576
mutex_lock(&dev->kvm->lock);
571577

572-
if (unlikely(!vgic_initialized(dev->kvm))) {
573-
ret = -EBUSY;
574-
goto out;
578+
if (!lock_all_vcpus(dev->kvm)) {
579+
mutex_unlock(&dev->kvm->lock);
580+
return -EBUSY;
575581
}
576582

577-
if (!lock_all_vcpus(dev->kvm)) {
583+
mutex_lock(&dev->kvm->arch.config_lock);
584+
585+
if (unlikely(!vgic_initialized(dev->kvm))) {
578586
ret = -EBUSY;
579587
goto out;
580588
}
@@ -609,8 +617,9 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
609617
break;
610618
}
611619

612-
unlock_all_vcpus(dev->kvm);
613620
out:
621+
mutex_unlock(&dev->kvm->arch.config_lock);
622+
unlock_all_vcpus(dev->kvm);
614623
mutex_unlock(&dev->kvm->lock);
615624

616625
if (!ret && uaccess && !is_write) {

arch/arm64/kvm/vgic/vgic-mmio-v3.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
111111
case GICD_CTLR: {
112112
bool was_enabled, is_hwsgi;
113113

114-
mutex_lock(&vcpu->kvm->lock);
114+
mutex_lock(&vcpu->kvm->arch.config_lock);
115115

116116
was_enabled = dist->enabled;
117117
is_hwsgi = dist->nassgireq;
@@ -139,7 +139,7 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
139139
else if (!was_enabled && dist->enabled)
140140
vgic_kick_vcpus(vcpu->kvm);
141141

142-
mutex_unlock(&vcpu->kvm->lock);
142+
mutex_unlock(&vcpu->kvm->arch.config_lock);
143143
break;
144144
}
145145
case GICD_TYPER:

0 commit comments

Comments
 (0)