Re: [PATCH v2 2/4] irqchip/gic-v4: Unwind what its_alloc_vcpu_irqs() allocated on failure
Yao Yuan <[email protected]>
| Newsgroups | org.infradead.lists.linux-arm-kernel,dev.linux.lists.kvmarm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <newqqvl3kuyv3tzlmg5gvt6j2bqf4htk4rwotawrhfud4fv3dr@pcd3uodxdsbj> |
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 <[email protected]> > > Fixes: 6d31b6ff985d ("irqchip/gic-v4.1: Add VSGI allocation/teardown") > Signed-off-by: Fuad Tabba <[email protected]> > --- > 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 >