Re: [PATCH v2 2/4] irqchip/gic-v4: Unwind what its_alloc_vcpu_irqs() allocated on failure
From: Yao Yuan
Date: Tue Aug 25 2026 - 05:12:16 EST
On Mon, Aug 24, 2026 at 08:42:43AM +0800, Fuad Tabba wrote:
> A failure in the its_alloc_vcpu_sgis() loop leaves behind both the SGI
> domains created for the vPEs below the failing index and the vPE irqs
> allocated before the loop, since irq_domain_remove() frees neither. Each
> leaked vPE takes its ITS state with it, a vpe_id and an LPI pending
> table.
>
> Free both from a second label before the existing unwind. With the
> freed pointers now cleared, its_free_sgi_irqs() can skip a vPE with no
> SGI domain and be reused there. The check has to precede the lookup:
> irq_find_mapping(NULL, 0) falls back to irq_default_domain, and the
> live irq it returns would then be freed.
Reviewed-by: Yuan Yao <yaoyuan@xxxxxxxxxxxxxxxxx>
>
> Fixes: 6d31b6ff985d ("irqchip/gic-v4.1: Add VSGI allocation/teardown")
> Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
> ---
> drivers/irqchip/irq-gic-v4.c | 14 ++++++++++++--
> 1 file changed, 12 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
> index 754839e409f88..f707a3cb281aa 100644
> --- a/drivers/irqchip/irq-gic-v4.c
> +++ b/drivers/irqchip/irq-gic-v4.c
> @@ -159,6 +159,8 @@ static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
> return -ENOMEM;
> }
>
> +static void its_free_sgi_irqs(struct its_vm *vm);
> +
> int its_alloc_vcpu_irqs(struct its_vm *vm)
> {
> int vpe_base_irq, i;
> @@ -189,11 +191,14 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
> vm->vpes[i]->irq = vpe_base_irq + i;
> ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
> if (ret)
> - goto err;
> + goto err_free_irqs;
> }
>
> return 0;
>
> +err_free_irqs:
> + its_free_sgi_irqs(vm);
> + irq_domain_free_irqs(vpe_base_irq, vm->nr_vpes);
> err:
> if (vm->domain) {
> irq_domain_remove(vm->domain);
> @@ -215,8 +220,13 @@ static void its_free_sgi_irqs(struct its_vm *vm)
> return;
>
> for (i = 0; i < vm->nr_vpes; i++) {
> - unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
> + unsigned int irq;
>
> + /* irq_find_mapping() falls back to the default domain on NULL. */
> + if (!vm->vpes[i]->sgi_domain)
> + continue;
> +
> + irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
> if (WARN_ON(!irq))
> continue;
>
> --
> 2.39.5
>