vgic_init() compares created_vcpus with online_vcpus to detect a vCPU being created. However, CTRL_INIT only holds config_lock, while admission of new vCPUs and updates to created_vcpus are protected by kvm->lock. A concurrent KVM_CREATE_VCPU can therefore increment created_vcpus after vgic_init() checks the counters, then block on config_lock before publishing the new vCPU. For a GICv4 VM, vgic_v4_init() consequently sizes its vPE array using a stale online_vcpus value, leaving no vPE entry for the new vCPU once its creation completes. The upcoming GICv5 IRS support would hit the same issue when sizing its doorbell domain. Hold kvm->lock around CTRL_INIT. The existing counter check detects a vCPU creation already in progress, while the lock prevents a new one from starting until initialisation has completed. Fixes: f00327731131 ("KVM: arm64: Use config_lock to protect vgic state") Reported-by: Sashiko Link: https://lore.kernel.org/r/20260807124506.ED85C1F000E9@smtp.kernel.org Signed-off-by: Sascha Bischoff --- arch/arm64/kvm/vgic/vgic-kvm-device.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kvm/vgic/vgic-kvm-device.c b/arch/arm64/kvm/vgic/vgic-kvm-device.c index 90be99443df3b..219881915bf41 100644 --- a/arch/arm64/kvm/vgic/vgic-kvm-device.c +++ b/arch/arm64/kvm/vgic/vgic-kvm-device.c @@ -255,9 +255,11 @@ static int vgic_set_common_attr(struct kvm_device *dev, case KVM_DEV_ARM_VGIC_GRP_CTRL: { switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: + mutex_lock(&dev->kvm->lock); mutex_lock(&dev->kvm->arch.config_lock); r = vgic_init(dev->kvm); mutex_unlock(&dev->kvm->arch.config_lock); + mutex_unlock(&dev->kvm->lock); return r; case KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES: /* -- 2.34.1