Index: sys/arch/xen/x86/xen_shm_machdep.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/x86/xen_shm_machdep.c,v retrieving revision 1.18 diff -p -u -r1.18 xen_shm_machdep.c --- sys/arch/xen/x86/xen_shm_machdep.c 1 Sep 2022 12:29:00 -0000 1.18 +++ sys/arch/xen/x86/xen_shm_machdep.c 11 Sep 2026 16:10:35 -0000 @@ -30,6 +30,7 @@ __KERNEL_RCSID(0, "$NetBSD: xen_shm_mach #include "opt_xen.h" #include +#include #include #include #include @@ -59,18 +60,19 @@ int xen_shm_map(int nentries, int domid, grant_ref_t *grefp, vaddr_t va, grant_handle_t *handlep, int flags) { - gnttab_map_grant_ref_t op[XENSHM_MAX_PAGES_PER_REQUEST]; + gnttab_map_grant_ref_t *op; int ret, i; #ifndef XENPV paddr_t base_paddr; #endif - #ifdef DIAGNOSTIC if (nentries > XENSHM_MAX_PAGES_PER_REQUEST) { panic("xen_shm_map: %d entries", nentries); } #endif + op = kmem_alloc(nentries * sizeof(*op), KM_SLEEP); + #ifndef XENPV base_paddr = xenmem_alloc_pa(nentries * PAGE_SIZE, PAGE_SIZE, false); if (base_paddr == 0) @@ -166,12 +168,13 @@ xen_shm_map(int nentries, int domid, gra VM_PROT_READ | VM_PROT_WRITE, 0); } #endif - + kmem_free(op, nentries * sizeof(*op)); return 0; err1: #ifndef XENPV xenmem_free_pa(base_paddr, nentries * PAGE_SIZE); #endif + kmem_free(op, nentries * sizeof(*op)); return ret; } Index: sys/arch/xen/xen/xbd_xenbus.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/xen/xbd_xenbus.c,v retrieving revision 1.136 diff -p -u -r1.136 xbd_xenbus.c --- sys/arch/xen/xen/xbd_xenbus.c 15 Jul 2026 15:38:21 -0000 1.136 +++ sys/arch/xen/xen/xbd_xenbus.c 11 Sep 2026 16:10:35 -0000 @@ -95,13 +95,14 @@ __KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c #define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) #define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST) -#define XBD_MAX_CHUNK 32*1024 /* max I/O size we process in 1 req */ -#define XBD_XFER_LIMIT (2*XBD_MAX_XFER) +#define XBD_MAX_CHUNK (32*1024) /* max I/O size we process in 1 req */ +#define XBD_XFER_LIMIT MAXPHYS +#define XBD_NUM_CHUNK (XBD_XFER_LIMIT / XBD_MAX_CHUNK) #define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */ #define XEN_BSIZE (1 << XEN_BSHIFT) -CTASSERT((MAXPHYS <= 2*XBD_MAX_CHUNK)); +CTASSERT((XBD_MAX_XFER <= XBD_NUM_CHUNK * XBD_MAX_CHUNK)); CTASSERT(XEN_BSIZE == DEV_BSIZE); struct xbd_indirect { @@ -114,11 +115,10 @@ struct xbd_req { SLIST_ENTRY(xbd_req) req_next; uint16_t req_id; /* ID passed to backend */ bus_dmamap_t req_dmamap; - struct xbd_req *req_parent, *req_child; - bool req_parent_done; + struct xbd_req *req_parent, *req_child, *req_first; union { struct { - grant_ref_t req_gntref[XBD_XFER_LIMIT >> PAGE_SHIFT]; + grant_ref_t req_gntref[MAXPHYS >> PAGE_SHIFT]; struct buf *req_bp; /* buffer associated with this request */ void *req_data; /* pointer to the data buffer */ struct xbd_indirect *req_indirect; /* indirect page */ @@ -169,9 +169,8 @@ struct xbd_xenbus_softc { #define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */ #define BLKIF_SHUTDOWN_LOCAL 2 /* locally-initiated shutdown in progress */ - uint64_t sc_sectors; /* number of sc_secsize sectors for this device */ + uint64_t sc_sectors; /* number of sectors for this device */ u_long sc_secsize; /* sector size */ - uint64_t sc_xbdsize; /* size of disk in DEV_BSIZE */ u_long sc_info; /* VDISK_* */ u_long sc_handle; /* from backend */ int sc_features; @@ -344,7 +343,7 @@ xbd_xenbus_attach(device_t parent, devic for (i = 0; i < XBD_RING_SIZE; i++) { if (bus_dmamap_create(sc->sc_xbusd->xbusd_dmat, - MAXPHYS, XBD_XFER_LIMIT >> PAGE_SHIFT, + MAXPHYS, MAXPHYS >> PAGE_SHIFT, PAGE_SIZE, PAGE_SIZE, BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, &sc->sc_reqs[i].req_dmamap) != 0) { aprint_error_dev(self, "can't alloc dma maps\n"); @@ -675,16 +674,15 @@ xbd_backend_changed(void *arg, XenbusSta xbd_connect(sc); sc->sc_shutdown = BLKIF_SHUTDOWN_RUN; - sc->sc_xbdsize = - sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE; dg = &sc->sc_dksc.sc_dkdev.dk_geom; memset(dg, 0, sizeof(*dg)); dg->dg_secperunit = sc->sc_sectors; dg->dg_secsize = sc->sc_secsize; + /* Fake geometry with 1MByte cylinders */ dg->dg_ntracks = 1; dg->dg_nsectors = (1024 * 1024) / dg->dg_secsize; - dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; + dg->dg_ncylinders = dg->dg_secperunit / (dg->dg_nsectors * dg->dg_ntracks); bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0); dk_attach(&sc->sc_dksc); @@ -694,10 +692,10 @@ xbd_backend_changed(void *arg, XenbusSta hypervisor_unmask_event(sc->sc_evtchn); format_bytes(buf, uimin(9, sizeof(buf)), - sc->sc_sectors * dg->dg_secsize); + sc->sc_sectors * sc->sc_secsize); aprint_normal_dev(sc->sc_dksc.sc_dev, - "%s, %d bytes/sect x %" PRIu64 " sectors\n", - buf, (int)dg->dg_secsize, sc->sc_sectors); + "%s, %u bytes/sect x %" PRIu64 " sectors\n", + buf, (unsigned)sc->sc_secsize, sc->sc_sectors); snprintb(buf, sizeof(buf), BLKIF_FEATURE_BITS, sc->sc_features); aprint_normal_dev(sc->sc_dksc.sc_dev, @@ -759,7 +757,7 @@ xbd_connect(struct xbd_xenbus_softc *sc) panic("%s: can't read number from %s/sectors\n", device_xname(sc->sc_dksc.sc_dev), sc->sc_xbusd->xbusd_otherend); - sc->sc_sectors = sectors * (uint64_t)XEN_BSIZE / sc->sc_secsize; + sc->sc_sectors = sectors; xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); } @@ -788,7 +786,7 @@ xbd_features(struct xbd_xenbus_softc *sc "feature-max-indirect-segments", &val, 10); if (err) val = 0; - if (val >= (MAXPHYS >> PAGE_SHIFT) + 1) { + if (val >= XBD_XFER_LIMIT >> PAGE_SHIFT) { /* We can use indirect segments, the limit is big enough */ sc->sc_features |= BLKIF_FEATURE_INDIRECT; } @@ -828,7 +826,7 @@ again: if (rep->operation != BLKIF_OP_READ && rep->operation != BLKIF_OP_WRITE) { - aprint_error_dev(sc->sc_dksc.sc_dev, + device_printf(sc->sc_dksc.sc_dev, "bad operation %d from backend\n", rep->operation); continue; } @@ -847,28 +845,35 @@ again: } if (xbdreq->req_parent) { - struct xbd_req *req_parent = xbdreq->req_parent; + /* Unhook request with busy parent */ + xbdreq->req_parent->req_child = xbdreq->req_child; + } + + if (xbdreq->req_child) { + /* Unhook request with busy parent */ + xbdreq->req_child->req_parent = xbdreq->req_parent; + } - /* Unhook and recycle child */ + if (xbdreq->req_parent != NULL || xbdreq->req_child != NULL) { + /* Finished before other requests */ xbdreq->req_parent = NULL; - req_parent->req_child = NULL; - SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, - req_next); + xbdreq->req_child = NULL; - if (!req_parent->req_parent_done) { - /* Finished before parent, nothing else to do */ - continue; + /* Recycle unless first request */ + if (xbdreq != xbdreq->req_first) { + SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, + req_next); } - - /* Must do the cleanup now */ - xbdreq = req_parent; - } - if (xbdreq->req_child) { - /* Finished before child, child will cleanup */ - xbdreq->req_parent_done = true; continue; } + if (xbdreq != xbdreq->req_first) { + struct xbd_req *req_first = xbdreq->req_first; + SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, + req_next); + xbdreq = req_first; + } + if (bp->b_error == 0) bp->b_resid = 0; @@ -1124,7 +1129,7 @@ static int xbd_diskstart(device_t self, struct buf *bp) { struct xbd_xenbus_softc *sc = device_private(self); - struct xbd_req *xbdreq; + struct xbd_req *xbdreq, *req_parent; int error = 0; int notify; @@ -1140,7 +1145,7 @@ xbd_diskstart(device_t self, struct buf goto out; } - if (bp->b_rawblkno < 0 || bp->b_rawblkno > sc->sc_sectors) { + if (bp->b_rawblkno < 0 || bp->b_rawblkno >= sc->sc_sectors) { /* invalid block number */ error = EINVAL; goto out; @@ -1164,12 +1169,16 @@ xbd_diskstart(device_t self, struct buf } KASSERT(!RING_FULL(&sc->sc_ring)); - if ((sc->sc_features & BLKIF_FEATURE_INDIRECT) == 0 - && bp->b_bcount > XBD_MAX_CHUNK) { - if (!SLIST_NEXT(xbdreq, req_next)) { - DPRINTF(("%s: need extra req\n", __func__)); - error = EAGAIN; - goto out; + if ((sc->sc_features & BLKIF_FEATURE_INDIRECT) == 0) { + struct xbd_req *req_next = xbdreq; + for (int count = bp->b_bcount; count > XBD_MAX_CHUNK; + count -= XBD_MAX_CHUNK) { + req_next = SLIST_NEXT(req_next, req_next); + if (!req_next) { + DPRINTF(("%s: need extra req\n", __func__)); + error = EAGAIN; + goto out; + } } } @@ -1187,8 +1196,9 @@ xbd_diskstart(device_t self, struct buf if (__predict_false(bus_dmamap_load(sc->sc_xbusd->xbusd_dmat, xbdreq->req_dmamap, xbdreq->req_data, bp->b_bcount, NULL, BUS_DMA_NOWAIT) != 0)) { - printf("%s: %s: bus_dmamap_load failed\n", - device_xname(sc->sc_dksc.sc_dev), __func__); + printf("%s: %s: bus_dmamap_load failed (bcount=%d)\n", + device_xname(sc->sc_dksc.sc_dev), __func__, + bp->b_bcount); if (__predict_false(bp->b_data != xbdreq->req_data)) xbd_unmap_align(sc, xbdreq, NULL); error = EINVAL; @@ -1225,6 +1235,9 @@ xbd_diskstart(device_t self, struct buf KASSERT(xbdreq->req_parent == NULL); KASSERT(xbdreq->req_child == NULL); + /* Request chain starts here */ + xbdreq->req_first = xbdreq; + /* We are now committed to the transfer */ SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); @@ -1237,18 +1250,25 @@ xbd_diskstart(device_t self, struct buf xbd_diskstart_submit(sc, xbdreq->req_id, bp, 0, xbdreq->req_dmamap, xbdreq->req_gntref); - if (bp->b_bcount > XBD_MAX_CHUNK) { + req_parent = xbdreq; + for (int count = bp->b_bcount, start = XBD_MAX_CHUNK; + count > XBD_MAX_CHUNK; + count -= XBD_MAX_CHUNK, start += XBD_MAX_CHUNK) { + KASSERT(!RING_FULL(&sc->sc_ring)); struct xbd_req *xbdreq2 = SLIST_FIRST(&sc->sc_xbdreq_head); KASSERT(xbdreq2 != NULL); /* Checked earlier */ SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); - xbdreq->req_child = xbdreq2; - xbdreq->req_parent_done = false; - xbdreq2->req_parent = xbdreq; + req_parent->req_child = xbdreq2; + xbdreq2->req_parent = req_parent; + xbdreq2->req_child = NULL; + xbdreq2->req_first = xbdreq; xbdreq2->req_bp = bp; xbdreq2->req_data = xbdreq->req_data; + req_parent = xbdreq2; + xbd_diskstart_submit(sc, xbdreq2->req_id, - bp, XBD_MAX_CHUNK, xbdreq->req_dmamap, + bp, start, xbdreq->req_dmamap, xbdreq->req_gntref); } Index: sys/arch/xen/xen/xbdback_xenbus.c =================================================================== RCS file: /cvsroot/src/sys/arch/xen/xen/xbdback_xenbus.c,v retrieving revision 1.108 diff -p -u -r1.108 xbdback_xenbus.c --- sys/arch/xen/xen/xbdback_xenbus.c 10 Mar 2026 21:59:29 -0000 1.108 +++ sys/arch/xen/xen/xbdback_xenbus.c 11 Sep 2026 16:10:35 -0000 @@ -208,6 +208,7 @@ struct xbdback_instance { const struct bdevsw *xbdi_bdevsw; /* pointer to the device's bdevsw */ struct vnode *xbdi_vp; uint64_t xbdi_size; + unsigned xbdi_secsize; bool xbdi_ro; /* is device read-only ? */ /* parameters for the communication */ unsigned int xbdi_evtchn; @@ -397,7 +398,10 @@ xbdback_xenbus_create(struct xenbus_devi * is 128 so this helps us avoiding a page boundary withing a * block of VBD_MAX_INDIRECT_SEGMENTS segments. */ - CTASSERT(sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS == 128); + + CTASSERT(PAGE_SIZE % (sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS) == 0); + CTASSERT(PAGE_SIZE / (sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS) > 1); + xbdi->xbdi_segs = (void *)uvm_km_alloc(kernel_map, round_page( sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS * BLKIF_RING_SIZE), PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_WAITVA); @@ -572,7 +576,7 @@ xbdback_connect(struct xbdback_instance xbdi->xbdi_proto = XBDIP_64; proto = XEN_IO_PROTO_ABI_X86_64; } else { - aprint_error("xbd domain %d: unknown proto %s\n", + printf("xbd domain %d: unknown proto %s\n", xbdi->xbdi_domid, xsproto); return -1; } @@ -591,7 +595,7 @@ xbdback_connect(struct xbdback_instance gring_ref = ring_ref; if (xen_shm_map(1, xbdi->xbdi_domid, &gring_ref, xbdi->xbdi_ring_va, &xbdi->xbdi_ring_handle, 0) != 0) { - aprint_error("xbdback %s: can't map grant ref\n", + printf("xbdback %s: can't map grant ref\n", xbusd->xbusd_path); xenbus_dev_fatal(xbusd, EINVAL, "can't map ring", xbusd->xbusd_otherend); @@ -625,7 +629,7 @@ xbdback_connect(struct xbdback_instance evop.u.bind_interdomain.remote_port = revtchn; err = HYPERVISOR_event_channel_op(&evop); if (err) { - aprint_error("blkback %s: " + printf("blkback %s: " "can't get event channel: %d\n", xbusd->xbusd_otherend, err); xenbus_dev_fatal(xbusd, err, @@ -639,7 +643,7 @@ xbdback_connect(struct xbdback_instance xbdi->xbdi_evtchn, IST_LEVEL, IPL_BIO, xbdback_evthandler, xbdi, true, xbdi->xbdi_name); KASSERT(xbdi->xbdi_ih != NULL); - aprint_verbose("xbd backend domain %d handle %#x (%d) " + printf("xbd backend domain %d handle %#x (%d) " "using event channel %d, protocol %s\n", xbdi->xbdi_domid, xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto); @@ -713,7 +717,7 @@ xbdback_frontend_changed(void *arg, Xenb case XenbusStateUnknown: case XenbusStateInitWait: default: - aprint_error("xbdback %s: invalid frontend state %d\n", + printf("xbdback %s: invalid frontend state %d\n", xbusd->xbusd_path, new_state); } return; @@ -800,16 +804,19 @@ xbdback_backend_changed(struct xenbus_wa } VOP_UNLOCK(xbdi->xbdi_vp); - /* dk device; get wedge data */ struct dkwedge_info wi; - if ((err = getdiskinfo(xbdi->xbdi_vp, &wi)) == 0) { - xbdi->xbdi_size = wi.dkw_size; - printf("xbd backend: attach device %s (size %" PRIu64 ") " - "for domain %d\n", wi.dkw_devname, xbdi->xbdi_size, - xbdi->xbdi_domid); + if (getdiskinfo(xbdi->xbdi_vp, &wi) == 0) + devname = wi.dkw_devname; + + err = getdisksize(xbdi->xbdi_vp, &xbdi->xbdi_size, &xbdi->xbdi_secsize); + if (err == 0) { + printf("xbd backend: attach device %s" + " (size %" PRIu64 " x %u) for domain %d\n", + devname, xbdi->xbdi_size, + xbdi->xbdi_secsize, xbdi->xbdi_domid); } else { - /* If both Ioctls failed set device size to 0 and return */ - printf("xbdback %s: can't DIOCGWEDGEINFO device " + /* If Ioctls failed set device size to 0 and return */ + printf("xbdback %s: can't get size of device " "0x%"PRIx64": %d\n", xbusd->xbusd_path, xbdi->xbdi_dev, err); xbdi->xbdi_size = xbdi->xbdi_dev = 0; @@ -839,7 +846,7 @@ again: goto abort; } err = xenbus_printf(xbt, xbusd->xbusd_path, "sector-size", "%lu", - (u_long)DEV_BSIZE); + (u_long)xbdi->xbdi_secsize); if (err) { printf("xbdback: failed to write %s/sector-size: %d\n", xbusd->xbusd_path, err); @@ -1460,7 +1467,7 @@ xbdback_co_do_io(struct xbdback_instance kauth_cred_get()); mutex_enter(&xbdi->xbdi_lock); if (error) { - aprint_error("xbdback %s: DIOCCACHESYNC returned %d\n", + printf("xbdback %s: DIOCCACHESYNC returned %d\n", xbdi->xbdi_xbusd->xbusd_path, error); if (error == EOPNOTSUPP || error == ENOTTY) error = BLKIF_RSP_EOPNOTSUPP;