Module Name: src Committed By: jmcneill Date: Fri Nov 23 16:01:27 UTC 2018
Modified Files: src/sys/arch/arm/cortex: gicv3_its.c Log Message: Only allocate what we need for ITT tables To generate a diff of this commit: cvs rdiff -u -r1.6 -r1.7 src/sys/arch/arm/cortex/gicv3_its.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/arch/arm/cortex/gicv3_its.c diff -u src/sys/arch/arm/cortex/gicv3_its.c:1.6 src/sys/arch/arm/cortex/gicv3_its.c:1.7 --- src/sys/arch/arm/cortex/gicv3_its.c:1.6 Fri Nov 23 11:48:12 2018 +++ src/sys/arch/arm/cortex/gicv3_its.c Fri Nov 23 16:01:27 2018 @@ -1,4 +1,4 @@ -/* $NetBSD: gicv3_its.c,v 1.6 2018/11/23 11:48:12 jmcneill Exp $ */ +/* $NetBSD: gicv3_its.c,v 1.7 2018/11/23 16:01:27 jmcneill Exp $ */ /*- * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -32,12 +32,13 @@ #define _INTR_PRIVATE #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.6 2018/11/23 11:48:12 jmcneill Exp $"); +__KERNEL_RCSID(0, "$NetBSD: gicv3_its.c,v 1.7 2018/11/23 16:01:27 jmcneill Exp $"); #include <sys/param.h> #include <sys/kmem.h> #include <sys/bus.h> #include <sys/cpu.h> +#include <sys/bitops.h> #include <uvm/uvm.h> @@ -281,19 +282,23 @@ gicv3_its_devid(pci_chipset_tag_t pc, pc return (b << 8) | (d << 3) | f; } -static void -gicv3_its_device_map(struct gicv3_its *its, uint32_t devid) +static int +gicv3_its_device_map(struct gicv3_its *its, uint32_t devid, u_int count) { struct gicv3_its_device *dev; LIST_FOREACH(dev, &its->its_devices, dev_list) if (dev->dev_id == devid) - return; + return EEXIST; + + const u_int vectors = MAX(2, count); + if (!powerof2(vectors)) + return EINVAL; const uint64_t typer = gits_read_8(its, GITS_TYPER); const u_int id_bits = __SHIFTOUT(typer, GITS_TYPER_ID_bits) + 1; const u_int itt_entry_size = __SHIFTOUT(typer, GITS_TYPER_ITT_entry_size) + 1; - const u_int itt_size = roundup2((itt_entry_size * (1 << id_bits)) / NBBY, GITS_ITT_ALIGN); + const u_int itt_size = roundup(vectors * itt_entry_size, GITS_ITT_ALIGN); dev = kmem_alloc(sizeof(*dev), KM_SLEEP); dev->dev_id = devid; @@ -305,6 +310,8 @@ gicv3_its_device_map(struct gicv3_its *i */ gits_command_mapd(its, devid, dev->dev_itt.segs[0].ds_addr, id_bits - 1, true); gits_wait(its); + + return 0; } static void @@ -414,7 +421,8 @@ gicv3_its_msi_alloc(struct arm_pci_msi * const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); - gicv3_its_device_map(its, devid); + if (gicv3_its_device_map(its, devid, *count) != 0) + return NULL; vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); for (n = 0; n < *count; n++) { @@ -479,7 +487,10 @@ gicv3_its_msix_alloc(struct arm_pci_msi const uint32_t devid = gicv3_its_devid(pa->pa_pc, pa->pa_tag); - gicv3_its_device_map(its, devid); + if (gicv3_its_device_map(its, devid, *count) != 0) { + bus_space_unmap(bst, bsh, bsz); + return NULL; + } vectors = kmem_alloc(sizeof(*vectors) * *count, KM_SLEEP); for (n = 0; n < *count; n++) {