5We2DZXBmxDjJREqpXYfeyfbQK9Wwj8kLi7kGI2d5iJOOk0LQOzcU i47+PXNOCL0gu/X5bKa3bCzEQNBg9E8IhkbdXEGTmS1X44dzp8Q5apVkYKsFaz0j00d8iXZK8vE Zz/7UgvLFabU3VIwGpp7qk1Tk2gi1YIA//+qTBYCFJrrY/jSXSH8HOY8JPglclUGhgia6DxqVwl j5t3IRaG9x9SOozx/hHEmqKFkpTElYez0O7a/On+YX6V2pbQ99EiE4J+qqewremY1Spf2GXphrv Kd+jmA= X-Received: by 2002:a05:690c:c4f9:b0:7bd:4b22:a05c with SMTP id 00721157ae682-7bd772a3173mr88650727b3.49.1777869020485; Sun, 03 May 2026 21:30:20 -0700 (PDT) Received: from mail-yx1-f48.google.com (mail-yx1-f48.google.com. [74.125.224.48]) by smtp.gmail.com with ESMTPSA id 00721157ae682-7bd6683a849sm44477677b3.29.2026.05.03.21.30.19 for (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Sun, 03 May 2026 21:30:20 -0700 (PDT) Received: by mail-yx1-f48.google.com with SMTP id 956f58d0204a3-651c366f7efso3440524d50.1 for ; Sun, 03 May 2026 21:30:19 -0700 (PDT) X-Forwarded-Encrypted: i=1; AFNElJ/8sygzEESzqTcPoYG0atqMVGMK/eKChvyt2onQWfftKsRHWusjjm4/bF0NUr0OMJpFZXxz3BiyszS6vYL8BQsSQfoM@freebsd.org X-Received: by 2002:a05:690e:4090:b0:651:c264:dd61 with SMTP id 956f58d0204a3-65c3d9d0399mr8508734d50.7.1777869019535; Sun, 03 May 2026 21:30:19 -0700 (PDT) List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 References: <69ef4acf.1fcd2.4d4d3e54@gitrepo.freebsd.org> In-Reply-To: <69ef4acf.1fcd2.4d4d3e54@gitrepo.freebsd.org> From: Ryan Libby Date: Sun, 3 May 2026 21:30:08 -0700 X-Gmail-Original-Message-ID: X-Gm-Features: AVHnY4JpLlZ6WrMsndOgRIl76yOC-rr4-rkn1iF77kYK3PgjBnP_l9z3xKNuxUM Message-ID: Subject: Re: git: c16c95192f01 - main - virtio_net: Use bus_dma for rxq/txq buffers To: Andrew Turner Cc: src-committers@freebsd.org, dev-commits-src-all@freebsd.org, dev-commits-src-main@freebsd.org, Sarah Walker Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Spamd-Result: default: False [-0.56 / 15.00]; RBL_VIRUSFREE_BOTNET(2.00)[74.125.224.42:from]; NEURAL_HAM_LONG(-1.00)[-0.996]; NEURAL_HAM_MEDIUM(-0.99)[-0.988]; NEURAL_HAM_SHORT(-0.97)[-0.974]; FORGED_SENDER(0.30)[rlibby@freebsd.org,rlibby@gmail.com]; DMARC_POLICY_SOFTFAIL(0.10)[freebsd.org : SPF not aligned (relaxed), No valid DKIM,none]; MIME_GOOD(-0.10)[text/plain]; BAD_REP_POLICIES(0.10)[]; RCVD_TLS_LAST(0.00)[]; RCVD_COUNT_THREE(0.00)[3]; FROM_HAS_DN(0.00)[]; MIME_TRACE(0.00)[0:+]; ARC_NA(0.00)[]; FREEMAIL_ENVFROM(0.00)[gmail.com]; TO_DN_SOME(0.00)[]; MISSING_XM_UA(0.00)[]; FREEFALL_USER(0.00)[rlibby]; ASN(0.00)[asn:15169, ipnet:74.125.0.0/16, country:US]; PREVIOUSLY_DELIVERED(0.00)[dev-commits-src-all@freebsd.org]; TO_MATCH_ENVRCPT_SOME(0.00)[]; FROM_NEQ_ENVFROM(0.00)[rlibby@freebsd.org,rlibby@gmail.com]; RCVD_IN_DNSWL_NONE(0.00)[74.125.224.42:from,74.125.224.48:received]; MLMMJ_DEST(0.00)[dev-commits-src-all@freebsd.org]; RWL_MAILSPIKE_POSSIBLE(0.00)[74.125.224.42:from]; R_DKIM_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; R_SPF_ALLOW(0.00)[+ip4:74.125.0.0/16:c]; RCPT_COUNT_FIVE(0.00)[5] X-Spamd-Bar: / X-Rspamd-Queue-Id: 4g87wt2Cc0z4Gfx On Mon, Apr 27, 2026 at 4:39=E2=80=AFAM Andrew Turner = wrote: > > The branch main has been updated by andrew: > > URL: https://cgit.FreeBSD.org/src/commit/?id=3Dc16c95192f01237a876eb7bc33= 6e3bbda9310171 > > commit c16c95192f01237a876eb7bc336e3bbda9310171 > Author: Sarah Walker > AuthorDate: 2026-02-16 14:19:13 +0000 > Commit: Andrew Turner > CommitDate: 2026-04-27 11:37:53 +0000 > > virtio_net: Use bus_dma for rxq/txq buffers > > While the majority of virtio platforms will be fully coherent, some m= ay > require cache maintenance or other specific device memory handling (e= g for > secure partitioning). Using bus_dma allows for these usecases. > > The virtio buffers are marked as coherent; this should ensure that sy= nc > calls are no-ops in the common cases. > > Reviewed by: andrew > Sponsored by: Arm Ltd > Differential Revision: https://reviews.freebsd.org/D55492 > --- > sys/dev/virtio/network/if_vtnet.c | 275 +++++++++++++++++++++++++++++= +++--- > sys/dev/virtio/network/if_vtnetvar.h | 10 ++ > 2 files changed, 268 insertions(+), 17 deletions(-) > > diff --git a/sys/dev/virtio/network/if_vtnet.c b/sys/dev/virtio/network/i= f_vtnet.c > index ef01833b9e03..e88602a44664 100644 > --- a/sys/dev/virtio/network/if_vtnet.c > +++ b/sys/dev/virtio/network/if_vtnet.c > @@ -96,6 +96,17 @@ > #define VTNET_ETHER_ALIGN ETHER_ALIGN > #endif > > +/* > + * Worst case offset to ensure header doesn't share any cache lines with > + * payload. > + */ > +#define VTNET_RX_BUFFER_HEADER_OFFSET 128 > + > +struct vtnet_rx_buffer_header { > + bus_addr_t addr; > + bus_dmamap_t dmap; > +}; > + > static int vtnet_modevent(module_t, int, void *); > > static int vtnet_probe(device_t); > @@ -384,6 +395,17 @@ MODULE_DEPEND(vtnet, netmap, 1, 1, 1); > > VIRTIO_SIMPLE_PNPINFO(vtnet, VIRTIO_ID_NETWORK, "VirtIO Networking Adapt= er"); > > +static struct vtnet_rx_buffer_header * > +vtnet_mbuf_to_rx_buffer_header(struct vtnet_softc *sc, struct mbuf *m) > +{ > + if (VTNET_ETHER_ALIGN !=3D 0 && sc->vtnet_hdr_size % 4 =3D=3D 0) > + return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_= data - > + VTNET_RX_BUFFER_HEADER_OFFSET - VTNET_ETHER_ALIGN); > + else > + return (struct vtnet_rx_buffer_header *)((uintptr_t)m->m_= data - > + VTNET_RX_BUFFER_HEADER_OFFSET); > +} > + > static int > vtnet_modevent(module_t mod __unused, int type, void *unused __unused) > { > @@ -457,6 +479,60 @@ vtnet_attach(device_t dev) > goto fail; > } > > + mtx_init(&sc->vtnet_rx_mtx, device_get_nameunit(dev), > + "VirtIO Net RX lock", MTX_DEF); > + > + error =3D bus_dma_tag_create( > + bus_get_dma_tag(dev), /* parent */ > + sizeof(uint16_t), /* alignment */ > + 0, /* boundary */ > + BUS_SPACE_MAXADDR, /* lowaddr */ > + BUS_SPACE_MAXADDR, /* highaddr */ > + NULL, NULL, /* filter, filterarg */ > + MJUM9BYTES, /* max request size */ > + 1, /* max # segments */ > + MJUM9BYTES, /* maxsegsize - worst cas= e */ > + BUS_DMA_COHERENT, /* flags */ > + busdma_lock_mutex, /* lockfunc */ > + &sc->vtnet_rx_mtx, /* lockarg */ > + &sc->vtnet_rx_dmat); > + if (error) { > + device_printf(dev, "cannot create bus_dma_tag\n"); > + goto fail; > + } > + > + mtx_init(&sc->vtnet_tx_mtx, device_get_nameunit(dev), > + "VirtIO Net TX lock", MTX_DEF); > + > + error =3D bus_dma_tag_create( > + bus_get_dma_tag(dev), /* parent */ > + sizeof(uint16_t), /* alignment */ > + 0, /* boundary */ > + BUS_SPACE_MAXADDR, /* lowaddr */ > + BUS_SPACE_MAXADDR, /* highaddr */ > + NULL, NULL, /* filter, filterarg */ > + sc->vtnet_tx_nsegs * MJUM9BYTES, /* max request size */ > + sc->vtnet_tx_nsegs, /* max # segments */ > + MJUM9BYTES, /* maxsegsize */ > + BUS_DMA_COHERENT, /* flags */ > + busdma_lock_mutex, /* lockfunc */ > + &sc->vtnet_tx_mtx, /* lockarg */ > + &sc->vtnet_tx_dmat); > + if (error) { > + device_printf(dev, "cannot create bus_dma_tag\n"); > + goto fail; > + } > + > +#ifdef __powerpc__ > + /* > + * Virtio uses physical addresses rather than bus addresses, so = we > + * need to ask busdma to skip the iommu physical->bus mapping. = At > + * present, this is only a thing on the powerpc architectures. > + */ > + bus_dma_tag_set_iommu(sc->vtnet_rx_dmat, NULL, NULL); > + bus_dma_tag_set_iommu(sc->vtnet_tx_dmat, NULL, NULL); > +#endif > + > error =3D vtnet_alloc_rx_filters(sc); > if (error) { > device_printf(dev, "cannot allocate Rx filters\n"); > @@ -1545,6 +1621,11 @@ static struct mbuf * > vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nbufs, struct mbuf **m_ta= ilp) > { > struct mbuf *m_head, *m_tail, *m; > + struct vtnet_rx_buffer_header *vthdr; > + bus_dma_segment_t segs[1]; > + bus_dmamap_t dmap; > + int nsegs; > + int err; > int i, size; > > m_head =3D NULL; > @@ -1562,13 +1643,43 @@ vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nb= ufs, struct mbuf **m_tailp) > } > > m->m_len =3D size; > + vthdr =3D (struct vtnet_rx_buffer_header *)m->m_data; > + > + /* Reserve space for header */ > + m_adj(m, VTNET_RX_BUFFER_HEADER_OFFSET); > + > /* > * Need to offset the mbuf if the header we're going to a= dd > * will misalign. > */ > - if (VTNET_ETHER_ALIGN !=3D 0 && sc->vtnet_hdr_size % 4 = =3D=3D 0) { > + if (VTNET_ETHER_ALIGN !=3D 0 && sc->vtnet_hdr_size % 4 = =3D=3D 0) > m_adj(m, VTNET_ETHER_ALIGN); > + > + err =3D bus_dmamap_create(sc->vtnet_rx_dmat, 0, &dmap); > + if (err) { > + printf("Failed to create dmamap, err :%d\n", > + err); > + m_freem(m); > + return (NULL); > } > + > + nsegs =3D 0; > + err =3D bus_dmamap_load_mbuf_sg(sc->vtnet_rx_dmat, dmap, = m, segs, > + &nsegs, BUS_DMA_NOWAIT); > + if (err !=3D 0) { > + printf("Failed to map mbuf into DMA visible memor= y, err: %d\n", > + err); > + m_freem(m); > + bus_dmamap_destroy(sc->vtnet_rx_dmat, dmap); > + return (NULL); > + } > + KASSERT(nsegs =3D=3D 1, > + ("%s: unexpected number of DMA segments for rx buffer= : %d", > + __func__, nsegs)); > + > + vthdr->addr =3D segs[0].ds_addr; > + vthdr->dmap =3D dmap; > + > if (m_head !=3D NULL) { > m_tail->m_next =3D m; > m_tail =3D m; > @@ -1594,7 +1705,7 @@ vtnet_rxq_replace_lro_nomrg_buf(struct vtnet_rxq *r= xq, struct mbuf *m0, > int len, clustersz, nreplace, error; > > sc =3D rxq->vtnrx_sc; > - clustersz =3D sc->vtnet_rx_clustersz; > + clustersz =3D sc->vtnet_rx_clustersz - VTNET_RX_BUFFER_HEADER_OFF= SET; > /* > * Need to offset the mbuf if the header we're going to add will > * misalign, account for that here. > @@ -1709,9 +1820,12 @@ vtnet_rxq_replace_buf(struct vtnet_rxq *rxq, struc= t mbuf *m, int len) > static int > vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, struct mbuf *m) > { > + struct vtnet_rx_buffer_header *hdr; > struct vtnet_softc *sc; > struct sglist *sg; > int header_inlined, error; > + bus_addr_t paddr; > + struct mbuf *mp; > > sc =3D rxq->vtnrx_sc; > sg =3D rxq->vtnrx_sg; > @@ -1724,28 +1838,38 @@ vtnet_rxq_enqueue_buf(struct vtnet_rxq *rxq, stru= ct mbuf *m) > header_inlined =3D vtnet_modern(sc) || > (sc->vtnet_flags & VTNET_FLAG_MRG_RXBUFS) !=3D 0; /* TODO: AN= Y_LAYOUT */ > > + hdr =3D vtnet_mbuf_to_rx_buffer_header(sc, m); > + paddr =3D hdr->addr; > + > /* > * Note: The mbuf has been already adjusted when we allocate it i= f we > * have to do strict alignment. > */ > - if (header_inlined) > - error =3D sglist_append_mbuf(sg, m); > - else { > - struct vtnet_rx_header *rxhdr =3D > - mtod(m, struct vtnet_rx_header *); > + if (header_inlined) { > + error =3D sglist_append_phys(sg, paddr, m->m_len); > + } else { > MPASS(sc->vtnet_hdr_size =3D=3D sizeof(struct virtio_net_= hdr)); > > /* Append the header and remaining mbuf data. */ > - error =3D sglist_append(sg, &rxhdr->vrh_hdr, sc->vtnet_hd= r_size); > + error =3D sglist_append_phys(sg, paddr, sc->vtnet_hdr_siz= e); > if (error) > return (error); > - error =3D sglist_append(sg, &rxhdr[1], > + error =3D sglist_append_phys(sg, > + paddr + sizeof(struct vtnet_rx_header), > m->m_len - sizeof(struct vtnet_rx_header)); > if (error) > return (error); > > - if (m->m_next !=3D NULL) > - error =3D sglist_append_mbuf(sg, m->m_next); > + mp =3D m->m_next; > + while (mp) { > + hdr =3D vtnet_mbuf_to_rx_buffer_header(sc, mp); > + paddr =3D hdr->addr; > + error =3D sglist_append_phys(sg, paddr, mp->m_len= ); > + if (error) > + return (error); > + > + mp =3D mp->m_next; > + } > } > > if (error) > @@ -1931,6 +2055,7 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct = mbuf *m_head, int nbufs) > m_tail =3D m_head; > > while (--nbufs > 0) { > + struct vtnet_rx_buffer_header *vthdr; > struct mbuf *m; > uint32_t len; > > @@ -1940,6 +2065,10 @@ vtnet_rxq_merged_eof(struct vtnet_rxq *rxq, struct= mbuf *m_head, int nbufs) > goto fail; > } > > + vthdr =3D vtnet_mbuf_to_rx_buffer_header(sc, m); > + bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap, > + BUS_DMASYNC_POSTREAD); > + > if (vtnet_rxq_new_buf(rxq) !=3D 0) { > rxq->vtnrx_stats.vrxs_iqdrops++; > vtnet_rxq_discard_buf(rxq, m); > @@ -2060,6 +2189,7 @@ static int > vtnet_rxq_eof(struct vtnet_rxq *rxq) > { > struct virtio_net_hdr lhdr, *hdr; > + struct vtnet_rx_buffer_header *vthdr; > struct vtnet_softc *sc; > if_t ifp; > struct virtqueue *vq; > @@ -2075,14 +2205,31 @@ vtnet_rxq_eof(struct vtnet_rxq *rxq) > > CURVNET_SET(if_getvnet(ifp)); > while (count-- > 0) { > - struct mbuf *m; > + struct mbuf *m, *mp; > uint32_t len, nbufs, adjsz; > + uint32_t synced; > > m =3D virtqueue_dequeue(vq, &len); > if (m =3D=3D NULL) > break; > deq++; > > + mp =3D m; > + > + /* > + * Sync all mbufs in this packet. There will only be a si= ngle > + * mbuf unless LRO is in use. > + */ > + synced =3D 0; > + while (mp && synced < len) { > + vthdr =3D vtnet_mbuf_to_rx_buffer_header(sc, mp); > + bus_dmamap_sync(sc->vtnet_rx_dmat, vthdr->dmap, > + BUS_DMASYNC_POSTREAD); > + > + synced +=3D mp->m_len; > + mp =3D mp->m_next; > + } > + > if (len < sc->vtnet_hdr_size + ETHER_HDR_LEN) { > rxq->vtnrx_stats.vrxs_ierrors++; > vtnet_rxq_discard_buf(rxq, m); > @@ -2342,6 +2489,14 @@ vtnet_txq_free_mbufs(struct vtnet_txq *txq) > > while ((txhdr =3D virtqueue_drain(vq, &last)) !=3D NULL) { > if (kring =3D=3D NULL) { > + bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat, > + txhdr->dmap); > + bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat, > + txhdr->dmap); > + bus_dmamap_unload(txq->vtntx_sc->vtnet_tx_dmat, > + txhdr->hdr_dmap); > + bus_dmamap_destroy(txq->vtntx_sc->vtnet_tx_dmat, > + txhdr->hdr_dmap); > m_freem(txhdr->vth_mbuf); > uma_zfree(vtnet_tx_header_zone, txhdr); > } > @@ -2511,15 +2666,36 @@ drop: > return (NULL); > } > > +static void > +vtnet_txq_enqueue_callback(void *arg, bus_dma_segment_t *segs, > + int nsegs, int error) > +{ > + vm_paddr_t *hdr_paddr; > + > + if (error !=3D 0) > + return; > + > + KASSERT(nsegs =3D=3D 1, ("%s: %d segments returned!", __func__, n= segs)); > + > + hdr_paddr =3D (vm_paddr_t *)arg; > + *hdr_paddr =3D segs[0].ds_addr; > +} > + > static int > vtnet_txq_enqueue_buf(struct vtnet_txq *txq, struct mbuf **m_head, > struct vtnet_tx_header *txhdr) > { > + bus_dma_segment_t segs[VTNET_TX_SEGS_MAX]; > + int nsegs; > struct vtnet_softc *sc; > struct virtqueue *vq; > struct sglist *sg; > struct mbuf *m; > int error; > + vm_paddr_t hdr_paddr; > + bus_dmamap_t hdr_dmap; > + bus_dmamap_t dmap; > + int i; > > sc =3D txq->vtntx_sc; > vq =3D txq->vtntx_vq; > @@ -2527,15 +2703,55 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, stru= ct mbuf **m_head, > m =3D *m_head; > > sglist_reset(sg); > - error =3D sglist_append(sg, &txhdr->vth_uhdr, sc->vtnet_hdr_size)= ; > + > + error =3D bus_dmamap_create(sc->vtnet_tx_dmat, 0, &hdr_dmap); > + if (error) > + goto fail; > + > + error =3D bus_dmamap_load(sc->vtnet_tx_dmat, hdr_dmap, &txhdr->vt= h_uhdr, > + sc->vtnet_hdr_size, vtnet_txq_enqueue_callback, &hdr_paddr, > + BUS_DMA_NOWAIT); > + if (error) > + goto fail_hdr_dmamap_destroy; > + > + error =3D sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr_size); > if (error !=3D 0 || sg->sg_nseg !=3D 1) { > KASSERT(0, ("%s: cannot add header to sglist error %d nse= g %d", > __func__, error, sg->sg_nseg)); > - goto fail; > + goto fail_hdr_dmamap_unload; > } > > - error =3D sglist_append_mbuf(sg, m); > + bus_dmamap_sync(sc->vtnet_tx_dmat, hdr_dmap, BUS_DMASYNC_PREWRITE= ); > + > + error =3D bus_dmamap_create(sc->vtnet_tx_dmat, 0, &dmap); > + if (error) > + goto fail_hdr_dmamap_unload; > + > + nsegs =3D 0; > + error =3D bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap, m, seg= s, > + &nsegs, BUS_DMA_NOWAIT); > + if (error !=3D 0) > + goto fail_dmamap_destroy; > + KASSERT(nsegs <=3D sc->vtnet_tx_nsegs, > + ("%s: unexpected number of DMA segments for tx buffer: %d (ma= x %d)", > + __func__, nsegs, sc->vtnet_tx_nsegs)); > + > + bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREWRITE); > + > + for (i =3D 0; i < nsegs && !error; i++) > + error =3D sglist_append_phys(sg, segs[i].ds_addr, segs[i]= .ds_len); > + > if (error) { > + sglist_reset(sg); > + bus_dmamap_unload(sc->vtnet_tx_dmat, dmap); > + > + error =3D sglist_append_phys(sg, hdr_paddr, sc->vtnet_hdr= _size); > + if (error !=3D 0 || sg->sg_nseg !=3D 1) { > + KASSERT(0, ("%s: cannot add header to sglist erro= r %d nseg %d", > + __func__, error, sg->sg_nseg)); > + goto fail_dmamap_destroy; > + } > + > m =3D m_defrag(m, M_NOWAIT); > if (m =3D=3D NULL) { > sc->vtnet_stats.tx_defrag_failed++; > @@ -2545,16 +2761,41 @@ vtnet_txq_enqueue_buf(struct vtnet_txq *txq, stru= ct mbuf **m_head, > *m_head =3D m; > sc->vtnet_stats.tx_defragged++; > > - error =3D sglist_append_mbuf(sg, m); > + nsegs =3D 0; > + error =3D bus_dmamap_load_mbuf_sg(sc->vtnet_tx_dmat, dmap= , m, > + segs, &nsegs, BUS_DMA_NOWAIT); > + if (error !=3D 0) > + goto fail_dmamap_destroy; > + KASSERT(nsegs <=3D sc->vtnet_tx_nsegs, > + ("%s: unexpected number of DMA segments for tx buffer= : %d (max %d)", > + __func__, nsegs, sc->vtnet_tx_nsegs)); > + > + bus_dmamap_sync(sc->vtnet_tx_dmat, dmap, BUS_DMASYNC_PREW= RITE); > + > + for (i =3D 0; i < nsegs && !error; i++) > + error =3D sglist_append_phys(sg, segs[i].ds_addr, > + segs[i].ds_len); > + > if (error) > - goto fail; > + goto fail_dmamap_unload; > } > > txhdr->vth_mbuf =3D m; > + txhdr->dmap =3D dmap; > + txhdr->hdr_dmap =3D hdr_dmap; > + > error =3D virtqueue_enqueue(vq, txhdr, sg, sg->sg_nseg, 0); > > return (error); > > +fail_dmamap_unload: > + bus_dmamap_unload(sc->vtnet_tx_dmat, dmap); > +fail_dmamap_destroy: > + bus_dmamap_destroy(sc->vtnet_tx_dmat, dmap); > +fail_hdr_dmamap_unload: > + bus_dmamap_unload(sc->vtnet_tx_dmat, hdr_dmap); > +fail_hdr_dmamap_destroy: > + bus_dmamap_destroy(sc->vtnet_tx_dmat, hdr_dmap); > fail: > m_freem(*m_head); > *m_head =3D NULL; > diff --git a/sys/dev/virtio/network/if_vtnetvar.h b/sys/dev/virtio/networ= k/if_vtnetvar.h > index eb5e6784b07f..6cafe827d733 100644 > --- a/sys/dev/virtio/network/if_vtnetvar.h > +++ b/sys/dev/virtio/network/if_vtnetvar.h > @@ -190,6 +190,12 @@ struct vtnet_softc { > struct mtx vtnet_mtx; > char vtnet_mtx_name[16]; > uint8_t vtnet_hwaddr[ETHER_ADDR_LEN]; > + > + bus_dma_tag_t vtnet_rx_dmat; > + struct mtx vtnet_rx_mtx; > + > + bus_dma_tag_t vtnet_tx_dmat; > + struct mtx vtnet_tx_mtx; > }; > /* vtnet flag descriptions for use with printf(9) %b identifier. */ > #define VTNET_FLAGS_BITS \ > @@ -273,6 +279,10 @@ struct vtnet_tx_header { > } vth_uhdr; > > struct mbuf *vth_mbuf; > + > + bus_dmamap_t dmap; > + > + bus_dmamap_t hdr_dmap; > }; > > /* > I believe this is causing a massive memory leak in the devbuf malloc type. I can't even get through a build over nfs on a VM without hitting OOM. Reverting b5bad6df467cc95bea641afe674c55cd5b9f1510 and c16c95192f01237a876eb7bc336e3bbda9310171 fixes the leak. Can you please fix or revert this? You can monitor the leak with something like vmstat -m | grep devbuf > @@ -1562,13 +1643,43 @@ vtnet_rx_alloc_buf(struct vtnet_softc *sc, int nb= ufs, struct mbuf **m_tailp) > } > > m->m_len =3D size; > + vthdr =3D (struct vtnet_rx_buffer_header *)m->m_data; > + > + /* Reserve space for header */ > + m_adj(m, VTNET_RX_BUFFER_HEADER_OFFSET); > + > /* > * Need to offset the mbuf if the header we're going to a= dd > * will misalign. > */ > - if (VTNET_ETHER_ALIGN !=3D 0 && sc->vtnet_hdr_size % 4 = =3D=3D 0) { > + if (VTNET_ETHER_ALIGN !=3D 0 && sc->vtnet_hdr_size % 4 = =3D=3D 0) > m_adj(m, VTNET_ETHER_ALIGN); > + > + err =3D bus_dmamap_create(sc->vtnet_rx_dmat, 0, &dmap); > + if (err) { > + printf("Failed to create dmamap, err :%d\n", > + err); > + m_freem(m); > + return (NULL); > } > + > + nsegs =3D 0; > + err =3D bus_dmamap_load_mbuf_sg(sc->vtnet_rx_dmat, dmap, = m, segs, > + &nsegs, BUS_DMA_NOWAIT); Where is the bus_dmamap_unload and bus_dmamap_destroy for the rx bufs? Ryan