| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: xbd_xenbus.c,v 1.130 2023/02/25 00:33:03 riastradh Exp $ */ | | 1 | /* $NetBSD: xbd_xenbus.c,v 1.131 2023/02/25 00:35:15 riastradh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 Manuel Bouyer. | | 4 | * Copyright (c) 2006 Manuel Bouyer. |
5 | * | | 5 | * |
6 | * Redistribution and use in source and binary forms, with or without | | 6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions | | 7 | * modification, are permitted provided that the following conditions |
8 | * are met: | | 8 | * are met: |
9 | * 1. Redistributions of source code must retain the above copyright | | 9 | * 1. Redistributions of source code must retain the above copyright |
10 | * notice, this list of conditions and the following disclaimer. | | 10 | * notice, this list of conditions and the following disclaimer. |
11 | * 2. Redistributions in binary form must reproduce the above copyright | | 11 | * 2. Redistributions in binary form must reproduce the above copyright |
12 | * notice, this list of conditions and the following disclaimer in the | | 12 | * notice, this list of conditions and the following disclaimer in the |
13 | * documentation and/or other materials provided with the distribution. | | 13 | * documentation and/or other materials provided with the distribution. |
14 | * | | 14 | * |
| @@ -40,27 +40,27 @@ | | | @@ -40,27 +40,27 @@ |
40 | * - initiate request: xbdread/write/open/ioctl/.. | | 40 | * - initiate request: xbdread/write/open/ioctl/.. |
41 | * - depending on operation, it is handled directly by disk(9) subsystem or | | 41 | * - depending on operation, it is handled directly by disk(9) subsystem or |
42 | * goes through physio(9) first. | | 42 | * goes through physio(9) first. |
43 | * - the request is ultimately processed by xbd_diskstart() that prepares the | | 43 | * - the request is ultimately processed by xbd_diskstart() that prepares the |
44 | * xbd requests, post them in the ring I/O queue, then signal the backend. | | 44 | * xbd requests, post them in the ring I/O queue, then signal the backend. |
45 | * | | 45 | * |
46 | * When a response is available in the queue, the backend signals the frontend | | 46 | * When a response is available in the queue, the backend signals the frontend |
47 | * via its event channel. This triggers xbd_handler(), which will link back | | 47 | * via its event channel. This triggers xbd_handler(), which will link back |
48 | * the response to its request through the request ID, and mark the I/O as | | 48 | * the response to its request through the request ID, and mark the I/O as |
49 | * completed. | | 49 | * completed. |
50 | */ | | 50 | */ |
51 | | | 51 | |
52 | #include <sys/cdefs.h> | | 52 | #include <sys/cdefs.h> |
53 | __KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.130 2023/02/25 00:33:03 riastradh Exp $"); | | 53 | __KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.131 2023/02/25 00:35:15 riastradh Exp $"); |
54 | | | 54 | |
55 | #include "opt_xen.h" | | 55 | #include "opt_xen.h" |
56 | | | 56 | |
57 | | | 57 | |
58 | #include <sys/param.h> | | 58 | #include <sys/param.h> |
59 | #include <sys/buf.h> | | 59 | #include <sys/buf.h> |
60 | #include <sys/bufq.h> | | 60 | #include <sys/bufq.h> |
61 | #include <sys/device.h> | | 61 | #include <sys/device.h> |
62 | #include <sys/disk.h> | | 62 | #include <sys/disk.h> |
63 | #include <sys/disklabel.h> | | 63 | #include <sys/disklabel.h> |
64 | #include <sys/conf.h> | | 64 | #include <sys/conf.h> |
65 | #include <sys/fcntl.h> | | 65 | #include <sys/fcntl.h> |
66 | #include <sys/kernel.h> | | 66 | #include <sys/kernel.h> |
| @@ -89,27 +89,27 @@ __KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c | | | @@ -89,27 +89,27 @@ __KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c |
89 | #define DPRINTF(x) printf x; | | 89 | #define DPRINTF(x) printf x; |
90 | #else | | 90 | #else |
91 | #define DPRINTF(x) | | 91 | #define DPRINTF(x) |
92 | #endif | | 92 | #endif |
93 | | | 93 | |
94 | #define GRANT_INVALID_REF -1 | | 94 | #define GRANT_INVALID_REF -1 |
95 | | | 95 | |
96 | #define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) | | 96 | #define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) |
97 | #define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST) | | 97 | #define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST) |
98 | #define XBD_MAX_CHUNK 32*1024 /* max I/O size we process in 1 req */ | | 98 | #define XBD_MAX_CHUNK 32*1024 /* max I/O size we process in 1 req */ |
99 | #define XBD_XFER_LIMIT (2*XBD_MAX_XFER) | | 99 | #define XBD_XFER_LIMIT (2*XBD_MAX_XFER) |
100 | | | 100 | |
101 | #define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */ | | 101 | #define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */ |
102 | #define XEN_BSIZE (1 << XEN_BSHIFT) | | 102 | #define XEN_BSIZE (1 << XEN_BSHIFT) |
103 | | | 103 | |
104 | CTASSERT((MAXPHYS <= 2*XBD_MAX_CHUNK)); | | 104 | CTASSERT((MAXPHYS <= 2*XBD_MAX_CHUNK)); |
105 | CTASSERT(XEN_BSIZE == DEV_BSIZE); | | 105 | CTASSERT(XEN_BSIZE == DEV_BSIZE); |
106 | | | 106 | |
107 | struct xbd_indirect { | | 107 | struct xbd_indirect { |
108 | SLIST_ENTRY(xbd_indirect) in_next; | | 108 | SLIST_ENTRY(xbd_indirect) in_next; |
109 | struct blkif_request_segment *in_addr; | | 109 | struct blkif_request_segment *in_addr; |
110 | grant_ref_t in_gntref; | | 110 | grant_ref_t in_gntref; |
111 | }; | | 111 | }; |
112 | | | 112 | |
113 | struct xbd_req { | | 113 | struct xbd_req { |
114 | SLIST_ENTRY(xbd_req) req_next; | | 114 | SLIST_ENTRY(xbd_req) req_next; |
115 | uint16_t req_id; /* ID passed to backend */ | | 115 | uint16_t req_id; /* ID passed to backend */ |
| @@ -666,27 +666,27 @@ xbd_backend_changed(void *arg, XenbusSta | | | @@ -666,27 +666,27 @@ xbd_backend_changed(void *arg, XenbusSta |
666 | * the xenbus thread. | | 666 | * the xenbus thread. |
667 | */ | | 667 | */ |
668 | | | 668 | |
669 | if (sc->sc_backend_status == BLKIF_STATE_CONNECTED || | | 669 | if (sc->sc_backend_status == BLKIF_STATE_CONNECTED || |
670 | sc->sc_backend_status == BLKIF_STATE_SUSPENDED) | | 670 | sc->sc_backend_status == BLKIF_STATE_SUSPENDED) |
671 | /* already connected */ | | 671 | /* already connected */ |
672 | return; | | 672 | return; |
673 | | | 673 | |
674 | xbd_connect(sc); | | 674 | xbd_connect(sc); |
675 | sc->sc_shutdown = BLKIF_SHUTDOWN_RUN; | | 675 | sc->sc_shutdown = BLKIF_SHUTDOWN_RUN; |
676 | sc->sc_xbdsize = | | 676 | sc->sc_xbdsize = |
677 | sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE; | | 677 | sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE; |
678 | dg = &sc->sc_dksc.sc_dkdev.dk_geom; | | 678 | dg = &sc->sc_dksc.sc_dkdev.dk_geom; |
679 | memset(dg, 0, sizeof(*dg)); | | 679 | memset(dg, 0, sizeof(*dg)); |
680 | | | 680 | |
681 | dg->dg_secperunit = sc->sc_xbdsize; | | 681 | dg->dg_secperunit = sc->sc_xbdsize; |
682 | dg->dg_secsize = DEV_BSIZE; | | 682 | dg->dg_secsize = DEV_BSIZE; |
683 | dg->dg_ntracks = 1; | | 683 | dg->dg_ntracks = 1; |
684 | // XXX: Ok to hard-code DEV_BSIZE? | | 684 | // XXX: Ok to hard-code DEV_BSIZE? |
685 | dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize); | | 685 | dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize); |
686 | dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; | | 686 | dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; |
687 | | | 687 | |
688 | bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0); | | 688 | bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0); |
689 | dk_attach(&sc->sc_dksc); | | 689 | dk_attach(&sc->sc_dksc); |
690 | disk_attach(&sc->sc_dksc.sc_dkdev); | | 690 | disk_attach(&sc->sc_dksc.sc_dkdev); |
691 | | | 691 | |
692 | sc->sc_backend_status = BLKIF_STATE_CONNECTED; | | 692 | sc->sc_backend_status = BLKIF_STATE_CONNECTED; |
| @@ -726,47 +726,47 @@ xbd_connect(struct xbd_xenbus_softc *sc) | | | @@ -726,47 +726,47 @@ xbd_connect(struct xbd_xenbus_softc *sc) |
726 | * Must read feature-persistent later, e.g. Linux Dom0 writes | | 726 | * Must read feature-persistent later, e.g. Linux Dom0 writes |
727 | * this together with the device info. | | 727 | * this together with the device info. |
728 | */ | | 728 | */ |
729 | err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, | | 729 | err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, |
730 | "feature-persistent", &val, 10); | | 730 | "feature-persistent", &val, 10); |
731 | if (err) | | 731 | if (err) |
732 | val = 0; | | 732 | val = 0; |
733 | if (val > 0) | | 733 | if (val > 0) |
734 | sc->sc_features |= BLKIF_FEATURE_PERSISTENT; | | 734 | sc->sc_features |= BLKIF_FEATURE_PERSISTENT; |
735 | | | 735 | |
736 | err = xenbus_read_ul(NULL, | | 736 | err = xenbus_read_ul(NULL, |
737 | sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10); | | 737 | sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10); |
738 | if (err) | | 738 | if (err) |
739 | panic("%s: can't read number from %s/virtual-device\n", | | 739 | panic("%s: can't read number from %s/virtual-device\n", |
740 | device_xname(sc->sc_dksc.sc_dev), | | 740 | device_xname(sc->sc_dksc.sc_dev), |
741 | sc->sc_xbusd->xbusd_otherend); | | 741 | sc->sc_xbusd->xbusd_otherend); |
742 | err = xenbus_read_ull(NULL, | | 742 | err = xenbus_read_ull(NULL, |
743 | sc->sc_xbusd->xbusd_otherend, "sectors", §ors, 10); | | 743 | sc->sc_xbusd->xbusd_otherend, "sectors", §ors, 10); |
744 | if (err) | | 744 | if (err) |
745 | panic("%s: can't read number from %s/sectors\n", | | 745 | panic("%s: can't read number from %s/sectors\n", |
746 | device_xname(sc->sc_dksc.sc_dev), | | 746 | device_xname(sc->sc_dksc.sc_dev), |
747 | sc->sc_xbusd->xbusd_otherend); | | 747 | sc->sc_xbusd->xbusd_otherend); |
748 | sc->sc_sectors = sectors; | | 748 | sc->sc_sectors = sectors; |
749 | | | 749 | |
750 | err = xenbus_read_ul(NULL, | | 750 | err = xenbus_read_ul(NULL, |
751 | sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10); | | 751 | sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10); |
752 | if (err) | | 752 | if (err) |
753 | panic("%s: can't read number from %s/info\n", | | 753 | panic("%s: can't read number from %s/info\n", |
754 | device_xname(sc->sc_dksc.sc_dev), | | 754 | device_xname(sc->sc_dksc.sc_dev), |
755 | sc->sc_xbusd->xbusd_otherend); | | 755 | sc->sc_xbusd->xbusd_otherend); |
756 | err = xenbus_read_ul(NULL, | | 756 | err = xenbus_read_ul(NULL, |
757 | sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10); | | 757 | sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10); |
758 | if (err) | | 758 | if (err) |
759 | panic("%s: can't read number from %s/sector-size\n", | | 759 | panic("%s: can't read number from %s/sector-size\n", |
760 | device_xname(sc->sc_dksc.sc_dev), | | 760 | device_xname(sc->sc_dksc.sc_dev), |
761 | sc->sc_xbusd->xbusd_otherend); | | 761 | sc->sc_xbusd->xbusd_otherend); |
762 | | | 762 | |
763 | xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); | | 763 | xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); |
764 | } | | 764 | } |
765 | | | 765 | |
766 | static void | | 766 | static void |
767 | xbd_features(struct xbd_xenbus_softc *sc) | | 767 | xbd_features(struct xbd_xenbus_softc *sc) |
768 | { | | 768 | { |
769 | int err; | | 769 | int err; |
770 | u_long val; | | 770 | u_long val; |
771 | | | 771 | |
772 | err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, | | 772 | err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, |
| @@ -924,27 +924,27 @@ static void | | | @@ -924,27 +924,27 @@ static void |
924 | xbdminphys(struct buf *bp) | | 924 | xbdminphys(struct buf *bp) |
925 | { | | 925 | { |
926 | if (bp->b_bcount > XBD_XFER_LIMIT) { | | 926 | if (bp->b_bcount > XBD_XFER_LIMIT) { |
927 | bp->b_bcount = XBD_XFER_LIMIT; | | 927 | bp->b_bcount = XBD_XFER_LIMIT; |
928 | } | | 928 | } |
929 | minphys(bp); | | 929 | minphys(bp); |
930 | } | | 930 | } |
931 | | | 931 | |
932 | static void | | 932 | static void |
933 | xbd_iosize(device_t dev, int *maxxfer) | | 933 | xbd_iosize(device_t dev, int *maxxfer) |
934 | { | | 934 | { |
935 | /* | | 935 | /* |
936 | * Always restrict dumps to XBD_MAX_XFER to avoid indirect segments, | | 936 | * Always restrict dumps to XBD_MAX_XFER to avoid indirect segments, |
937 | * so that it uses as little memory as possible. | | 937 | * so that it uses as little memory as possible. |
938 | */ | | 938 | */ |
939 | if (*maxxfer > XBD_MAX_XFER) | | 939 | if (*maxxfer > XBD_MAX_XFER) |
940 | *maxxfer = XBD_MAX_XFER; | | 940 | *maxxfer = XBD_MAX_XFER; |
941 | } | | 941 | } |
942 | | | 942 | |
943 | static int | | 943 | static int |
944 | xbdopen(dev_t dev, int flags, int fmt, struct lwp *l) | | 944 | xbdopen(dev_t dev, int flags, int fmt, struct lwp *l) |
945 | { | | 945 | { |
946 | struct xbd_xenbus_softc *sc; | | 946 | struct xbd_xenbus_softc *sc; |
947 | | | 947 | |
948 | sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); | | 948 | sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); |
949 | if (sc == NULL) | | 949 | if (sc == NULL) |
950 | return (ENXIO); | | 950 | return (ENXIO); |
| @@ -998,27 +998,27 @@ xbdsize(dev_t dev) | | | @@ -998,27 +998,27 @@ xbdsize(dev_t dev) |
998 | struct xbd_xenbus_softc *sc; | | 998 | struct xbd_xenbus_softc *sc; |
999 | | | 999 | |
1000 | DPRINTF(("xbdsize(%" PRIx64 ")\n", dev)); | | 1000 | DPRINTF(("xbdsize(%" PRIx64 ")\n", dev)); |
1001 | | | 1001 | |
1002 | sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); | | 1002 | sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); |
1003 | if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) | | 1003 | if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) |
1004 | return -1; | | 1004 | return -1; |
1005 | return dk_size(&sc->sc_dksc, dev); | | 1005 | return dk_size(&sc->sc_dksc, dev); |
1006 | } | | 1006 | } |
1007 | | | 1007 | |
1008 | static int | | 1008 | static int |
1009 | xbdread(dev_t dev, struct uio *uio, int flags) | | 1009 | xbdread(dev_t dev, struct uio *uio, int flags) |
1010 | { | | 1010 | { |
1011 | struct xbd_xenbus_softc *sc = | | 1011 | struct xbd_xenbus_softc *sc = |
1012 | device_lookup_private(&xbd_cd, DISKUNIT(dev)); | | 1012 | device_lookup_private(&xbd_cd, DISKUNIT(dev)); |
1013 | struct dk_softc *dksc = &sc->sc_dksc; | | 1013 | struct dk_softc *dksc = &sc->sc_dksc; |
1014 | | | 1014 | |
1015 | if (!DK_ATTACHED(dksc)) | | 1015 | if (!DK_ATTACHED(dksc)) |
1016 | return ENXIO; | | 1016 | return ENXIO; |
1017 | return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio); | | 1017 | return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio); |
1018 | } | | 1018 | } |
1019 | | | 1019 | |
1020 | static int | | 1020 | static int |
1021 | xbdwrite(dev_t dev, struct uio *uio, int flags) | | 1021 | xbdwrite(dev_t dev, struct uio *uio, int flags) |
1022 | { | | 1022 | { |
1023 | struct xbd_xenbus_softc *sc = | | 1023 | struct xbd_xenbus_softc *sc = |
1024 | device_lookup_private(&xbd_cd, DISKUNIT(dev)); | | 1024 | device_lookup_private(&xbd_cd, DISKUNIT(dev)); |
| @@ -1267,27 +1267,27 @@ xbd_diskstart_submit(struct xbd_xenbus_s | | | @@ -1267,27 +1267,27 @@ xbd_diskstart_submit(struct xbd_xenbus_s |
1267 | paddr_t ma; | | 1267 | paddr_t ma; |
1268 | int nsects, nbytes, dmaseg, first_sect, size, segidx = 0; | | 1268 | int nsects, nbytes, dmaseg, first_sect, size, segidx = 0; |
1269 | struct blkif_request_segment *reqseg; | | 1269 | struct blkif_request_segment *reqseg; |
1270 | | | 1270 | |
1271 | KASSERT(mutex_owned(&sc->sc_lock)); | | 1271 | KASSERT(mutex_owned(&sc->sc_lock)); |
1272 | | | 1272 | |
1273 | req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt); | | 1273 | req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt); |
1274 | req->id = req_id; | | 1274 | req->id = req_id; |
1275 | req->operation = | | 1275 | req->operation = |
1276 | bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE; | | 1276 | bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE; |
1277 | req->sector_number = bp->b_rawblkno + (start >> XEN_BSHIFT); | | 1277 | req->sector_number = bp->b_rawblkno + (start >> XEN_BSHIFT); |
1278 | req->handle = sc->sc_handle; | | 1278 | req->handle = sc->sc_handle; |
1279 | | | 1279 | |
1280 | size = uimin(bp->b_bcount - start, XBD_MAX_CHUNK); | | 1280 | size = uimin(bp->b_bcount - start, XBD_MAX_CHUNK); |
1281 | for (dmaseg = 0; dmaseg < dmamap->dm_nsegs && size > 0; dmaseg++) { | | 1281 | for (dmaseg = 0; dmaseg < dmamap->dm_nsegs && size > 0; dmaseg++) { |
1282 | bus_dma_segment_t *ds = &dmamap->dm_segs[dmaseg]; | | 1282 | bus_dma_segment_t *ds = &dmamap->dm_segs[dmaseg]; |
1283 | | | 1283 | |
1284 | ma = ds->ds_addr; | | 1284 | ma = ds->ds_addr; |
1285 | nbytes = ds->ds_len; | | 1285 | nbytes = ds->ds_len; |
1286 | | | 1286 | |
1287 | if (start > 0) { | | 1287 | if (start > 0) { |
1288 | if (start >= nbytes) { | | 1288 | if (start >= nbytes) { |
1289 | start -= nbytes; | | 1289 | start -= nbytes; |
1290 | continue; | | 1290 | continue; |
1291 | } | | 1291 | } |
1292 | ma += start; | | 1292 | ma += start; |
1293 | nbytes -= start; | | 1293 | nbytes -= start; |