Skip to content

Commit a24f1d8

Browse files
Marc Zyngiergregkh
authored andcommitted
KVM: arm64: Eagerly init vgic dist/redist on vgic creation
[ Upstream commit ac6769c ] If vgic_allocate_private_irqs_locked() fails for any odd reason, we exit kvm_vgic_create() early, leaving dist->rd_regions uninitialised. kvm_vgic_dist_destroy() then comes along and walks into the weeds trying to free the RDs. Got to love this stuff. Solve it by moving all the static initialisation early, and make sure that if we fail halfway, we're in a reasonable shape to perform the rest of the teardown. While at it, reset the vgic model on failure, just in case... Reported-by: syzbot+f6a46b038fc243ac0175@syzkaller.appspotmail.com Tested-by: syzbot+f6a46b038fc243ac0175@syzkaller.appspotmail.com Fixes: b3aa928 ("KVM: arm64: vgic: Hoist SGI/PPI alloc from vgic_init() to kvm_create_vgic()") Link: https://lore.kernel.org/r/69a2d58c.050a0220.3a55be.003b.GAE@google.com Link: https://patch.msgid.link/20260228164559.936268-1-maz@kernel.org Signed-off-by: Marc Zyngier <maz@kernel.org> Cc: stable@vger.kernel.org Signed-off-by: Sasha Levin <sashal@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 61f2d56 commit a24f1d8

1 file changed

Lines changed: 16 additions & 16 deletions

File tree

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

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,21 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
143143
kvm->arch.vgic.in_kernel = true;
144144
kvm->arch.vgic.vgic_model = type;
145145
kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST;
146+
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
147+
148+
aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC;
149+
pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC;
150+
151+
if (type == KVM_DEV_TYPE_ARM_VGIC_V2) {
152+
kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
153+
} else {
154+
INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
155+
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
156+
pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
157+
}
158+
159+
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0);
160+
kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1);
146161

147162
kvm_for_each_vcpu(i, vcpu, kvm) {
148163
ret = vgic_allocate_private_irqs_locked(vcpu, type);
@@ -157,25 +172,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
157172
vgic_cpu->private_irqs = NULL;
158173
}
159174

175+
kvm->arch.vgic.vgic_model = 0;
160176
goto out_unlock;
161177
}
162178

163-
kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
164-
165-
aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC;
166-
pfr1 = kvm_read_vm_id_reg(kvm, SYS_ID_PFR1_EL1) & ~ID_PFR1_EL1_GIC;
167-
168-
if (type == KVM_DEV_TYPE_ARM_VGIC_V2) {
169-
kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
170-
} else {
171-
INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
172-
aa64pfr0 |= SYS_FIELD_PREP_ENUM(ID_AA64PFR0_EL1, GIC, IMP);
173-
pfr1 |= SYS_FIELD_PREP_ENUM(ID_PFR1_EL1, GIC, GICv3);
174-
}
175-
176-
kvm_set_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1, aa64pfr0);
177-
kvm_set_vm_id_reg(kvm, SYS_ID_PFR1_EL1, pfr1);
178-
179179
if (type == KVM_DEV_TYPE_ARM_VGIC_V3)
180180
kvm->arch.vgic.nassgicap = system_supports_direct_sgis();
181181

0 commit comments

Comments
 (0)