Re: [PATCH v2 3/4] KVM: arm64: vgic: Tear down what vgic_init() created when it fails
From: Yao Yuan
Date: Tue Aug 25 2026 - 05:19:46 EST
On Mon, Aug 24, 2026 at 08:42:44AM +0800, Fuad Tabba wrote:
> Once kvm_vgic_dist_init() has succeeded, every later failure in
> vgic_init() returns with the SPI array still allocated. A failure after
> vgic_v4_init() has also succeeded, which today means only
> kvm_vgic_setup_default_irq_routing(), leaves the vPE array behind as
> well.
>
> A failed vgic_init() leaves kvm_arch_vcpu_precreate() admitting new
> vCPUs, so a retry of KVM_DEV_ARM_VGIC_CTRL_INIT reaches
> vgic_v4_init()'s early return with an array that no longer covers every
> vCPU, and vgic_v3_load()'s WARN_ON(vgic_v4_load()) fires on the first
> one it misses.
>
> Release both on the two paths that can reach them, so the ioctl is all
> or nothing and a retry starts from scratch. dist->nr_spis stays frozen,
> since the SPI count cannot change once vgic_init() has supplied it.
>
> Fixes: 180ae7b11823 ("KVM: arm/arm64: Enable irqchip routing")
> Fixes: 74fe55dc9ab7 ("KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain")
> Reported-by: Sashiko <sashiko-bot@xxxxxxxxxx>
> Closes: https://lore.kernel.org/all/20260807105558.73D701F000E9@xxxxxxxxxxxxxxx/
> Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
> ---
> arch/arm64/kvm/vgic/vgic-init.c | 11 +++++++++--
> 1 file changed, 9 insertions(+), 2 deletions(-)
>
> diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
> index 4012df6002ea6..7493fded53acc 100644
> --- a/arch/arm64/kvm/vgic/vgic-init.c
> +++ b/arch/arm64/kvm/vgic/vgic-init.c
> @@ -462,7 +462,7 @@ int vgic_init(struct kvm *kvm)
> if (vgic_supports_direct_irqs(kvm)) {
> ret = vgic_v4_init(kvm);
> if (ret)
Hi Tabba,
> - return ret;
> + goto out_teardown;
The vigc_v4_init already called vgic_v4_teardown() in error path,
thus I think just free dist->spis is enough yet ?
> }
> } else {
> ret = vgic_v5_init(kvm);
> @@ -475,12 +475,19 @@ int vgic_init(struct kvm *kvm)
>
> ret = kvm_vgic_setup_default_irq_routing(kvm);
> if (ret)
> - return ret;
> + goto out_teardown;
>
> vgic_debug_init(kvm);
> dist->initialized = true;
>
> return 0;
> +
> +out_teardown:
> + vgic_v4_teardown(kvm);
> + kfree(dist->spis);
> + dist->spis = NULL;
> +
> + return ret;
> }
>
> static void kvm_vgic_dist_destroy(struct kvm *kvm)
> --
> 2.39.5
>