Download raw body.
agintc(4): clamp down to maximum possible deviceid
> Date: Sun, 23 Jun 2024 22:55:20 +0200
> From: Patrick Wildt <patrick@blueri.se>
>
> 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.
If the hardware really generated deviceids that can't be handled, they
probably would have noticed that the hardware is broken. So I don't
think we need to worry about that.
ok kettenis@
I still think we want INDIRECT support. That'll come after this?
> 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,
>
>
agintc(4): clamp down to maximum possible deviceid