From: Patrick Wildt Subject: agintc(4): clamp down to maximum possible deviceid To: tech@openbsd.org Cc: kettenis@openbsd.org Date: Sun, 23 Jun 2024 22:55:20 +0200 Hi, the Qualcomm Snapdragon X Elite (X1E80100) claims to support 32 device-id bits, but it also seems to only allow a 4k pagesize with 8 bytes per entry. Without support for INDIRECT (status quo) this yields a maximum deviceid of 0x1ffff, which is way less than the 32 devbits. Even with INDIRECT we would only get 0x3ffffff. Hence let's only allocate as much as possibly configurable, and bail out when someone tries to establish a device with it. With this establishing nvme(4) on the Lenovo Yoga Slim 7x is still being attempted, but will fail. It would be nicer if the MSI map failed, but with this the machine at least doesn't hang anymore on boot. Patrick diff --git a/sys/arch/arm64/dev/agintc.c b/sys/arch/arm64/dev/agintc.c index e0fe1de31fb..86b8aefc384 100644 --- a/sys/arch/arm64/dev/agintc.c +++ b/sys/arch/arm64/dev/agintc.c @@ -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,