[tip: irq/drivers] irqchip/gic-v3-its: Don't free a vPE table shared with another ITS

From: tip-bot2 for Fuad Tabba

Date: Thu Oct 15 2026 - 06:22:09 EST


The following commit has been merged into the irq/drivers branch of tip:

Commit-ID: 32e056cc1d1582951f981113ca8b98914f29c32a
Gitweb: https://git.kernel.org/tip/32e056cc1d1582951f981113ca8b98914f29c32a
Author: Fuad Tabba <fuad.tabba@xxxxxxxxx>
AuthorDate: Fri, 25 Sep 2026 09:49:58 +01:00
Committer: Thomas Gleixner <tglx@xxxxxxxxxx>
CommitterDate: Thu, 15 Oct 2026 11:55:41 +02:00

irqchip/gic-v3-its: Don't free a vPE table shared with another ITS

On GICv4.1, its_alloc_tables() copies a sibling's vPE table baser
rather than allocating one, but its_free_tables() frees it like the
rest. A probe failure on the copying ITS then frees pages the enabled
sibling still points GITS_BASER2 at, and the kernel comes up running
on that sibling.

Mark a shared table so its_free_tables() skips it.

Fixes: 5e5168461c22c ("irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation")
Signed-off-by: Fuad Tabba <fuad.tabba@xxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxx>
Reviewed-by: Marc Zyngier <maz@xxxxxxxxxx>
Link: https://patch.msgid.link/20260925085000.753400-2-fuad.tabba@xxxxxxxxx
---
drivers/irqchip/irq-gic-v3-its.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 872d342..259ec0c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -87,6 +87,8 @@ struct its_baser {
u64 val;
u32 order;
u32 psz;
+ /* Inherited from a sibling ITS, not freed here */
+ bool shared;
};

struct its_device;
@@ -2605,7 +2607,8 @@ static void its_free_tables(struct its_node *its)

for (i = 0; i < GITS_BASER_NR_REGS; i++) {
if (its->tables[i].base) {
- its_free_pages(its->tables[i].base, its->tables[i].order);
+ if (!its->tables[i].shared)
+ its_free_pages(its->tables[i].base, its->tables[i].order);
its->tables[i].base = NULL;
}
}
@@ -2704,6 +2707,7 @@ static int its_alloc_tables(struct its_node *its)
WARN_ON(i != 2);
if ((sibling = find_sibling_its(its))) {
*baser = sibling->tables[2];
+ baser->shared = true;
its_write_baser(its, baser, baser->val);
continue;
}