From: Vitaliy Makkoveev Subject: Re: sys/ihidev: prevent crash on interrupt storm To: "Kirill A. Korinsky" Cc: OpenBSD tech Date: Mon, 23 Dec 2024 14:23:09 +0300 > On 23 Dec 2024, at 13:21, Kirill A. Korinsky wrote: > > tech@, > > Before I move forward with quirks, I'd like to fix the cause of a crash in a > system on HONOR MagicBook Art 14 Snapdragon. > > Let's assume that we have a device on a machine I2C bus which goes into a > so-called interrupt storm for some reason. Under this condition, the system > crashes if an interrupt arrives before we allocate a buffer to read it. > > Here's an example of a trace: > > panic: attempt to access user address 0x0 from EL1 > Stopped at panic+0x140: cmp w21, #0x0 > > TID PID UID PRFLAGS PFLAGS CPU COMMAND > db_enter() at panic+0x13c > panic() at kdata_abort+0x180 > do_el0_sync() at handle_el1h_sync+0x68 > handle_el1h_sync() at qciic_exec+0x2d4 > qciic_exec() at ihidev_intr+0x70 > ihidev_intr() at qcgpio_intr+0xac > qcgpio_intr() at agintc_irq_handler+0x2bc > > Tested on the same machine, without any additional patches. System boots, > but touchpad doesn't work. > > Ok? > This is not related to your diff, but since you are working in this area, please look at the following code. timeout_del_barrier(9) looks very suspicious to me. As I understand, the following code could be executed from interrupt context, so barrier can’t be used here. Sorry if I’m wrong and this is always thread context. ihidev_intr(void *arg) { struct ihidev_softc *sc = arg; struct ihidev *scd; int psize, res, i, fast = 0; u_char *p; u_int rep = 0; if (sc->sc_poll && !sc->sc_frompoll) { DPRINTF(("%s: received interrupt while polling, disabling " "polling\n", sc->sc_dev.dv_xname)); sc->sc_poll = 0; timeout_del_barrier(&sc->sc_timer); } > Index: sys/dev/i2c/ihidev.c > =================================================================== > RCS file: /home/cvs/src/sys/dev/i2c/ihidev.c,v > diff -u -p -r1.33 ihidev.c > --- sys/dev/i2c/ihidev.c 18 Oct 2024 12:53:49 -0000 1.33 > +++ sys/dev/i2c/ihidev.c 23 Dec 2024 09:46:36 -0000 > @@ -646,6 +646,15 @@ ihidev_intr(void *arg) > timeout_del_barrier(&sc->sc_timer); > } > > + if (sc->sc_ibuf == NULL) { > + /* ignore interrupt before bufer is allocated */ > + if (sc->sc_poll) { > + sc->sc_fastpoll = 0; > + goto more_polling; > + } > + return (1); > + } > + > /* > * XXX: force I2C_F_POLL for now to avoid dwiic interrupting > * while we are interrupting > > > -- > wbr, Kirill >