> Date: Wed, 18 Oct 2023 16:40:20 +0000
> From: Miod Vallat <m...@online.fr>
> 
> 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))
> 
> 

Reply via email to