Skip to content

Commit b3aa928

Browse files
author
Marc Zyngier
committed
KVM: arm64: vgic: Hoist SGI/PPI alloc from vgic_init() to kvm_create_vgic()
If userspace creates vcpus, then a vgic, we end-up in a situation where irqchip_in_kernel() will return true, but no private interrupt has been allocated for these vcpus. This situation will continue until userspace initialises the vgic, at which point we fix the early vcpus. Should a vcpu run or be initialised in the interval, bad things may happen. An obvious solution is to move this fix-up phase to the point where the vgic is created. This ensures that from that point onwards, all vcpus have their private interrupts, as new vcpus will directly allocate them. With that, we have the invariant that when irqchip_in_kernel() is true, all vcpus have their private interrupts. Reported-by: Alexander Potapenko <[email protected]> Reviewed-by: Oliver Upton <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent e6e3e00 commit b3aa928

File tree

1 file changed

+37
-37
lines changed

1 file changed

+37
-37
lines changed

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

+37-37
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@
3434
*
3535
* CPU Interface:
3636
*
37-
* - kvm_vgic_vcpu_init(): initialization of static data that
38-
* doesn't depend on any sizing information or emulation type. No
39-
* allocation is allowed there.
37+
* - kvm_vgic_vcpu_init(): initialization of static data that doesn't depend
38+
* on any sizing information. Private interrupts are allocated if not
39+
* already allocated at vgic-creation time.
4040
*/
4141

4242
/* EARLY INIT */
@@ -58,6 +58,8 @@ void kvm_vgic_early_init(struct kvm *kvm)
5858

5959
/* CREATION */
6060

61+
static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type);
62+
6163
/**
6264
* kvm_vgic_create: triggered by the instantiation of the VGIC device by
6365
* user space, either through the legacy KVM_CREATE_IRQCHIP ioctl (v2 only)
@@ -112,6 +114,22 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
112114
goto out_unlock;
113115
}
114116

117+
kvm_for_each_vcpu(i, vcpu, kvm) {
118+
ret = vgic_allocate_private_irqs_locked(vcpu, type);
119+
if (ret)
120+
break;
121+
}
122+
123+
if (ret) {
124+
kvm_for_each_vcpu(i, vcpu, kvm) {
125+
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
126+
kfree(vgic_cpu->private_irqs);
127+
vgic_cpu->private_irqs = NULL;
128+
}
129+
130+
goto out_unlock;
131+
}
132+
115133
kvm->arch.vgic.in_kernel = true;
116134
kvm->arch.vgic.vgic_model = type;
117135

@@ -180,7 +198,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
180198
return 0;
181199
}
182200

183-
static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu)
201+
static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu, u32 type)
184202
{
185203
struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
186204
int i;
@@ -218,17 +236,28 @@ static int vgic_allocate_private_irqs_locked(struct kvm_vcpu *vcpu)
218236
/* PPIs */
219237
irq->config = VGIC_CONFIG_LEVEL;
220238
}
239+
240+
switch (type) {
241+
case KVM_DEV_TYPE_ARM_VGIC_V3:
242+
irq->group = 1;
243+
irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
244+
break;
245+
case KVM_DEV_TYPE_ARM_VGIC_V2:
246+
irq->group = 0;
247+
irq->targets = BIT(vcpu->vcpu_id);
248+
break;
249+
}
221250
}
222251

223252
return 0;
224253
}
225254

226-
static int vgic_allocate_private_irqs(struct kvm_vcpu *vcpu)
255+
static int vgic_allocate_private_irqs(struct kvm_vcpu *vcpu, u32 type)
227256
{
228257
int ret;
229258

230259
mutex_lock(&vcpu->kvm->arch.config_lock);
231-
ret = vgic_allocate_private_irqs_locked(vcpu);
260+
ret = vgic_allocate_private_irqs_locked(vcpu, type);
232261
mutex_unlock(&vcpu->kvm->arch.config_lock);
233262

234263
return ret;
@@ -258,7 +287,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
258287
if (!irqchip_in_kernel(vcpu->kvm))
259288
return 0;
260289

261-
ret = vgic_allocate_private_irqs(vcpu);
290+
ret = vgic_allocate_private_irqs(vcpu, dist->vgic_model);
262291
if (ret)
263292
return ret;
264293

@@ -295,7 +324,7 @@ int vgic_init(struct kvm *kvm)
295324
{
296325
struct vgic_dist *dist = &kvm->arch.vgic;
297326
struct kvm_vcpu *vcpu;
298-
int ret = 0, i;
327+
int ret = 0;
299328
unsigned long idx;
300329

301330
lockdep_assert_held(&kvm->arch.config_lock);
@@ -315,35 +344,6 @@ int vgic_init(struct kvm *kvm)
315344
if (ret)
316345
goto out;
317346

318-
/* Initialize groups on CPUs created before the VGIC type was known */
319-
kvm_for_each_vcpu(idx, vcpu, kvm) {
320-
ret = vgic_allocate_private_irqs_locked(vcpu);
321-
if (ret)
322-
goto out;
323-
324-
for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
325-
struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
326-
327-
switch (dist->vgic_model) {
328-
case KVM_DEV_TYPE_ARM_VGIC_V3:
329-
irq->group = 1;
330-
irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
331-
break;
332-
case KVM_DEV_TYPE_ARM_VGIC_V2:
333-
irq->group = 0;
334-
irq->targets = 1U << idx;
335-
break;
336-
default:
337-
ret = -EINVAL;
338-
}
339-
340-
vgic_put_irq(kvm, irq);
341-
342-
if (ret)
343-
goto out;
344-
}
345-
}
346-
347347
/*
348348
* If we have GICv4.1 enabled, unconditionally request enable the
349349
* v4 support so that we get HW-accelerated vSGIs. Otherwise, only

0 commit comments

Comments
 (0)