summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2024-06-23 21:58:35 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2024-06-23 21:58:35 +0000
commita58f820bc92a44aa5bf4bf0ff8c2bb3d4602e8f2 (patch)
treea7b402a42de689e5b5ddbfdd48d45c64c841b123 /sys/arch
parent2b32552445a970cb4c7d1a30f48cf53142c00cde (diff)
While Qualcomm Snapdragon X Elite (X1E80100) claims to support 32 device-id
bits, it only seems to allow a 4k pagesize with 8 bytes per entry. This is not enough to handle all 32 device-id bits, but we also don't necessarily need to handle all of them. Hence clamp down the number of maximum device IDs to as much as we can possibly configure in hardware. ok kettenis@
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/arm64/dev/agintc.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c
index e0fe1de31fb..79da7f4da7e 100644
--- a/sys/arch/arm64/dev/agintc.c
+++ b/sys/arch/arm64/dev/agintc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: agintc.c,v 1.57 2024/06/19 22:10:45 patrick Exp $ */
+/* $OpenBSD: agintc.c,v 1.58 2024/06/23 21:58:34 patrick Exp $ */
/*
* Copyright (c) 2007, 2009, 2011, 2017 Dale Rahn <drahn@dalerahn.com>
* Copyright (c) 2018 Mark Kettenis <kettenis@openbsd.org>
@@ -1516,6 +1516,7 @@ agintc_send_ipi(struct cpu_info *ci, int id)
#define GITS_BASER_PGSZ_4K (0ULL << 8)
#define GITS_BASER_PGSZ_16K (1ULL << 8)
#define GITS_BASER_PGSZ_64K (2ULL << 8)
+#define GITS_BASER_SZ_MASK (0xffULL)
#define GITS_BASER_PA_MASK 0x7ffffffff000ULL
#define GITS_TRANSLATER 0x10040
@@ -1572,6 +1573,7 @@ struct agintc_msi_softc {
uint16_t sc_cmdidx;
int sc_devbits;
+ uint32_t sc_deviceid_max;
struct agintc_dmamem *sc_dtt;
size_t sc_dtt_pgsz;
uint8_t sc_dte_sz;
@@ -1703,6 +1705,13 @@ agintc_msi_attach(struct device *parent, struct device *self, void *aux)
size = (1ULL << sc->sc_devbits) * sc->sc_dte_sz;
size = roundup(size, sc->sc_dtt_pgsz);
+ /* Clamp down to maximum configurable num pages */
+ if (size / sc->sc_dtt_pgsz > GITS_BASER_SZ_MASK + 1)
+ size = (GITS_BASER_SZ_MASK + 1) * sc->sc_dtt_pgsz;
+
+ /* Calculate max deviceid based off configured size */
+ sc->sc_deviceid_max = (size / sc->sc_dte_sz) - 1;
+
/* Allocate table. */
sc->sc_dtt = agintc_dmamem_alloc(sc->sc_dmat,
size, sc->sc_dtt_pgsz);
@@ -1858,6 +1867,9 @@ agintc_msi_create_device(struct agintc_msi_softc *sc, uint32_t deviceid)
struct agintc_msi_device *md;
struct gits_cmd cmd;
+ if (deviceid > sc->sc_deviceid_max)
+ return NULL;
+
md = malloc(sizeof(*md), M_DEVBUF, M_ZERO | M_WAITOK);
md->md_deviceid = deviceid;
md->md_itt = agintc_dmamem_alloc(sc->sc_dmat,