From: Kirill A. Korinsky Subject: sys/cnmac: read next RX buffer pointer before release To: OpenBSD tech , visa@openbsd.org Date: Thu, 18 Jun 2026 11:02:36 +0200 tech@, Visa, My ER-4 which I use as home's gw crashed some time ago with stacktrace: ddb{0}> trace cnmac_recv_mbuf+0x13c (77e060040f88a,1,980000000fd979f8,980000000fd979f4) ra 0 xffffffff810f13a0 sp 0x980000000fd97990, sz 32 cnmac_recv+0x88 (77e060040f88a,1,980000000fd979f8,b14f8e2ae1694c1c) ra 0xfffff fff810eddb0 sp 0x980000000fd979b0, sz 144 cnmac_intr+0x100 (77e060040f88a,593aedd32134a2c6,980000000fd979f8,4) ra 0xffff ffff8124a06c sp 0x980000000fd97a40, sz 112 octciu_intr_bank+0x274 (77e060040f88a,593aedd32134a2c6,980000000fd979f8,47bf232 1b40c9360) ra 0xffffffff8124976c sp 0x980000000fd97ab0, sz 160 octciu_intr0+0x94 (77e060040f88a,593aedd32134a2c6,57aacbc77ca5909c,47bf2321b40c 9360) ra 0xffffffff811a0f68 sp 0x980000000fd97b50, sz 64 interrupt+0x170 (77e060040f88a,1da67593047e9497,57aacbc77ca5909c,47bf2321b40c93 60) ra 0xffffffff813461f4 sp 0x980000000fd97b90, sz 64 k_intr+0xb4 (980000000fd97bf8,1da67593047e9497,57aacbc77ca5909c,ffffffff811e948 c) ra 0x0 sp 0x980000000fd97bd0, sz 0 (KERNEL INTERRUPT) cpu_idle_cycle_wait+0x4 (980000000fd97bf8,1da67593047e9497,57aacbc77ca5909c,fff fffff811e948c) ra 0xffffffff810a7ccc sp 0x980000000fd97d50, sz 0 sched_idle+0x314 (980000000fd97bf8,1da67593047e9497,57aacbc77ca5909c,ffffffff81 1e948c) ra 0xffffffff811e95bc sp 0x980000000fd97d50, sz 96 proc_trampoline+0x1c (980000000fd97bf8,1da67593047e9497,57aacbc77ca5909c,ffffff ff811e948c) ra 0x0 sp 0x980000000fd97db0, sz 0 User-level: pid 7056 ddb{0}> I not completley sure that had happened, but here some thoughts that can fix that, as blind shot, or it can be absolutley wrong. The idea that in both RX drop and receive paths, copy the next WQE word before the current packet buffer is returned to FPA or its hidden mbuf pointer is cleared. Returning the buffer first allows hardware to reuse it before the driver has consumed the chained buffer pointer; that can corrupt word3 and later fault in cnmac_recv_mbuf() while recovering the mbuf from pktbuf. Thougths? Ok? Index: sys/arch/octeon/dev/if_cnmac.c =================================================================== RCS file: /home/cvs/src/sys/arch/octeon/dev/if_cnmac.c,v diff -u -p -r1.90 if_cnmac.c --- sys/arch/octeon/dev/if_cnmac.c 27 Apr 2026 16:54:49 -0000 1.90 +++ sys/arch/octeon/dev/if_cnmac.c 18 Jun 2026 01:23:19 -0000 @@ -722,12 +722,12 @@ cnmac_buf_free_work(struct cnmac_softc * PIP_WQE_WORD3_BACK_SHIFT; pktbuf = (addr & ~(CACHELINESIZE - 1)) - back * CACHELINESIZE; - cn30xxfpa_store(pktbuf, OCTEON_POOL_NO_PKT, - OCTEON_POOL_SIZE_PKT / CACHELINESIZE); - if (nbufs > 0) memcpy(&word3, (void *)PHYS_TO_XKPHYS(addr - sizeof(word3), CCA_CACHED), sizeof(word3)); + + cn30xxfpa_store(pktbuf, OCTEON_POOL_NO_PKT, + OCTEON_POOL_SIZE_PKT / CACHELINESIZE); } cn30xxfpa_buf_put_paddr(cnmac_fb_wqe, XKPHYS_TO_PHYS(work)); @@ -1244,6 +1244,9 @@ cnmac_recv_mbuf(struct cnmac_softc *sc, addr = word3 & PIP_WQE_WORD3_ADDR; back = (word3 & PIP_WQE_WORD3_BACK) >> PIP_WQE_WORD3_BACK_SHIFT; pktbuf = (addr & ~(CACHELINESIZE - 1)) - back * CACHELINESIZE; + if (i + 1 < nbufs) + memcpy(&word3, (void *)PHYS_TO_XKPHYS(addr - + sizeof(word3), CCA_CACHED), sizeof(word3)); pm = (struct mbuf **)PHYS_TO_XKPHYS(pktbuf, CCA_CACHED) - 1; m = *pm; *pm = NULL; @@ -1276,10 +1279,6 @@ cnmac_recv_mbuf(struct cnmac_softc *sc, mprev->m_next = m; } mprev = m; - - if (i + 1 < nbufs) - memcpy(&word3, (void *)PHYS_TO_XKPHYS(addr - - sizeof(word3), CCA_CACHED), sizeof(word3)); } m0->m_pkthdr.len = total; -- wbr, Kirill