]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
irqchip/gic-v3-its: Avoid truncating memory addresses
authorArnd Bergmann <arnd@arndb.de>
Mon, 19 Jan 2026 20:15:12 +0000 (21:15 +0100)
committerThomas Gleixner <tglx@kernel.org>
Tue, 20 Jan 2026 09:11:29 +0000 (10:11 +0100)
On 32-bit machines with CONFIG_ARM_LPAE, it is possible for lowmem
allocations to be backed by addresses physical memory above the 32-bit
address limit, as found while experimenting with larger VMSPLIT
configurations.

This caused the qemu virt model to crash in the GICv3 driver, which
allocates the 'itt' object using GFP_KERNEL. Since all memory below
the 4GB physical address limit is in ZONE_DMA in this configuration,
kmalloc() defaults to higher addresses for ZONE_NORMAL, and the
ITS driver stores the physical address in a 32-bit 'unsigned long'
variable.

Change the itt_addr variable to the correct phys_addr_t type instead,
along with all other variables in this driver that hold a physical
address.

The gicv5 driver correctly uses u64 variables, while all other irqchip
drivers don't call virt_to_phys or similar interfaces. It's expected that
other device drivers have similar issues, but fixing this one is
sufficient for booting a virtio based guest.

Fixes: cc2d3216f53c ("irqchip: GICv3: ITS command queue")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Reviewed-by: Marc Zyngier <maz@kernel.org>
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/20260119201603.2713066-1-arnd@kernel.org
drivers/irqchip/irq-gic-v3-its.c

index ada585bfa4517d1375c4b30e1b32db5c5a509a60..2988def30972b548d13ccaccbe0a9e4338f2959a 100644 (file)
@@ -709,7 +709,7 @@ static struct its_collection *its_build_mapd_cmd(struct its_node *its,
                                                 struct its_cmd_block *cmd,
                                                 struct its_cmd_desc *desc)
 {
-       unsigned long itt_addr;
+       phys_addr_t itt_addr;
        u8 size = ilog2(desc->its_mapd_cmd.dev->nr_ites);
 
        itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
@@ -879,7 +879,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
                                           struct its_cmd_desc *desc)
 {
        struct its_vpe *vpe = valid_vpe(its, desc->its_vmapp_cmd.vpe);
-       unsigned long vpt_addr, vconf_addr;
+       phys_addr_t vpt_addr, vconf_addr;
        u64 target;
        bool alloc;
 
@@ -2477,10 +2477,10 @@ retry_baser:
        baser->psz = psz;
        tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
 
-       pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
+       pr_info("ITS@%pa: allocated %d %s @%llx (%s, esz %d, psz %dK, shr %d)\n",
                &its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
                its_base_type_string[type],
-               (unsigned long)virt_to_phys(base),
+               (u64)virt_to_phys(base),
                indirect ? "indirect" : "flat", (int)esz,
                psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);