1 /* $NetBSD: xbdback_xenbus.c,v 1.111 2026/10/04 06:46:55 mlelstv Exp $ */ 2 3 /* 4 * Copyright (c) 2006,2024 Manuel Bouyer. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 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 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 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 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 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #include <sys/cdefs.h> 29 __KERNEL_RCSID(0, "$NetBSD: xbdback_xenbus.c,v 1.111 2026/10/04 06:46:55 mlelstv Exp $"); 30 31 #include <sys/buf.h> 32 #include <sys/condvar.h> 33 #include <sys/conf.h> 34 #include <sys/disk.h> 35 #include <sys/device.h> 36 #include <sys/fcntl.h> 37 #include <sys/kauth.h> 38 #include <sys/kernel.h> 39 #include <sys/kmem.h> 40 #include <sys/kthread.h> 41 #include <sys/mutex.h> 42 #include <sys/param.h> 43 #include <sys/queue.h> 44 #include <sys/systm.h> 45 #include <sys/time.h> 46 #include <sys/types.h> 47 #include <sys/vnode.h> 48 49 #include <xen/intr.h> 50 #include <xen/hypervisor.h> 51 #include <xen/xen.h> 52 #include <xen/xen_shm.h> 53 #include <xen/evtchn.h> 54 #include <xen/xenbus.h> 55 #include <xen/xenring.h> 56 #include <xen/include/public/io/protocols.h> 57 58 /* #define XENDEBUG_VBD */ 59 #ifdef XENDEBUG_VBD 60 #define XENPRINTF(x) printf x 61 #else 62 #define XENPRINTF(x) 63 #endif 64 65 #define BLKIF_RING_SIZE __CONST_RING_SIZE(blkif, PAGE_SIZE) 66 67 /* 68 * Backend block device driver for Xen 69 */ 70 71 /* Values are expressed in 512-byte sectors */ 72 #define VBD_BSIZE 512 73 #define VBD_MAXSECT ((PAGE_SIZE / VBD_BSIZE) - 1) 74 75 #define VBD_VA_SIZE MAXPHYS 76 #define VBD_MAX_INDIRECT_SEGMENTS (VBD_VA_SIZE >> PAGE_SHIFT) 77 78 CTASSERT(XENSHM_MAX_PAGES_PER_REQUEST >= VBD_MAX_INDIRECT_SEGMENTS); 79 80 struct xbdback_instance; 81 82 /* 83 * status of a xbdback instance: 84 * WAITING: xbdback instance is connected, waiting for requests 85 * RUN: xbdi thread must be woken up, I/Os have to be processed 86 * DISCONNECTING: the instance is closing, no more I/Os can be scheduled 87 * DISCONNECTED: no I/Os, no ring, the thread should terminate. 88 */ 89 typedef enum {WAITING, RUN, DISCONNECTING, DISCONNECTED} xbdback_state_t; 90 91 /* 92 * Each xbdback instance is managed by a single thread that handles all 93 * the I/O processing. As there are a variety of conditions that can block, 94 * everything will be done in a sort of continuation-passing style. 95 * 96 * When the execution has to block to delay processing, for example to 97 * allow system to recover because of memory shortage (via shared memory 98 * callback), the return value of a continuation can be set to NULL. In that 99 * case, the thread will go back to sleeping and wait for the proper 100 * condition before it starts processing requests again from where it left. 101 * Continuation state is "stored" in the xbdback instance (xbdi_cont), 102 * and should only be manipulated by the instance thread. 103 * If a continuation has to be restarted from a specific point, 104 * the callback and argument can be stored in xbdi_cont_restart and 105 * xbdi_cont_restart_obj 106 * 107 * 108 * As xbdback(4) has to handle different sort of asynchronous events (Xen 109 * event channels, biointr() soft interrupts, xenbus commands), the xbdi_lock 110 * mutex is used to protect specific elements of the xbdback instance from 111 * concurrent access: thread status and ring access (when pushing responses). 112 * 113 * Here's how the call graph is supposed to be for a single I/O: 114 * 115 * xbdback_co_main() 116 * | --> xbdback_co_cache_flush() 117 * | | | 118 * | | -> xbdback_co_do_io() or NULL 119 * xbdback_co_main_loop()-| 120 * | |-> xbdback_co_main_done2() or NULL 121 * | | 122 * | --> xbdback_co_main_incr() -> xbdback_co_main_loop() 123 * | 124 * xbdback_co_io() -> xbdback_co_main_incr() -> xbdback_co_main_loop() 125 * | 126 * xbdback_co_io_gotio() -> xbdback_co_main_incr() -> xbdback_co_main_loop() 127 * | 128 * xbdback_co_do_io() 129 * | 130 * xbdback_co_main_incr() -> xbdback_co_main_loop() 131 */ 132 typedef void *(* xbdback_cont_t)(struct xbdback_instance *, void *); 133 134 enum xbdi_proto { 135 XBDIP_NATIVE, 136 XBDIP_32, 137 XBDIP_64 138 }; 139 140 struct xbdback_va { 141 SLIST_ENTRY(xbdback_va) xv_next; 142 vaddr_t xv_vaddr; 143 }; 144 145 /* 146 * For each I/O operation associated with one of those requests, an 147 * xbdback_io is allocated from a pool. It may correspond to multiple 148 * Xen disk requests, or parts of them, if several arrive at once that 149 * can be coalesced. 150 */ 151 struct xbdback_io { 152 SLIST_ENTRY(xbdback_io) xio_next; 153 /* The instance pointer is duplicated for convenience. */ 154 struct xbdback_instance *xio_xbdi; /* our xbd instance */ 155 /* _request state: track requests fetched from ring */ 156 blkif_request_t xio_xen_req; 157 /* array of segments[VBD_MAX_INDIRECT_SEGMENTS] allocated separately */ 158 struct blkif_request_segment *xio_seg; 159 bus_dmamap_t xio_seg_dmamap; 160 /* internal states */ 161 union { 162 struct { 163 struct buf xio_buf; /* our I/O */ 164 /* the virtual address to map the request at */ 165 vaddr_t xio_vaddr; 166 struct xbdback_va *xio_xv; 167 vaddr_t xio_start_offset; /* I/O start offset */ 168 /* grants to map */ 169 grant_ref_t xio_gref[VBD_MAX_INDIRECT_SEGMENTS]; 170 /* grants release */ 171 grant_handle_t xio_gh[VBD_MAX_INDIRECT_SEGMENTS]; 172 bool xio_need_bounce; /* request is not contiguous */ 173 } xio_rw; 174 } u; 175 }; 176 #define xio_buf u.xio_rw.xio_buf 177 #define xio_vaddr u.xio_rw.xio_vaddr 178 #define xio_start_offset u.xio_rw.xio_start_offset 179 #define xio_xv u.xio_rw.xio_xv 180 #define xio_gref u.xio_rw.xio_gref 181 #define xio_gh u.xio_rw.xio_gh 182 #define xio_need_bounce u.xio_rw.xio_need_bounce 183 184 /* we keep the xbdback instances in a linked list */ 185 struct xbdback_instance { 186 SLIST_ENTRY(xbdback_instance) next; 187 struct xenbus_device *xbdi_xbusd; /* our xenstore entry */ 188 struct xenbus_watch xbdi_watch; /* to watch our store */ 189 domid_t xbdi_domid; /* attached to this domain */ 190 uint32_t xbdi_handle; /* domain-specific handle */ 191 char xbdi_name[16]; /* name of this instance */ 192 /* mutex that protects concurrent access to the xbdback instance */ 193 kmutex_t xbdi_lock; 194 kcondvar_t xbdi_cv; /* wait channel for thread work */ 195 xbdback_state_t xbdi_status; /* thread's status */ 196 /* context and KVA for mapping transfers */ 197 struct xbdback_io xbdi_io[BLKIF_RING_SIZE]; 198 SLIST_HEAD(, xbdback_io) xbdi_io_free; 199 struct xbdback_va xbdi_va[BLKIF_RING_SIZE]; 200 SLIST_HEAD(, xbdback_va) xbdi_va_free; 201 /* segments structure allocated in page-aligned chunks */ 202 struct blkif_request_segment *xbdi_segs; 203 /* bounce buffer in case a transfer is not contiguous */ 204 vaddr_t xbdi_bouncebuf; 205 int xbdi_bouncebuf_use; /* is bounce buffer in use? */ 206 /* backing device parameters */ 207 dev_t xbdi_dev; 208 const struct bdevsw *xbdi_bdevsw; /* pointer to the device's bdevsw */ 209 struct vnode *xbdi_vp; 210 uint64_t xbdi_size; 211 unsigned xbdi_secsize; 212 bool xbdi_ro; /* is device read-only ? */ 213 /* parameters for the communication */ 214 unsigned int xbdi_evtchn; 215 struct intrhand *xbdi_ih; 216 /* private parameters for communication */ 217 blkif_back_ring_proto_t xbdi_ring; 218 enum xbdi_proto xbdi_proto; 219 grant_handle_t xbdi_ring_handle; /* to unmap the ring */ 220 vaddr_t xbdi_ring_va; /* to unmap the ring */ 221 /* disconnection must be postponed until all I/O is done */ 222 int xbdi_refcnt; 223 /* 224 * State for I/O processing/coalescing follows; this has to 225 * live here instead of on the stack because of the 226 * continuation-ness (see above). 227 */ 228 RING_IDX xbdi_req_prod; /* limit on request indices */ 229 xbdback_cont_t xbdi_cont; 230 /* if not NULL, will restart here after thread wakes up */ 231 xbdback_cont_t xbdi_cont_restart; 232 void *xbdi_cont_restart_obj; 233 /* other state */ 234 uint xbdi_pendingreqs; /* number of I/O in fly */ 235 struct timeval xbdi_lasterr_time; /* error time tracking */ 236 }; 237 /* Manipulation of the above reference count. */ 238 #define xbdi_get(xbdip) \ 239 do { \ 240 KASSERT(mutex_owned(&xbdip->xbdi_lock)); \ 241 (xbdip)->xbdi_refcnt++; \ 242 } while (0) 243 244 #define xbdi_put(xbdip) \ 245 do { \ 246 KASSERT(mutex_owned(&xbdip->xbdi_lock)); \ 247 if (--((xbdip)->xbdi_refcnt) == 0) \ 248 xbdback_finish_disconnect(xbdip); \ 249 } while (0) 250 251 static SLIST_HEAD(, xbdback_instance) xbdback_instances; 252 static kmutex_t xbdback_lock; 253 254 /* Interval between reports of I/O errors from frontend */ 255 static const struct timeval xbdback_err_intvl = { 1, 0 }; 256 257 void xbdbackattach(int); 258 static int xbdback_xenbus_create(struct xenbus_device *); 259 static int xbdback_xenbus_destroy(void *); 260 static void xbdback_frontend_changed(void *, XenbusState); 261 static void xbdback_backend_changed(struct xenbus_watch *, 262 const char **, unsigned int); 263 static int xbdback_evthandler(void *); 264 265 static int xbdback_connect(struct xbdback_instance *); 266 static void xbdback_disconnect(struct xbdback_instance *); 267 static void xbdback_finish_disconnect(struct xbdback_instance *); 268 269 static bool xbdif_lookup(domid_t, uint32_t); 270 271 static void *xbdback_co_main(struct xbdback_instance *, void *); 272 static void *xbdback_co_main_loop(struct xbdback_instance *, void *); 273 static void *xbdback_co_main_incr(struct xbdback_instance *, void *); 274 static void *xbdback_co_main_done2(struct xbdback_instance *, void *); 275 276 static void *xbdback_co_cache_flush(struct xbdback_instance *, void *); 277 278 static void *xbdback_co_io(struct xbdback_instance *, void *); 279 static void *xbdback_co_io_gotio(struct xbdback_instance *, void *); 280 281 static void *xbdback_co_do_io(struct xbdback_instance *, void *); 282 283 static void xbdback_io_error(struct xbdback_io *, int); 284 static void xbdback_iodone(struct buf *); 285 static void xbdback_iodone_locked(struct xbdback_instance *, 286 struct xbdback_io *, struct buf *); 287 static void xbdback_send_reply(struct xbdback_instance *, uint64_t , int , int); 288 289 static int xbdback_map_shm(struct xbdback_io *); 290 static void xbdback_unmap_shm(struct xbdback_io *); 291 292 static struct xbdback_io *xbdback_io_get(struct xbdback_instance *); 293 static void xbdback_io_put(struct xbdback_instance *, struct xbdback_io *); 294 static void xbdback_thread(void *); 295 static void xbdback_wakeup_thread(struct xbdback_instance *); 296 static void xbdback_trampoline(struct xbdback_instance *, void *); 297 298 static struct xenbus_backend_driver xbd_backend_driver = { 299 .xbakd_create = xbdback_xenbus_create, 300 .xbakd_type = "vbd" 301 }; 302 303 void 304 xbdbackattach(int n) 305 { 306 XENPRINTF(("xbdbackattach\n")); 307 308 /* 309 * initialize the backend driver, register the control message handler 310 * and send driver up message. 311 */ 312 SLIST_INIT(&xbdback_instances); 313 mutex_init(&xbdback_lock, MUTEX_DEFAULT, IPL_NONE); 314 315 xenbus_backend_register(&xbd_backend_driver); 316 } 317 318 static int 319 xbdback_xenbus_create(struct xenbus_device *xbusd) 320 { 321 struct xbdback_instance *xbdi; 322 long domid, handle; 323 int error, i; 324 int segalloc = 0; 325 char *ep; 326 327 if ((error = xenbus_read_ul(NULL, xbusd->xbusd_path, 328 "frontend-id", &domid, 10)) != 0) { 329 aprint_error("xbdback: can't read %s/frontend-id: %d\n", 330 xbusd->xbusd_path, error); 331 return error; 332 } 333 334 /* 335 * get handle: this is the last component of the path; which is 336 * a decimal number. $path/dev contains the device name, which is not 337 * appropriate. 338 */ 339 for (i = strlen(xbusd->xbusd_path); i > 0; i--) { 340 if (xbusd->xbusd_path[i] == '/') 341 break; 342 } 343 if (i == 0) { 344 aprint_error("xbdback: can't parse %s\n", 345 xbusd->xbusd_path); 346 return EFTYPE; 347 } 348 handle = strtoul(&xbusd->xbusd_path[i+1], &ep, 10); 349 if (*ep != '\0') { 350 aprint_error("xbdback: can't parse %s\n", 351 xbusd->xbusd_path); 352 return EFTYPE; 353 } 354 355 xbdi = kmem_zalloc(sizeof(*xbdi), KM_SLEEP); 356 357 xbdi->xbdi_domid = domid; 358 xbdi->xbdi_handle = handle; 359 snprintf(xbdi->xbdi_name, sizeof(xbdi->xbdi_name), "xbdb%di%d", 360 xbdi->xbdi_domid, xbdi->xbdi_handle); 361 362 mutex_enter(&xbdback_lock); 363 if (xbdif_lookup(domid, handle)) { 364 mutex_exit(&xbdback_lock); 365 kmem_free(xbdi, sizeof(*xbdi)); 366 return EEXIST; 367 } 368 SLIST_INSERT_HEAD(&xbdback_instances, xbdi, next); 369 mutex_exit(&xbdback_lock); 370 371 /* initialize status and reference counter */ 372 xbdi->xbdi_status = DISCONNECTED; 373 374 mutex_init(&xbdi->xbdi_lock, MUTEX_DEFAULT, IPL_BIO); 375 cv_init(&xbdi->xbdi_cv, xbdi->xbdi_name); 376 377 mutex_enter(&xbdi->xbdi_lock); 378 xbdi_get(xbdi); 379 mutex_exit(&xbdi->xbdi_lock); 380 381 xbusd->xbusd_u.b.b_cookie = xbdi; 382 xbusd->xbusd_u.b.b_detach = xbdback_xenbus_destroy; 383 xbusd->xbusd_otherend_changed = xbdback_frontend_changed; 384 xbdi->xbdi_xbusd = xbusd; 385 386 SLIST_INIT(&xbdi->xbdi_va_free); 387 for (i = 0; i < BLKIF_RING_SIZE; i++) { 388 xbdi->xbdi_va[i].xv_vaddr = uvm_km_alloc(kernel_map, 389 VBD_VA_SIZE, 0, UVM_KMF_VAONLY|UVM_KMF_WAITVA); 390 SLIST_INSERT_HEAD(&xbdi->xbdi_va_free, &xbdi->xbdi_va[i], 391 xv_next); 392 } 393 394 /* 395 * allocate page-aligned memory for segments, so that for each 396 * xbdback_io its segments are in a single page. 397 * avoid a page boundary within a block of VBD_MAX_INDIRECT_SEGMENTS 398 * segments. 399 */ 400 401 CTASSERT(PAGE_SIZE % (sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS) == 0); 402 CTASSERT(PAGE_SIZE / (sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS) >= 1); 403 404 xbdi->xbdi_segs = (void *)uvm_km_alloc(kernel_map, round_page( 405 sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS * BLKIF_RING_SIZE), 406 PAGE_SIZE, UVM_KMF_WIRED | UVM_KMF_WAITVA); 407 408 SLIST_INIT(&xbdi->xbdi_io_free); 409 for (i = 0; i < BLKIF_RING_SIZE; i++) { 410 struct xbdback_io *xbd_io = &xbdi->xbdi_io[i]; 411 xbd_io->xio_seg = 412 &xbdi->xbdi_segs[i * VBD_MAX_INDIRECT_SEGMENTS]; 413 error = bus_dmamap_create(xbdi->xbdi_xbusd->xbusd_dmat, 414 PAGE_SIZE, 1, PAGE_SIZE, PAGE_SIZE, 415 BUS_DMA_WAITOK | BUS_DMA_ALLOCNOW, 416 &xbd_io->xio_seg_dmamap); 417 if (error != 0) { 418 printf("%s: can't create dma map for indirect segments %d\n", 419 xbdi->xbdi_name, i); 420 goto fail; 421 } 422 error = bus_dmamap_load(xbdi->xbdi_xbusd->xbusd_dmat, 423 xbd_io->xio_seg_dmamap, xbd_io->xio_seg, 424 sizeof(struct blkif_request_segment) * VBD_MAX_INDIRECT_SEGMENTS, 425 NULL, BUS_DMA_WAITOK); 426 if (error != 0) { 427 printf("%s: can't load dma map for indirect segments %d @%p (%d, %zu)\n", 428 xbdi->xbdi_name, i, xbd_io->xio_seg, error, sizeof(xbd_io->xio_seg)); 429 bus_dmamap_destroy(xbdi->xbdi_xbusd->xbusd_dmat, 430 xbd_io->xio_seg_dmamap); 431 goto fail; 432 } 433 KASSERT(xbd_io->xio_seg_dmamap->dm_nsegs == 1); 434 segalloc = i; 435 SLIST_INSERT_HEAD(&xbdi->xbdi_io_free, xbd_io, xio_next); 436 } 437 438 error = xenbus_watch_path2(xbusd, xbusd->xbusd_path, "physical-device", 439 &xbdi->xbdi_watch, xbdback_backend_changed); 440 if (error) { 441 printf("failed to watch on %s/physical-device: %d\n", 442 xbusd->xbusd_path, error); 443 goto fail; 444 } 445 xbdi->xbdi_watch.xbw_dev = xbusd; 446 error = xenbus_switch_state(xbusd, NULL, XenbusStateInitWait); 447 if (error) { 448 printf("failed to switch state on %s: %d\n", 449 xbusd->xbusd_path, error); 450 goto fail2; 451 } 452 453 xbdi->xbdi_bouncebuf = uvm_km_alloc(kernel_map, MAXPHYS, PAGE_SIZE, 454 UVM_KMF_WIRED | UVM_KMF_WAITVA); 455 return 0; 456 fail2: 457 unregister_xenbus_watch(&xbdi->xbdi_watch); 458 fail: 459 for (i = 0; i < segalloc; i++) { 460 struct xbdback_io *xbd_io = &xbdi->xbdi_io[i]; 461 bus_dmamap_unload(xbdi->xbdi_xbusd->xbusd_dmat, 462 xbd_io->xio_seg_dmamap); 463 bus_dmamap_destroy(xbdi->xbdi_xbusd->xbusd_dmat, 464 xbd_io->xio_seg_dmamap); 465 } 466 mutex_enter(&xbdback_lock); 467 SLIST_REMOVE(&xbdback_instances, xbdi, xbdback_instance, next); 468 mutex_exit(&xbdback_lock); 469 kmem_free(xbdi, sizeof(*xbdi)); 470 return error; 471 } 472 473 static int 474 xbdback_xenbus_destroy(void *arg) 475 { 476 struct xbdback_instance *xbdi = arg; 477 478 XENPRINTF(("xbdback_xenbus_destroy state %d\n", xbdi->xbdi_status)); 479 480 xbdback_disconnect(xbdi); 481 482 /* unregister watch */ 483 if (xbdi->xbdi_watch.node) 484 xenbus_unwatch_path(&xbdi->xbdi_watch); 485 /* unmap ring */ 486 if (xbdi->xbdi_ring_handle) { 487 xen_shm_unmap(xbdi->xbdi_ring_va, 1, &xbdi->xbdi_ring_handle); 488 } 489 490 if (xbdi->xbdi_ring_va != 0) { 491 uvm_km_free(kernel_map, xbdi->xbdi_ring_va, 492 PAGE_SIZE, UVM_KMF_VAONLY); 493 } 494 495 /* close device */ 496 if (xbdi->xbdi_size) { 497 const char *name; 498 struct dkwedge_info wi; 499 if (getdiskinfo(xbdi->xbdi_vp, &wi) == 0) 500 name = wi.dkw_devname; 501 else 502 name = "*unknown*"; 503 printf("xbd backend: detach device %s for domain %d\n", 504 name, xbdi->xbdi_domid); 505 vn_close(xbdi->xbdi_vp, FREAD, NOCRED); 506 } 507 mutex_enter(&xbdback_lock); 508 SLIST_REMOVE(&xbdback_instances, xbdi, xbdback_instance, next); 509 mutex_exit(&xbdback_lock); 510 511 for (int i = 0; i < BLKIF_RING_SIZE; i++) { 512 struct xbdback_io *xbd_io = &xbdi->xbdi_io[i]; 513 bus_dmamap_unload(xbdi->xbdi_xbusd->xbusd_dmat, 514 xbd_io->xio_seg_dmamap); 515 bus_dmamap_destroy(xbdi->xbdi_xbusd->xbusd_dmat, 516 xbd_io->xio_seg_dmamap); 517 if (xbdi->xbdi_va[i].xv_vaddr != 0) { 518 uvm_km_free(kernel_map, xbdi->xbdi_va[i].xv_vaddr, 519 VBD_VA_SIZE, UVM_KMF_VAONLY); 520 xbdi->xbdi_va[i].xv_vaddr = 0; 521 } 522 } 523 524 525 mutex_destroy(&xbdi->xbdi_lock); 526 cv_destroy(&xbdi->xbdi_cv); 527 kmem_free(xbdi, sizeof(*xbdi)); 528 return 0; 529 } 530 531 static int 532 xbdback_connect(struct xbdback_instance *xbdi) 533 { 534 int err; 535 evtchn_op_t evop; 536 grant_ref_t gring_ref; 537 u_long ring_ref, revtchn; 538 char xsproto[32]; 539 const char *proto; 540 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 541 542 XENPRINTF(("xbdback %s: connect\n", xbusd->xbusd_path)); 543 /* read communication informations */ 544 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 545 "ring-ref", &ring_ref, 10); 546 if (err) { 547 xenbus_dev_fatal(xbusd, err, "reading %s/ring-ref", 548 xbusd->xbusd_otherend); 549 return -1; 550 } 551 XENPRINTF(("xbdback %s: connect ring-ref %lu\n", xbusd->xbusd_path, ring_ref)); 552 err = xenbus_read_ul(NULL, xbusd->xbusd_otherend, 553 "event-channel", &revtchn, 10); 554 if (err) { 555 xenbus_dev_fatal(xbusd, err, "reading %s/event-channel", 556 xbusd->xbusd_otherend); 557 return -1; 558 } 559 XENPRINTF(("xbdback %s: connect revtchn %lu\n", xbusd->xbusd_path, revtchn)); 560 err = xenbus_read(NULL, xbusd->xbusd_otherend, "protocol", 561 xsproto, sizeof(xsproto)); 562 if (err) { 563 xbdi->xbdi_proto = XBDIP_NATIVE; 564 proto = "unspecified"; 565 XENPRINTF(("xbdback %s: connect no xsproto\n", xbusd->xbusd_path)); 566 } else { 567 XENPRINTF(("xbdback %s: connect xsproto %s\n", xbusd->xbusd_path, xsproto)); 568 if (strcmp(xsproto, XEN_IO_PROTO_ABI_NATIVE) == 0) { 569 xbdi->xbdi_proto = XBDIP_NATIVE; 570 proto = XEN_IO_PROTO_ABI_NATIVE; 571 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_32) == 0) { 572 xbdi->xbdi_proto = XBDIP_32; 573 proto = XEN_IO_PROTO_ABI_X86_32; 574 } else if (strcmp(xsproto, XEN_IO_PROTO_ABI_X86_64) == 0) { 575 xbdi->xbdi_proto = XBDIP_64; 576 proto = XEN_IO_PROTO_ABI_X86_64; 577 } else { 578 printf("xbd domain %d: unknown proto %s\n", 579 xbdi->xbdi_domid, xsproto); 580 return -1; 581 } 582 } 583 584 /* allocate VA space and map rings */ 585 xbdi->xbdi_ring_va = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, 586 UVM_KMF_VAONLY); 587 if (xbdi->xbdi_ring_va == 0) { 588 xenbus_dev_fatal(xbusd, ENOMEM, 589 "can't get VA for ring", xbusd->xbusd_otherend); 590 return -1; 591 } 592 XENPRINTF(("xbdback %s: connect va 0x%" PRIxVADDR "\n", xbusd->xbusd_path, xbdi->xbdi_ring_va)); 593 594 gring_ref = ring_ref; 595 if (xen_shm_map(1, xbdi->xbdi_domid, &gring_ref, xbdi->xbdi_ring_va, 596 &xbdi->xbdi_ring_handle, 0) != 0) { 597 printf("xbdback %s: can't map grant ref\n", 598 xbusd->xbusd_path); 599 xenbus_dev_fatal(xbusd, EINVAL, 600 "can't map ring", xbusd->xbusd_otherend); 601 goto err1; 602 } 603 XENPRINTF(("xbdback %s: connect grhandle %d\n", xbusd->xbusd_path, xbdi->xbdi_ring_handle)); 604 605 switch(xbdi->xbdi_proto) { 606 case XBDIP_NATIVE: 607 { 608 blkif_sring_t *sring = (void *)xbdi->xbdi_ring_va; 609 BACK_RING_INIT(&xbdi->xbdi_ring.ring_n, sring, PAGE_SIZE); 610 break; 611 } 612 case XBDIP_32: 613 { 614 blkif_x86_32_sring_t *sring = (void *)xbdi->xbdi_ring_va; 615 BACK_RING_INIT(&xbdi->xbdi_ring.ring_32, sring, PAGE_SIZE); 616 break; 617 } 618 case XBDIP_64: 619 { 620 blkif_x86_64_sring_t *sring = (void *)xbdi->xbdi_ring_va; 621 BACK_RING_INIT(&xbdi->xbdi_ring.ring_64, sring, PAGE_SIZE); 622 break; 623 } 624 } 625 626 evop.cmd = EVTCHNOP_bind_interdomain; 627 evop.u.bind_interdomain.remote_dom = xbdi->xbdi_domid; 628 evop.u.bind_interdomain.remote_port = revtchn; 629 err = HYPERVISOR_event_channel_op(&evop); 630 if (err) { 631 printf("blkback %s: " 632 "can't get event channel: %d\n", 633 xbusd->xbusd_otherend, err); 634 xenbus_dev_fatal(xbusd, err, 635 "can't bind event channel", xbusd->xbusd_otherend); 636 goto err2; 637 } 638 xbdi->xbdi_evtchn = evop.u.bind_interdomain.local_port; 639 XENPRINTF(("xbdback %s: connect evchannel %d\n", xbusd->xbusd_path, xbdi->xbdi_evtchn)); 640 641 xbdi->xbdi_ih = xen_intr_establish_xname(-1, &xen_pic, 642 xbdi->xbdi_evtchn, IST_LEVEL, IPL_BIO, xbdback_evthandler, xbdi, 643 true, xbdi->xbdi_name); 644 KASSERT(xbdi->xbdi_ih != NULL); 645 printf("xbd backend domain %d handle %#x (%d) " 646 "using event channel %d, protocol %s\n", xbdi->xbdi_domid, 647 xbdi->xbdi_handle, xbdi->xbdi_handle, xbdi->xbdi_evtchn, proto); 648 649 /* enable the xbdback event handler machinery */ 650 xbdi->xbdi_status = WAITING; 651 hypervisor_unmask_event(xbdi->xbdi_evtchn); 652 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); 653 654 if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, 655 xbdback_thread, xbdi, NULL, "%s", xbdi->xbdi_name) == 0) 656 return 0; 657 658 err2: 659 /* unmap ring */ 660 xen_shm_unmap(xbdi->xbdi_ring_va, 1, &xbdi->xbdi_ring_handle); 661 err1: 662 /* free ring VA space */ 663 uvm_km_free(kernel_map, xbdi->xbdi_ring_va, PAGE_SIZE, UVM_KMF_VAONLY); 664 return -1; 665 } 666 667 /* 668 * Signal a xbdback thread to disconnect. Done in 'xenwatch' thread context. 669 */ 670 static void 671 xbdback_disconnect(struct xbdback_instance *xbdi) 672 { 673 674 mutex_enter(&xbdi->xbdi_lock); 675 if (xbdi->xbdi_status == DISCONNECTED) { 676 mutex_exit(&xbdi->xbdi_lock); 677 return; 678 } 679 hypervisor_mask_event(xbdi->xbdi_evtchn); 680 681 /* signal thread that we want to disconnect, then wait for it */ 682 xbdi->xbdi_status = DISCONNECTING; 683 cv_signal(&xbdi->xbdi_cv); 684 685 while (xbdi->xbdi_status != DISCONNECTED) 686 cv_wait(&xbdi->xbdi_cv, &xbdi->xbdi_lock); 687 688 mutex_exit(&xbdi->xbdi_lock); 689 xen_intr_disestablish(xbdi->xbdi_ih); 690 691 xenbus_switch_state(xbdi->xbdi_xbusd, NULL, XenbusStateClosing); 692 } 693 694 static void 695 xbdback_frontend_changed(void *arg, XenbusState new_state) 696 { 697 struct xbdback_instance *xbdi = arg; 698 struct xenbus_device *xbusd = xbdi->xbdi_xbusd; 699 700 XENPRINTF(("xbdback %s: new state %d\n", xbusd->xbusd_path, new_state)); 701 switch(new_state) { 702 case XenbusStateInitialising: 703 break; 704 case XenbusStateInitialised: 705 case XenbusStateConnected: 706 if (xbdi->xbdi_status == WAITING || xbdi->xbdi_status == RUN) 707 break; 708 xbdback_connect(xbdi); 709 break; 710 case XenbusStateClosing: 711 xbdback_disconnect(xbdi); 712 break; 713 case XenbusStateClosed: 714 /* otherend_changed() should handle it for us */ 715 panic("xbdback_frontend_changed: closed\n"); 716 case XenbusStateUnknown: 717 case XenbusStateInitWait: 718 default: 719 printf("xbdback %s: invalid frontend state %d\n", 720 xbusd->xbusd_path, new_state); 721 } 722 return; 723 } 724 725 static void 726 xbdback_backend_changed(struct xenbus_watch *watch, 727 const char **vec, unsigned int len) 728 { 729 struct xenbus_device *xbusd = watch->xbw_dev; 730 struct xbdback_instance *xbdi = xbusd->xbusd_u.b.b_cookie; 731 int err; 732 long dev; 733 char mode[32]; 734 struct xenbus_transaction *xbt; 735 const char *devname; 736 int major; 737 738 err = xenbus_read_ul(NULL, xbusd->xbusd_path, "physical-device", 739 &dev, 10); 740 /* 741 * An error can occur as the watch can fire up just after being 742 * registered. So we have to ignore error :( 743 */ 744 if (err) 745 return; 746 /* 747 * we can also fire up after having opened the device, don't try 748 * to do it twice. 749 */ 750 if (xbdi->xbdi_vp != NULL) { 751 if (xbdi->xbdi_status == WAITING || xbdi->xbdi_status == RUN) { 752 if (xbdi->xbdi_dev != dev) { 753 printf("xbdback %s: changing physical device " 754 "from %#"PRIx64" to %#lx not supported\n", 755 xbusd->xbusd_path, xbdi->xbdi_dev, dev); 756 } 757 } 758 return; 759 } 760 xbdi->xbdi_dev = dev; 761 err = xenbus_read(NULL, xbusd->xbusd_path, "mode", mode, sizeof(mode)); 762 if (err) { 763 printf("xbdback: failed to read %s/mode: %d\n", 764 xbusd->xbusd_path, err); 765 return; 766 } 767 if (mode[0] == 'w') 768 xbdi->xbdi_ro = false; 769 else 770 xbdi->xbdi_ro = true; 771 major = major(xbdi->xbdi_dev); 772 devname = devsw_blk2name(major); 773 if (devname == NULL) { 774 printf("xbdback %s: unknown device 0x%"PRIx64"\n", 775 xbusd->xbusd_path, xbdi->xbdi_dev); 776 return; 777 } 778 xbdi->xbdi_bdevsw = bdevsw_lookup(xbdi->xbdi_dev); 779 if (xbdi->xbdi_bdevsw == NULL) { 780 printf("xbdback %s: no bdevsw for device 0x%"PRIx64"\n", 781 xbusd->xbusd_path, xbdi->xbdi_dev); 782 return; 783 } 784 err = bdevvp(xbdi->xbdi_dev, &xbdi->xbdi_vp); 785 if (err) { 786 printf("xbdback %s: can't open device 0x%"PRIx64": %d\n", 787 xbusd->xbusd_path, xbdi->xbdi_dev, err); 788 return; 789 } 790 err = vn_lock(xbdi->xbdi_vp, LK_EXCLUSIVE | LK_RETRY); 791 if (err) { 792 printf("xbdback %s: can't vn_lock device 0x%"PRIx64": %d\n", 793 xbusd->xbusd_path, xbdi->xbdi_dev, err); 794 vrele(xbdi->xbdi_vp); 795 return; 796 } 797 err = VOP_OPEN(xbdi->xbdi_vp, FREAD, NOCRED); 798 if (err) { 799 printf("xbdback %s: can't VOP_OPEN device 0x%"PRIx64": %d\n", 800 xbusd->xbusd_path, xbdi->xbdi_dev, err); 801 vput(xbdi->xbdi_vp); 802 return; 803 } 804 VOP_UNLOCK(xbdi->xbdi_vp); 805 806 struct dkwedge_info wi; 807 if (getdiskinfo(xbdi->xbdi_vp, &wi) == 0) 808 devname = wi.dkw_devname; 809 810 err = getdisksize(xbdi->xbdi_vp, &xbdi->xbdi_size, &xbdi->xbdi_secsize); 811 if (err == 0) { 812 printf("xbd backend: attach device %s" 813 " (size %" PRIu64 " x %u) for domain %d\n", 814 devname, xbdi->xbdi_size, 815 xbdi->xbdi_secsize, xbdi->xbdi_domid); 816 } else { 817 /* If Ioctls failed set device size to 0 and return */ 818 printf("xbdback %s: can't get size of device " 819 "0x%"PRIx64": %d\n", xbusd->xbusd_path, 820 xbdi->xbdi_dev, err); 821 xbdi->xbdi_size = xbdi->xbdi_dev = 0; 822 vn_close(xbdi->xbdi_vp, FREAD, NOCRED); 823 xbdi->xbdi_vp = NULL; 824 return; 825 } 826 again: 827 xbt = xenbus_transaction_start(); 828 if (xbt == NULL) { 829 printf("xbdback %s: can't start transaction\n", 830 xbusd->xbusd_path); 831 return; 832 } 833 err = xenbus_printf(xbt, xbusd->xbusd_path, "sectors", "%" PRIu64 , 834 xbdi->xbdi_size * xbdi->xbdi_secsize / VBD_BSIZE); 835 if (err) { 836 printf("xbdback: failed to write %s/sectors: %d\n", 837 xbusd->xbusd_path, err); 838 goto abort; 839 } 840 err = xenbus_printf(xbt, xbusd->xbusd_path, "info", "%u", 841 xbdi->xbdi_ro ? VDISK_READONLY : 0); 842 if (err) { 843 printf("xbdback: failed to write %s/info: %d\n", 844 xbusd->xbusd_path, err); 845 goto abort; 846 } 847 848 /* 849 * don't pass true sector size as defined by spec but 850 * constant 512 bytes. 851 * 1. doesn't confuse guests that cannot handle large sectors 852 * 2. matches the disk-size above 853 * 3. what Linux does 854 * 4. guest needs to take care about alignment on its own 855 */ 856 err = xenbus_printf(xbt, xbusd->xbusd_path, "sector-size", "%lu", 857 (u_long)VBD_BSIZE); 858 if (err) { 859 printf("xbdback: failed to write %s/sector-size: %d\n", 860 xbusd->xbusd_path, err); 861 goto abort; 862 } 863 err = xenbus_printf(xbt, xbusd->xbusd_path, "feature-flush-cache", 864 "%u", 1); 865 if (err) { 866 printf("xbdback: failed to write %s/feature-flush-cache: %d\n", 867 xbusd->xbusd_path, err); 868 goto abort; 869 } 870 err = xenbus_printf(xbt, xbusd->xbusd_path, 871 "feature-max-indirect-segments", "%u", VBD_MAX_INDIRECT_SEGMENTS); 872 if (err) { 873 printf("xbdback: failed to write %s/feature-indirect: %d\n", 874 xbusd->xbusd_path, err); 875 goto abort; 876 } 877 err = xenbus_transaction_end(xbt, 0); 878 if (err == EAGAIN) 879 goto again; 880 if (err) { 881 printf("xbdback %s: can't end transaction: %d\n", 882 xbusd->xbusd_path, err); 883 } 884 err = xenbus_switch_state(xbusd, NULL, XenbusStateConnected); 885 if (err) { 886 printf("xbdback %s: can't switch state: %d\n", 887 xbusd->xbusd_path, err); 888 } 889 return; 890 abort: 891 xenbus_transaction_end(xbt, 1); 892 } 893 894 /* 895 * Used by a xbdi thread to signal that it is now disconnected. 896 */ 897 static void 898 xbdback_finish_disconnect(struct xbdback_instance *xbdi) 899 { 900 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 901 KASSERT(xbdi->xbdi_status == DISCONNECTING); 902 903 xbdi->xbdi_status = DISCONNECTED; 904 905 cv_broadcast(&xbdi->xbdi_cv); 906 } 907 908 static bool 909 xbdif_lookup(domid_t dom , uint32_t handle) 910 { 911 struct xbdback_instance *xbdi; 912 bool found = false; 913 914 KASSERT(mutex_owned(&xbdback_lock)); 915 916 SLIST_FOREACH(xbdi, &xbdback_instances, next) { 917 if (xbdi->xbdi_domid == dom && xbdi->xbdi_handle == handle) { 918 found = true; 919 break; 920 } 921 } 922 923 return found; 924 } 925 926 static int 927 xbdback_evthandler(void *arg) 928 { 929 struct xbdback_instance *xbdi = arg; 930 931 XENPRINTF(("xbdback_evthandler domain %d: cont %p\n", 932 xbdi->xbdi_domid, xbdi->xbdi_cont)); 933 934 mutex_enter(&xbdi->xbdi_lock); 935 xbdback_wakeup_thread(xbdi); 936 mutex_exit(&xbdi->xbdi_lock); 937 938 return 1; 939 } 940 941 /* 942 * Main thread routine for one xbdback instance. Woken up by 943 * xbdback_evthandler when a domain has I/O work scheduled in a I/O ring. 944 */ 945 static void 946 xbdback_thread(void *arg) 947 { 948 struct xbdback_instance *xbdi = arg; 949 void *obj; 950 951 mutex_enter(&xbdi->xbdi_lock); 952 for (;;) { 953 switch (xbdi->xbdi_status) { 954 case WAITING: 955 cv_wait(&xbdi->xbdi_cv, &xbdi->xbdi_lock); 956 break; 957 case RUN: 958 xbdi->xbdi_status = WAITING; /* reset state */ 959 obj = xbdi; 960 if (xbdi->xbdi_cont_restart != NULL) { 961 KASSERT(xbdi->xbdi_cont == NULL); 962 xbdi->xbdi_cont = xbdi->xbdi_cont_restart; 963 obj = xbdi->xbdi_cont_restart_obj; 964 xbdi->xbdi_cont_restart = NULL; 965 xbdi->xbdi_cont_restart_obj = NULL; 966 } 967 if (xbdi->xbdi_cont == NULL) { 968 xbdi->xbdi_cont = xbdback_co_main; 969 } 970 971 xbdback_trampoline(xbdi, obj); 972 break; 973 case DISCONNECTING: 974 if (xbdi->xbdi_pendingreqs > 0) { 975 /* there are pending I/Os. Wait for them. */ 976 cv_wait(&xbdi->xbdi_cv, &xbdi->xbdi_lock); 977 continue; 978 } 979 980 /* All I/Os should have been processed by now, 981 * xbdi_refcnt should drop to 0 */ 982 xbdi_put(xbdi); 983 KASSERT(xbdi->xbdi_refcnt == 0); 984 goto out; 985 /* NOTREACHED */ 986 default: 987 panic("%s: invalid state %d", 988 xbdi->xbdi_name, xbdi->xbdi_status); 989 } 990 } 991 out: 992 mutex_exit(&xbdi->xbdi_lock); 993 994 kthread_exit(0); 995 } 996 997 static void * 998 xbdback_co_main(struct xbdback_instance *xbdi, void *obj) 999 { 1000 (void)obj; 1001 1002 xbdi->xbdi_req_prod = xbdi->xbdi_ring.ring_n.sring->req_prod; 1003 xen_rmb(); /* ensure we see all requests up to req_prod */ 1004 /* 1005 * note that we'll eventually get a full ring of request. 1006 * in this case, MASK_BLKIF_IDX(req_cons) == MASK_BLKIF_IDX(req_prod) 1007 */ 1008 xbdi->xbdi_cont = xbdback_co_main_loop; 1009 return xbdi; 1010 } 1011 1012 /* 1013 * Fetch a blkif request from the ring, and pass control to the appropriate 1014 * continuation. 1015 * If someone asked for disconnection, do not fetch any more request from 1016 * the ring. 1017 */ 1018 static void * 1019 xbdback_co_main_loop(struct xbdback_instance *xbdi, void *obj __unused) 1020 { 1021 blkif_request_t *req, *reqn; 1022 blkif_x86_32_request_t *req32; 1023 blkif_x86_64_request_t *req64; 1024 blkif_request_indirect_t *rinn; 1025 blkif_x86_32_request_indirect_t *rin32; 1026 blkif_x86_64_request_indirect_t *rin64; 1027 1028 if (xbdi->xbdi_ring.ring_n.req_cons != xbdi->xbdi_req_prod) { 1029 struct xbdback_io *xbd_io = xbdback_io_get(xbdi); 1030 uint8_t real_op = 0xff; 1031 1032 if (xbd_io == NULL) { 1033 /* retry after iodone */ 1034 xbdi->xbdi_cont = NULL; 1035 return NULL; 1036 } 1037 memset(&xbd_io->u, 0, sizeof(xbd_io->u)); 1038 1039 buf_init(&xbd_io->xio_buf); 1040 xbd_io->xio_xbdi = xbdi; 1041 1042 req = &xbd_io->xio_xen_req; 1043 memset(req, 0, sizeof(*req)); 1044 1045 switch(xbdi->xbdi_proto) { 1046 case XBDIP_NATIVE: 1047 reqn = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_n, 1048 xbdi->xbdi_ring.ring_n.req_cons); 1049 real_op = req->operation = reqn->operation; 1050 if (real_op == BLKIF_OP_INDIRECT) { 1051 rinn = (blkif_request_indirect_t *)reqn; 1052 real_op = rinn->indirect_op; 1053 } 1054 req->id = reqn->id; 1055 break; 1056 case XBDIP_32: 1057 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32, 1058 xbdi->xbdi_ring.ring_n.req_cons); 1059 real_op = req->operation = req32->operation; 1060 if (real_op == BLKIF_OP_INDIRECT) { 1061 rin32 = (blkif_x86_32_request_indirect_t*)req32; 1062 real_op = rin32->indirect_op; 1063 } 1064 req->id = req32->id; 1065 break; 1066 case XBDIP_64: 1067 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64, 1068 xbdi->xbdi_ring.ring_n.req_cons); 1069 real_op = req->operation = req64->operation; 1070 if (real_op == BLKIF_OP_INDIRECT) { 1071 rin64 = (blkif_x86_64_request_indirect_t*)req64; 1072 real_op = rin64->indirect_op; 1073 } 1074 req->id = req64->id; 1075 break; 1076 } 1077 __insn_barrier(); 1078 XENPRINTF(("xbdback op %d req_cons 0x%x req_prod 0x%x " 1079 "resp_prod 0x%x id %" PRIu64 "\n", req->operation, 1080 xbdi->xbdi_ring.ring_n.req_cons, 1081 xbdi->xbdi_req_prod, 1082 xbdi->xbdi_ring.ring_n.rsp_prod_pvt, 1083 req->id)); 1084 switch (req->operation) { 1085 case BLKIF_OP_INDIRECT: 1086 /* just check indirect_op, rest is handled later */ 1087 if (real_op != BLKIF_OP_READ && 1088 real_op != BLKIF_OP_WRITE) { 1089 if (ratecheck(&xbdi->xbdi_lasterr_time, 1090 &xbdback_err_intvl)) { 1091 printf("%s: unknown ind operation %d\n", 1092 xbdi->xbdi_name, 1093 real_op); 1094 } 1095 goto fail; 1096 } 1097 /* FALLTHROUGH */ 1098 case BLKIF_OP_READ: 1099 case BLKIF_OP_WRITE: 1100 xbdi->xbdi_cont = xbdback_co_io; 1101 return xbd_io; 1102 case BLKIF_OP_FLUSH_DISKCACHE: 1103 xbdi->xbdi_cont = xbdback_co_cache_flush; 1104 return xbd_io; 1105 default: 1106 if (ratecheck(&xbdi->xbdi_lasterr_time, 1107 &xbdback_err_intvl)) { 1108 printf("%s: unknown operation %d\n", 1109 xbdi->xbdi_name, req->operation); 1110 } 1111 fail: 1112 xbdback_send_reply(xbdi, req->id, real_op, 1113 BLKIF_RSP_ERROR); 1114 xbdi->xbdi_cont = xbdback_co_main_incr; 1115 return xbdi; 1116 } 1117 } else { 1118 xbdi->xbdi_cont = xbdback_co_main_done2; 1119 return xbdi; 1120 } 1121 } 1122 1123 /* 1124 * Increment consumer index and move on to the next request. In case 1125 * we want to disconnect, leave continuation now. 1126 */ 1127 static void * 1128 xbdback_co_main_incr(struct xbdback_instance *xbdi, void *obj __unused) 1129 { 1130 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1131 1132 blkif_back_ring_t *ring = &xbdi->xbdi_ring.ring_n; 1133 1134 ring->req_cons++; 1135 1136 if (xbdi->xbdi_status == DISCONNECTING) 1137 xbdi->xbdi_cont = NULL; 1138 else 1139 xbdi->xbdi_cont = xbdback_co_main_loop; 1140 1141 return xbdi; 1142 } 1143 1144 /* 1145 * Check for requests in the instance's ring. In case there are, start again 1146 * from the beginning. If not, stall. 1147 */ 1148 static void * 1149 xbdback_co_main_done2(struct xbdback_instance *xbdi, void *obj) 1150 { 1151 int work_to_do; 1152 1153 xen_wmb(); 1154 RING_FINAL_CHECK_FOR_REQUESTS(&xbdi->xbdi_ring.ring_n, work_to_do); 1155 if (work_to_do) 1156 xbdi->xbdi_cont = xbdback_co_main; 1157 else 1158 xbdi->xbdi_cont = NULL; 1159 1160 return xbdi; 1161 } 1162 1163 /* 1164 * Frontend requested a cache flush operation. 1165 */ 1166 static void * 1167 xbdback_co_cache_flush(struct xbdback_instance *xbdi, void *obj) 1168 { 1169 struct xbdback_io *xbd_io = obj; 1170 KASSERT(xbd_io->xio_xen_req.operation == BLKIF_OP_FLUSH_DISKCACHE); 1171 if (xbdi->xbdi_pendingreqs > 0) { 1172 /* 1173 * There are pending requests. 1174 * Event or iodone() will restart processing 1175 */ 1176 xbdi->xbdi_cont_restart = xbdback_co_cache_flush; 1177 xbdi->xbdi_cont_restart_obj = xbd_io; 1178 xbdi->xbdi_cont = NULL; 1179 return NULL; 1180 } 1181 xbdi_get(xbdi); 1182 xbdi->xbdi_cont = xbdback_co_do_io; 1183 return xbd_io; 1184 } 1185 1186 /* 1187 * A read or write I/O request must be processed. Do some checks first, 1188 * then get the segment information directly from the ring request. 1189 */ 1190 static void * 1191 xbdback_co_io(struct xbdback_instance *xbdi, void *obj) 1192 { 1193 int i, error; 1194 blkif_request_t *req, *reqn; 1195 blkif_x86_32_request_t *req32; 1196 blkif_x86_64_request_t *req64; 1197 blkif_request_indirect_t *rinn; 1198 blkif_x86_32_request_indirect_t *rin32; 1199 blkif_x86_64_request_indirect_t *rin64; 1200 const char *errstr; 1201 struct xbdback_io *xbd_io = obj; 1202 grant_ref_t in_gntref = 0; 1203 1204 req = &xbd_io->xio_xen_req; 1205 1206 /* some sanity checks */ 1207 KASSERT(req->operation == BLKIF_OP_READ || 1208 req->operation == BLKIF_OP_WRITE || 1209 req->operation == BLKIF_OP_INDIRECT); 1210 1211 /* copy request segments */ 1212 switch (xbdi->xbdi_proto) { 1213 case XBDIP_NATIVE: 1214 reqn = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_n, 1215 xbdi->xbdi_ring.ring_n.req_cons); 1216 req->handle = reqn->handle; 1217 req->sector_number = reqn->sector_number; 1218 if (reqn->operation == BLKIF_OP_INDIRECT) { 1219 rinn = (blkif_request_indirect_t *)reqn; 1220 req->operation = rinn->indirect_op; 1221 req->nr_segments = (uint8_t)rinn->nr_segments; 1222 if (req->nr_segments > VBD_MAX_INDIRECT_SEGMENTS) { 1223 errstr = "too many indirect segments"; 1224 goto bad_segments; 1225 } 1226 in_gntref = rinn->indirect_grefs[0]; 1227 /* first_sect and segment grefs fetched later */ 1228 } else { 1229 req->nr_segments = reqn->nr_segments; 1230 if (req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) { 1231 errstr = "too many segments"; 1232 goto bad_segments; 1233 } 1234 for (i = 0; i < req->nr_segments; i++) 1235 xbd_io->xio_seg[i] = reqn->seg[i]; 1236 } 1237 break; 1238 case XBDIP_32: 1239 req32 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_32, 1240 xbdi->xbdi_ring.ring_n.req_cons); 1241 req->handle = req32->handle; 1242 req->sector_number = req32->sector_number; 1243 if (req32->operation == BLKIF_OP_INDIRECT) { 1244 rin32 = (blkif_x86_32_request_indirect_t *)req32; 1245 req->operation = rin32->indirect_op; 1246 req->nr_segments = (uint8_t)rin32->nr_segments; 1247 if (req->nr_segments > VBD_MAX_INDIRECT_SEGMENTS) { 1248 errstr = "too many indirect segments"; 1249 goto bad_segments; 1250 } 1251 in_gntref = rin32->indirect_grefs[0]; 1252 /* first_sect and segment grefs fetched later */ 1253 } else { 1254 req->nr_segments = req32->nr_segments; 1255 if (req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) { 1256 errstr = "too many segments"; 1257 goto bad_segments; 1258 } 1259 for (i = 0; i < req->nr_segments; i++) 1260 xbd_io->xio_seg[i] = req32->seg[i]; 1261 } 1262 break; 1263 case XBDIP_64: 1264 req64 = RING_GET_REQUEST(&xbdi->xbdi_ring.ring_64, 1265 xbdi->xbdi_ring.ring_n.req_cons); 1266 req->handle = req64->handle; 1267 req->sector_number = req64->sector_number; 1268 if (req64->operation == BLKIF_OP_INDIRECT) { 1269 rin64 = (blkif_x86_64_request_indirect_t *)req64; 1270 req->nr_segments = (uint8_t)rin64->nr_segments; 1271 if (req->nr_segments > VBD_MAX_INDIRECT_SEGMENTS) { 1272 errstr = "too many indirect segments"; 1273 goto bad_segments; 1274 } 1275 in_gntref = rin64->indirect_grefs[0]; 1276 /* first_sect and segment grefs fetched later */ 1277 } else { 1278 req->nr_segments = req64->nr_segments; 1279 if (req->nr_segments > BLKIF_MAX_SEGMENTS_PER_REQUEST) { 1280 errstr = "too many segments"; 1281 goto bad_segments; 1282 } 1283 for (i = 0; i < req->nr_segments; i++) 1284 xbd_io->xio_seg[i] = req64->seg[i]; 1285 } 1286 break; 1287 } 1288 1289 if (req->operation == BLKIF_OP_WRITE) { 1290 if (xbdi->xbdi_ro) { 1291 error = EROFS; 1292 goto end; 1293 } 1294 } 1295 1296 /* Max value checked already earlier */ 1297 if (req->nr_segments < 1) { 1298 errstr = "invalid number of segments"; 1299 goto bad_segments; 1300 } 1301 1302 /* If segments are on an indirect page, copy them now */ 1303 if (in_gntref) { 1304 gnttab_copy_t gop; 1305 paddr_t ma; 1306 1307 gop.flags = GNTCOPY_source_gref; 1308 gop.len = req->nr_segments 1309 * sizeof(struct blkif_request_segment); 1310 1311 gop.source.u.ref = in_gntref; 1312 gop.source.offset = 0; 1313 gop.source.domid = xbdi->xbdi_domid; 1314 1315 ma = xbd_io->xio_seg_dmamap->dm_segs[0].ds_addr; 1316 gop.dest.offset = ma & PAGE_MASK; 1317 gop.dest.domid = DOMID_SELF; 1318 gop.dest.u.gmfn = ma >> PAGE_SHIFT; 1319 1320 if (HYPERVISOR_grant_table_op(GNTTABOP_copy, &gop, 1) != 0) { 1321 errstr = "GNTTABOP_copy failed"; 1322 goto bad_segments; 1323 } 1324 } 1325 1326 xbdi_get(xbdi); 1327 xbdi->xbdi_cont = xbdback_co_io_gotio; 1328 return xbd_io; 1329 1330 bad_segments: 1331 if (ratecheck(&xbdi->xbdi_lasterr_time, &xbdback_err_intvl)) { 1332 printf("%s: %s\n", xbdi->xbdi_name, errstr); 1333 } 1334 error = EINVAL; 1335 /* FALLTHROUGH */ 1336 1337 end: 1338 xbdback_send_reply(xbdi, req->id, req->operation, 1339 (error == EROFS) ? BLKIF_RSP_EOPNOTSUPP : BLKIF_RSP_ERROR); 1340 xbdi->xbdi_cont = xbdback_co_main_incr; 1341 return xbdi; 1342 } 1343 1344 /* Prepare an I/O buffer for a xbdback instance */ 1345 static void * 1346 xbdback_co_io_gotio(struct xbdback_instance *xbdi, void *obj) 1347 { 1348 struct xbdback_io *xbd_io = obj; 1349 int buf_flags; 1350 size_t bcount; 1351 blkif_request_t *req = &xbd_io->xio_xen_req; 1352 uint8_t last_sect; 1353 int error; 1354 1355 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1356 KASSERT(xbdi->xbdi_refcnt > 0); 1357 1358 /* Process segments */ 1359 bcount = 0; 1360 for (int i = 0; i < req->nr_segments; i++) { 1361 struct blkif_request_segment *seg = &xbd_io->xio_seg[i]; 1362 if (seg->last_sect > VBD_MAXSECT || 1363 seg->first_sect > VBD_MAXSECT) { 1364 if (ratecheck(&xbdi->xbdi_lasterr_time, 1365 &xbdback_err_intvl)) { 1366 printf("%s: invalid segment sectors %d %d\n", 1367 xbdi->xbdi_name, 1368 seg->first_sect, seg->last_sect); 1369 } 1370 xbdi->xbdi_pendingreqs++; /* xbdback_io_error will -- */ 1371 xbd_io->xio_need_bounce = 0; /* bouncebuf not setup yet */ 1372 xbdback_io_error(xbd_io, EINVAL); 1373 /* do not retry */ 1374 xbdi->xbdi_cont = xbdback_co_main_incr; 1375 return xbdi; 1376 } 1377 1378 if (i > 0) { 1379 if (last_sect != VBD_MAXSECT || 1380 seg->first_sect != 0) { 1381 xbd_io->xio_need_bounce = 1; 1382 } 1383 } 1384 last_sect = seg->last_sect; 1385 xbd_io->xio_gref[i] = seg->gref; 1386 bcount += (seg->last_sect - seg->first_sect + 1) 1387 * VBD_BSIZE; 1388 } 1389 xbd_io->xio_start_offset = xbd_io->xio_seg[0].first_sect * VBD_BSIZE; 1390 1391 KASSERT(bcount <= MAXPHYS); 1392 KASSERT(xbd_io->xio_start_offset < PAGE_SIZE); 1393 KASSERT(bcount + xbd_io->xio_start_offset <= VBD_VA_SIZE); 1394 1395 /* Fill-in the buf */ 1396 if (req->operation == BLKIF_OP_WRITE) { 1397 buf_flags = B_WRITE; 1398 } else { 1399 buf_flags = B_READ; 1400 } 1401 1402 xbd_io->xio_buf.b_flags = buf_flags; 1403 xbd_io->xio_buf.b_cflags = 0; 1404 xbd_io->xio_buf.b_oflags = 0; 1405 xbd_io->xio_buf.b_iodone = xbdback_iodone; 1406 xbd_io->xio_buf.b_proc = NULL; 1407 xbd_io->xio_buf.b_vp = xbdi->xbdi_vp; 1408 xbd_io->xio_buf.b_objlock = xbdi->xbdi_vp->v_interlock; 1409 xbd_io->xio_buf.b_dev = xbdi->xbdi_dev; 1410 xbd_io->xio_buf.b_blkno = req->sector_number; 1411 xbd_io->xio_buf.b_bcount = bcount; 1412 if (__predict_false(xbd_io->xio_need_bounce)) { 1413 if (__predict_false(xbdi->xbdi_bouncebuf_use)) { 1414 KASSERT(xbdi->xbdi_pendingreqs > 0); 1415 /* retry later */ 1416 xbdi->xbdi_cont_restart = xbdback_co_io_gotio; 1417 xbdi->xbdi_cont_restart_obj = xbd_io; 1418 xbdi->xbdi_cont = NULL; 1419 return NULL; 1420 } 1421 xbdi->xbdi_bouncebuf_use++; 1422 KASSERT(xbdi->xbdi_bouncebuf_use == 1); 1423 xbd_io->xio_buf.b_data = (void *)xbdi->xbdi_bouncebuf; 1424 } 1425 xbdi->xbdi_pendingreqs++; 1426 if ((error = xbdback_map_shm(xbd_io)) != 0) { 1427 xbdback_io_error(xbd_io, error); 1428 /* do not retry */ 1429 xbdi->xbdi_cont = xbdback_co_main_incr; 1430 return xbdi; 1431 } 1432 if (__predict_true(xbd_io->xio_need_bounce == 0)) { 1433 xbd_io->xio_buf.b_data = (void *) 1434 (xbd_io->xio_vaddr + xbd_io->xio_start_offset); 1435 } 1436 1437 1438 xbd_io->xio_buf.b_private = xbd_io; 1439 1440 xbdi->xbdi_cont = xbdback_co_do_io; 1441 return xbd_io; 1442 } 1443 1444 static void 1445 xbdback_io_error(struct xbdback_io *xbd_io, int error) 1446 { 1447 KASSERT(mutex_owned(&xbd_io->xio_xbdi->xbdi_lock)); 1448 1449 struct buf *bp = &xbd_io->xio_buf; 1450 1451 bp->b_error = error; 1452 xbdback_iodone_locked(xbd_io->xio_xbdi, xbd_io, bp); 1453 } 1454 1455 /* 1456 * Main xbdback I/O routine. It can either perform a flush operation or 1457 * schedule a read/write operation. 1458 */ 1459 static void * 1460 xbdback_co_do_io(struct xbdback_instance *xbdi, void *obj) 1461 { 1462 struct xbdback_io *xbd_io = obj; 1463 blkif_request_t *req = &xbd_io->xio_xen_req; 1464 1465 KASSERT(xbdi->xbdi_refcnt > 0); 1466 1467 switch (req->operation) { 1468 case BLKIF_OP_FLUSH_DISKCACHE: 1469 { 1470 int error; 1471 int force = 1; 1472 1473 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1474 mutex_exit(&xbdi->xbdi_lock); 1475 error = VOP_IOCTL(xbdi->xbdi_vp, DIOCCACHESYNC, &force, FWRITE, 1476 kauth_cred_get()); 1477 mutex_enter(&xbdi->xbdi_lock); 1478 if (error) { 1479 printf("xbdback %s: DIOCCACHESYNC returned %d\n", 1480 xbdi->xbdi_xbusd->xbusd_path, error); 1481 if (error == EOPNOTSUPP || error == ENOTTY) 1482 error = BLKIF_RSP_EOPNOTSUPP; 1483 else 1484 error = BLKIF_RSP_ERROR; 1485 } else 1486 error = BLKIF_RSP_OKAY; 1487 xbdback_send_reply(xbdi, req->id, req->operation, error); 1488 xbdback_io_put(xbdi, xbd_io); 1489 xbdi_put(xbdi); 1490 xbdi->xbdi_cont = xbdback_co_main_incr; 1491 return xbdi; 1492 } 1493 case BLKIF_OP_READ: 1494 case BLKIF_OP_WRITE: 1495 if (__predict_false(xbd_io->xio_need_bounce) && 1496 req->operation == BLKIF_OP_WRITE) { 1497 vaddr_t boffset = 0; 1498 for (int i = 0; i < req->nr_segments; i++) { 1499 struct blkif_request_segment *seg = 1500 &xbd_io->xio_seg[i]; 1501 vaddr_t segoffset = seg->first_sect * VBD_BSIZE; 1502 size_t segbcount = 1503 (seg->last_sect - seg->first_sect + 1) * 1504 VBD_BSIZE; 1505 KASSERT(segoffset + segbcount <= PAGE_SIZE); 1506 KASSERT(boffset + segbcount < MAXPHYS); 1507 segoffset += PAGE_SIZE * i; 1508 memcpy( 1509 (void *)(xbdi->xbdi_bouncebuf + boffset), 1510 (void *)(xbd_io->xio_vaddr + segoffset), 1511 segbcount); 1512 boffset += segbcount; 1513 } 1514 } 1515 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1516 mutex_exit(&xbdi->xbdi_lock); 1517 if ((xbd_io->xio_buf.b_flags & B_READ) == 0) { 1518 mutex_enter(xbd_io->xio_buf.b_vp->v_interlock); 1519 xbd_io->xio_buf.b_vp->v_numoutput++; 1520 mutex_exit(xbd_io->xio_buf.b_vp->v_interlock); 1521 } 1522 /* will call xbdback_iodone() asynchronously when done */ 1523 bdev_strategy(&xbd_io->xio_buf); 1524 mutex_enter(&xbdi->xbdi_lock); 1525 xbdi->xbdi_cont = xbdback_co_main_incr; 1526 return xbdi; 1527 default: 1528 /* Should never happen */ 1529 panic("xbdback_co_do_io: unsupported operation %d", 1530 req->operation); 1531 } 1532 } 1533 1534 /* 1535 * Called from softint(9) context when an I/O is done: for each request, send 1536 * back the associated reply to the domain. 1537 */ 1538 static void 1539 xbdback_iodone(struct buf *bp) 1540 { 1541 struct xbdback_io *xbd_io; 1542 struct xbdback_instance *xbdi; 1543 1544 xbd_io = bp->b_private; 1545 KASSERT(bp == &xbd_io->xio_buf); 1546 xbdi = xbd_io->xio_xbdi; 1547 1548 mutex_enter(&xbdi->xbdi_lock); 1549 xbdback_iodone_locked(xbdi, xbd_io, bp); 1550 mutex_exit(&xbdi->xbdi_lock); 1551 } 1552 1553 /* 1554 * This gets reused by xbdback_io_error to report errors from other sources. 1555 */ 1556 static void 1557 xbdback_iodone_locked(struct xbdback_instance *xbdi, struct xbdback_io *xbd_io, 1558 struct buf *bp) 1559 { 1560 int status; 1561 blkif_request_t *req = &xbd_io->xio_xen_req; 1562 1563 XENPRINTF(("xbdback_io domain %d: iodone ptr 0x%lx\n", 1564 xbdi->xbdi_domid, (long)xbd_io)); 1565 1566 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1567 1568 KASSERT(bp->b_error != 0 || xbd_io->xio_xv != NULL); 1569 if (__predict_false(xbd_io->xio_need_bounce)) { 1570 KASSERT(xbd_io->xio_buf.b_data == (void *)xbdi->xbdi_bouncebuf); 1571 1572 KASSERT(req->operation == BLKIF_OP_WRITE || 1573 req->operation == BLKIF_OP_READ); 1574 1575 if (req->operation == BLKIF_OP_READ && bp->b_error == 0) { 1576 vaddr_t boffset = 0; 1577 for (int i = 0; i < req->nr_segments; i++) { 1578 struct blkif_request_segment *seg = 1579 &xbd_io->xio_seg[i]; 1580 vaddr_t segoffset = seg->first_sect * VBD_BSIZE; 1581 size_t segbcount = 1582 (seg->last_sect - seg->first_sect + 1) * 1583 VBD_BSIZE; 1584 KASSERT(segoffset + segbcount <= PAGE_SIZE); 1585 KASSERT(boffset + segbcount < MAXPHYS); 1586 segoffset += PAGE_SIZE * i; 1587 memcpy( 1588 (void *)(xbd_io->xio_vaddr + segoffset), 1589 (void *)(xbdi->xbdi_bouncebuf + boffset), 1590 segbcount); 1591 boffset += segbcount; 1592 } 1593 } 1594 KASSERT(xbdi->xbdi_bouncebuf_use == 1); 1595 xbdi->xbdi_bouncebuf_use--; 1596 } 1597 if (xbd_io->xio_xv != NULL) 1598 xbdback_unmap_shm(xbd_io); 1599 1600 if (bp->b_error != 0) { 1601 printf("xbd IO domain %d: error %d\n", 1602 xbdi->xbdi_domid, bp->b_error); 1603 status = BLKIF_RSP_ERROR; 1604 } else 1605 status = BLKIF_RSP_OKAY; 1606 1607 xbdback_send_reply(xbdi, req->id, req->operation, status); 1608 1609 xbdi_put(xbdi); 1610 KASSERT(xbdi->xbdi_pendingreqs > 0); 1611 xbdi->xbdi_pendingreqs--; 1612 buf_destroy(&xbd_io->xio_buf); 1613 xbdback_io_put(xbdi, xbd_io); 1614 1615 xbdback_wakeup_thread(xbdi); 1616 } 1617 1618 /* 1619 * Wake up the per xbdback instance thread. 1620 */ 1621 static void 1622 xbdback_wakeup_thread(struct xbdback_instance *xbdi) 1623 { 1624 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1625 1626 /* only set RUN state when we are WAITING for work */ 1627 if (xbdi->xbdi_status == WAITING) 1628 xbdi->xbdi_status = RUN; 1629 cv_signal(&xbdi->xbdi_cv); 1630 } 1631 1632 /* 1633 * called once a request has completed. Place the reply in the ring and 1634 * notify the guest OS. 1635 */ 1636 static void 1637 xbdback_send_reply(struct xbdback_instance *xbdi, uint64_t id, 1638 int op, int status) 1639 { 1640 blkif_response_t *resp_n; 1641 blkif_x86_32_response_t *resp32; 1642 blkif_x86_64_response_t *resp64; 1643 int notify; 1644 1645 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1646 1647 /* 1648 * The ring can be accessed by the xbdback thread, xbdback_iodone() 1649 * handler, or any handler that triggered the shm callback. So 1650 * protect ring access via the xbdi_lock mutex. 1651 */ 1652 switch (xbdi->xbdi_proto) { 1653 case XBDIP_NATIVE: 1654 resp_n = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_n, 1655 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1656 resp_n->id = id; 1657 resp_n->operation = op; 1658 resp_n->status = status; 1659 break; 1660 case XBDIP_32: 1661 resp32 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_32, 1662 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1663 resp32->id = id; 1664 resp32->operation = op; 1665 resp32->status = status; 1666 break; 1667 case XBDIP_64: 1668 resp64 = RING_GET_RESPONSE(&xbdi->xbdi_ring.ring_64, 1669 xbdi->xbdi_ring.ring_n.rsp_prod_pvt); 1670 resp64->id = id; 1671 resp64->operation = op; 1672 resp64->status = status; 1673 break; 1674 } 1675 xbdi->xbdi_ring.ring_n.rsp_prod_pvt++; 1676 RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&xbdi->xbdi_ring.ring_n, notify); 1677 1678 if (notify) { 1679 XENPRINTF(("xbdback_send_reply notify %d\n", xbdi->xbdi_domid)); 1680 hypervisor_notify_via_evtchn(xbdi->xbdi_evtchn); 1681 } 1682 } 1683 1684 /* 1685 * Map multiple entries of an I/O request into backend's VA space. 1686 * The xbd_io->xio_gref array has to be filled out by the caller. 1687 */ 1688 static int 1689 xbdback_map_shm(struct xbdback_io *xbd_io) 1690 { 1691 struct xbdback_instance *xbdi = xbd_io->xio_xbdi; 1692 blkif_request_t *req = &xbd_io->xio_xen_req; 1693 int error; 1694 1695 #ifdef XENDEBUG_VBD 1696 int i; 1697 printf("xbdback_map_shm map grant "); 1698 for (i = 0; i < req->nr_segments; i++) { 1699 printf("%u ", (u_int)xbd_io->xio_gref[i]); 1700 } 1701 #endif 1702 1703 KASSERT(mutex_owned(&xbdi->xbdi_lock)); 1704 KASSERT(xbd_io->xio_xv == NULL); 1705 1706 xbd_io->xio_xv = SLIST_FIRST(&xbdi->xbdi_va_free); 1707 KASSERT(xbd_io->xio_xv != NULL); 1708 SLIST_REMOVE_HEAD(&xbdi->xbdi_va_free, xv_next); 1709 xbd_io->xio_vaddr = xbd_io->xio_xv->xv_vaddr; 1710 1711 error = xen_shm_map(req->nr_segments, xbdi->xbdi_domid, 1712 xbd_io->xio_gref, xbd_io->xio_vaddr, xbd_io->xio_gh, 1713 (req->operation == BLKIF_OP_WRITE) ? XSHM_RO : 0); 1714 1715 switch(error) { 1716 case 0: 1717 #ifdef XENDEBUG_VBD 1718 printf("handle"); 1719 for (i = 0; i < req->nr_segments; i++) { 1720 printf(" %u ", (u_int)xbd_io->xio_gh[i]); 1721 } 1722 printf("\n"); 1723 #endif 1724 return 0; 1725 default: 1726 /* reset xio_xv so error handling won't try to unmap it */ 1727 SLIST_INSERT_HEAD(&xbdi->xbdi_va_free, xbd_io->xio_xv, xv_next); 1728 xbd_io->xio_xv = NULL; 1729 return error; 1730 } 1731 } 1732 1733 /* unmap a request from our virtual address space (request is done) */ 1734 static void 1735 xbdback_unmap_shm(struct xbdback_io *xbd_io) 1736 { 1737 struct xbdback_instance *xbdi = xbd_io->xio_xbdi; 1738 blkif_request_t *req = &xbd_io->xio_xen_req; 1739 1740 #ifdef XENDEBUG_VBD 1741 int i; 1742 printf("xbdback_unmap_shm handle "); 1743 for (i = 0; i < req->nr_segments; i++) { 1744 printf("%u ", (u_int)xbd_io->xio_gh[i]); 1745 } 1746 printf("\n"); 1747 #endif 1748 1749 KASSERT(xbd_io->xio_xv != NULL); 1750 xen_shm_unmap(xbd_io->xio_vaddr, req->nr_segments, 1751 xbd_io->xio_gh); 1752 SLIST_INSERT_HEAD(&xbdi->xbdi_va_free, xbd_io->xio_xv, xv_next); 1753 xbd_io->xio_xv = NULL; 1754 xbd_io->xio_vaddr = -1; 1755 } 1756 1757 /* Obtain memory from a pool */ 1758 static struct xbdback_io * 1759 xbdback_io_get(struct xbdback_instance *xbdi) 1760 { 1761 struct xbdback_io *xbd_io = SLIST_FIRST(&xbdi->xbdi_io_free); 1762 SLIST_REMOVE_HEAD(&xbdi->xbdi_io_free, xio_next); 1763 return xbd_io; 1764 } 1765 1766 /* Restore memory to a pool */ 1767 static void 1768 xbdback_io_put(struct xbdback_instance *xbdi, struct xbdback_io *xbd_io) 1769 { 1770 KASSERT(xbd_io->xio_xv == NULL); 1771 KASSERT(xbd_io != NULL); 1772 SLIST_INSERT_HEAD(&xbdi->xbdi_io_free, xbd_io, xio_next); 1773 } 1774 1775 /* 1776 * Trampoline routine. Calls continuations in a loop and only exits when 1777 * either the returned object or the next callback is NULL. 1778 */ 1779 static void 1780 xbdback_trampoline(struct xbdback_instance *xbdi, void *obj) 1781 { 1782 xbdback_cont_t cont; 1783 1784 while(obj != NULL && xbdi->xbdi_cont != NULL) { 1785 KASSERT(xbdi->xbdi_cont_restart == NULL); 1786 KASSERT(xbdi->xbdi_cont_restart_obj == NULL); 1787 cont = xbdi->xbdi_cont; 1788 #ifdef DIAGNOSTIC 1789 xbdi->xbdi_cont = (xbdback_cont_t)0xDEADBEEF; 1790 #endif 1791 obj = (*cont)(xbdi, obj); 1792 #ifdef DIAGNOSTIC 1793 if (xbdi->xbdi_cont == (xbdback_cont_t)0xDEADBEEF) { 1794 printf("xbdback_trampoline: 0x%lx didn't set " 1795 "xbdi->xbdi_cont!\n", (long)cont); 1796 panic("xbdback_trampoline: bad continuation"); 1797 } 1798 if (xbdi->xbdi_cont_restart != NULL || 1799 xbdi->xbdi_cont_restart_obj != NULL) { 1800 KASSERT(xbdi->xbdi_cont_restart != NULL); 1801 KASSERT(xbdi->xbdi_cont_restart_obj != NULL); 1802 KASSERT(xbdi->xbdi_cont == NULL); 1803 KASSERT(obj == NULL); 1804 } 1805 #endif 1806 } 1807 } 1808