Tue Aug 21 18:55:09 2018 UTC ()
(only commit message for rev 1.85, no actual change)

shuffle code in xbd_handler() response loop so that req_bp is never
touched for non I/O responses; unknown commands are now just skipped, also
without touching neither xbdreq, nor req_bp

add some KASSERTS() for xbdreq->req_nr_segments and xbdreq->req_bp,
and reset req_bp after it's processed to ensure the buf can never
be processed twice

intended to simplify debugging in cases like PR port-xen/53506


(jdolecek)
diff -r1.85 -r1.86 src/sys/arch/xen/xen/xbd_xenbus.c

cvs diff -r1.85 -r1.86 src/sys/arch/xen/xen/xbd_xenbus.c (switch to unified diff)

--- src/sys/arch/xen/xen/xbd_xenbus.c 2018/08/21 18:45:16 1.85
+++ src/sys/arch/xen/xen/xbd_xenbus.c 2018/08/21 18:55:08 1.86
@@ -1,1029 +1,1030 @@ @@ -1,1029 +1,1030 @@
1/* $NetBSD: xbd_xenbus.c,v 1.85 2018/08/21 18:45:16 jdolecek Exp $ */ 1/* $NetBSD: xbd_xenbus.c,v 1.86 2018/08/21 18:55:08 jdolecek 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 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 * 25 *
26 */ 26 */
27 27
28/* 28/*
29 * The file contains the xbd frontend code required for block-level 29 * The file contains the xbd frontend code required for block-level
30 * communications (similar to hard disks) between two Xen domains. 30 * communications (similar to hard disks) between two Xen domains.
31 * 31 *
32 * We are not supposed to receive solicitations spontaneously from backend. The 32 * We are not supposed to receive solicitations spontaneously from backend. The
33 * protocol is therefore fairly simple and uses only one ring to communicate 33 * protocol is therefore fairly simple and uses only one ring to communicate
34 * with backend: frontend posts requests to the ring then wait for their 34 * with backend: frontend posts requests to the ring then wait for their
35 * replies asynchronously. 35 * replies asynchronously.
36 * 36 *
37 * xbd follows NetBSD's disk(9) convention. At any time, a LWP can schedule 37 * xbd follows NetBSD's disk(9) convention. At any time, a LWP can schedule
38 * an operation request for the device (be it open(), read(), write(), ...). 38 * an operation request for the device (be it open(), read(), write(), ...).
39 * Calls are typically processed that way: 39 * Calls are typically processed that way:
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.85 2018/08/21 18:45:16 jdolecek Exp $"); 53__KERNEL_RCSID(0, "$NetBSD: xbd_xenbus.c,v 1.86 2018/08/21 18:55:08 jdolecek 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>
67#include <sys/proc.h> 67#include <sys/proc.h>
68#include <sys/systm.h> 68#include <sys/systm.h>
69#include <sys/stat.h> 69#include <sys/stat.h>
70#include <sys/vnode.h> 70#include <sys/vnode.h>
71 71
72#include <dev/dkvar.h> 72#include <dev/dkvar.h>
73 73
74#include <uvm/uvm.h> 74#include <uvm/uvm.h>
75 75
76#include <xen/hypervisor.h> 76#include <xen/hypervisor.h>
77#include <xen/evtchn.h> 77#include <xen/evtchn.h>
78#include <xen/granttables.h> 78#include <xen/granttables.h>
79#include <xen/xen-public/io/blkif.h> 79#include <xen/xen-public/io/blkif.h>
80#include <xen/xen-public/io/protocols.h> 80#include <xen/xen-public/io/protocols.h>
81 81
82#include <xen/xenbus.h> 82#include <xen/xenbus.h>
83#include "locators.h" 83#include "locators.h"
84 84
85#undef XBD_DEBUG 85#undef XBD_DEBUG
86#ifdef XBD_DEBUG 86#ifdef XBD_DEBUG
87#define DPRINTF(x) printf x; 87#define DPRINTF(x) printf x;
88#else 88#else
89#define DPRINTF(x) 89#define DPRINTF(x)
90#endif 90#endif
91 91
92#define GRANT_INVALID_REF -1 92#define GRANT_INVALID_REF -1
93 93
94#define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) 94#define XBD_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE)
95#define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST) 95#define XBD_MAX_XFER (PAGE_SIZE * BLKIF_MAX_SEGMENTS_PER_REQUEST)
96 96
97#define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */ 97#define XEN_BSHIFT 9 /* log2(XEN_BSIZE) */
98#define XEN_BSIZE (1 << XEN_BSHIFT)  98#define XEN_BSIZE (1 << XEN_BSHIFT)
99 99
100struct xbd_req { 100struct xbd_req {
101 SLIST_ENTRY(xbd_req) req_next; 101 SLIST_ENTRY(xbd_req) req_next;
102 uint16_t req_id; /* ID passed to backend */ 102 uint16_t req_id; /* ID passed to backend */
103 union { 103 union {
104 struct { 104 struct {
105 grant_ref_t req_gntref[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 105 grant_ref_t req_gntref[BLKIF_MAX_SEGMENTS_PER_REQUEST];
106 int req_nr_segments; /* number of segments in this request */ 106 int req_nr_segments; /* number of segments in this request */
107 struct buf *req_bp; /* buffer associated with this request */ 107 struct buf *req_bp; /* buffer associated with this request */
108 } req_rw; 108 } req_rw;
109 struct { 109 struct {
110 int s_error; 110 int s_error;
111 volatile int s_done; 111 volatile int s_done;
112 } req_sync; 112 } req_sync;
113 } u; 113 } u;
114}; 114};
115#define req_gntref u.req_rw.req_gntref 115#define req_gntref u.req_rw.req_gntref
116#define req_nr_segments u.req_rw.req_nr_segments 116#define req_nr_segments u.req_rw.req_nr_segments
117#define req_bp u.req_rw.req_bp 117#define req_bp u.req_rw.req_bp
118#define req_sync u.req_sync 118#define req_sync u.req_sync
119 119
120struct xbd_xenbus_softc { 120struct xbd_xenbus_softc {
121 struct dk_softc sc_dksc; /* Must be first in this struct */ 121 struct dk_softc sc_dksc; /* Must be first in this struct */
122 struct xenbus_device *sc_xbusd; 122 struct xenbus_device *sc_xbusd;
123 123
124 struct intrhand *sc_ih; /* Interrupt handler for this instance. */ 124 struct intrhand *sc_ih; /* Interrupt handler for this instance. */
125  125
126 blkif_front_ring_t sc_ring; 126 blkif_front_ring_t sc_ring;
127 127
128 unsigned int sc_evtchn; 128 unsigned int sc_evtchn;
129 129
130 grant_ref_t sc_ring_gntref; 130 grant_ref_t sc_ring_gntref;
131 131
132 struct xbd_req sc_reqs[XBD_RING_SIZE]; 132 struct xbd_req sc_reqs[XBD_RING_SIZE];
133 SLIST_HEAD(,xbd_req) sc_xbdreq_head; /* list of free requests */ 133 SLIST_HEAD(,xbd_req) sc_xbdreq_head; /* list of free requests */
134 bool sc_xbdreq_wait; /* special waiting on xbd_req */ 134 bool sc_xbdreq_wait; /* special waiting on xbd_req */
135 135
136 int sc_backend_status; /* our status with backend */ 136 int sc_backend_status; /* our status with backend */
137#define BLKIF_STATE_DISCONNECTED 0 137#define BLKIF_STATE_DISCONNECTED 0
138#define BLKIF_STATE_CONNECTED 1 138#define BLKIF_STATE_CONNECTED 1
139#define BLKIF_STATE_SUSPENDED 2 139#define BLKIF_STATE_SUSPENDED 2
140 140
141 int sc_shutdown; 141 int sc_shutdown;
142#define BLKIF_SHUTDOWN_RUN 0 /* no shutdown */ 142#define BLKIF_SHUTDOWN_RUN 0 /* no shutdown */
143#define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */ 143#define BLKIF_SHUTDOWN_REMOTE 1 /* backend-initiated shutdown in progress */
144#define BLKIF_SHUTDOWN_LOCAL 2 /* locally-initiated shutdown in progress */ 144#define BLKIF_SHUTDOWN_LOCAL 2 /* locally-initiated shutdown in progress */
145 145
146 uint64_t sc_sectors; /* number of sectors for this device */ 146 uint64_t sc_sectors; /* number of sectors for this device */
147 u_long sc_secsize; /* sector size */ 147 u_long sc_secsize; /* sector size */
148 uint64_t sc_xbdsize; /* size of disk in DEV_BSIZE */ 148 uint64_t sc_xbdsize; /* size of disk in DEV_BSIZE */
149 u_long sc_info; /* VDISK_* */ 149 u_long sc_info; /* VDISK_* */
150 u_long sc_handle; /* from backend */ 150 u_long sc_handle; /* from backend */
151 int sc_cache_flush; /* backend supports BLKIF_OP_FLUSH_DISKCACHE */ 151 int sc_cache_flush; /* backend supports BLKIF_OP_FLUSH_DISKCACHE */
152}; 152};
153 153
154#if 0 154#if 0
155/* too big to be on stack */ 155/* too big to be on stack */
156static multicall_entry_t rq_mcl[XBD_RING_SIZE+1]; 156static multicall_entry_t rq_mcl[XBD_RING_SIZE+1];
157static paddr_t rq_pages[XBD_RING_SIZE]; 157static paddr_t rq_pages[XBD_RING_SIZE];
158#endif 158#endif
159 159
160static int xbd_xenbus_match(device_t, cfdata_t, void *); 160static int xbd_xenbus_match(device_t, cfdata_t, void *);
161static void xbd_xenbus_attach(device_t, device_t, void *); 161static void xbd_xenbus_attach(device_t, device_t, void *);
162static int xbd_xenbus_detach(device_t, int); 162static int xbd_xenbus_detach(device_t, int);
163 163
164static bool xbd_xenbus_suspend(device_t, const pmf_qual_t *); 164static bool xbd_xenbus_suspend(device_t, const pmf_qual_t *);
165static bool xbd_xenbus_resume(device_t, const pmf_qual_t *); 165static bool xbd_xenbus_resume(device_t, const pmf_qual_t *);
166 166
167static int xbd_handler(void *); 167static int xbd_handler(void *);
168static int xbd_diskstart(device_t, struct buf *); 168static int xbd_diskstart(device_t, struct buf *);
169static void xbd_backend_changed(void *, XenbusState); 169static void xbd_backend_changed(void *, XenbusState);
170static void xbd_connect(struct xbd_xenbus_softc *); 170static void xbd_connect(struct xbd_xenbus_softc *);
171 171
172static void xbdminphys(struct buf *); 172static void xbdminphys(struct buf *);
173 173
174CFATTACH_DECL3_NEW(xbd, sizeof(struct xbd_xenbus_softc), 174CFATTACH_DECL3_NEW(xbd, sizeof(struct xbd_xenbus_softc),
175 xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL, NULL, NULL, 175 xbd_xenbus_match, xbd_xenbus_attach, xbd_xenbus_detach, NULL, NULL, NULL,
176 DVF_DETACH_SHUTDOWN); 176 DVF_DETACH_SHUTDOWN);
177 177
178dev_type_open(xbdopen); 178dev_type_open(xbdopen);
179dev_type_close(xbdclose); 179dev_type_close(xbdclose);
180dev_type_read(xbdread); 180dev_type_read(xbdread);
181dev_type_write(xbdwrite); 181dev_type_write(xbdwrite);
182dev_type_ioctl(xbdioctl); 182dev_type_ioctl(xbdioctl);
183dev_type_strategy(xbdstrategy); 183dev_type_strategy(xbdstrategy);
184dev_type_dump(xbddump); 184dev_type_dump(xbddump);
185dev_type_size(xbdsize); 185dev_type_size(xbdsize);
186 186
187const struct bdevsw xbd_bdevsw = { 187const struct bdevsw xbd_bdevsw = {
188 .d_open = xbdopen, 188 .d_open = xbdopen,
189 .d_close = xbdclose, 189 .d_close = xbdclose,
190 .d_strategy = xbdstrategy, 190 .d_strategy = xbdstrategy,
191 .d_ioctl = xbdioctl, 191 .d_ioctl = xbdioctl,
192 .d_dump = xbddump, 192 .d_dump = xbddump,
193 .d_psize = xbdsize, 193 .d_psize = xbdsize,
194 .d_discard = nodiscard, 194 .d_discard = nodiscard,
195 .d_flag = D_DISK 195 .d_flag = D_DISK
196}; 196};
197 197
198const struct cdevsw xbd_cdevsw = { 198const struct cdevsw xbd_cdevsw = {
199 .d_open = xbdopen, 199 .d_open = xbdopen,
200 .d_close = xbdclose, 200 .d_close = xbdclose,
201 .d_read = xbdread, 201 .d_read = xbdread,
202 .d_write = xbdwrite, 202 .d_write = xbdwrite,
203 .d_ioctl = xbdioctl, 203 .d_ioctl = xbdioctl,
204 .d_stop = nostop, 204 .d_stop = nostop,
205 .d_tty = notty, 205 .d_tty = notty,
206 .d_poll = nopoll, 206 .d_poll = nopoll,
207 .d_mmap = nommap, 207 .d_mmap = nommap,
208 .d_kqfilter = nokqfilter, 208 .d_kqfilter = nokqfilter,
209 .d_discard = nodiscard, 209 .d_discard = nodiscard,
210 .d_flag = D_DISK 210 .d_flag = D_DISK
211}; 211};
212 212
213extern struct cfdriver xbd_cd; 213extern struct cfdriver xbd_cd;
214 214
215static struct dkdriver xbddkdriver = { 215static struct dkdriver xbddkdriver = {
216 .d_strategy = xbdstrategy, 216 .d_strategy = xbdstrategy,
217 .d_minphys = xbdminphys, 217 .d_minphys = xbdminphys,
218 .d_open = xbdopen, 218 .d_open = xbdopen,
219 .d_close = xbdclose, 219 .d_close = xbdclose,
220 .d_diskstart = xbd_diskstart, 220 .d_diskstart = xbd_diskstart,
221}; 221};
222 222
223static int 223static int
224xbd_xenbus_match(device_t parent, cfdata_t match, void *aux) 224xbd_xenbus_match(device_t parent, cfdata_t match, void *aux)
225{ 225{
226 struct xenbusdev_attach_args *xa = aux; 226 struct xenbusdev_attach_args *xa = aux;
227 227
228 if (strcmp(xa->xa_type, "vbd") != 0) 228 if (strcmp(xa->xa_type, "vbd") != 0)
229 return 0; 229 return 0;
230 230
231 if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT && 231 if (match->cf_loc[XENBUSCF_ID] != XENBUSCF_ID_DEFAULT &&
232 match->cf_loc[XENBUSCF_ID] != xa->xa_id) 232 match->cf_loc[XENBUSCF_ID] != xa->xa_id)
233 return 0; 233 return 0;
234 234
235 return 1; 235 return 1;
236} 236}
237 237
238static void 238static void
239xbd_xenbus_attach(device_t parent, device_t self, void *aux) 239xbd_xenbus_attach(device_t parent, device_t self, void *aux)
240{ 240{
241 struct xbd_xenbus_softc *sc = device_private(self); 241 struct xbd_xenbus_softc *sc = device_private(self);
242 struct xenbusdev_attach_args *xa = aux; 242 struct xenbusdev_attach_args *xa = aux;
243 blkif_sring_t *ring; 243 blkif_sring_t *ring;
244 RING_IDX i; 244 RING_IDX i;
245#ifdef XBD_DEBUG 245#ifdef XBD_DEBUG
246 char **dir, *val; 246 char **dir, *val;
247 int dir_n = 0; 247 int dir_n = 0;
248 char id_str[20]; 248 char id_str[20];
249 int err; 249 int err;
250#endif 250#endif
251 251
252 config_pending_incr(self); 252 config_pending_incr(self);
253 aprint_normal(": Xen Virtual Block Device Interface\n"); 253 aprint_normal(": Xen Virtual Block Device Interface\n");
254 254
255 dk_init(&sc->sc_dksc, self, DKTYPE_ESDI); 255 dk_init(&sc->sc_dksc, self, DKTYPE_ESDI);
256 disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver); 256 disk_init(&sc->sc_dksc.sc_dkdev, device_xname(self), &xbddkdriver);
257 257
258#ifdef XBD_DEBUG 258#ifdef XBD_DEBUG
259 printf("path: %s\n", xa->xa_xbusd->xbusd_path); 259 printf("path: %s\n", xa->xa_xbusd->xbusd_path);
260 snprintf(id_str, sizeof(id_str), "%d", xa->xa_id); 260 snprintf(id_str, sizeof(id_str), "%d", xa->xa_id);
261 err = xenbus_directory(NULL, "device/vbd", id_str, &dir_n, &dir); 261 err = xenbus_directory(NULL, "device/vbd", id_str, &dir_n, &dir);
262 if (err) { 262 if (err) {
263 aprint_error_dev(self, "xenbus_directory err %d\n", err); 263 aprint_error_dev(self, "xenbus_directory err %d\n", err);
264 } else { 264 } else {
265 printf("%s/\n", xa->xa_xbusd->xbusd_path); 265 printf("%s/\n", xa->xa_xbusd->xbusd_path);
266 for (i = 0; i < dir_n; i++) { 266 for (i = 0; i < dir_n; i++) {
267 printf("\t/%s", dir[i]); 267 printf("\t/%s", dir[i]);
268 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path, 268 err = xenbus_read(NULL, xa->xa_xbusd->xbusd_path,
269 dir[i], NULL, &val); 269 dir[i], NULL, &val);
270 if (err) { 270 if (err) {
271 aprint_error_dev(self, "xenbus_read err %d\n", 271 aprint_error_dev(self, "xenbus_read err %d\n",
272 err); 272 err);
273 } else { 273 } else {
274 printf(" = %s\n", val); 274 printf(" = %s\n", val);
275 free(val, M_DEVBUF); 275 free(val, M_DEVBUF);
276 } 276 }
277 } 277 }
278 } 278 }
279#endif /* XBD_DEBUG */ 279#endif /* XBD_DEBUG */
280 sc->sc_xbusd = xa->xa_xbusd; 280 sc->sc_xbusd = xa->xa_xbusd;
281 sc->sc_xbusd->xbusd_otherend_changed = xbd_backend_changed; 281 sc->sc_xbusd->xbusd_otherend_changed = xbd_backend_changed;
282 282
283 /* initialize free requests list */ 283 /* initialize free requests list */
284 SLIST_INIT(&sc->sc_xbdreq_head); 284 SLIST_INIT(&sc->sc_xbdreq_head);
285 for (i = 0; i < XBD_RING_SIZE; i++) { 285 for (i = 0; i < XBD_RING_SIZE; i++) {
286 sc->sc_reqs[i].req_id = i; 286 sc->sc_reqs[i].req_id = i;
287 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, &sc->sc_reqs[i], 287 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, &sc->sc_reqs[i],
288 req_next); 288 req_next);
289 } 289 }
290 290
291 sc->sc_backend_status = BLKIF_STATE_DISCONNECTED; 291 sc->sc_backend_status = BLKIF_STATE_DISCONNECTED;
292 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE; 292 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
293 293
294 ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED); 294 ring = (void *)uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_WIRED);
295 if (ring == NULL) 295 if (ring == NULL)
296 panic("%s: can't alloc ring", device_xname(self)); 296 panic("%s: can't alloc ring", device_xname(self));
297 sc->sc_ring.sring = ring; 297 sc->sc_ring.sring = ring;
298 298
299 /* resume shared structures and tell backend that we are ready */ 299 /* resume shared structures and tell backend that we are ready */
300 if (xbd_xenbus_resume(self, PMF_Q_NONE) == false) { 300 if (xbd_xenbus_resume(self, PMF_Q_NONE) == false) {
301 uvm_km_free(kernel_map, (vaddr_t)ring, PAGE_SIZE, 301 uvm_km_free(kernel_map, (vaddr_t)ring, PAGE_SIZE,
302 UVM_KMF_WIRED); 302 UVM_KMF_WIRED);
303 return; 303 return;
304 } 304 }
305 305
306 if (!pmf_device_register(self, xbd_xenbus_suspend, xbd_xenbus_resume)) 306 if (!pmf_device_register(self, xbd_xenbus_suspend, xbd_xenbus_resume))
307 aprint_error_dev(self, "couldn't establish power handler\n"); 307 aprint_error_dev(self, "couldn't establish power handler\n");
308 308
309} 309}
310 310
311static int 311static int
312xbd_xenbus_detach(device_t dev, int flags) 312xbd_xenbus_detach(device_t dev, int flags)
313{ 313{
314 struct xbd_xenbus_softc *sc = device_private(dev); 314 struct xbd_xenbus_softc *sc = device_private(dev);
315 int bmaj, cmaj, i, mn, rc, s; 315 int bmaj, cmaj, i, mn, rc, s;
316 316
317 rc = disk_begindetach(&sc->sc_dksc.sc_dkdev, NULL, dev, flags); 317 rc = disk_begindetach(&sc->sc_dksc.sc_dkdev, NULL, dev, flags);
318 if (rc != 0) 318 if (rc != 0)
319 return rc; 319 return rc;
320 320
321 s = splbio(); /* XXXSMP */ 321 s = splbio(); /* XXXSMP */
322 DPRINTF(("%s: xbd_detach\n", device_xname(dev))); 322 DPRINTF(("%s: xbd_detach\n", device_xname(dev)));
323 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) { 323 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) {
324 sc->sc_shutdown = BLKIF_SHUTDOWN_LOCAL; 324 sc->sc_shutdown = BLKIF_SHUTDOWN_LOCAL;
325 /* wait for requests to complete */ 325 /* wait for requests to complete */
326 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 326 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
327 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 327 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
328 /* XXXSMP */ 328 /* XXXSMP */
329 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2); 329 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
330 } 330 }
331 331
332 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosing); 332 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosing);
333 } 333 }
334 if ((flags & DETACH_FORCE) == 0) { 334 if ((flags & DETACH_FORCE) == 0) {
335 /* xbd_xenbus_detach already in progress */ 335 /* xbd_xenbus_detach already in progress */
336 wakeup(xbd_xenbus_detach); /* XXXSMP */ 336 wakeup(xbd_xenbus_detach); /* XXXSMP */
337 splx(s); 337 splx(s);
338 return EALREADY; 338 return EALREADY;
339 } 339 }
340 while (xenbus_read_driver_state(sc->sc_xbusd->xbusd_otherend) 340 while (xenbus_read_driver_state(sc->sc_xbusd->xbusd_otherend)
341 != XenbusStateClosed) { 341 != XenbusStateClosed) {
342 /* XXXSMP */ 342 /* XXXSMP */
343 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach2", hz/2); 343 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach2", hz/2);
344 } 344 }
345 splx(s); 345 splx(s);
346 346
347 /* locate the major number */ 347 /* locate the major number */
348 bmaj = bdevsw_lookup_major(&xbd_bdevsw); 348 bmaj = bdevsw_lookup_major(&xbd_bdevsw);
349 cmaj = cdevsw_lookup_major(&xbd_cdevsw); 349 cmaj = cdevsw_lookup_major(&xbd_cdevsw);
350 350
351 /* Nuke the vnodes for any open instances. */ 351 /* Nuke the vnodes for any open instances. */
352 for (i = 0; i < MAXPARTITIONS; i++) { 352 for (i = 0; i < MAXPARTITIONS; i++) {
353 mn = DISKMINOR(device_unit(dev), i); 353 mn = DISKMINOR(device_unit(dev), i);
354 vdevgone(bmaj, mn, mn, VBLK); 354 vdevgone(bmaj, mn, mn, VBLK);
355 vdevgone(cmaj, mn, mn, VCHR); 355 vdevgone(cmaj, mn, mn, VCHR);
356 } 356 }
357 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED) { 357 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED) {
358 /* Delete all of our wedges. */ 358 /* Delete all of our wedges. */
359 dkwedge_delall(&sc->sc_dksc.sc_dkdev); 359 dkwedge_delall(&sc->sc_dksc.sc_dkdev);
360 360
361 /* Kill off any queued buffers. */ 361 /* Kill off any queued buffers. */
362 dk_drain(&sc->sc_dksc); 362 dk_drain(&sc->sc_dksc);
363 bufq_free(sc->sc_dksc.sc_bufq); 363 bufq_free(sc->sc_dksc.sc_bufq);
364 364
365 /* detach disk */ 365 /* detach disk */
366 disk_detach(&sc->sc_dksc.sc_dkdev); 366 disk_detach(&sc->sc_dksc.sc_dkdev);
367 disk_destroy(&sc->sc_dksc.sc_dkdev); 367 disk_destroy(&sc->sc_dksc.sc_dkdev);
368 dk_detach(&sc->sc_dksc); 368 dk_detach(&sc->sc_dksc);
369 } 369 }
370 370
371 hypervisor_mask_event(sc->sc_evtchn); 371 hypervisor_mask_event(sc->sc_evtchn);
372 intr_disestablish(sc->sc_ih); 372 intr_disestablish(sc->sc_ih);
373 373
374 while (xengnt_status(sc->sc_ring_gntref)) { 374 while (xengnt_status(sc->sc_ring_gntref)) {
375 /* XXXSMP */ 375 /* XXXSMP */
376 tsleep(xbd_xenbus_detach, PRIBIO, "xbd_ref", hz/2); 376 tsleep(xbd_xenbus_detach, PRIBIO, "xbd_ref", hz/2);
377 } 377 }
378 xengnt_revoke_access(sc->sc_ring_gntref); 378 xengnt_revoke_access(sc->sc_ring_gntref);
379 uvm_km_free(kernel_map, (vaddr_t)sc->sc_ring.sring, 379 uvm_km_free(kernel_map, (vaddr_t)sc->sc_ring.sring,
380 PAGE_SIZE, UVM_KMF_WIRED); 380 PAGE_SIZE, UVM_KMF_WIRED);
381 381
382 pmf_device_deregister(dev); 382 pmf_device_deregister(dev);
383 383
384 return 0; 384 return 0;
385} 385}
386 386
387static bool 387static bool
388xbd_xenbus_suspend(device_t dev, const pmf_qual_t *qual) { 388xbd_xenbus_suspend(device_t dev, const pmf_qual_t *qual) {
389 389
390 int s; 390 int s;
391 struct xbd_xenbus_softc *sc; 391 struct xbd_xenbus_softc *sc;
392 392
393 sc = device_private(dev); 393 sc = device_private(dev);
394 394
395 s = splbio(); /* XXXSMP */ 395 s = splbio(); /* XXXSMP */
396 /* wait for requests to complete, then suspend device */ 396 /* wait for requests to complete, then suspend device */
397 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 397 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
398 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 398 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
399 /* XXXSMP */ 399 /* XXXSMP */
400 tsleep(xbd_xenbus_suspend, PRIBIO, "xbdsuspend", hz/2); 400 tsleep(xbd_xenbus_suspend, PRIBIO, "xbdsuspend", hz/2);
401 } 401 }
402 402
403 hypervisor_mask_event(sc->sc_evtchn); 403 hypervisor_mask_event(sc->sc_evtchn);
404 sc->sc_backend_status = BLKIF_STATE_SUSPENDED; 404 sc->sc_backend_status = BLKIF_STATE_SUSPENDED;
405 intr_disestablish(sc->sc_ih); 405 intr_disestablish(sc->sc_ih);
406 406
407 splx(s); 407 splx(s);
408 408
409 xenbus_device_suspend(sc->sc_xbusd); 409 xenbus_device_suspend(sc->sc_xbusd);
410 aprint_verbose_dev(dev, "removed event channel %d\n", sc->sc_evtchn); 410 aprint_verbose_dev(dev, "removed event channel %d\n", sc->sc_evtchn);
411 411
412 return true; 412 return true;
413} 413}
414 414
415static bool 415static bool
416xbd_xenbus_resume(device_t dev, const pmf_qual_t *qual) 416xbd_xenbus_resume(device_t dev, const pmf_qual_t *qual)
417{ 417{
418 struct xbd_xenbus_softc *sc; 418 struct xbd_xenbus_softc *sc;
419 struct xenbus_transaction *xbt; 419 struct xenbus_transaction *xbt;
420 int error; 420 int error;
421 blkif_sring_t *ring; 421 blkif_sring_t *ring;
422 paddr_t ma; 422 paddr_t ma;
423 const char *errmsg; 423 const char *errmsg;
424 424
425 sc = device_private(dev); 425 sc = device_private(dev);
426 426
427 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) { 427 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) {
428 /* 428 /*
429 * Device was suspended, so ensure that access associated to 429 * Device was suspended, so ensure that access associated to
430 * the block I/O ring is revoked. 430 * the block I/O ring is revoked.
431 */ 431 */
432 xengnt_revoke_access(sc->sc_ring_gntref); 432 xengnt_revoke_access(sc->sc_ring_gntref);
433 } 433 }
434 sc->sc_ring_gntref = GRANT_INVALID_REF; 434 sc->sc_ring_gntref = GRANT_INVALID_REF;
435 435
436 /* Initialize ring */ 436 /* Initialize ring */
437 ring = sc->sc_ring.sring; 437 ring = sc->sc_ring.sring;
438 memset(ring, 0, PAGE_SIZE); 438 memset(ring, 0, PAGE_SIZE);
439 SHARED_RING_INIT(ring); 439 SHARED_RING_INIT(ring);
440 FRONT_RING_INIT(&sc->sc_ring, ring, PAGE_SIZE); 440 FRONT_RING_INIT(&sc->sc_ring, ring, PAGE_SIZE);
441 441
442 /* 442 /*
443 * get MA address of the ring, and use it to set up the grant entry 443 * get MA address of the ring, and use it to set up the grant entry
444 * for the block device 444 * for the block device
445 */ 445 */
446 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)ring, &ma); 446 (void)pmap_extract_ma(pmap_kernel(), (vaddr_t)ring, &ma);
447 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_ring_gntref); 447 error = xenbus_grant_ring(sc->sc_xbusd, ma, &sc->sc_ring_gntref);
448 if (error) 448 if (error)
449 goto abort_resume; 449 goto abort_resume;
450 450
451 error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn); 451 error = xenbus_alloc_evtchn(sc->sc_xbusd, &sc->sc_evtchn);
452 if (error) 452 if (error)
453 goto abort_resume; 453 goto abort_resume;
454 454
455 aprint_verbose_dev(dev, "using event channel %d\n", 455 aprint_verbose_dev(dev, "using event channel %d\n",
456 sc->sc_evtchn); 456 sc->sc_evtchn);
457 sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL, 457 sc->sc_ih = intr_establish_xname(0, &xen_pic, sc->sc_evtchn, IST_LEVEL,
458 IPL_BIO, &xbd_handler, sc, false, device_xname(dev)); 458 IPL_BIO, &xbd_handler, sc, false, device_xname(dev));
459 KASSERT(sc->sc_ih != NULL); 459 KASSERT(sc->sc_ih != NULL);
460 460
461again: 461again:
462 xbt = xenbus_transaction_start(); 462 xbt = xenbus_transaction_start();
463 if (xbt == NULL) 463 if (xbt == NULL)
464 return false; 464 return false;
465 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 465 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
466 "ring-ref","%u", sc->sc_ring_gntref); 466 "ring-ref","%u", sc->sc_ring_gntref);
467 if (error) { 467 if (error) {
468 errmsg = "writing ring-ref"; 468 errmsg = "writing ring-ref";
469 goto abort_transaction; 469 goto abort_transaction;
470 } 470 }
471 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 471 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
472 "event-channel", "%u", sc->sc_evtchn); 472 "event-channel", "%u", sc->sc_evtchn);
473 if (error) { 473 if (error) {
474 errmsg = "writing event channel"; 474 errmsg = "writing event channel";
475 goto abort_transaction; 475 goto abort_transaction;
476 } 476 }
477 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path, 477 error = xenbus_printf(xbt, sc->sc_xbusd->xbusd_path,
478 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE); 478 "protocol", "%s", XEN_IO_PROTO_ABI_NATIVE);
479 if (error) { 479 if (error) {
480 errmsg = "writing protocol"; 480 errmsg = "writing protocol";
481 goto abort_transaction; 481 goto abort_transaction;
482 } 482 }
483 error = xenbus_transaction_end(xbt, 0); 483 error = xenbus_transaction_end(xbt, 0);
484 if (error == EAGAIN) 484 if (error == EAGAIN)
485 goto again; 485 goto again;
486 if (error != 0) { 486 if (error != 0) {
487 xenbus_dev_fatal(sc->sc_xbusd, error, 487 xenbus_dev_fatal(sc->sc_xbusd, error,
488 "completing transaction"); 488 "completing transaction");
489 return false; 489 return false;
490 } 490 }
491 491
492 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateInitialised); 492 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateInitialised);
493 493
494 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) { 494 if (sc->sc_backend_status == BLKIF_STATE_SUSPENDED) {
495 /* 495 /*
496 * device was suspended, softc structures are 496 * device was suspended, softc structures are
497 * already initialized - we use a shortcut 497 * already initialized - we use a shortcut
498 */ 498 */
499 sc->sc_backend_status = BLKIF_STATE_CONNECTED; 499 sc->sc_backend_status = BLKIF_STATE_CONNECTED;
500 xenbus_device_resume(sc->sc_xbusd); 500 xenbus_device_resume(sc->sc_xbusd);
501 hypervisor_enable_event(sc->sc_evtchn); 501 hypervisor_enable_event(sc->sc_evtchn);
502 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); 502 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected);
503 } 503 }
504 504
505 return true; 505 return true;
506 506
507abort_resume: 507abort_resume:
508 xenbus_dev_fatal(sc->sc_xbusd, error, "resuming device"); 508 xenbus_dev_fatal(sc->sc_xbusd, error, "resuming device");
509 return false; 509 return false;
510 510
511abort_transaction: 511abort_transaction:
512 xenbus_transaction_end(xbt, 1); 512 xenbus_transaction_end(xbt, 1);
513 xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg); 513 xenbus_dev_fatal(sc->sc_xbusd, error, "%s", errmsg);
514 return false; 514 return false;
515} 515}
516 516
517static void 517static void
518xbd_backend_changed(void *arg, XenbusState new_state) 518xbd_backend_changed(void *arg, XenbusState new_state)
519{ 519{
520 struct xbd_xenbus_softc *sc = device_private((device_t)arg); 520 struct xbd_xenbus_softc *sc = device_private((device_t)arg);
521 struct disk_geom *dg; 521 struct disk_geom *dg;
522 522
523 char buf[9]; 523 char buf[9];
524 int s; 524 int s;
525 DPRINTF(("%s: new backend state %d\n", 525 DPRINTF(("%s: new backend state %d\n",
526 device_xname(sc->sc_dksc.sc_dev), new_state)); 526 device_xname(sc->sc_dksc.sc_dev), new_state));
527 527
528 switch (new_state) { 528 switch (new_state) {
529 case XenbusStateUnknown: 529 case XenbusStateUnknown:
530 case XenbusStateInitialising: 530 case XenbusStateInitialising:
531 case XenbusStateInitWait: 531 case XenbusStateInitWait:
532 case XenbusStateInitialised: 532 case XenbusStateInitialised:
533 break; 533 break;
534 case XenbusStateClosing: 534 case XenbusStateClosing:
535 s = splbio(); /* XXXSMP */ 535 s = splbio(); /* XXXSMP */
536 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN) 536 if (sc->sc_shutdown == BLKIF_SHUTDOWN_RUN)
537 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE; 537 sc->sc_shutdown = BLKIF_SHUTDOWN_REMOTE;
538 /* wait for requests to complete */ 538 /* wait for requests to complete */
539 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED && 539 while (sc->sc_backend_status == BLKIF_STATE_CONNECTED &&
540 disk_isbusy(&sc->sc_dksc.sc_dkdev)) { 540 disk_isbusy(&sc->sc_dksc.sc_dkdev)) {
541 /* XXXSMP */ 541 /* XXXSMP */
542 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2); 542 tsleep(xbd_xenbus_detach, PRIBIO, "xbddetach", hz/2);
543 } 543 }
544 splx(s); 544 splx(s);
545 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed); 545 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateClosed);
546 break; 546 break;
547 case XenbusStateConnected: 547 case XenbusStateConnected:
548 /* 548 /*
549 * note that xbd_backend_changed() can only be called by 549 * note that xbd_backend_changed() can only be called by
550 * the xenbus thread. 550 * the xenbus thread.
551 */ 551 */
552 552
553 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED || 553 if (sc->sc_backend_status == BLKIF_STATE_CONNECTED ||
554 sc->sc_backend_status == BLKIF_STATE_SUSPENDED) 554 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)
555 /* already connected */ 555 /* already connected */
556 return; 556 return;
557 557
558 xbd_connect(sc); 558 xbd_connect(sc);
559 sc->sc_shutdown = BLKIF_SHUTDOWN_RUN; 559 sc->sc_shutdown = BLKIF_SHUTDOWN_RUN;
560 hypervisor_enable_event(sc->sc_evtchn); 560 hypervisor_enable_event(sc->sc_evtchn);
561 561
562 sc->sc_xbdsize = 562 sc->sc_xbdsize =
563 sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE; 563 sc->sc_sectors * (uint64_t)sc->sc_secsize / DEV_BSIZE;
564 dg = &sc->sc_dksc.sc_dkdev.dk_geom; 564 dg = &sc->sc_dksc.sc_dkdev.dk_geom;
565 memset(dg, 0, sizeof(*dg));  565 memset(dg, 0, sizeof(*dg));
566 566
567 dg->dg_secperunit = sc->sc_xbdsize; 567 dg->dg_secperunit = sc->sc_xbdsize;
568 dg->dg_secsize = DEV_BSIZE; 568 dg->dg_secsize = DEV_BSIZE;
569 dg->dg_ntracks = 1; 569 dg->dg_ntracks = 1;
570 // XXX: Ok to hard-code DEV_BSIZE? 570 // XXX: Ok to hard-code DEV_BSIZE?
571 dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize); 571 dg->dg_nsectors = 1024 * (1024 / dg->dg_secsize);
572 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors; 572 dg->dg_ncylinders = dg->dg_secperunit / dg->dg_nsectors;
573 573
574 bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0); 574 bufq_alloc(&sc->sc_dksc.sc_bufq, "fcfs", 0);
575 dk_attach(&sc->sc_dksc); 575 dk_attach(&sc->sc_dksc);
576 disk_attach(&sc->sc_dksc.sc_dkdev); 576 disk_attach(&sc->sc_dksc.sc_dkdev);
577 577
578 sc->sc_backend_status = BLKIF_STATE_CONNECTED; 578 sc->sc_backend_status = BLKIF_STATE_CONNECTED;
579 579
580 /* try to read the disklabel */ 580 /* try to read the disklabel */
581 dk_getdisklabel(&sc->sc_dksc, 0 /* XXX ? */); 581 dk_getdisklabel(&sc->sc_dksc, 0 /* XXX ? */);
582 format_bytes(buf, sizeof(buf), sc->sc_sectors * sc->sc_secsize); 582 format_bytes(buf, sizeof(buf), sc->sc_sectors * sc->sc_secsize);
583 aprint_verbose_dev(sc->sc_dksc.sc_dev, 583 aprint_verbose_dev(sc->sc_dksc.sc_dev,
584 "%s, %d bytes/sect x %" PRIu64 " sectors\n", 584 "%s, %d bytes/sect x %" PRIu64 " sectors\n",
585 buf, (int)dg->dg_secsize, sc->sc_xbdsize); 585 buf, (int)dg->dg_secsize, sc->sc_xbdsize);
586 /* Discover wedges on this disk. */ 586 /* Discover wedges on this disk. */
587 dkwedge_discover(&sc->sc_dksc.sc_dkdev); 587 dkwedge_discover(&sc->sc_dksc.sc_dkdev);
588 588
589 disk_set_info(sc->sc_dksc.sc_dev, &sc->sc_dksc.sc_dkdev, NULL); 589 disk_set_info(sc->sc_dksc.sc_dev, &sc->sc_dksc.sc_dkdev, NULL);
590 590
591 /* the disk should be working now */ 591 /* the disk should be working now */
592 config_pending_decr(sc->sc_dksc.sc_dev); 592 config_pending_decr(sc->sc_dksc.sc_dev);
593 break; 593 break;
594 default: 594 default:
595 panic("bad backend state %d", new_state); 595 panic("bad backend state %d", new_state);
596 } 596 }
597} 597}
598 598
599static void 599static void
600xbd_connect(struct xbd_xenbus_softc *sc) 600xbd_connect(struct xbd_xenbus_softc *sc)
601{ 601{
602 int err; 602 int err;
603 unsigned long long sectors; 603 unsigned long long sectors;
604 u_long cache_flush; 604 u_long cache_flush;
605 605
606 err = xenbus_read_ul(NULL, 606 err = xenbus_read_ul(NULL,
607 sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10); 607 sc->sc_xbusd->xbusd_path, "virtual-device", &sc->sc_handle, 10);
608 if (err) 608 if (err)
609 panic("%s: can't read number from %s/virtual-device\n",  609 panic("%s: can't read number from %s/virtual-device\n",
610 device_xname(sc->sc_dksc.sc_dev), 610 device_xname(sc->sc_dksc.sc_dev),
611 sc->sc_xbusd->xbusd_otherend); 611 sc->sc_xbusd->xbusd_otherend);
612 err = xenbus_read_ull(NULL, 612 err = xenbus_read_ull(NULL,
613 sc->sc_xbusd->xbusd_otherend, "sectors", &sectors, 10); 613 sc->sc_xbusd->xbusd_otherend, "sectors", &sectors, 10);
614 if (err) 614 if (err)
615 panic("%s: can't read number from %s/sectors\n",  615 panic("%s: can't read number from %s/sectors\n",
616 device_xname(sc->sc_dksc.sc_dev), 616 device_xname(sc->sc_dksc.sc_dev),
617 sc->sc_xbusd->xbusd_otherend); 617 sc->sc_xbusd->xbusd_otherend);
618 sc->sc_sectors = sectors; 618 sc->sc_sectors = sectors;
619 619
620 err = xenbus_read_ul(NULL, 620 err = xenbus_read_ul(NULL,
621 sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10); 621 sc->sc_xbusd->xbusd_otherend, "info", &sc->sc_info, 10);
622 if (err) 622 if (err)
623 panic("%s: can't read number from %s/info\n",  623 panic("%s: can't read number from %s/info\n",
624 device_xname(sc->sc_dksc.sc_dev), 624 device_xname(sc->sc_dksc.sc_dev),
625 sc->sc_xbusd->xbusd_otherend); 625 sc->sc_xbusd->xbusd_otherend);
626 err = xenbus_read_ul(NULL, 626 err = xenbus_read_ul(NULL,
627 sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10); 627 sc->sc_xbusd->xbusd_otherend, "sector-size", &sc->sc_secsize, 10);
628 if (err) 628 if (err)
629 panic("%s: can't read number from %s/sector-size\n",  629 panic("%s: can't read number from %s/sector-size\n",
630 device_xname(sc->sc_dksc.sc_dev), 630 device_xname(sc->sc_dksc.sc_dev),
631 sc->sc_xbusd->xbusd_otherend); 631 sc->sc_xbusd->xbusd_otherend);
632 632
633 err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend, 633 err = xenbus_read_ul(NULL, sc->sc_xbusd->xbusd_otherend,
634 "feature-flush-cache", &cache_flush, 10); 634 "feature-flush-cache", &cache_flush, 10);
635 if (err) 635 if (err)
636 cache_flush = 0; 636 cache_flush = 0;
637 if (cache_flush > 0) 637 if (cache_flush > 0)
638 sc->sc_cache_flush = 1; 638 sc->sc_cache_flush = 1;
639 else 639 else
640 sc->sc_cache_flush = 0; 640 sc->sc_cache_flush = 0;
641 641
642 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected); 642 xenbus_switch_state(sc->sc_xbusd, NULL, XenbusStateConnected);
643} 643}
644 644
645static int 645static int
646xbd_handler(void *arg) 646xbd_handler(void *arg)
647{ 647{
648 struct xbd_xenbus_softc *sc = arg; 648 struct xbd_xenbus_softc *sc = arg;
649 struct buf *bp; 649 struct buf *bp;
650 RING_IDX resp_prod, i; 650 RING_IDX resp_prod, i;
651 int more_to_do; 651 int more_to_do;
652 int seg; 652 int seg;
653 653
654 DPRINTF(("xbd_handler(%s)\n", device_xname(sc->sc_dksc.sc_dev))); 654 DPRINTF(("xbd_handler(%s)\n", device_xname(sc->sc_dksc.sc_dev)));
655 655
656 if (__predict_false(sc->sc_backend_status != BLKIF_STATE_CONNECTED)) 656 if (__predict_false(sc->sc_backend_status != BLKIF_STATE_CONNECTED))
657 return 0; 657 return 0;
658again: 658again:
659 resp_prod = sc->sc_ring.sring->rsp_prod; 659 resp_prod = sc->sc_ring.sring->rsp_prod;
660 xen_rmb(); /* ensure we see replies up to resp_prod */ 660 xen_rmb(); /* ensure we see replies up to resp_prod */
661 for (i = sc->sc_ring.rsp_cons; i != resp_prod; i++) { 661 for (i = sc->sc_ring.rsp_cons; i != resp_prod; i++) {
662 blkif_response_t *rep = RING_GET_RESPONSE(&sc->sc_ring, i); 662 blkif_response_t *rep = RING_GET_RESPONSE(&sc->sc_ring, i);
663 struct xbd_req *xbdreq = &sc->sc_reqs[rep->id]; 663 struct xbd_req *xbdreq = &sc->sc_reqs[rep->id];
664 664
665 if (rep->operation == BLKIF_OP_FLUSH_DISKCACHE) { 665 if (rep->operation == BLKIF_OP_FLUSH_DISKCACHE) {
666 KASSERT(xbdreq->req_bp == NULL); 666 KASSERT(xbdreq->req_bp == NULL);
667 xbdreq->req_sync.s_error = rep->status; 667 xbdreq->req_sync.s_error = rep->status;
668 xbdreq->req_sync.s_done = 1; 668 xbdreq->req_sync.s_done = 1;
669 wakeup(xbdreq); /* XXXSMP */ 669 wakeup(xbdreq); /* XXXSMP */
670 /* caller will free the req */ 670 /* caller will free the req */
671 continue; 671 continue;
672 } 672 }
673 673
674 if (rep->operation != BLKIF_OP_READ && 674 if (rep->operation != BLKIF_OP_READ &&
675 rep->operation != BLKIF_OP_WRITE) { 675 rep->operation != BLKIF_OP_WRITE) {
676 aprint_error_dev(sc->sc_dksc.sc_dev, 676 aprint_error_dev(sc->sc_dksc.sc_dev,
677 "bad operation %d from backend\n", rep->operation); 677 "bad operation %d from backend\n", rep->operation);
678 continue; 678 continue;
679 } 679 }
680 680
681 for (seg = xbdreq->req_nr_segments - 1; seg >= 0; seg--) { 681 for (seg = xbdreq->req_nr_segments - 1; seg >= 0; seg--) {
682 if (__predict_false( 682 if (__predict_false(
683 xengnt_status(xbdreq->req_gntref[seg]))) { 683 xengnt_status(xbdreq->req_gntref[seg]))) {
684 aprint_verbose_dev(sc->sc_dksc.sc_dev, 684 aprint_verbose_dev(sc->sc_dksc.sc_dev,
685 "grant still used by backend\n"); 685 "grant still used by backend\n");
686 sc->sc_ring.rsp_cons = i; 686 sc->sc_ring.rsp_cons = i;
687 xbdreq->req_nr_segments = seg + 1; 687 xbdreq->req_nr_segments = seg + 1;
688 goto done; 688 goto done;
689 } 689 }
690 xengnt_revoke_access(xbdreq->req_gntref[seg]); 690 xengnt_revoke_access(xbdreq->req_gntref[seg]);
691 xbdreq->req_nr_segments--; 691 xbdreq->req_nr_segments--;
692 } 692 }
693 KASSERT(xbdreq->req_nr_segments == 0); 693 KASSERT(xbdreq->req_nr_segments == 0);
694 694
695 bp = xbdreq->req_bp; 695 bp = xbdreq->req_bp;
 696 KASSERT(bp != NULL);
696 xbdreq->req_bp = NULL; 697 xbdreq->req_bp = NULL;
697 DPRINTF(("%s(%p): b_bcount = %ld\n", __func__, 698 DPRINTF(("%s(%p): b_bcount = %ld\n", __func__,
698 bp, (long)bp->b_bcount)); 699 bp, (long)bp->b_bcount));
699 700
700 if (rep->status != BLKIF_RSP_OKAY) { 701 if (rep->status != BLKIF_RSP_OKAY) {
701 bp->b_error = EIO; 702 bp->b_error = EIO;
702 bp->b_resid = bp->b_bcount; 703 bp->b_resid = bp->b_bcount;
703 goto next; 704 goto next;
704 } 705 }
705 /* b_resid was set in dk_start */ 706 /* b_resid was set in dk_start */
706next: 707next:
707 dk_done(&sc->sc_dksc, bp); 708 dk_done(&sc->sc_dksc, bp);
708 709
709 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next); 710 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, req_next);
710 } 711 }
711done: 712done:
712 xen_rmb(); 713 xen_rmb();
713 sc->sc_ring.rsp_cons = i; 714 sc->sc_ring.rsp_cons = i;
714 715
715 RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_ring, more_to_do); 716 RING_FINAL_CHECK_FOR_RESPONSES(&sc->sc_ring, more_to_do);
716 if (more_to_do) 717 if (more_to_do)
717 goto again; 718 goto again;
718 719
719 if (sc->sc_xbdreq_wait) 720 if (sc->sc_xbdreq_wait)
720 wakeup(&sc->sc_xbdreq_wait); /* XXXSMP */ 721 wakeup(&sc->sc_xbdreq_wait); /* XXXSMP */
721 else 722 else
722 dk_start(&sc->sc_dksc, NULL); 723 dk_start(&sc->sc_dksc, NULL);
723 return 1; 724 return 1;
724} 725}
725 726
726static void 727static void
727xbdminphys(struct buf *bp) 728xbdminphys(struct buf *bp)
728{ 729{
729 if (bp->b_bcount > XBD_MAX_XFER) { 730 if (bp->b_bcount > XBD_MAX_XFER) {
730 bp->b_bcount = XBD_MAX_XFER; 731 bp->b_bcount = XBD_MAX_XFER;
731 } 732 }
732 minphys(bp); 733 minphys(bp);
733} 734}
734 735
735int 736int
736xbdopen(dev_t dev, int flags, int fmt, struct lwp *l) 737xbdopen(dev_t dev, int flags, int fmt, struct lwp *l)
737{ 738{
738 struct xbd_xenbus_softc *sc; 739 struct xbd_xenbus_softc *sc;
739 740
740 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 741 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
741 if (sc == NULL) 742 if (sc == NULL)
742 return (ENXIO); 743 return (ENXIO);
743 if ((flags & FWRITE) && (sc->sc_info & VDISK_READONLY)) 744 if ((flags & FWRITE) && (sc->sc_info & VDISK_READONLY))
744 return EROFS; 745 return EROFS;
745 746
746 DPRINTF(("xbdopen(0x%04x, %d)\n", dev, flags)); 747 DPRINTF(("xbdopen(0x%04x, %d)\n", dev, flags));
747 return dk_open(&sc->sc_dksc, dev, flags, fmt, l); 748 return dk_open(&sc->sc_dksc, dev, flags, fmt, l);
748} 749}
749 750
750int 751int
751xbdclose(dev_t dev, int flags, int fmt, struct lwp *l) 752xbdclose(dev_t dev, int flags, int fmt, struct lwp *l)
752{ 753{
753 struct xbd_xenbus_softc *sc; 754 struct xbd_xenbus_softc *sc;
754 755
755 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 756 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
756 757
757 DPRINTF(("xbdclose(%d, %d)\n", dev, flags)); 758 DPRINTF(("xbdclose(%d, %d)\n", dev, flags));
758 return dk_close(&sc->sc_dksc, dev, flags, fmt, l); 759 return dk_close(&sc->sc_dksc, dev, flags, fmt, l);
759} 760}
760 761
761void 762void
762xbdstrategy(struct buf *bp) 763xbdstrategy(struct buf *bp)
763{ 764{
764 struct xbd_xenbus_softc *sc; 765 struct xbd_xenbus_softc *sc;
765 766
766 sc = device_lookup_private(&xbd_cd, DISKUNIT(bp->b_dev)); 767 sc = device_lookup_private(&xbd_cd, DISKUNIT(bp->b_dev));
767 768
768 DPRINTF(("xbdstrategy(%p): b_bcount = %ld\n", bp, 769 DPRINTF(("xbdstrategy(%p): b_bcount = %ld\n", bp,
769 (long)bp->b_bcount)); 770 (long)bp->b_bcount));
770 771
771 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) { 772 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
772 bp->b_error = EIO; 773 bp->b_error = EIO;
773 biodone(bp); 774 biodone(bp);
774 return; 775 return;
775 } 776 }
776 if (__predict_false((sc->sc_info & VDISK_READONLY) && 777 if (__predict_false((sc->sc_info & VDISK_READONLY) &&
777 (bp->b_flags & B_READ) == 0)) { 778 (bp->b_flags & B_READ) == 0)) {
778 bp->b_error = EROFS; 779 bp->b_error = EROFS;
779 biodone(bp); 780 biodone(bp);
780 return; 781 return;
781 } 782 }
782 783
783 dk_strategy(&sc->sc_dksc, bp); 784 dk_strategy(&sc->sc_dksc, bp);
784 return; 785 return;
785} 786}
786 787
787int 788int
788xbdsize(dev_t dev) 789xbdsize(dev_t dev)
789{ 790{
790 struct xbd_xenbus_softc *sc; 791 struct xbd_xenbus_softc *sc;
791 792
792 DPRINTF(("xbdsize(%d)\n", dev)); 793 DPRINTF(("xbdsize(%d)\n", dev));
793 794
794 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 795 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
795 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) 796 if (sc == NULL || sc->sc_shutdown != BLKIF_SHUTDOWN_RUN)
796 return -1; 797 return -1;
797 return dk_size(&sc->sc_dksc, dev); 798 return dk_size(&sc->sc_dksc, dev);
798} 799}
799 800
800int 801int
801xbdread(dev_t dev, struct uio *uio, int flags) 802xbdread(dev_t dev, struct uio *uio, int flags)
802{ 803{
803 struct xbd_xenbus_softc *sc =  804 struct xbd_xenbus_softc *sc =
804 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 805 device_lookup_private(&xbd_cd, DISKUNIT(dev));
805 struct dk_softc *dksc = &sc->sc_dksc; 806 struct dk_softc *dksc = &sc->sc_dksc;
806 807
807 if (!DK_ATTACHED(dksc)) 808 if (!DK_ATTACHED(dksc))
808 return ENXIO; 809 return ENXIO;
809 return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio); 810 return physio(xbdstrategy, NULL, dev, B_READ, xbdminphys, uio);
810} 811}
811 812
812int 813int
813xbdwrite(dev_t dev, struct uio *uio, int flags) 814xbdwrite(dev_t dev, struct uio *uio, int flags)
814{ 815{
815 struct xbd_xenbus_softc *sc = 816 struct xbd_xenbus_softc *sc =
816 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 817 device_lookup_private(&xbd_cd, DISKUNIT(dev));
817 struct dk_softc *dksc = &sc->sc_dksc; 818 struct dk_softc *dksc = &sc->sc_dksc;
818 819
819 if (!DK_ATTACHED(dksc)) 820 if (!DK_ATTACHED(dksc))
820 return ENXIO; 821 return ENXIO;
821 if (__predict_false(sc->sc_info & VDISK_READONLY)) 822 if (__predict_false(sc->sc_info & VDISK_READONLY))
822 return EROFS; 823 return EROFS;
823 return physio(xbdstrategy, NULL, dev, B_WRITE, xbdminphys, uio); 824 return physio(xbdstrategy, NULL, dev, B_WRITE, xbdminphys, uio);
824} 825}
825 826
826int 827int
827xbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l) 828xbdioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
828{ 829{
829 struct xbd_xenbus_softc *sc = 830 struct xbd_xenbus_softc *sc =
830 device_lookup_private(&xbd_cd, DISKUNIT(dev)); 831 device_lookup_private(&xbd_cd, DISKUNIT(dev));
831 struct dk_softc *dksc; 832 struct dk_softc *dksc;
832 int error; 833 int error;
833 int s; 834 int s;
834 struct xbd_req *xbdreq; 835 struct xbd_req *xbdreq;
835 blkif_request_t *req; 836 blkif_request_t *req;
836 int notify; 837 int notify;
837 838
838 DPRINTF(("xbdioctl(%d, %08lx, %p, %d, %p)\n", 839 DPRINTF(("xbdioctl(%d, %08lx, %p, %d, %p)\n",
839 dev, cmd, data, flag, l)); 840 dev, cmd, data, flag, l));
840 dksc = &sc->sc_dksc; 841 dksc = &sc->sc_dksc;
841 842
842 switch (cmd) { 843 switch (cmd) {
843 case DIOCSSTRATEGY: 844 case DIOCSSTRATEGY:
844 error = EOPNOTSUPP; 845 error = EOPNOTSUPP;
845 break; 846 break;
846 case DIOCCACHESYNC: 847 case DIOCCACHESYNC:
847 if (sc->sc_cache_flush <= 0) { 848 if (sc->sc_cache_flush <= 0) {
848 if (sc->sc_cache_flush == 0) { 849 if (sc->sc_cache_flush == 0) {
849 aprint_error_dev(sc->sc_dksc.sc_dev, 850 aprint_error_dev(sc->sc_dksc.sc_dev,
850 "WARNING: cache flush not supported " 851 "WARNING: cache flush not supported "
851 "by backend\n"); 852 "by backend\n");
852 sc->sc_cache_flush = -1; 853 sc->sc_cache_flush = -1;
853 } 854 }
854 return EOPNOTSUPP; 855 return EOPNOTSUPP;
855 } 856 }
856 857
857 s = splbio(); /* XXXSMP */ 858 s = splbio(); /* XXXSMP */
858 859
859 while (RING_FULL(&sc->sc_ring)) { 860 while (RING_FULL(&sc->sc_ring)) {
860 sc->sc_xbdreq_wait = 1; 861 sc->sc_xbdreq_wait = 1;
861 /* XXXSMP */ 862 /* XXXSMP */
862 tsleep(&sc->sc_xbdreq_wait, PRIBIO, "xbdreq", 0); 863 tsleep(&sc->sc_xbdreq_wait, PRIBIO, "xbdreq", 0);
863 } 864 }
864 sc->sc_xbdreq_wait = 0; 865 sc->sc_xbdreq_wait = 0;
865 866
866 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head); 867 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head);
867 if (__predict_false(xbdreq == NULL)) { 868 if (__predict_false(xbdreq == NULL)) {
868 DPRINTF(("xbdioctl: no req\n")); 869 DPRINTF(("xbdioctl: no req\n"));
869 error = ENOMEM; 870 error = ENOMEM;
870 } else { 871 } else {
871 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); 872 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next);
872 req = RING_GET_REQUEST(&sc->sc_ring, 873 req = RING_GET_REQUEST(&sc->sc_ring,
873 sc->sc_ring.req_prod_pvt); 874 sc->sc_ring.req_prod_pvt);
874 req->id = xbdreq->req_id; 875 req->id = xbdreq->req_id;
875 req->operation = BLKIF_OP_FLUSH_DISKCACHE; 876 req->operation = BLKIF_OP_FLUSH_DISKCACHE;
876 req->handle = sc->sc_handle; 877 req->handle = sc->sc_handle;
877 xbdreq->req_sync.s_done = 0; 878 xbdreq->req_sync.s_done = 0;
878 sc->sc_ring.req_prod_pvt++; 879 sc->sc_ring.req_prod_pvt++;
879 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, 880 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring,
880 notify); 881 notify);
881 if (notify) 882 if (notify)
882 hypervisor_notify_via_evtchn(sc->sc_evtchn); 883 hypervisor_notify_via_evtchn(sc->sc_evtchn);
883 /* request sent, now wait for completion */ 884 /* request sent, now wait for completion */
884 while (xbdreq->req_sync.s_done == 0) { 885 while (xbdreq->req_sync.s_done == 0) {
885 /* XXXSMP */ 886 /* XXXSMP */
886 tsleep(xbdreq, PRIBIO, "xbdsync", 0); 887 tsleep(xbdreq, PRIBIO, "xbdsync", 0);
887 } 888 }
888 if (xbdreq->req_sync.s_error == BLKIF_RSP_EOPNOTSUPP) 889 if (xbdreq->req_sync.s_error == BLKIF_RSP_EOPNOTSUPP)
889 error = EOPNOTSUPP; 890 error = EOPNOTSUPP;
890 else if (xbdreq->req_sync.s_error == BLKIF_RSP_OKAY) 891 else if (xbdreq->req_sync.s_error == BLKIF_RSP_OKAY)
891 error = 0; 892 error = 0;
892 else 893 else
893 error = EIO; 894 error = EIO;
894 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq, 895 SLIST_INSERT_HEAD(&sc->sc_xbdreq_head, xbdreq,
895 req_next); 896 req_next);
896 } 897 }
897 splx(s); 898 splx(s);
898 break; 899 break;
899 900
900 default: 901 default:
901 error = dk_ioctl(dksc, dev, cmd, data, flag, l); 902 error = dk_ioctl(dksc, dev, cmd, data, flag, l);
902 break; 903 break;
903 } 904 }
904 905
905 return error; 906 return error;
906} 907}
907 908
908int 909int
909xbddump(dev_t dev, daddr_t blkno, void *va, size_t size) 910xbddump(dev_t dev, daddr_t blkno, void *va, size_t size)
910{ 911{
911 struct xbd_xenbus_softc *sc; 912 struct xbd_xenbus_softc *sc;
912 913
913 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev)); 914 sc = device_lookup_private(&xbd_cd, DISKUNIT(dev));
914 if (sc == NULL) 915 if (sc == NULL)
915 return (ENXIO); 916 return (ENXIO);
916 917
917 DPRINTF(("xbddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va, 918 DPRINTF(("xbddump(%d, %" PRId64 ", %p, %lu)\n", dev, blkno, va,
918 (unsigned long)size)); 919 (unsigned long)size));
919 return dk_dump(&sc->sc_dksc, dev, blkno, va, size); 920 return dk_dump(&sc->sc_dksc, dev, blkno, va, size);
920} 921}
921 922
922static int 923static int
923xbd_diskstart(device_t self, struct buf *bp) 924xbd_diskstart(device_t self, struct buf *bp)
924{ 925{
925 struct xbd_xenbus_softc *sc = device_private(self); 926 struct xbd_xenbus_softc *sc = device_private(self);
926 struct xbd_req *xbdreq; 927 struct xbd_req *xbdreq;
927 blkif_request_t *req; 928 blkif_request_t *req;
928 size_t bcount, off; 929 size_t bcount, off;
929 paddr_t ma; 930 paddr_t ma;
930 vaddr_t va; 931 vaddr_t va;
931 int nsects, nbytes, seg; 932 int nsects, nbytes, seg;
932 int notify, error = 0; 933 int notify, error = 0;
933 int s; 934 int s;
934 935
935 DPRINTF(("xbd_diskstart(%p): b_bcount = %ld\n", 936 DPRINTF(("xbd_diskstart(%p): b_bcount = %ld\n",
936 bp, (long)bp->b_bcount)); 937 bp, (long)bp->b_bcount));
937 938
938 if (sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) { 939 if (sc->sc_shutdown != BLKIF_SHUTDOWN_RUN) {
939 error = EIO; 940 error = EIO;
940 goto err; 941 goto err;
941 } 942 }
942 943
943 if (bp->b_rawblkno < 0 || bp->b_rawblkno > sc->sc_xbdsize) { 944 if (bp->b_rawblkno < 0 || bp->b_rawblkno > sc->sc_xbdsize) {
944 /* invalid block number */ 945 /* invalid block number */
945 error = EINVAL; 946 error = EINVAL;
946 goto err; 947 goto err;
947 } 948 }
948 949
949 s = splbio(); /* XXX SMP */ 950 s = splbio(); /* XXX SMP */
950 951
951 if (__predict_false( 952 if (__predict_false(
952 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)) { 953 sc->sc_backend_status == BLKIF_STATE_SUSPENDED)) {
953 /* device is suspended, do not consume buffer */ 954 /* device is suspended, do not consume buffer */
954 DPRINTF(("%s: (xbd_diskstart) device suspended\n", 955 DPRINTF(("%s: (xbd_diskstart) device suspended\n",
955 sc->sc_dksc.sc_xname)); 956 sc->sc_dksc.sc_xname));
956 error = EAGAIN; 957 error = EAGAIN;
957 goto out; 958 goto out;
958 } 959 }
959 960
960 if (RING_FULL(&sc->sc_ring) || sc->sc_xbdreq_wait) { 961 if (RING_FULL(&sc->sc_ring) || sc->sc_xbdreq_wait) {
961 DPRINTF(("xbd_diskstart: ring_full\n")); 962 DPRINTF(("xbd_diskstart: ring_full\n"));
962 error = EAGAIN; 963 error = EAGAIN;
963 goto out; 964 goto out;
964 } 965 }
965 966
966 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head); 967 xbdreq = SLIST_FIRST(&sc->sc_xbdreq_head);
967 if (__predict_false(xbdreq == NULL)) { 968 if (__predict_false(xbdreq == NULL)) {
968 DPRINTF(("xbd_diskstart: no req\n")); 969 DPRINTF(("xbd_diskstart: no req\n"));
969 error = EAGAIN; 970 error = EAGAIN;
970 goto out; 971 goto out;
971 } 972 }
972 973
973 if ((vaddr_t)bp->b_data & (XEN_BSIZE - 1)) { 974 if ((vaddr_t)bp->b_data & (XEN_BSIZE - 1)) {
974 DPRINTF(("xbd_diskstart: no align\n")); 975 DPRINTF(("xbd_diskstart: no align\n"));
975 error = EINVAL; 976 error = EINVAL;
976 goto out; 977 goto out;
977 } 978 }
978 979
979 xbdreq->req_bp = bp; 980 xbdreq->req_bp = bp;
980 981
981 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next); 982 SLIST_REMOVE_HEAD(&sc->sc_xbdreq_head, req_next);
982 req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt); 983 req = RING_GET_REQUEST(&sc->sc_ring, sc->sc_ring.req_prod_pvt);
983 req->id = xbdreq->req_id; 984 req->id = xbdreq->req_id;
984 req->operation = 985 req->operation =
985 bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE; 986 bp->b_flags & B_READ ? BLKIF_OP_READ : BLKIF_OP_WRITE;
986 req->sector_number = bp->b_rawblkno; 987 req->sector_number = bp->b_rawblkno;
987 req->handle = sc->sc_handle; 988 req->handle = sc->sc_handle;
988 989
989 va = (vaddr_t)bp->b_data & ~PAGE_MASK; 990 va = (vaddr_t)bp->b_data & ~PAGE_MASK;
990 off = (vaddr_t)bp->b_data & PAGE_MASK; 991 off = (vaddr_t)bp->b_data & PAGE_MASK;
991 bcount = bp->b_bcount; 992 bcount = bp->b_bcount;
992 bp->b_resid = 0; 993 bp->b_resid = 0;
993 for (seg = 0; bcount > 0;) { 994 for (seg = 0; bcount > 0;) {
994 pmap_extract_ma(pmap_kernel(), va, &ma); 995 pmap_extract_ma(pmap_kernel(), va, &ma);
995 KASSERT((ma & (XEN_BSIZE - 1)) == 0); 996 KASSERT((ma & (XEN_BSIZE - 1)) == 0);
996 if (bcount > PAGE_SIZE - off) 997 if (bcount > PAGE_SIZE - off)
997 nbytes = PAGE_SIZE - off; 998 nbytes = PAGE_SIZE - off;
998 else 999 else
999 nbytes = bcount; 1000 nbytes = bcount;
1000 nsects = nbytes >> XEN_BSHIFT; 1001 nsects = nbytes >> XEN_BSHIFT;
1001 req->seg[seg].first_sect = off >> XEN_BSHIFT; 1002 req->seg[seg].first_sect = off >> XEN_BSHIFT;
1002 req->seg[seg].last_sect = 1003 req->seg[seg].last_sect =
1003 (off >> XEN_BSHIFT) + nsects - 1; 1004 (off >> XEN_BSHIFT) + nsects - 1;
1004 KASSERT(req->seg[seg].first_sect <= 1005 KASSERT(req->seg[seg].first_sect <=
1005 req->seg[seg].last_sect); 1006 req->seg[seg].last_sect);
1006 KASSERT(req->seg[seg].last_sect < 8); 1007 KASSERT(req->seg[seg].last_sect < 8);
1007 if (__predict_false(xengnt_grant_access( 1008 if (__predict_false(xengnt_grant_access(
1008 sc->sc_xbusd->xbusd_otherend_id, ma, 1009 sc->sc_xbusd->xbusd_otherend_id, ma,
1009 (bp->b_flags & B_READ) == 0, 1010 (bp->b_flags & B_READ) == 0,
1010 &xbdreq->req_gntref[seg]))) 1011 &xbdreq->req_gntref[seg])))
1011 panic("xbd_diskstart: xengnt_grant_access"); /* XXX XXX !!! */ 1012 panic("xbd_diskstart: xengnt_grant_access"); /* XXX XXX !!! */
1012 req->seg[seg].gref = xbdreq->req_gntref[seg]; 1013 req->seg[seg].gref = xbdreq->req_gntref[seg];
1013 seg++; 1014 seg++;
1014 KASSERT(seg <= BLKIF_MAX_SEGMENTS_PER_REQUEST); 1015 KASSERT(seg <= BLKIF_MAX_SEGMENTS_PER_REQUEST);
1015 va += PAGE_SIZE; 1016 va += PAGE_SIZE;
1016 off = 0; 1017 off = 0;
1017 bcount -= nbytes; 1018 bcount -= nbytes;
1018 } 1019 }
1019 xbdreq->req_nr_segments = req->nr_segments = seg; 1020 xbdreq->req_nr_segments = req->nr_segments = seg;
1020 sc->sc_ring.req_prod_pvt++; 1021 sc->sc_ring.req_prod_pvt++;
1021 1022
1022out: 1023out:
1023 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, notify); 1024 RING_PUSH_REQUESTS_AND_CHECK_NOTIFY(&sc->sc_ring, notify);
1024 if (notify) 1025 if (notify)
1025 hypervisor_notify_via_evtchn(sc->sc_evtchn); 1026 hypervisor_notify_via_evtchn(sc->sc_evtchn);
1026 splx(s); /* XXXSMP */ 1027 splx(s); /* XXXSMP */
1027err: 1028err:
1028 return error; 1029 return error;
1029} 1030}