From: Alexander Bluhm Subject: mbuf dma 64 bit To: tech@openbsd.org Date: Wed, 11 Feb 2026 16:43:16 -0500 Hi, Allow to allocate mbufs with physical address above 4 GB. If any network driver does not support 64 bit dma, the existing restrictions are used. I have added the IFXF_MBUF_64BIT flag to all drivers I could test. There is no solution for hotplug devices yet. And I have not tested USB network. Is this diff the right direction? 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 11 Feb 2026 21:19:45 -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_constraints(0, ULONG_MAX); +} + /* * 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: arch/amd64/amd64/bus_dma.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/bus_dma.c,v diff -u -p -r1.60 bus_dma.c --- arch/amd64/amd64/bus_dma.c 13 Mar 2025 13:24:04 -0000 1.60 +++ arch/amd64/amd64/bus_dma.c 11 Feb 2026 21:19:27 -0000 @@ -102,7 +102,8 @@ #endif int _bus_dmamap_load_buffer(bus_dma_tag_t, bus_dmamap_t, void *, bus_size_t, - struct proc *, int, paddr_t *, int *, int *, int); + struct proc *, int, paddr_t *, int *, int *, int, + struct uvm_constraint_range *); /* * Common function for DMA map creation. May be called by bus-specific @@ -269,7 +270,7 @@ _bus_dmamap_load(bus_dma_tag_t t, bus_dm seg = 0; used = 0; error = _bus_dmamap_load_buffer(t, map, buf, buflen, p, flags, - &lastaddr, &seg, &used, 1); + &lastaddr, &seg, &used, 1, &dma_constraint); if (error == 0) { map->dm_mapsize = buflen; map->dm_nsegs = seg + 1; @@ -311,7 +312,8 @@ _bus_dmamap_load_mbuf(bus_dma_tag_t t, b if (m->m_len == 0) continue; error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len, - NULL, flags, &lastaddr, &seg, &used, first); + NULL, flags, &lastaddr, &seg, &used, first, + &mbuf_constraint); first = 0; } if (error == 0) { @@ -366,7 +368,8 @@ _bus_dmamap_load_uio(bus_dma_tag_t t, bu addr = (caddr_t)iov[i].iov_base; error = _bus_dmamap_load_buffer(t, map, addr, minlen, - p, flags, &lastaddr, &seg, &used, first); + p, flags, &lastaddr, &seg, &used, first, + &dma_constraint); first = 0; resid -= minlen; @@ -721,7 +724,7 @@ _bus_dmamem_mmap(bus_dma_tag_t t, bus_dm int _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf, bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp, - int *segp, int *usedp, int first) + int *segp, int *usedp, int first, struct uvm_constraint_range *constraint) { bus_size_t sgsize; bus_addr_t curaddr, lastaddr, baddr, bmask; @@ -746,7 +749,7 @@ _bus_dmamap_load_buffer(bus_dma_tag_t t, */ pmap_extract(pmap, vaddr, (paddr_t *)&curaddr); - if (curaddr > dma_constraint.ucr_high && + if (curaddr > constraint->ucr_high && (map->_dm_flags & BUS_DMA_64BIT) == 0) panic("Non dma-reachable buffer at curaddr %#lx(raw)", curaddr); Index: arch/amd64/amd64/machdep.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/machdep.c,v diff -u -p -r1.306 machdep.c --- arch/amd64/amd64/machdep.c 24 Nov 2025 17:20:40 -0000 1.306 +++ arch/amd64/amd64/machdep.c 11 Feb 2026 21:19:27 -0000 @@ -218,9 +218,11 @@ struct vm_map *phys_map = NULL; /* UVM constraint ranges. */ struct uvm_constraint_range isa_constraint = { 0x0, 0x00ffffffUL }; struct uvm_constraint_range dma_constraint = { 0x0, 0xffffffffUL }; +struct uvm_constraint_range mbuf_constraint = { 0x0, 0xffffffffUL }; struct uvm_constraint_range *uvm_md_constraints[] = { &isa_constraint, &dma_constraint, + &mbuf_constraint, NULL, }; Index: dev/pci/if_bnxt.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/dev/pci/if_bnxt.c,v diff -u -p -r1.64 if_bnxt.c --- dev/pci/if_bnxt.c 20 Jan 2026 05:08:04 -0000 1.64 +++ dev/pci/if_bnxt.c 11 Feb 2026 21:19:27 -0000 @@ -640,7 +640,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 11 Feb 2026 21:19:27 -0000 @@ -1990,7 +1990,7 @@ em_setup_interface(struct em_softc *sc) strlcpy(ifp->if_xname, DEVNAME(sc), 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 = em_ioctl; ifp->if_qstart = em_start; ifp->if_watchdog = em_watchdog; @@ -2158,7 +2158,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 | BUS_DMA_64BIT, + &dma->dma_map); if (r != 0) return (r); @@ -2250,10 +2251,11 @@ 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 | BUS_DMA_64BIT, + &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 +2774,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 | BUS_DMA_64BIT, + &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_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 11 Feb 2026 21:19:27 -0000 @@ -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 11 Feb 2026 21:19:27 -0000 @@ -737,8 +737,8 @@ 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)) @@ -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 11 Feb 2026 21:19:27 -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); @@ -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 11 Feb 2026 21:19:27 -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 11 Feb 2026 21:19:27 -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 11 Feb 2026 21:19:27 -0000 @@ -1477,7 +1477,21 @@ void m_pool_init(struct pool *pp, u_int size, u_int align, const char *wmesg) { pool_init(pp, size, align, IPL_NET, 0, wmesg, &m_pool_allocator); - pool_set_constraints(pp, &kp_dma_contig); + pool_set_constraints(pp, &kp_mbuf_contig); +} + +void +m_pool_constraints(paddr_t low, paddr_t high) +{ + int i; + + mbuf_constraint.ucr_low = low; + mbuf_constraint.ucr_high = high; + + pool_set_constraints(&mbpool, &kp_mbuf_contig); + + for (i = 0; i < nitems(mclsizes); i++) + pool_set_constraints(&mclpools[i], &kp_mbuf_contig); } u_int 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 11 Feb 2026 21:19:27 -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 11 Feb 2026 21:19:27 -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_constraints(paddr_t, paddr_t); 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 11 Feb 2026 21:19:27 -0000 @@ -232,6 +232,7 @@ extern struct uvmexp uvmexp; /* Constraint ranges, set by MD code. */ extern struct uvm_constraint_range isa_constraint; extern struct uvm_constraint_range dma_constraint; +extern struct uvm_constraint_range mbuf_constraint; extern struct uvm_constraint_range no_constraint; extern struct uvm_constraint_range *uvm_md_constraints[]; @@ -358,6 +359,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 11 Feb 2026 21:19:27 -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 = &mbuf_constraint, + .kp_maxseg = 1 +}; + const struct kmem_pa_mode kp_zero = { .kp_constraint = &no_constraint, .kp_zero = 1