Index | Thread | Search

From:
Alexander Bluhm <bluhm@openbsd.org>
Subject:
Re: mbuf dma 64 bit
To:
Mark Kettenis <mark.kettenis@xs4all.nl>
Cc:
tech@openbsd.org
Date:
Fri, 13 Feb 2026 18:31:22 +0100

Download raw body.

Thread
On Fri, Feb 13, 2026 at 11:37:27AM +0100, Mark Kettenis wrote:
> > Date: Thu, 12 Feb 2026 18:11:17 -0500
> > From: Alexander Bluhm <bluhm@openbsd.org>
> > I have added USB hotplug as discussed in the hackroom.  If the
> > controller does not support 64 bit DMA, we restrict mbufs to below
> > 4 GB.  Still not clear what to do with PCI hotplug and how relevant
> > this is.  Maybe bounce buffers just for them?
> 
> USB hotplug isn't an issue.  I keep getting confused by this myself,
> but our USB stack already uses its own buffers that it copies mbufs
> into before it does DMA.  If the USB controller isn't 64-bit capable,
> those buffers are allocated from DMA-reachable memory.  We effectively
> USB drivers are already using bounce buffers.

Good.  I removed checks for 64 bit DMA on USB controller again.

> So the problem is hotplug PCI (CardBus, ExpressCard, hotplug-capable
> servers).

mlarkin@ also mentioned Thunderbolt.

> > > > +void
> > > > +mbuf_dma_64bit_enable(void)
> > > > +{
> > > > +	struct ifnet *ifp;
> > > > +
> > > > +	TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
> > > > +		if (!ISSET(ifp->if_xflags, IFXF_MBUF_64BIT)) {
> > > > +			printf("%s: restrict all mbufs to low memory\n",
> > > > +			    ifp->if_xname);
> > > > +			return;
> > > > +		}
> > > > +	}
> > > > +
> > > > +	printf("enable mbufs in high memory\n");
> > > > +	m_pool_constraints(0, ULONG_MAX);
> > > > +}
> > > > +
> > > 
> > > I hope those are just debug printfs.
> > 
> > I think we should keep the restrict message.  If a system is not
> > capable to run with high mbufs, we should inform the user what
> > causes trouble.  At least until we have figured out how to deal
> > with all corner cases.  The positive meassage will be rmeoved before
> > commit.
> 
> Well, it is the unrestricted case that is "dangerous".

I depends what you think is "dangerous".  Too few mbufs in the
system and failing to allocate mbuf memory, wasting too much memory
for bounce buffers, slow machine due to too much bouncing, panic
as 64 bit mbuf is used but driver does not support it, hardware is
not working as the driver erroneously expected it would support 64
bit DMA?

We should keep both messages until we are confident that everything
works.

> > > Are we sure older em(4) variants do actually support 64-bit DMA?
> > 
> > I have a machine with these, tests currently running.
> > 
> > em0 at pci2 dev 0 function 0 "Intel 82571EB" rev 0x06: apic 2 int 8, address 00:1b:21:7b:d1:10
> > em2 at pci3 dev 0 function 0 "Intel 82580" rev 0x01: msi, address 90:e2:ba:78:7c:f0
> > em6 at pci4 dev 0 function 0 "Intel 82576" rev 0x01: msi, address 00:1b:21:da:f6:ec
> > em8 at pci5 dev 0 function 0 "Intel I350" rev 0x01: msi, address 00:25:90:e7:ec:7c
> > em14 at pci11 dev 0 function 0 "Intel 82576" rev 0x01: msi, address 00:1b:21:60:58:28
> > em16 at pci16 dev 0 function 0 "Intel 82571EB" rev 0x06: apic 3 int 20, address 00:50:c2:01:f4:60
> > 
> > Do you think these variants are sufficient or do you have some more?
> 
> It's the older stuff that I'm worried about.  Looking at the Linux
> e1000 driver it seems that some of the older PCI devices have issues
> with 64-bit DMA.  So they only "enable" it on PCI-X devices.  Now
> Linux has the newer PCIe variants in its e1000e driver and enables
> 64-bit DMA unconditionally in that driver.  So we should enable it for
> PCIe devices as well.  So setting the flags if sc->hw.bus_type is
> em_bus_type_pcix or em_bus_type_pci_express is probably what we need.

Done.

Has anyone old 32 bit em hardware running in an amd64 machine to
test?

> > I would like to keep it as a single diff for easier testing.  If
> > someone wants to review a single driver, I can commit it separately.
> > If nobody cares, I will beg for OKs in separate diffs.
> 
> Getting the driver bits in will help the bounce buffers.  And I don't
> think the rest of this diff should be considered before we have bounce
> buffers.

Yes, drivers setting BUS_DMA_64BIT is the first thing we need.

And then maybe bounce buffers for hotplug devices.  But I would
prefer use low mbufs if we know that the system has non 64 bit
network devices during autoconf.

Note that I need my whole diff without bouncing to test the drivers.
Actually testing found a missing BUS_DMA_64BIT in ice.

Updated diff below.

bluhm

Index: arch/amd64/amd64/autoconf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/autoconf.c,v
diff -u -p -r1.59 autoconf.c
--- arch/amd64/amd64/autoconf.c	12 Nov 2025 10:00:27 -0000	1.59
+++ arch/amd64/amd64/autoconf.c	13 Feb 2026 12:03:14 -0000
@@ -108,6 +108,23 @@ unmap_startup(void)
 	} while (p < (vaddr_t)endboot);
 }
 
+void
+mbuf_dma_64bit_enable(void)
+{
+	struct ifnet *ifp;
+
+	TAILQ_FOREACH(ifp, &ifnetlist, if_list) {
+		if (!ISSET(ifp->if_xflags, IFXF_MBUF_64BIT)) {
+			printf("%s: restrict all mbufs to low memory\n",
+			    ifp->if_xname);
+			return;
+		}
+	}
+
+	printf("enable mbufs in high memory\n");
+	m_pool_noconstraints();
+}
+
 /*
  * Determine i/o configuration for a machine.
  */
@@ -123,6 +140,8 @@ cpu_configure(void)
 		panic("configure: mainbus not configured");
 
 	intr_printconfig();
+
+	mbuf_dma_64bit_enable();
 
 #if NIOAPIC > 0
 	lapic_set_lvt();
Index: dev/pci/if_bnxt.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_bnxt.c,v
diff -u -p -r1.65 if_bnxt.c
--- dev/pci/if_bnxt.c	11 Feb 2026 09:35:07 -0000	1.65
+++ dev/pci/if_bnxt.c	13 Feb 2026 12:02:20 -0000
@@ -642,7 +642,7 @@ bnxt_attach(struct device *parent, struc
 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 	ifp->if_ioctl = bnxt_ioctl;
 	ifp->if_qstart = bnxt_start;
 	ifp->if_watchdog = bnxt_watchdog;
Index: dev/pci/if_em.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em.c,v
diff -u -p -r1.379 if_em.c
--- dev/pci/if_em.c	14 Jul 2025 11:52:43 -0000	1.379
+++ dev/pci/if_em.c	13 Feb 2026 17:00:26 -0000
@@ -534,6 +534,23 @@ em_attach(struct device *parent, struct 
 	sc->hw.min_frame_size = 
 	    ETHER_MIN_LEN + ETHER_CRC_LEN;
 
+	em_get_bus_info(&sc->hw);
+	switch (sc->hw.bus_type) {
+	case em_bus_type_pcix:
+		/* Identify 82544 on PCI-X */
+		if (sc->hw.mac_type == em_82544)
+			sc->pcix_82544 = TRUE;
+		else
+			sc->pcix_82544 = FALSE;
+		/* FALLTHROUGH */
+	case em_bus_type_pci_express:
+		/* Only PCI-X and PCIe support 64 bit DMA */
+		sc->sc_dmaflags |= BUS_DMA_64BIT;
+		break;
+	default:
+		break;
+	}
+
 	if (em_allocate_desc_rings(sc) != 0) {
 		printf("%s: Unable to allocate descriptor ring memory\n",
 		    DEVNAME(sc));
@@ -609,14 +626,6 @@ em_attach(struct device *parent, struct 
 		printf("%s: PHY reset is blocked due to SOL/IDER session.\n",
 		    DEVNAME(sc));
 
-	/* Identify 82544 on PCI-X */
-	em_get_bus_info(&sc->hw);
-	if (sc->hw.bus_type == em_bus_type_pcix &&
-	    sc->hw.mac_type == em_82544)
-		sc->pcix_82544 = TRUE;
-        else
-		sc->pcix_82544 = FALSE;
-
 	sc->hw.icp_xxxx_is_link_up = FALSE;
 
 	INIT_DEBUGOUT("em_attach: end");
@@ -1991,6 +2000,8 @@ em_setup_interface(struct em_softc *sc)
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
 	ifp->if_xflags = IFXF_MPSAFE;
+	if (ISSET(sc->sc_dmaflags, BUS_DMA_64BIT))
+		ifp->if_xflags |= IFXF_MBUF_64BIT;
 	ifp->if_ioctl = em_ioctl;
 	ifp->if_qstart = em_start;
 	ifp->if_watchdog = em_watchdog;
@@ -2158,7 +2169,8 @@ em_dma_malloc(struct em_softc *sc, bus_s
 	int r;
 
 	r = bus_dmamap_create(sc->sc_dmat, size, 1,
-	    size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &dma->dma_map);
+	    size, 0, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW | sc->sc_dmaflags,
+	    &dma->dma_map);
 	if (r != 0)
 		return (r);
 
@@ -2250,10 +2262,12 @@ em_setup_transmit_structures(struct em_s
 			pkt = &que->tx.sc_tx_pkts_ring[i];
 			error = bus_dmamap_create(sc->sc_dmat, EM_TSO_SIZE,
 			    EM_MAX_SCATTER / (sc->pcix_82544 ? 2 : 1),
-			    EM_TSO_SEG_SIZE, 0, BUS_DMA_NOWAIT, &pkt->pkt_map);
+			    EM_TSO_SEG_SIZE, 0,
+			    BUS_DMA_NOWAIT | sc->sc_dmaflags,
+			    &pkt->pkt_map);
 			if (error != 0) {
-				printf("%s: Unable to create TX DMA map\n",
-				    DEVNAME(sc));
+				printf("%s: Unable to create TX DMA map, "
+				    "error %d\n", DEVNAME(sc), error);
 				goto fail;
 			}
 		}
@@ -2772,11 +2786,11 @@ em_allocate_receive_structures(struct em
 			pkt = &que->rx.sc_rx_pkts_ring[i];
 
 			error = bus_dmamap_create(sc->sc_dmat, EM_MCLBYTES, 1,
-			    EM_MCLBYTES, 0, BUS_DMA_NOWAIT, &pkt->pkt_map);
+			    EM_MCLBYTES, 0, BUS_DMA_NOWAIT | sc->sc_dmaflags,
+			    &pkt->pkt_map);
 			if (error != 0) {
-				printf("%s: em_allocate_receive_structures: "
-				    "bus_dmamap_create failed; error %u\n",
-				    DEVNAME(sc), error);
+				printf("%s: Unable to create RX DMA map, "
+				    "error %d\n", DEVNAME(sc), error);
 				goto fail;
 			}
 
Index: dev/pci/if_em.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_em.h,v
diff -u -p -r1.83 if_em.h
--- dev/pci/if_em.h	16 Feb 2024 22:30:54 -0000	1.83
+++ dev/pci/if_em.h	13 Feb 2026 16:29:36 -0000
@@ -385,6 +385,7 @@ struct em_softc {
 	struct arpcom	sc_ac;
 
 	bus_dma_tag_t	sc_dmat;
+	int		sc_dmaflags;
 
 	struct em_hw	hw;
 
Index: dev/pci/if_ice.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ice.c,v
diff -u -p -r1.66 if_ice.c
--- dev/pci/if_ice.c	18 Nov 2025 09:13:55 -0000	1.66
+++ dev/pci/if_ice.c	13 Feb 2026 13:18:53 -0000
@@ -1315,13 +1315,13 @@ ice_alloc_dma_mem(struct ice_hw *hw, str
 
 	mem->tag = sc->sc_dmat;
 
-	err = bus_dmamap_create(mem->tag, size, 1, size, 0, BUS_DMA_NOWAIT,
-	    &mem->map);
+	err = bus_dmamap_create(mem->tag, size, 1, size, 0,
+	    BUS_DMA_NOWAIT  | BUS_DMA_64BIT, &mem->map);
 	if (err)
 		goto fail;
 
 	err = bus_dmamem_alloc(mem->tag, size, 1, 0, &mem->seg, 1, &nsegs,
-	    BUS_DMA_NOWAIT | BUS_DMA_ZERO);
+	    BUS_DMA_NOWAIT | BUS_DMA_ZERO | BUS_DMA_64BIT);
 	if (err || nsegs != 1)
 		goto fail_1;
 
@@ -30657,7 +30657,7 @@ ice_attach_hook(struct device *self)
 	ifp->if_softc = sc;
 	strlcpy(ifp->if_xname, sc->sc_dev.dv_xname, IFNAMSIZ);
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 	ifp->if_ioctl = ice_ioctl;
 	ifp->if_qstart = ice_start;
 	ifp->if_watchdog = ice_watchdog;
Index: dev/pci/if_igc.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_igc.c,v
diff -u -p -r1.30 if_igc.c
--- dev/pci/if_igc.c	17 Dec 2025 01:14:42 -0000	1.30
+++ dev/pci/if_igc.c	13 Feb 2026 12:02:20 -0000
@@ -737,11 +737,11 @@ igc_dma_malloc(struct igc_softc *sc, bus
 
 	dma->dma_tag = os->os_pa.pa_dmat;
 
-	if (bus_dmamap_create(dma->dma_tag, size, 1, size, 0, BUS_DMA_NOWAIT,
-	    &dma->dma_map))
+	if (bus_dmamap_create(dma->dma_tag, size, 1, size, 0,
+	    BUS_DMA_NOWAIT | BUS_DMA_64BIT, &dma->dma_map))
 		return 1;
 	if (bus_dmamem_alloc(dma->dma_tag, size, PAGE_SIZE, 0, &dma->dma_seg,
-	    1, &dma->dma_nseg, BUS_DMA_NOWAIT))
+	    1, &dma->dma_nseg, BUS_DMA_NOWAIT | BUS_DMA_64BIT))
 		goto destroy;
 	if (bus_dmamem_map(dma->dma_tag, &dma->dma_seg, dma->dma_nseg, size,
 	    &dma->dma_vaddr, BUS_DMA_NOWAIT | BUS_DMA_COHERENT))
@@ -796,7 +796,7 @@ igc_setup_interface(struct igc_softc *sc
 	ifp->if_softc = sc;
 	strlcpy(ifp->if_xname, DEVNAME(sc), IFNAMSIZ);
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 	ifp->if_ioctl = igc_ioctl;
 	ifp->if_qstart = igc_start;
 	ifp->if_watchdog = igc_watchdog;
@@ -1855,10 +1855,11 @@ igc_allocate_transmit_buffers(struct igc
 	for (i = 0; i < sc->num_tx_desc; i++) {
 		txbuf = &txr->tx_buffers[i];
 		error = bus_dmamap_create(txr->txdma.dma_tag, IGC_TSO_SIZE,
-		    IGC_MAX_SCATTER, PAGE_SIZE, 0, BUS_DMA_NOWAIT, &txbuf->map);
+		    IGC_MAX_SCATTER, PAGE_SIZE, 0,
+		    BUS_DMA_NOWAIT | BUS_DMA_64BIT, &txbuf->map);
 		if (error != 0) {
-			printf("%s: Unable to create TX DMA map\n",
-			    DEVNAME(sc));
+			printf("%s: Unable to create TX DMA map, error %d\n",
+			    DEVNAME(sc), error);
 			goto fail;
 		}
 	}
@@ -2161,10 +2162,10 @@ igc_allocate_receive_buffers(struct igc_
 	for (i = 0; i < sc->num_rx_desc; i++, rxbuf++) {
 		error = bus_dmamap_create(rxr->rxdma.dma_tag,
 		    sc->rx_mbuf_sz, 1, sc->rx_mbuf_sz, 0,
-		    BUS_DMA_NOWAIT, &rxbuf->map);
+		    BUS_DMA_NOWAIT | BUS_DMA_64BIT, &rxbuf->map);
 		if (error) {
-			printf("%s: Unable to create RX DMA map\n",
-			    DEVNAME(sc));
+			printf("%s: Unable to create RX DMA map, error %d\n",
+			    DEVNAME(sc), error);
 			goto fail;
 		}
 	}
Index: dev/pci/if_ix.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ix.c,v
diff -u -p -r1.222 if_ix.c
--- dev/pci/if_ix.c	11 Nov 2025 17:43:18 -0000	1.222
+++ dev/pci/if_ix.c	13 Feb 2026 12:02:20 -0000
@@ -1929,7 +1929,7 @@ ixgbe_setup_interface(struct ix_softc *s
 	strlcpy(ifp->if_xname, sc->dev.dv_xname, IFNAMSIZ);
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 	ifp->if_ioctl = ixgbe_ioctl;
 	ifp->if_qstart = ixgbe_start;
 	ifp->if_timer = 0;
@@ -2087,7 +2087,7 @@ ixgbe_dma_malloc(struct ix_softc *sc, bu
 
 	dma->dma_tag = os->os_pa.pa_dmat;
 	r = bus_dmamap_create(dma->dma_tag, size, 1,
-	    size, 0, BUS_DMA_NOWAIT, &dma->dma_map);
+	    size, 0, BUS_DMA_NOWAIT | BUS_DMA_64BIT, &dma->dma_map);
 	if (r != 0) {
 		printf("%s: ixgbe_dma_malloc: bus_dmamap_create failed; "
 		       "error %u\n", ifp->if_xname, r);
@@ -2095,7 +2095,7 @@ ixgbe_dma_malloc(struct ix_softc *sc, bu
 	}
 
 	r = bus_dmamem_alloc(dma->dma_tag, size, PAGE_SIZE, 0, &dma->dma_seg,
-	    1, &dma->dma_nseg, BUS_DMA_NOWAIT);
+	    1, &dma->dma_nseg, BUS_DMA_NOWAIT | BUS_DMA_64BIT);
 	if (r != 0) {
 		printf("%s: ixgbe_dma_malloc: bus_dmamem_alloc failed; "
 		       "error %u\n", ifp->if_xname, r);
@@ -2293,11 +2293,11 @@ ixgbe_allocate_transmit_buffers(struct i
 		txbuf = &txr->tx_buffers[i];
 		error = bus_dmamap_create(txr->txdma.dma_tag, MAXMCLBYTES,
 			    sc->num_segs, PAGE_SIZE, 0,
-			    BUS_DMA_NOWAIT, &txbuf->map);
+			    BUS_DMA_NOWAIT | BUS_DMA_64BIT, &txbuf->map);
 
 		if (error != 0) {
-			printf("%s: Unable to create TX DMA map\n",
-			    ifp->if_xname);
+			printf("%s: Unable to create TX DMA map, error %d\n",
+			    ifp->if_xname, error);
 			goto fail;
 		}
 	}
@@ -2776,10 +2776,10 @@ ixgbe_allocate_receive_buffers(struct ix
 	rxbuf = rxr->rx_buffers;
 	for (i = 0; i < sc->num_rx_desc; i++, rxbuf++) {
 		error = bus_dmamap_create(rxr->rxdma.dma_tag, 16 * 1024, 1,
-		    16 * 1024, 0, BUS_DMA_NOWAIT, &rxbuf->map);
+		    16 * 1024, 0, BUS_DMA_NOWAIT | BUS_DMA_64BIT, &rxbuf->map);
 		if (error) {
-			printf("%s: Unable to create Pack DMA map\n",
-			    ifp->if_xname);
+			printf("%s: Unable to create RX DMA map, error %d\n",
+			    ifp->if_xname, error);
 			goto fail;
 		}
 	}
Index: dev/pci/if_ixl.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_ixl.c,v
diff -u -p -r1.114 if_ixl.c
--- dev/pci/if_ixl.c	4 Dec 2025 16:51:29 -0000	1.114
+++ dev/pci/if_ixl.c	13 Feb 2026 12:02:20 -0000
@@ -1914,7 +1914,7 @@ ixl_attach(struct device *parent, struct
 
 	ifp->if_softc = sc;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 	ifp->if_ioctl = ixl_ioctl;
 	ifp->if_qstart = ixl_start;
 	ifp->if_watchdog = ixl_watchdog;
Index: dev/pv/if_vio.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pv/if_vio.c,v
diff -u -p -r1.78 if_vio.c
--- dev/pv/if_vio.c	15 Jan 2026 09:06:19 -0000	1.78
+++ dev/pv/if_vio.c	13 Feb 2026 12:02:20 -0000
@@ -750,7 +750,7 @@ negotiate:
 
 	ifp->if_capabilities = 0;
 	ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
-	ifp->if_xflags = IFXF_MPSAFE;
+	ifp->if_xflags = IFXF_MPSAFE | IFXF_MBUF_64BIT;
 #if NVLAN > 0
 	ifp->if_capabilities |= IFCAP_VLAN_MTU;
 	ifp->if_capabilities |= IFCAP_VLAN_HWOFFLOAD;
Index: kern/uipc_mbuf.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/kern/uipc_mbuf.c,v
diff -u -p -r1.304 uipc_mbuf.c
--- kern/uipc_mbuf.c	5 Feb 2026 03:26:00 -0000	1.304
+++ kern/uipc_mbuf.c	13 Feb 2026 12:02:20 -0000
@@ -1480,6 +1480,17 @@ m_pool_init(struct pool *pp, u_int size,
 	pool_set_constraints(pp, &kp_dma_contig);
 }
 
+void
+m_pool_noconstraints(void)
+{
+	int i;
+
+	pool_set_constraints(&mbpool, &kp_mbuf_contig);
+
+	for (i = 0; i < nitems(mclsizes); i++)
+		pool_set_constraints(&mclpools[i], &kp_mbuf_contig);
+}
+
 u_int
 m_pool_used(void)
 {
Index: net/if.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/net/if.h,v
diff -u -p -r1.223 if.h
--- net/if.h	9 Dec 2025 03:33:06 -0000	1.223
+++ net/if.h	13 Feb 2026 12:02:20 -0000
@@ -232,6 +232,7 @@ struct if_status_description {
 #define	IFXF_AUTOCONF4		0x80	/* [N] v4 autoconf (aka dhcp) enabled */
 #define	IFXF_MONITOR		0x100	/* [N] only used for bpf */
 #define	IFXF_LRO		0x200	/* [N] TCP large recv offload */
+#define	IFXF_MBUF_64BIT		0x400	/* [I] mbuf with 64 bit DMA supported */
 
 #define	IFXF_CANTCHANGE \
 	(IFXF_MPSAFE|IFXF_CLONED)
Index: sys/mbuf.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/sys/mbuf.h,v
diff -u -p -r1.269 mbuf.h
--- sys/mbuf.h	5 Feb 2026 03:26:00 -0000	1.269
+++ sys/mbuf.h	13 Feb 2026 12:02:20 -0000
@@ -441,6 +441,7 @@ void	m_align(struct mbuf *, int);
 struct mbuf *m_clget(struct mbuf *, int, u_int);
 void	m_extref(struct mbuf *, struct mbuf *);
 void	m_pool_init(struct pool *, u_int, u_int, const char *);
+void	m_pool_noconstraints(void);
 u_int	m_pool_used(void);
 void	m_extfree_pool(caddr_t, u_int, void *);
 void	m_adj(struct mbuf *, int);
Index: uvm/uvm_extern.h
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/uvm/uvm_extern.h,v
diff -u -p -r1.187 uvm_extern.h
--- uvm/uvm_extern.h	13 Nov 2025 10:55:51 -0000	1.187
+++ uvm/uvm_extern.h	13 Feb 2026 12:02:20 -0000
@@ -358,6 +358,7 @@ extern const struct kmem_pa_mode kp_zero
 extern const struct kmem_pa_mode kp_dma;
 extern const struct kmem_pa_mode kp_dma_contig;
 extern const struct kmem_pa_mode kp_dma_zero;
+extern const struct kmem_pa_mode kp_mbuf_contig;
 extern const struct kmem_pa_mode kp_pageable;
 extern const struct kmem_pa_mode kp_none;
 
Index: uvm/uvm_km.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/sys/uvm/uvm_km.c,v
diff -u -p -r1.159 uvm_km.c
--- uvm/uvm_km.c	13 Nov 2025 10:55:51 -0000	1.159
+++ uvm/uvm_km.c	13 Feb 2026 12:02:20 -0000
@@ -745,6 +745,11 @@ const struct kmem_pa_mode kp_dma_zero = 
 	.kp_zero = 1
 };
 
+const struct kmem_pa_mode kp_mbuf_contig = {
+	.kp_constraint = &no_constraint,
+	.kp_maxseg = 1
+};
+
 const struct kmem_pa_mode kp_zero = {
 	.kp_constraint = &no_constraint,
 	.kp_zero = 1