> Date: Wed, 18 Oct 2023 16:40:20 +0000
> From: Miod Vallat <[email protected]>
>
> I had the misfortune of hitting a KASSERT in dwge:
>
> panic: kernel diagnostic assertion "len > 0" failed: file
> "/usr/src/sys/dev/fdt
> /if_dwge.c", line 1102
> Stopped at panic+0x106: addi a0,zero,256 TID PID UID
> PR
> FLAGS PFLAGS CPU COMMAND
> *405136 98879 1500 0x3 0 0 git
> 301471 67731 0 0x14000 0x200 1 softnet0
> panic() at panic+0x106
> panic() at panic
> dwge_rx_proc() at dwge_rx_proc+0x1d4
> dwge_intr() at dwge_intr+0x4e
> plic_irq_dispatch() at plic_irq_dispatch+0xec
> plic_irq_handler() at plic_irq_handler+0x56
> riscv_cpu_intr() at riscv_cpu_intr+0x22
> cpu_exception_handler_supervisor() at cpu_exception_handler_supervisor+0x7a
> pmap_copy_page() at pmap_copy_page+0x94
> uvm_pagerealloc_multi() at uvm_pagerealloc_multi+0x24e
> buf_realloc_pages() at buf_realloc_pages+0xa0
> buf_flip_high() at buf_flip_high+0x64
> bufcache_recover_dmapages() at bufcache_recover_dmapages+0x13a
> buf_get() at buf_get+0xec
> end trace frame: 0xffffffc04d9ac870, count: 0
>
> The following diff should count the error and skirt the panic.
You probably hit a receive error and hit this code path because we
don't check the error bit in the receive descriptor. I fixed this in
dwqe(4) recently, and would prefer a similar fix here. The (untested)
diff for that is attached here.
We may still want to check the length on top of that (and make a
similar change for dwqe(4)). I think I saw packets with the error bit
set that had a length > 0 on dwqe(4) and this makes me suspect that it
happens on dwge(4) as well.
Index: dev/fdt/if_dwge.c
===================================================================
RCS file: /cvs/src/sys/dev/fdt/if_dwge.c,v
retrieving revision 1.19
diff -u -p -r1.19 if_dwge.c
--- dev/fdt/if_dwge.c 15 Aug 2023 08:27:30 -0000 1.19
+++ dev/fdt/if_dwge.c 18 Oct 2023 22:29:16 -0000
@@ -214,6 +214,7 @@ struct dwge_desc {
#define RDES0_OE (1 << 11)
#define RDES0_SAF (1 << 13)
#define RDES0_DE (1 << 14)
+#define RDES0_ES (1 << 15)
#define RDES0_FL_MASK 0x3fff
#define RDES0_FL_SHIFT 16
#define RDES0_AFM (1 << 30)
@@ -1097,15 +1098,20 @@ dwge_rx_proc(struct dwge_softc *sc)
len, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);
- /* Strip off CRC. */
- len -= ETHER_CRC_LEN;
- KASSERT(len > 0);
-
m = rxb->tb_m;
rxb->tb_m = NULL;
- m->m_pkthdr.len = m->m_len = len;
+ if (rxd->sd_status & RDES0_ES) {
+ ifp->if_ierrors++;
+ m_freem(m);
+ } else {
+ /* Strip off CRC. */
+ len -= ETHER_CRC_LEN;
+ KASSERT(len > 0);
- ml_enqueue(&ml, m);
+ m->m_pkthdr.len = m->m_len = len;
+
+ ml_enqueue(&ml, m);
+ }
put++;
if (sc->sc_rx_cons == (DWGE_NRXDESC - 1))
>
> Index: if_dwge.c
> ===================================================================
> RCS file: /OpenBSD/src/sys/dev/fdt/if_dwge.c,v
> retrieving revision 1.19
> diff -u -p -r1.19 if_dwge.c
> --- if_dwge.c 15 Aug 2023 08:27:30 -0000 1.19
> +++ if_dwge.c 18 Oct 2023 16:37:59 -0000
> @@ -1099,13 +1101,15 @@ dwge_rx_proc(struct dwge_softc *sc)
>
> /* Strip off CRC. */
> len -= ETHER_CRC_LEN;
> - KASSERT(len > 0);
> -
> - m = rxb->tb_m;
> - rxb->tb_m = NULL;
> - m->m_pkthdr.len = m->m_len = len;
> + if (len <= 0) {
> + ifp->if_ierrors++;
> + } else {
> + m = rxb->tb_m;
> + rxb->tb_m = NULL;
> + m->m_pkthdr.len = m->m_len = len;
>
> - ml_enqueue(&ml, m);
> + ml_enqueue(&ml, m);
> + }
>
> put++;
> if (sc->sc_rx_cons == (DWGE_NRXDESC - 1))
>
>