1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Note: This is the backend part of the split PV disk driver. This driver 29 * is not a nexus driver, nor is it a leaf driver(block/char/stream driver). 30 * Currently, it does not create any minor node. So, although, it runs in 31 * backend domain, it will not be used directly from within dom0. 32 * It simply gets block I/O requests issued by frontend from a shared page 33 * (blkif ring buffer - defined by Xen) between backend and frontend domain, 34 * generates a buf, and push it down to underlying disk target driver via 35 * ldi interface. When buf is done, this driver will generate a response 36 * and put it into ring buffer to inform frontend of the status of the I/O 37 * request issued by it. When a new virtual device entry is added in xenstore, 38 * there will be an watch event sent from Xen to xvdi framework, who will, 39 * in turn, create the devinfo node and try to attach this driver 40 * (see xvdi_create_dev). When frontend peer changes its state to 41 * XenbusStateClose, an event will also be sent from Xen to xvdi framework, 42 * who will detach and remove this devinfo node (see i_xvdi_oestate_handler). 43 * I/O requests get from ring buffer and event coming from xenstore cannot be 44 * trusted. We verify them in xdb_get_buf() and xdb_check_state_transition(). 45 * 46 * Virtual device configuration is read/written from/to the database via 47 * xenbus_* interfaces. Driver also use xvdi_* to interact with hypervisor. 48 * There is an on-going effort to make xvdi_* cover all xenbus_*. 49 */ 50 51 #include <sys/types.h> 52 #include <sys/conf.h> 53 #include <sys/ddi.h> 54 #include <sys/dditypes.h> 55 #include <sys/sunddi.h> 56 #include <sys/list.h> 57 #include <sys/dkio.h> 58 #include <sys/cmlb.h> 59 #include <sys/vtoc.h> 60 #include <sys/modctl.h> 61 #include <sys/bootconf.h> 62 #include <sys/promif.h> 63 #include <sys/sysmacros.h> 64 #include <public/io/xenbus.h> 65 #include <public/io/xs_wire.h> 66 #include <xen/sys/xenbus_impl.h> 67 #include <xen/sys/xendev.h> 68 #include <sys/gnttab.h> 69 #include <sys/scsi/generic/inquiry.h> 70 #include <vm/seg_kmem.h> 71 #include <vm/hat_i86.h> 72 #include <sys/gnttab.h> 73 #include <sys/lofi.h> 74 #include <io/xdf.h> 75 #include <xen/io/blkif_impl.h> 76 #include <io/xdb.h> 77 78 static xdb_t *xdb_statep; 79 static int xdb_debug = 0; 80 81 static void xdb_close(dev_info_t *); 82 static int xdb_push_response(xdb_t *, uint64_t, uint8_t, uint16_t); 83 static int xdb_get_request(xdb_t *, blkif_request_t *); 84 static void blkif_get_x86_32_req(blkif_request_t *, blkif_x86_32_request_t *); 85 static void blkif_get_x86_64_req(blkif_request_t *, blkif_x86_64_request_t *); 86 static int xdb_biodone(buf_t *); 87 88 89 #ifdef DEBUG 90 /* 91 * debug aid functions 92 */ 93 94 static void 95 logva(xdb_t *vdp, uint64_t va) 96 { 97 uint64_t *page_addrs; 98 int i; 99 100 page_addrs = vdp->page_addrs; 101 for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { 102 if (page_addrs[i] == va) 103 debug_enter("VA remapping found!"); 104 } 105 106 for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { 107 if (page_addrs[i] == 0) { 108 page_addrs[i] = va; 109 break; 110 } 111 } 112 ASSERT(i < XDB_MAX_IO_PAGES(vdp)); 113 } 114 115 static void 116 unlogva(xdb_t *vdp, uint64_t va) 117 { 118 uint64_t *page_addrs; 119 int i; 120 121 page_addrs = vdp->page_addrs; 122 for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) { 123 if (page_addrs[i] == va) { 124 page_addrs[i] = 0; 125 break; 126 } 127 } 128 ASSERT(i < XDB_MAX_IO_PAGES(vdp)); 129 } 130 131 static void 132 xdb_dump_request_oe(blkif_request_t *req) 133 { 134 int i; 135 136 /* 137 * Exploit the public interface definitions for BLKIF_OP_READ 138 * etc.. 139 */ 140 char *op_name[] = { "read", "write", "barrier", "flush" }; 141 142 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "op=%s", op_name[req->operation])); 143 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "num of segments=%d", 144 req->nr_segments)); 145 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "handle=%d", req->handle)); 146 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "id=%llu", 147 (unsigned long long)req->id)); 148 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "start sector=%llu", 149 (unsigned long long)req->sector_number)); 150 for (i = 0; i < req->nr_segments; i++) { 151 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "gref=%d, first sec=%d," 152 "last sec=%d", req->seg[i].gref, req->seg[i].first_sect, 153 req->seg[i].last_sect)); 154 } 155 } 156 #endif /* DEBUG */ 157 158 /* 159 * Statistics. 160 */ 161 static char *xdb_stats[] = { 162 "rd_reqs", 163 "wr_reqs", 164 "br_reqs", 165 "fl_reqs", 166 "oo_reqs" 167 }; 168 169 static int 170 xdb_kstat_update(kstat_t *ksp, int flag) 171 { 172 xdb_t *vdp; 173 kstat_named_t *knp; 174 175 if (flag != KSTAT_READ) 176 return (EACCES); 177 178 vdp = ksp->ks_private; 179 knp = ksp->ks_data; 180 181 /* 182 * Assignment order should match that of the names in 183 * xdb_stats. 184 */ 185 (knp++)->value.ui64 = vdp->xs_stat_req_reads; 186 (knp++)->value.ui64 = vdp->xs_stat_req_writes; 187 (knp++)->value.ui64 = vdp->xs_stat_req_barriers; 188 (knp++)->value.ui64 = vdp->xs_stat_req_flushes; 189 (knp++)->value.ui64 = 0; /* oo_req */ 190 191 return (0); 192 } 193 194 static boolean_t 195 xdb_kstat_init(xdb_t *vdp) 196 { 197 int nstat = sizeof (xdb_stats) / sizeof (xdb_stats[0]); 198 char **cp = xdb_stats; 199 kstat_named_t *knp; 200 201 if ((vdp->xs_kstats = kstat_create("xdb", 202 ddi_get_instance(vdp->xs_dip), 203 "req_statistics", "block", KSTAT_TYPE_NAMED, 204 nstat, 0)) == NULL) 205 return (B_FALSE); 206 207 vdp->xs_kstats->ks_private = vdp; 208 vdp->xs_kstats->ks_update = xdb_kstat_update; 209 210 knp = vdp->xs_kstats->ks_data; 211 while (nstat > 0) { 212 kstat_named_init(knp, *cp, KSTAT_DATA_UINT64); 213 knp++; 214 cp++; 215 nstat--; 216 } 217 218 kstat_install(vdp->xs_kstats); 219 220 return (B_TRUE); 221 } 222 223 static char * 224 i_pathname(dev_info_t *dip) 225 { 226 char *path, *rv; 227 228 path = kmem_alloc(MAXPATHLEN, KM_SLEEP); 229 (void) ddi_pathname(dip, path); 230 rv = strdup(path); 231 kmem_free(path, MAXPATHLEN); 232 233 return (rv); 234 } 235 236 static buf_t * 237 xdb_get_buf(xdb_t *vdp, blkif_request_t *req, xdb_request_t *xreq) 238 { 239 buf_t *bp; 240 uint8_t segs, curseg; 241 int sectors; 242 int i, err; 243 gnttab_map_grant_ref_t mapops[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 244 ddi_acc_handle_t acchdl; 245 246 acchdl = vdp->xs_ring_hdl; 247 bp = XDB_XREQ2BP(xreq); 248 curseg = xreq->xr_curseg; 249 /* init a new xdb request */ 250 if (req != NULL) { 251 ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); 252 boolean_t pagemapok = B_TRUE; 253 uint8_t op = ddi_get8(acchdl, &req->operation); 254 255 xreq->xr_vdp = vdp; 256 xreq->xr_op = op; 257 xreq->xr_id = ddi_get64(acchdl, &req->id); 258 segs = xreq->xr_buf_pages = ddi_get8(acchdl, &req->nr_segments); 259 if (segs == 0) { 260 if (op != BLKIF_OP_FLUSH_DISKCACHE) 261 cmn_err(CE_WARN, "!non-BLKIF_OP_FLUSH_DISKCACHE" 262 " is seen from domain %d with zero " 263 "length data buffer!", vdp->xs_peer); 264 bioinit(bp); 265 bp->b_bcount = 0; 266 bp->b_lblkno = 0; 267 bp->b_un.b_addr = NULL; 268 return (bp); 269 } else if (op == BLKIF_OP_FLUSH_DISKCACHE) { 270 cmn_err(CE_WARN, "!BLKIF_OP_FLUSH_DISKCACHE" 271 " is seen from domain %d with non-zero " 272 "length data buffer!", vdp->xs_peer); 273 } 274 275 /* 276 * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST 277 * according to the definition of blk interface by Xen 278 * we do sanity check here 279 */ 280 if (segs > BLKIF_MAX_SEGMENTS_PER_REQUEST) 281 segs = xreq->xr_buf_pages = 282 BLKIF_MAX_SEGMENTS_PER_REQUEST; 283 284 for (i = 0; i < segs; i++) { 285 uint8_t fs, ls; 286 287 mapops[i].host_addr = 288 (uint64_t)(uintptr_t)XDB_IOPAGE_VA( 289 vdp->xs_iopage_va, xreq->xr_idx, i); 290 mapops[i].dom = vdp->xs_peer; 291 mapops[i].ref = ddi_get32(acchdl, &req->seg[i].gref); 292 mapops[i].flags = GNTMAP_host_map; 293 if (op != BLKIF_OP_READ) 294 mapops[i].flags |= GNTMAP_readonly; 295 296 fs = ddi_get8(acchdl, &req->seg[i].first_sect); 297 ls = ddi_get8(acchdl, &req->seg[i].last_sect); 298 299 /* 300 * first_sect should be no bigger than last_sect and 301 * both of them should be no bigger than 302 * (PAGESIZE / XB_BSIZE - 1) according to definition 303 * of blk interface by Xen, so sanity check again 304 */ 305 if (fs > (PAGESIZE / XB_BSIZE - 1)) 306 fs = PAGESIZE / XB_BSIZE - 1; 307 if (ls > (PAGESIZE / XB_BSIZE - 1)) 308 ls = PAGESIZE / XB_BSIZE - 1; 309 if (fs > ls) 310 fs = ls; 311 312 xreq->xr_segs[i].fs = fs; 313 xreq->xr_segs[i].ls = ls; 314 } 315 316 /* map in io pages */ 317 err = xen_map_gref(GNTTABOP_map_grant_ref, mapops, i, B_FALSE); 318 if (err != 0) 319 return (NULL); 320 for (i = 0; i < segs; i++) { 321 /* 322 * Although HYPERVISOR_grant_table_op() returned no 323 * error, mapping of each single page can fail. So, 324 * we have to do the check here and handle the error 325 * if needed 326 */ 327 if (mapops[i].status != GNTST_okay) { 328 int j; 329 for (j = 0; j < i; j++) { 330 #ifdef DEBUG 331 unlogva(vdp, mapops[j].host_addr); 332 #endif 333 xen_release_pfn( 334 xreq->xr_plist[j].p_pagenum); 335 } 336 pagemapok = B_FALSE; 337 break; 338 } 339 /* record page mapping handle for unmapping later */ 340 xreq->xr_page_hdls[i] = mapops[i].handle; 341 #ifdef DEBUG 342 logva(vdp, mapops[i].host_addr); 343 #endif 344 /* 345 * Pass the MFNs down using the shadow list (xr_pplist) 346 * 347 * This is pretty ugly since we have implict knowledge 348 * of how the rootnex binds buffers. 349 * The GNTTABOP_map_grant_ref op makes us do some ugly 350 * stuff since we're not allowed to touch these PTEs 351 * from the VM. 352 * 353 * Obviously, these aren't real page_t's. The rootnex 354 * only needs p_pagenum. 355 * Also, don't use btop() here or 32 bit PAE breaks. 356 */ 357 xreq->xr_pplist[i] = &xreq->xr_plist[i]; 358 xreq->xr_plist[i].p_pagenum = 359 xen_assign_pfn(mapops[i].dev_bus_addr >> PAGESHIFT); 360 } 361 362 /* 363 * not all pages mapped in successfully, unmap those mapped-in 364 * page and return failure 365 */ 366 if (!pagemapok) { 367 gnttab_unmap_grant_ref_t unmapop; 368 369 for (i = 0; i < segs; i++) { 370 if (mapops[i].status != GNTST_okay) 371 continue; 372 unmapop.host_addr = 373 (uint64_t)(uintptr_t)XDB_IOPAGE_VA( 374 vdp->xs_iopage_va, xreq->xr_idx, i); 375 unmapop.dev_bus_addr = NULL; 376 unmapop.handle = mapops[i].handle; 377 (void) HYPERVISOR_grant_table_op( 378 GNTTABOP_unmap_grant_ref, &unmapop, 1); 379 } 380 381 return (NULL); 382 } 383 bioinit(bp); 384 bp->b_lblkno = ddi_get64(acchdl, &req->sector_number); 385 bp->b_flags = B_BUSY | B_SHADOW | B_PHYS; 386 bp->b_flags |= (ddi_get8(acchdl, &req->operation) == 387 BLKIF_OP_READ) ? B_READ : (B_WRITE | B_ASYNC); 388 } else { 389 uint64_t blkst; 390 int isread; 391 392 /* reuse this buf */ 393 blkst = bp->b_lblkno + bp->b_bcount / DEV_BSIZE; 394 isread = bp->b_flags & B_READ; 395 bioreset(bp); 396 bp->b_lblkno = blkst; 397 bp->b_flags = B_BUSY | B_SHADOW | B_PHYS; 398 bp->b_flags |= isread ? B_READ : (B_WRITE | B_ASYNC); 399 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "reuse buf, xreq is %d!!", 400 xreq->xr_idx)); 401 } 402 403 /* form a buf */ 404 bp->b_un.b_addr = XDB_IOPAGE_VA(vdp->xs_iopage_va, xreq->xr_idx, 405 curseg) + xreq->xr_segs[curseg].fs * DEV_BSIZE; 406 bp->b_shadow = &xreq->xr_pplist[curseg]; 407 bp->b_iodone = xdb_biodone; 408 sectors = 0; 409 for (i = curseg; i < xreq->xr_buf_pages; i++) { 410 /* 411 * The xreq->xr_segs[i].fs of the first seg can be non-zero 412 * otherwise, we'll break it into multiple bufs 413 */ 414 if ((i != curseg) && (xreq->xr_segs[i].fs != 0)) { 415 break; 416 } 417 sectors += (xreq->xr_segs[i].ls - xreq->xr_segs[i].fs + 1); 418 } 419 xreq->xr_curseg = i; 420 bp->b_bcount = sectors * DEV_BSIZE; 421 bp->b_bufsize = bp->b_bcount; 422 423 return (bp); 424 } 425 426 static xdb_request_t * 427 xdb_get_req(xdb_t *vdp) 428 { 429 xdb_request_t *req; 430 int idx; 431 432 ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); 433 ASSERT(vdp->xs_free_req != -1); 434 req = &vdp->xs_req[vdp->xs_free_req]; 435 vdp->xs_free_req = req->xr_next; 436 idx = req->xr_idx; 437 bzero(req, sizeof (xdb_request_t)); 438 req->xr_idx = idx; 439 return (req); 440 } 441 442 static void 443 xdb_free_req(xdb_request_t *req) 444 { 445 xdb_t *vdp = req->xr_vdp; 446 447 ASSERT(MUTEX_HELD(&vdp->xs_iomutex)); 448 req->xr_next = vdp->xs_free_req; 449 vdp->xs_free_req = req->xr_idx; 450 } 451 452 static void 453 xdb_response(xdb_t *vdp, blkif_request_t *req, boolean_t ok) 454 { 455 ddi_acc_handle_t acchdl = vdp->xs_ring_hdl; 456 457 if (xdb_push_response(vdp, ddi_get64(acchdl, &req->id), 458 ddi_get8(acchdl, &req->operation), ok)) 459 xvdi_notify_oe(vdp->xs_dip); 460 } 461 462 static void 463 xdb_init_ioreqs(xdb_t *vdp) 464 { 465 int i; 466 467 ASSERT(vdp->xs_nentry); 468 469 if (vdp->xs_req == NULL) 470 vdp->xs_req = kmem_alloc(vdp->xs_nentry * 471 sizeof (xdb_request_t), KM_SLEEP); 472 #ifdef DEBUG 473 if (vdp->page_addrs == NULL) 474 vdp->page_addrs = kmem_zalloc(XDB_MAX_IO_PAGES(vdp) * 475 sizeof (uint64_t), KM_SLEEP); 476 #endif 477 for (i = 0; i < vdp->xs_nentry; i++) { 478 vdp->xs_req[i].xr_idx = i; 479 vdp->xs_req[i].xr_next = i + 1; 480 } 481 vdp->xs_req[vdp->xs_nentry - 1].xr_next = -1; 482 vdp->xs_free_req = 0; 483 484 /* alloc va in host dom for io page mapping */ 485 vdp->xs_iopage_va = vmem_xalloc(heap_arena, 486 XDB_MAX_IO_PAGES(vdp) * PAGESIZE, PAGESIZE, 0, 0, 0, 0, 487 VM_SLEEP); 488 for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) 489 hat_prepare_mapping(kas.a_hat, 490 vdp->xs_iopage_va + i * PAGESIZE, NULL); 491 } 492 493 static void 494 xdb_uninit_ioreqs(xdb_t *vdp) 495 { 496 int i; 497 498 for (i = 0; i < XDB_MAX_IO_PAGES(vdp); i++) 499 hat_release_mapping(kas.a_hat, 500 vdp->xs_iopage_va + i * PAGESIZE); 501 vmem_xfree(heap_arena, vdp->xs_iopage_va, 502 XDB_MAX_IO_PAGES(vdp) * PAGESIZE); 503 if (vdp->xs_req != NULL) { 504 kmem_free(vdp->xs_req, vdp->xs_nentry * sizeof (xdb_request_t)); 505 vdp->xs_req = NULL; 506 } 507 #ifdef DEBUG 508 if (vdp->page_addrs != NULL) { 509 kmem_free(vdp->page_addrs, XDB_MAX_IO_PAGES(vdp) * 510 sizeof (uint64_t)); 511 vdp->page_addrs = NULL; 512 } 513 #endif 514 } 515 516 static uint_t 517 xdb_intr(caddr_t arg) 518 { 519 xdb_t *vdp = (xdb_t *)arg; 520 dev_info_t *dip = vdp->xs_dip; 521 blkif_request_t req, *reqp = &req; 522 xdb_request_t *xreq; 523 buf_t *bp; 524 uint8_t op; 525 int ret = DDI_INTR_UNCLAIMED; 526 527 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 528 "xdb@%s: I/O request received from dom %d", 529 ddi_get_name_addr(dip), vdp->xs_peer)); 530 531 mutex_enter(&vdp->xs_iomutex); 532 533 /* shouldn't touch ring buffer if not in connected state */ 534 if (!vdp->xs_if_connected) { 535 mutex_exit(&vdp->xs_iomutex); 536 return (DDI_INTR_UNCLAIMED); 537 } 538 ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised); 539 540 /* 541 * We'll loop till there is no more request in the ring 542 * We won't stuck in this loop for ever since the size of ring buffer 543 * is limited, and frontend will stop pushing requests into it when 544 * the ring buffer is full 545 */ 546 547 /* req_event will be increased in xvdi_ring_get_request() */ 548 while (xdb_get_request(vdp, reqp)) { 549 ret = DDI_INTR_CLAIMED; 550 551 op = ddi_get8(vdp->xs_ring_hdl, &reqp->operation); 552 if (op == BLKIF_OP_READ || 553 op == BLKIF_OP_WRITE || 554 op == BLKIF_OP_WRITE_BARRIER || 555 op == BLKIF_OP_FLUSH_DISKCACHE) { 556 #ifdef DEBUG 557 xdb_dump_request_oe(reqp); 558 #endif 559 xreq = xdb_get_req(vdp); 560 ASSERT(xreq); 561 switch (op) { 562 case BLKIF_OP_READ: 563 vdp->xs_stat_req_reads++; 564 break; 565 case BLKIF_OP_WRITE_BARRIER: 566 vdp->xs_stat_req_barriers++; 567 /* FALLTHRU */ 568 case BLKIF_OP_WRITE: 569 vdp->xs_stat_req_writes++; 570 break; 571 case BLKIF_OP_FLUSH_DISKCACHE: 572 vdp->xs_stat_req_flushes++; 573 break; 574 } 575 576 xreq->xr_curseg = 0; /* start from first segment */ 577 bp = xdb_get_buf(vdp, reqp, xreq); 578 if (bp == NULL) { 579 /* failed to form a buf */ 580 xdb_free_req(xreq); 581 xdb_response(vdp, reqp, B_FALSE); 582 continue; 583 } 584 bp->av_forw = NULL; 585 586 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 587 " buf %p, blkno %lld, size %lu, addr %p", 588 (void *)bp, (longlong_t)bp->b_blkno, 589 (ulong_t)bp->b_bcount, (void *)bp->b_un.b_addr)); 590 591 /* send bp to underlying blk driver */ 592 if (vdp->xs_f_iobuf == NULL) { 593 vdp->xs_f_iobuf = vdp->xs_l_iobuf = bp; 594 } else { 595 vdp->xs_l_iobuf->av_forw = bp; 596 vdp->xs_l_iobuf = bp; 597 } 598 } else { 599 xdb_response(vdp, reqp, B_FALSE); 600 XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: " 601 "Unsupported cmd received from dom %d", 602 ddi_get_name_addr(dip), vdp->xs_peer)); 603 } 604 } 605 /* notify our taskq to push buf to underlying blk driver */ 606 if (ret == DDI_INTR_CLAIMED) 607 cv_broadcast(&vdp->xs_iocv); 608 609 mutex_exit(&vdp->xs_iomutex); 610 611 return (ret); 612 } 613 614 static int 615 xdb_biodone(buf_t *bp) 616 { 617 int i, err, bioerr; 618 uint8_t segs; 619 gnttab_unmap_grant_ref_t unmapops[BLKIF_MAX_SEGMENTS_PER_REQUEST]; 620 xdb_request_t *xreq = XDB_BP2XREQ(bp); 621 xdb_t *vdp = xreq->xr_vdp; 622 buf_t *nbp; 623 624 bioerr = geterror(bp); 625 if (bioerr) 626 XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: I/O error %d", 627 ddi_get_name_addr(vdp->xs_dip), bioerr)); 628 629 /* check if we are done w/ this I/O request */ 630 if ((bioerr == 0) && (xreq->xr_curseg < xreq->xr_buf_pages)) { 631 nbp = xdb_get_buf(vdp, NULL, xreq); 632 if (nbp) { 633 err = ldi_strategy(vdp->xs_ldi_hdl, nbp); 634 if (err == 0) { 635 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 636 "sent buf to backend ok")); 637 return (DDI_SUCCESS); 638 } 639 bioerr = EIO; 640 XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, "xdb@%s: " 641 "sent buf to backend dev failed, err=%d", 642 ddi_get_name_addr(vdp->xs_dip), err)); 643 } else { 644 bioerr = EIO; 645 } 646 } 647 648 /* unmap io pages */ 649 segs = xreq->xr_buf_pages; 650 /* 651 * segs should be no bigger than BLKIF_MAX_SEGMENTS_PER_REQUEST 652 * according to the definition of blk interface by Xen 653 */ 654 ASSERT(segs <= BLKIF_MAX_SEGMENTS_PER_REQUEST); 655 for (i = 0; i < segs; i++) { 656 unmapops[i].host_addr = (uint64_t)(uintptr_t)XDB_IOPAGE_VA( 657 vdp->xs_iopage_va, xreq->xr_idx, i); 658 #ifdef DEBUG 659 mutex_enter(&vdp->xs_iomutex); 660 unlogva(vdp, unmapops[i].host_addr); 661 mutex_exit(&vdp->xs_iomutex); 662 #endif 663 unmapops[i].dev_bus_addr = NULL; 664 unmapops[i].handle = xreq->xr_page_hdls[i]; 665 } 666 err = HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, 667 unmapops, segs); 668 ASSERT(!err); 669 670 /* 671 * If we have reached a barrier write or a cache flush , then we must 672 * flush all our I/Os. 673 */ 674 if (xreq->xr_op == BLKIF_OP_WRITE_BARRIER || 675 xreq->xr_op == BLKIF_OP_FLUSH_DISKCACHE) { 676 /* 677 * XXX At this point the write did succeed, so I don't 678 * believe we should report an error because the flush 679 * failed. However, this is a debatable point, so 680 * maybe we need to think more carefully about this. 681 * For now, just cast to void. 682 */ 683 (void) ldi_ioctl(vdp->xs_ldi_hdl, 684 DKIOCFLUSHWRITECACHE, NULL, FKIOCTL, kcred, NULL); 685 } 686 687 mutex_enter(&vdp->xs_iomutex); 688 689 /* send response back to frontend */ 690 if (vdp->xs_if_connected) { 691 ASSERT(vdp->xs_hp_connected && vdp->xs_fe_initialised); 692 if (xdb_push_response(vdp, xreq->xr_id, xreq->xr_op, bioerr)) 693 xvdi_notify_oe(vdp->xs_dip); 694 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 695 "sent resp back to frontend, id=%llu", 696 (unsigned long long)xreq->xr_id)); 697 } 698 /* free io resources */ 699 biofini(bp); 700 xdb_free_req(xreq); 701 702 vdp->xs_ionum--; 703 if (!vdp->xs_if_connected && (vdp->xs_ionum == 0)) { 704 /* we're closing, someone is waiting for I/O clean-up */ 705 cv_signal(&vdp->xs_ionumcv); 706 } 707 708 mutex_exit(&vdp->xs_iomutex); 709 710 return (DDI_SUCCESS); 711 } 712 713 static int 714 xdb_bindto_frontend(xdb_t *vdp) 715 { 716 int err; 717 char *oename; 718 grant_ref_t gref; 719 evtchn_port_t evtchn; 720 dev_info_t *dip = vdp->xs_dip; 721 char protocol[64] = ""; 722 723 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 724 725 /* 726 * Switch to the XenbusStateInitialised state. This let's the 727 * frontend know that we're about to negotiate a connection. 728 */ 729 (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitialised); 730 731 /* 732 * Gather info from frontend 733 */ 734 oename = xvdi_get_oename(dip); 735 if (oename == NULL) 736 return (DDI_FAILURE); 737 738 err = xenbus_gather(XBT_NULL, oename, 739 XBP_RING_REF, "%lu", &gref, 740 XBP_EVENT_CHAN, "%u", &evtchn, 741 NULL); 742 if (err != 0) { 743 xvdi_dev_error(dip, err, 744 "Getting ring-ref and evtchn from frontend"); 745 return (DDI_FAILURE); 746 } 747 748 vdp->xs_blk_protocol = BLKIF_PROTOCOL_NATIVE; 749 vdp->xs_nentry = BLKIF_RING_SIZE; 750 vdp->xs_entrysize = sizeof (union blkif_sring_entry); 751 752 err = xenbus_gather(XBT_NULL, oename, 753 XBP_PROTOCOL, "%63s", protocol, NULL); 754 if (err) 755 (void) strcpy(protocol, "unspecified, assuming native"); 756 else { 757 /* 758 * We must check for NATIVE first, so that the fast path 759 * is taken for copying data from the guest to the host. 760 */ 761 if (strcmp(protocol, XEN_IO_PROTO_ABI_NATIVE) != 0) { 762 if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_32) == 0) { 763 vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_32; 764 vdp->xs_nentry = BLKIF_X86_32_RING_SIZE; 765 vdp->xs_entrysize = 766 sizeof (union blkif_x86_32_sring_entry); 767 } else if (strcmp(protocol, XEN_IO_PROTO_ABI_X86_64) == 768 0) { 769 vdp->xs_blk_protocol = BLKIF_PROTOCOL_X86_64; 770 vdp->xs_nentry = BLKIF_X86_64_RING_SIZE; 771 vdp->xs_entrysize = 772 sizeof (union blkif_x86_64_sring_entry); 773 } else { 774 xvdi_fatal_error(dip, err, "unknown protocol"); 775 return (DDI_FAILURE); 776 } 777 } 778 } 779 #ifdef DEBUG 780 cmn_err(CE_NOTE, "!xdb@%s: blkif protocol '%s' ", 781 ddi_get_name_addr(dip), protocol); 782 #endif 783 784 /* 785 * Map and init ring. The ring parameters must match those which 786 * have been allocated in the front end. 787 */ 788 if (xvdi_map_ring(dip, vdp->xs_nentry, vdp->xs_entrysize, 789 gref, &vdp->xs_ring) != DDI_SUCCESS) 790 return (DDI_FAILURE); 791 792 /* 793 * This will be removed after we use shadow I/O ring request since 794 * we don't need to access the ring itself directly, thus the access 795 * handle is not needed 796 */ 797 vdp->xs_ring_hdl = vdp->xs_ring->xr_acc_hdl; 798 799 /* bind event channel */ 800 err = xvdi_bind_evtchn(dip, evtchn); 801 if (err != DDI_SUCCESS) { 802 xvdi_unmap_ring(vdp->xs_ring); 803 return (DDI_FAILURE); 804 } 805 806 return (DDI_SUCCESS); 807 } 808 809 static void 810 xdb_unbindfrom_frontend(xdb_t *vdp) 811 { 812 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 813 814 xvdi_free_evtchn(vdp->xs_dip); 815 xvdi_unmap_ring(vdp->xs_ring); 816 } 817 818 /* 819 * xdb_params_change() initiates a allows change to the underlying device/file 820 * that the backend is accessing. It does this by disconnecting from the 821 * frontend, closing the old device, clearing a bunch of xenbus parameters, 822 * and switching back to the XenbusStateInitialising state. The frontend 823 * should notice this transition to the XenbusStateInitialising state and 824 * should attempt to reconnect to us (the backend). 825 */ 826 static void 827 xdb_params_change(xdb_t *vdp, char *params, boolean_t update_xs) 828 { 829 xenbus_transaction_t xbt; 830 dev_info_t *dip = vdp->xs_dip; 831 char *xsname; 832 int err; 833 834 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 835 ASSERT(vdp->xs_params_path != NULL); 836 837 if ((xsname = xvdi_get_xsname(dip)) == NULL) 838 return; 839 if (strcmp(vdp->xs_params_path, params) == 0) 840 return; 841 842 /* 843 * Close the device we're currently accessing and update the 844 * path which points to our backend device/file. 845 */ 846 xdb_close(dip); 847 vdp->xs_fe_initialised = B_FALSE; 848 849 trans_retry: 850 if ((err = xenbus_transaction_start(&xbt)) != 0) { 851 xvdi_dev_error(dip, err, "params change transaction init"); 852 goto errout; 853 } 854 855 /* 856 * Delete all the xenbus properties that are connection dependant 857 * and go back to the initializing state so that the frontend 858 * driver can re-negotiate a connection. 859 */ 860 if (((err = xenbus_rm(xbt, xsname, XBP_FB)) != 0) || 861 ((err = xenbus_rm(xbt, xsname, XBP_INFO)) != 0) || 862 ((err = xenbus_rm(xbt, xsname, "sector-size")) != 0) || 863 ((err = xenbus_rm(xbt, xsname, XBP_SECTORS)) != 0) || 864 ((err = xenbus_rm(xbt, xsname, "instance")) != 0) || 865 ((err = xenbus_rm(xbt, xsname, "node")) != 0) || 866 (update_xs && ((err = xenbus_printf(xbt, xsname, 867 "params", "%s", params)) != 0)) || 868 ((err = xvdi_switch_state(dip, 869 xbt, XenbusStateInitialising) > 0))) { 870 (void) xenbus_transaction_end(xbt, 1); 871 xvdi_dev_error(dip, err, "params change transaction setup"); 872 goto errout; 873 } 874 875 if ((err = xenbus_transaction_end(xbt, 0)) != 0) { 876 if (err == EAGAIN) { 877 /* transaction is ended, don't need to abort it */ 878 goto trans_retry; 879 } 880 xvdi_dev_error(dip, err, "params change transaction commit"); 881 goto errout; 882 } 883 884 /* Change the device that we plan to access */ 885 strfree(vdp->xs_params_path); 886 vdp->xs_params_path = strdup(params); 887 return; 888 889 errout: 890 (void) xvdi_switch_state(dip, xbt, XenbusStateInitialising); 891 } 892 893 /* 894 * xdb_watch_params_cb() - This callback is invoked whenever there 895 * is an update to the following xenbus parameter: 896 * /local/domain/0/backend/vbd/<domU_id>/<domU_dev>/params 897 * 898 * This normally happens during xm block-configure operations, which 899 * are used to change CD device images for HVM domUs. 900 */ 901 /*ARGSUSED*/ 902 static void 903 xdb_watch_params_cb(dev_info_t *dip, const char *path, void *arg) 904 { 905 xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); 906 char *xsname, *oename, *str, *str2; 907 908 if (((xsname = xvdi_get_xsname(dip)) == NULL) || 909 ((oename = xvdi_get_oename(dip)) == NULL)) { 910 return; 911 } 912 913 mutex_enter(&vdp->xs_cbmutex); 914 915 if (xenbus_read_str(xsname, "params", &str) != 0) { 916 mutex_exit(&vdp->xs_cbmutex); 917 return; 918 } 919 920 if (strcmp(vdp->xs_params_path, str) == 0) { 921 /* Nothing todo */ 922 mutex_exit(&vdp->xs_cbmutex); 923 strfree(str); 924 return; 925 } 926 927 /* 928 * If the frontend isn't a cd device, doesn't support media 929 * requests, or has locked the media, then we can't change 930 * the params value. restore the current value. 931 */ 932 str2 = NULL; 933 if (!XDB_IS_FE_CD(vdp) || 934 (xenbus_read_str(oename, XBP_MEDIA_REQ, &str2) != 0) || 935 (strcmp(str2, XBV_MEDIA_REQ_LOCK) == 0)) { 936 if (str2 != NULL) 937 strfree(str2); 938 strfree(str); 939 940 str = i_pathname(dip); 941 cmn_err(CE_NOTE, 942 "!%s: media locked, ignoring params update", str); 943 strfree(str); 944 945 mutex_exit(&vdp->xs_cbmutex); 946 return; 947 } 948 949 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, 950 "block-configure params request: \"%s\"", str)); 951 952 xdb_params_change(vdp, str, B_FALSE); 953 mutex_exit(&vdp->xs_cbmutex); 954 strfree(str); 955 } 956 957 /* 958 * xdb_watch_media_req_cb() - This callback is invoked whenever there 959 * is an update to the following xenbus parameter: 960 * /local/domain/<domU_id>/device/vbd/<domU_dev>/media-req 961 * 962 * Media requests are only supported on CD devices and are issued by 963 * the frontend. Currently the only supported media request operaions 964 * are "lock" and "eject". A "lock" prevents the backend from changing 965 * the backing device/file (via xm block-configure). An "eject" requests 966 * tells the backend device that it should disconnect from the frontend 967 * and closing the backing device/file that is currently in use. 968 */ 969 /*ARGSUSED*/ 970 static void 971 xdb_watch_media_req_cb(dev_info_t *dip, const char *path, void *arg) 972 { 973 xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); 974 char *oename, *str; 975 976 mutex_enter(&vdp->xs_cbmutex); 977 978 if ((oename = xvdi_get_oename(dip)) == NULL) { 979 mutex_exit(&vdp->xs_cbmutex); 980 return; 981 } 982 983 if (xenbus_read_str(oename, XBP_MEDIA_REQ, &str) != 0) { 984 mutex_exit(&vdp->xs_cbmutex); 985 return; 986 } 987 988 if (!XDB_IS_FE_CD(vdp)) { 989 xvdi_dev_error(dip, EINVAL, 990 "media-req only supported for cdrom devices"); 991 mutex_exit(&vdp->xs_cbmutex); 992 return; 993 } 994 995 if (strcmp(str, XBV_MEDIA_REQ_EJECT) != 0) { 996 mutex_exit(&vdp->xs_cbmutex); 997 strfree(str); 998 return; 999 } 1000 strfree(str); 1001 1002 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "media eject request")); 1003 1004 xdb_params_change(vdp, "", B_TRUE); 1005 (void) xenbus_printf(XBT_NULL, oename, 1006 XBP_MEDIA_REQ, "%s", XBV_MEDIA_REQ_NONE); 1007 mutex_exit(&vdp->xs_cbmutex); 1008 } 1009 1010 /* 1011 * If we're dealing with a cdrom device, let the frontend know that 1012 * we support media requests via XBP_MEDIA_REQ_SUP, and setup a watch 1013 * to handle those frontend media request changes, which modify the 1014 * following xenstore parameter: 1015 * /local/domain/<domU_id>/device/vbd/<domU_dev>/media-req 1016 */ 1017 static boolean_t 1018 xdb_media_req_init(xdb_t *vdp) 1019 { 1020 dev_info_t *dip = vdp->xs_dip; 1021 char *xsname, *oename; 1022 1023 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1024 1025 if (((xsname = xvdi_get_xsname(dip)) == NULL) || 1026 ((oename = xvdi_get_oename(dip)) == NULL)) 1027 return (B_FALSE); 1028 1029 if (!XDB_IS_FE_CD(vdp)) 1030 return (B_TRUE); 1031 1032 if (xenbus_printf(XBT_NULL, xsname, XBP_MEDIA_REQ_SUP, "%d", 1) != 0) 1033 return (B_FALSE); 1034 1035 if (xvdi_add_xb_watch_handler(dip, oename, 1036 XBP_MEDIA_REQ, xdb_watch_media_req_cb, NULL) != DDI_SUCCESS) { 1037 xvdi_dev_error(dip, EAGAIN, 1038 "Failed to register watch for cdrom media requests"); 1039 return (B_FALSE); 1040 } 1041 1042 return (B_TRUE); 1043 } 1044 1045 /* 1046 * Get our params value. Also, if we're using "params" then setup a 1047 * watch to handle xm block-configure operations which modify the 1048 * following xenstore parameter: 1049 * /local/domain/0/backend/vbd/<domU_id>/<domU_dev>/params 1050 */ 1051 static boolean_t 1052 xdb_params_init(xdb_t *vdp) 1053 { 1054 dev_info_t *dip = vdp->xs_dip; 1055 char *str, *xsname; 1056 int err, watch_params = B_FALSE; 1057 1058 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1059 ASSERT(vdp->xs_params_path == NULL); 1060 1061 if ((xsname = xvdi_get_xsname(dip)) == NULL) 1062 return (B_FALSE); 1063 1064 if ((err = xenbus_read_str(xsname, 1065 "dynamic-device-path", &str)) == ENOENT) { 1066 err = xenbus_read_str(xsname, "params", &str); 1067 watch_params = B_TRUE; 1068 } 1069 if (err != 0) 1070 return (B_FALSE); 1071 vdp->xs_params_path = str; 1072 1073 /* 1074 * If we got our backing store path from "dynamic-device-path" then 1075 * there's no reason to watch "params" 1076 */ 1077 if (!watch_params) 1078 return (B_TRUE); 1079 1080 if (xvdi_add_xb_watch_handler(dip, xsname, "params", 1081 xdb_watch_params_cb, NULL) != DDI_SUCCESS) { 1082 strfree(vdp->xs_params_path); 1083 vdp->xs_params_path = NULL; 1084 return (B_FALSE); 1085 } 1086 1087 return (B_TRUE); 1088 } 1089 1090 #define LOFI_CTRL_NODE "/dev/lofictl" 1091 #define LOFI_DEV_NODE "/devices/pseudo/lofi@0:" 1092 #define LOFI_MODE (FREAD | FWRITE | FEXCL) 1093 1094 static int 1095 xdb_setup_node(xdb_t *vdp, char *path) 1096 { 1097 dev_info_t *dip = vdp->xs_dip; 1098 char *xsname, *str; 1099 ldi_handle_t ldi_hdl; 1100 struct lofi_ioctl *li; 1101 int minor, err; 1102 1103 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1104 1105 if ((xsname = xvdi_get_xsname(dip)) == NULL) 1106 return (DDI_FAILURE); 1107 1108 if ((err = xenbus_read_str(xsname, "type", &str)) != 0) { 1109 xvdi_dev_error(dip, err, "Getting type from backend device"); 1110 return (DDI_FAILURE); 1111 } 1112 if (strcmp(str, "file") == 0) 1113 vdp->xs_type |= XDB_DEV_BE_LOFI; 1114 strfree(str); 1115 1116 if (!XDB_IS_BE_LOFI(vdp)) { 1117 (void) strlcpy(path, vdp->xs_params_path, MAXPATHLEN); 1118 ASSERT(vdp->xs_lofi_path == NULL); 1119 return (DDI_SUCCESS); 1120 } 1121 1122 do { 1123 err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred, 1124 &ldi_hdl, vdp->xs_ldi_li); 1125 } while (err == EBUSY); 1126 if (err != 0) { 1127 return (DDI_FAILURE); 1128 } 1129 1130 li = kmem_zalloc(sizeof (*li), KM_SLEEP); 1131 (void) strlcpy(li->li_filename, vdp->xs_params_path, 1132 sizeof (li->li_filename)); 1133 err = ldi_ioctl(ldi_hdl, LOFI_MAP_FILE, (intptr_t)li, 1134 LOFI_MODE | FKIOCTL, kcred, &minor); 1135 (void) ldi_close(ldi_hdl, LOFI_MODE, kcred); 1136 kmem_free(li, sizeof (*li)); 1137 1138 if (err != 0) { 1139 cmn_err(CE_WARN, "xdb@%s: Failed to create lofi dev for %s", 1140 ddi_get_name_addr(dip), vdp->xs_params_path); 1141 return (DDI_FAILURE); 1142 } 1143 1144 /* 1145 * return '/devices/...' instead of '/dev/lofi/...' since the 1146 * former is available immediately after calling ldi_ioctl 1147 */ 1148 (void) snprintf(path, MAXPATHLEN, LOFI_DEV_NODE "%d", minor); 1149 (void) xenbus_printf(XBT_NULL, xsname, "node", "%s", path); 1150 1151 ASSERT(vdp->xs_lofi_path == NULL); 1152 vdp->xs_lofi_path = strdup(path); 1153 1154 return (DDI_SUCCESS); 1155 } 1156 1157 static void 1158 xdb_teardown_node(xdb_t *vdp) 1159 { 1160 dev_info_t *dip = vdp->xs_dip; 1161 ldi_handle_t ldi_hdl; 1162 struct lofi_ioctl *li; 1163 int err; 1164 1165 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1166 1167 if (!XDB_IS_BE_LOFI(vdp)) 1168 return; 1169 1170 vdp->xs_type &= ~XDB_DEV_BE_LOFI; 1171 ASSERT(vdp->xs_lofi_path != NULL); 1172 1173 li = kmem_zalloc(sizeof (*li), KM_SLEEP); 1174 (void) strlcpy(li->li_filename, vdp->xs_params_path, 1175 sizeof (li->li_filename)); 1176 1177 do { 1178 err = ldi_open_by_name(LOFI_CTRL_NODE, LOFI_MODE, kcred, 1179 &ldi_hdl, vdp->xs_ldi_li); 1180 } while (err == EBUSY); 1181 1182 if (err != 0) { 1183 kmem_free(li, sizeof (*li)); 1184 return; 1185 } 1186 1187 if (ldi_ioctl(ldi_hdl, LOFI_UNMAP_FILE, (intptr_t)li, 1188 LOFI_MODE | FKIOCTL, kcred, NULL) != 0) { 1189 cmn_err(CE_WARN, "xdb@%s: Failed to delete lofi dev for %s", 1190 ddi_get_name_addr(dip), li->li_filename); 1191 } 1192 1193 (void) ldi_close(ldi_hdl, LOFI_MODE, kcred); 1194 kmem_free(li, sizeof (*li)); 1195 1196 strfree(vdp->xs_lofi_path); 1197 vdp->xs_lofi_path = NULL; 1198 } 1199 1200 static int 1201 xdb_open_device(xdb_t *vdp) 1202 { 1203 dev_info_t *dip = vdp->xs_dip; 1204 uint64_t devsize; 1205 char *nodepath; 1206 1207 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1208 1209 if (strlen(vdp->xs_params_path) == 0) { 1210 /* 1211 * it's possible to have no backing device when dealing 1212 * with a pv cdrom drive that has no virtual cd associated 1213 * with it. 1214 */ 1215 ASSERT(XDB_IS_FE_CD(vdp)); 1216 ASSERT(vdp->xs_sectors == 0); 1217 ASSERT(vdp->xs_ldi_li == NULL); 1218 ASSERT(vdp->xs_ldi_hdl == NULL); 1219 return (DDI_SUCCESS); 1220 } 1221 1222 if (ldi_ident_from_dip(dip, &vdp->xs_ldi_li) != 0) 1223 return (DDI_FAILURE); 1224 1225 nodepath = kmem_zalloc(MAXPATHLEN, KM_SLEEP); 1226 1227 /* try to open backend device */ 1228 if (xdb_setup_node(vdp, nodepath) != DDI_SUCCESS) { 1229 xvdi_dev_error(dip, ENXIO, 1230 "Getting device path of backend device"); 1231 ldi_ident_release(vdp->xs_ldi_li); 1232 kmem_free(nodepath, MAXPATHLEN); 1233 return (DDI_FAILURE); 1234 } 1235 1236 if (ldi_open_by_name(nodepath, 1237 FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), 1238 kcred, &vdp->xs_ldi_hdl, vdp->xs_ldi_li) != 0) { 1239 xdb_teardown_node(vdp); 1240 ldi_ident_release(vdp->xs_ldi_li); 1241 cmn_err(CE_WARN, "xdb@%s: Failed to open: %s", 1242 ddi_get_name_addr(dip), nodepath); 1243 kmem_free(nodepath, MAXPATHLEN); 1244 return (DDI_FAILURE); 1245 } 1246 1247 if (ldi_get_size(vdp->xs_ldi_hdl, &devsize) != DDI_SUCCESS) { 1248 (void) ldi_close(vdp->xs_ldi_hdl, 1249 FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred); 1250 xdb_teardown_node(vdp); 1251 ldi_ident_release(vdp->xs_ldi_li); 1252 kmem_free(nodepath, MAXPATHLEN); 1253 return (DDI_FAILURE); 1254 } 1255 vdp->xs_sectors = devsize / XB_BSIZE; 1256 1257 /* check if the underlying device is a CD/DVD disc */ 1258 if (ldi_prop_get_int(vdp->xs_ldi_hdl, LDI_DEV_T_ANY | DDI_PROP_DONTPASS, 1259 INQUIRY_DEVICE_TYPE, DTYPE_DIRECT) == DTYPE_RODIRECT) 1260 vdp->xs_type |= XDB_DEV_BE_CD; 1261 1262 /* check if the underlying device is a removable disk */ 1263 if (ldi_prop_exists(vdp->xs_ldi_hdl, 1264 LDI_DEV_T_ANY | DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 1265 "removable-media")) 1266 vdp->xs_type |= XDB_DEV_BE_RMB; 1267 1268 kmem_free(nodepath, MAXPATHLEN); 1269 return (DDI_SUCCESS); 1270 } 1271 1272 static void 1273 xdb_close_device(xdb_t *vdp) 1274 { 1275 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1276 1277 if (strlen(vdp->xs_params_path) == 0) { 1278 ASSERT(XDB_IS_FE_CD(vdp)); 1279 ASSERT(vdp->xs_sectors == 0); 1280 ASSERT(vdp->xs_ldi_li == NULL); 1281 ASSERT(vdp->xs_ldi_hdl == NULL); 1282 return; 1283 } 1284 1285 (void) ldi_close(vdp->xs_ldi_hdl, 1286 FREAD | (XDB_IS_RO(vdp) ? 0 : FWRITE), kcred); 1287 xdb_teardown_node(vdp); 1288 ldi_ident_release(vdp->xs_ldi_li); 1289 vdp->xs_type &= ~(XDB_DEV_BE_CD | XDB_DEV_BE_RMB); 1290 vdp->xs_sectors = 0; 1291 vdp->xs_ldi_li = NULL; 1292 vdp->xs_ldi_hdl = NULL; 1293 } 1294 1295 /* 1296 * Kick-off connect process 1297 * If xs_fe_initialised == B_TRUE and xs_hp_connected == B_TRUE 1298 * the xs_if_connected will be changed to B_TRUE on success, 1299 */ 1300 static void 1301 xdb_start_connect(xdb_t *vdp) 1302 { 1303 xenbus_transaction_t xbt; 1304 dev_info_t *dip = vdp->xs_dip; 1305 boolean_t fb_exists; 1306 int err, instance = ddi_get_instance(dip); 1307 uint64_t sectors; 1308 uint_t dinfo, ssize; 1309 char *xsname; 1310 1311 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1312 1313 if (((xsname = xvdi_get_xsname(dip)) == NULL) || 1314 ((vdp->xs_peer = xvdi_get_oeid(dip)) == (domid_t)-1)) 1315 return; 1316 1317 mutex_enter(&vdp->xs_iomutex); 1318 /* 1319 * if the hotplug scripts haven't run or if the frontend is not 1320 * initialized, then we can't try to connect. 1321 */ 1322 if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) { 1323 ASSERT(!vdp->xs_if_connected); 1324 mutex_exit(&vdp->xs_iomutex); 1325 return; 1326 } 1327 1328 /* If we're already connected then there's nothing todo */ 1329 if (vdp->xs_if_connected) { 1330 mutex_exit(&vdp->xs_iomutex); 1331 return; 1332 } 1333 mutex_exit(&vdp->xs_iomutex); 1334 1335 /* 1336 * Start connect to frontend only when backend device are ready 1337 * and frontend has moved to XenbusStateInitialised, which means 1338 * ready to connect. 1339 */ 1340 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, 1341 "xdb@%s: starting connection process", ddi_get_name_addr(dip))); 1342 1343 if (xdb_open_device(vdp) != DDI_SUCCESS) 1344 return; 1345 1346 if (xdb_bindto_frontend(vdp) != DDI_SUCCESS) { 1347 xdb_close_device(vdp); 1348 return; 1349 } 1350 1351 /* init i/o requests */ 1352 xdb_init_ioreqs(vdp); 1353 1354 if (ddi_add_intr(dip, 0, NULL, NULL, xdb_intr, (caddr_t)vdp) 1355 != DDI_SUCCESS) { 1356 xdb_uninit_ioreqs(vdp); 1357 xdb_unbindfrom_frontend(vdp); 1358 xdb_close_device(vdp); 1359 return; 1360 } 1361 1362 dinfo = 0; 1363 if (XDB_IS_RO(vdp)) 1364 dinfo |= VDISK_READONLY; 1365 if (XDB_IS_BE_RMB(vdp)) 1366 dinfo |= VDISK_REMOVABLE; 1367 if (XDB_IS_BE_CD(vdp)) 1368 dinfo |= VDISK_CDROM; 1369 if (XDB_IS_FE_CD(vdp)) 1370 dinfo |= VDISK_REMOVABLE | VDISK_CDROM; 1371 1372 /* 1373 * we can recieve intr any time from now on 1374 * mark that we're ready to take intr 1375 */ 1376 mutex_enter(&vdp->xs_iomutex); 1377 ASSERT(vdp->xs_fe_initialised); 1378 vdp->xs_if_connected = B_TRUE; 1379 mutex_exit(&vdp->xs_iomutex); 1380 1381 trans_retry: 1382 /* write into xenstore the info needed by frontend */ 1383 if ((err = xenbus_transaction_start(&xbt)) != 0) { 1384 xvdi_dev_error(dip, err, "connect transaction init"); 1385 goto errout; 1386 } 1387 1388 /* If feature-barrier isn't present in xenstore, add it. */ 1389 fb_exists = xenbus_exists(xsname, XBP_FB); 1390 1391 /* hard-coded 512-byte sector size */ 1392 ssize = DEV_BSIZE; 1393 sectors = vdp->xs_sectors; 1394 if (((!fb_exists && 1395 (err = xenbus_printf(xbt, xsname, XBP_FB, "%d", 1)))) || 1396 (err = xenbus_printf(xbt, xsname, XBP_INFO, "%u", dinfo)) || 1397 (err = xenbus_printf(xbt, xsname, "sector-size", "%u", ssize)) || 1398 (err = xenbus_printf(xbt, xsname, 1399 XBP_SECTORS, "%"PRIu64, sectors)) || 1400 (err = xenbus_printf(xbt, xsname, "instance", "%d", instance)) || 1401 ((err = xvdi_switch_state(dip, xbt, XenbusStateConnected)) > 0)) { 1402 (void) xenbus_transaction_end(xbt, 1); 1403 xvdi_dev_error(dip, err, "connect transaction setup"); 1404 goto errout; 1405 } 1406 1407 if ((err = xenbus_transaction_end(xbt, 0)) != 0) { 1408 if (err == EAGAIN) { 1409 /* transaction is ended, don't need to abort it */ 1410 goto trans_retry; 1411 } 1412 xvdi_dev_error(dip, err, "connect transaction commit"); 1413 goto errout; 1414 } 1415 1416 return; 1417 1418 errout: 1419 xdb_close(dip); 1420 } 1421 1422 /* 1423 * Disconnect from frontend and close backend device 1424 */ 1425 static void 1426 xdb_close(dev_info_t *dip) 1427 { 1428 xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); 1429 1430 ASSERT(MUTEX_HELD(&vdp->xs_cbmutex)); 1431 mutex_enter(&vdp->xs_iomutex); 1432 1433 /* 1434 * if the hotplug scripts haven't run or if the frontend is not 1435 * initialized, then we can't be connected, so there's no 1436 * connection to close. 1437 */ 1438 if (!vdp->xs_hp_connected || !vdp->xs_fe_initialised) { 1439 ASSERT(!vdp->xs_if_connected); 1440 mutex_exit(&vdp->xs_iomutex); 1441 return; 1442 } 1443 1444 /* if we're not connected, there's nothing to do */ 1445 if (!vdp->xs_if_connected) { 1446 cv_broadcast(&vdp->xs_iocv); 1447 mutex_exit(&vdp->xs_iomutex); 1448 return; 1449 } 1450 1451 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "closing while connected")); 1452 1453 vdp->xs_if_connected = B_FALSE; 1454 cv_broadcast(&vdp->xs_iocv); 1455 1456 mutex_exit(&vdp->xs_iomutex); 1457 1458 /* stop accepting I/O request from frontend */ 1459 ddi_remove_intr(dip, 0, NULL); 1460 1461 /* clear all on-going I/Os, if any */ 1462 mutex_enter(&vdp->xs_iomutex); 1463 while (vdp->xs_ionum > 0) 1464 cv_wait(&vdp->xs_ionumcv, &vdp->xs_iomutex); 1465 mutex_exit(&vdp->xs_iomutex); 1466 1467 /* clean up resources and close this interface */ 1468 xdb_uninit_ioreqs(vdp); 1469 xdb_unbindfrom_frontend(vdp); 1470 xdb_close_device(vdp); 1471 vdp->xs_peer = (domid_t)-1; 1472 } 1473 1474 static void 1475 xdb_send_buf(void *arg) 1476 { 1477 xdb_t *vdp = (xdb_t *)arg; 1478 buf_t *bp; 1479 int err; 1480 1481 mutex_enter(&vdp->xs_iomutex); 1482 while (vdp->xs_send_buf) { 1483 if ((bp = vdp->xs_f_iobuf) == NULL) { 1484 /* wait for some io to send */ 1485 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 1486 "send buf waiting for io")); 1487 cv_wait(&vdp->xs_iocv, &vdp->xs_iomutex); 1488 continue; 1489 } 1490 1491 vdp->xs_f_iobuf = bp->av_forw; 1492 bp->av_forw = NULL; 1493 vdp->xs_ionum++; 1494 1495 mutex_exit(&vdp->xs_iomutex); 1496 if (bp->b_bcount == 0) { 1497 /* no I/O needs to be done */ 1498 (void) xdb_biodone(bp); 1499 mutex_enter(&vdp->xs_iomutex); 1500 continue; 1501 } 1502 1503 err = EIO; 1504 if (vdp->xs_ldi_hdl != NULL) 1505 err = ldi_strategy(vdp->xs_ldi_hdl, bp); 1506 if (err != 0) { 1507 bp->b_flags |= B_ERROR; 1508 (void) xdb_biodone(bp); 1509 XDB_DBPRINT(XDB_DBG_IO, (CE_WARN, 1510 "xdb@%s: sent buf to backend devfailed, err=%d", 1511 ddi_get_name_addr(vdp->xs_dip), err)); 1512 } else { 1513 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, 1514 "sent buf to backend ok")); 1515 } 1516 mutex_enter(&vdp->xs_iomutex); 1517 } 1518 XDB_DBPRINT(XDB_DBG_IO, (CE_NOTE, "send buf finishing")); 1519 mutex_exit(&vdp->xs_iomutex); 1520 } 1521 1522 /*ARGSUSED*/ 1523 static void 1524 xdb_hp_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, 1525 void *impl_data) 1526 { 1527 xendev_hotplug_state_t state = *(xendev_hotplug_state_t *)impl_data; 1528 xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); 1529 1530 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: " 1531 "hotplug status change to %d!", ddi_get_name_addr(dip), state)); 1532 1533 if (state != Connected) 1534 return; 1535 1536 mutex_enter(&vdp->xs_cbmutex); 1537 1538 /* If hotplug script have already run, there's nothing todo */ 1539 if (vdp->xs_hp_connected) { 1540 mutex_exit(&vdp->xs_cbmutex); 1541 return; 1542 } 1543 1544 vdp->xs_hp_connected = B_TRUE; 1545 xdb_start_connect(vdp); 1546 mutex_exit(&vdp->xs_cbmutex); 1547 } 1548 1549 /*ARGSUSED*/ 1550 static void 1551 xdb_oe_state_change(dev_info_t *dip, ddi_eventcookie_t id, void *arg, 1552 void *impl_data) 1553 { 1554 XenbusState new_state = *(XenbusState *)impl_data; 1555 xdb_t *vdp = (xdb_t *)ddi_get_driver_private(dip); 1556 1557 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: " 1558 "otherend state change to %d!", ddi_get_name_addr(dip), new_state)); 1559 1560 mutex_enter(&vdp->xs_cbmutex); 1561 1562 /* 1563 * Now it'd really be nice if there was a well defined state 1564 * transition model for xen frontend drivers, but unfortunatly 1565 * there isn't. So we're stuck with assuming that all state 1566 * transitions are possible, and we'll just have to deal with 1567 * them regardless of what state we're in. 1568 */ 1569 switch (new_state) { 1570 case XenbusStateUnknown: 1571 case XenbusStateInitialising: 1572 case XenbusStateInitWait: 1573 /* tear down our connection to the frontend */ 1574 xdb_close(dip); 1575 vdp->xs_fe_initialised = B_FALSE; 1576 break; 1577 1578 case XenbusStateInitialised: 1579 /* 1580 * If we were conected, then we need to drop the connection 1581 * and re-negotiate it. 1582 */ 1583 xdb_close(dip); 1584 vdp->xs_fe_initialised = B_TRUE; 1585 xdb_start_connect(vdp); 1586 break; 1587 1588 case XenbusStateConnected: 1589 /* nothing todo here other than congratulate the frontend */ 1590 break; 1591 1592 case XenbusStateClosing: 1593 /* monkey see monkey do */ 1594 (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateClosing); 1595 break; 1596 1597 case XenbusStateClosed: 1598 /* tear down our connection to the frontend */ 1599 xdb_close(dip); 1600 vdp->xs_fe_initialised = B_FALSE; 1601 (void) xvdi_switch_state(dip, XBT_NULL, new_state); 1602 break; 1603 } 1604 1605 mutex_exit(&vdp->xs_cbmutex); 1606 } 1607 1608 static int 1609 xdb_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1610 { 1611 ddi_iblock_cookie_t ibc; 1612 xdb_t *vdp; 1613 int instance = ddi_get_instance(dip); 1614 char *xsname, *oename; 1615 char *str; 1616 1617 switch (cmd) { 1618 case DDI_RESUME: 1619 return (DDI_FAILURE); 1620 case DDI_ATTACH: 1621 break; 1622 default: 1623 return (DDI_FAILURE); 1624 } 1625 /* DDI_ATTACH */ 1626 1627 if (((xsname = xvdi_get_xsname(dip)) == NULL) || 1628 ((oename = xvdi_get_oename(dip)) == NULL)) 1629 return (DDI_FAILURE); 1630 1631 /* 1632 * Disable auto-detach. This is necessary so that we don't get 1633 * detached while we're disconnected from the front end. 1634 */ 1635 (void) ddi_prop_update_int(DDI_DEV_T_NONE, dip, DDI_NO_AUTODETACH, 1); 1636 1637 if (ddi_get_iblock_cookie(dip, 0, &ibc) != DDI_SUCCESS) 1638 return (DDI_FAILURE); 1639 1640 if (ddi_soft_state_zalloc(xdb_statep, instance) != DDI_SUCCESS) 1641 return (DDI_FAILURE); 1642 1643 vdp = ddi_get_soft_state(xdb_statep, instance); 1644 vdp->xs_dip = dip; 1645 mutex_init(&vdp->xs_iomutex, NULL, MUTEX_DRIVER, (void *)ibc); 1646 mutex_init(&vdp->xs_cbmutex, NULL, MUTEX_DRIVER, (void *)ibc); 1647 cv_init(&vdp->xs_iocv, NULL, CV_DRIVER, NULL); 1648 cv_init(&vdp->xs_ionumcv, NULL, CV_DRIVER, NULL); 1649 ddi_set_driver_private(dip, vdp); 1650 1651 if (!xdb_kstat_init(vdp)) 1652 goto errout1; 1653 1654 /* Check if the frontend device is supposed to be a cdrom */ 1655 if (xenbus_read_str(oename, XBP_DEV_TYPE, &str) != 0) 1656 return (DDI_FAILURE); 1657 if (strcmp(str, XBV_DEV_TYPE_CD) == 0) 1658 vdp->xs_type |= XDB_DEV_FE_CD; 1659 strfree(str); 1660 1661 /* Check if the frontend device is supposed to be read only */ 1662 if (xenbus_read_str(xsname, "mode", &str) != 0) 1663 return (DDI_FAILURE); 1664 if ((strcmp(str, "r") == NULL) || (strcmp(str, "ro") == NULL)) 1665 vdp->xs_type |= XDB_DEV_RO; 1666 strfree(str); 1667 1668 mutex_enter(&vdp->xs_cbmutex); 1669 if (!xdb_media_req_init(vdp) || !xdb_params_init(vdp)) { 1670 xvdi_remove_xb_watch_handlers(dip); 1671 mutex_exit(&vdp->xs_cbmutex); 1672 goto errout2; 1673 } 1674 mutex_exit(&vdp->xs_cbmutex); 1675 1676 vdp->xs_send_buf = B_TRUE; 1677 vdp->xs_iotaskq = ddi_taskq_create(dip, "xdb_iotask", 1, 1678 TASKQ_DEFAULTPRI, 0); 1679 (void) ddi_taskq_dispatch(vdp->xs_iotaskq, xdb_send_buf, vdp, 1680 DDI_SLEEP); 1681 1682 /* Watch frontend and hotplug state change */ 1683 if ((xvdi_add_event_handler(dip, XS_OE_STATE, xdb_oe_state_change, 1684 NULL) != DDI_SUCCESS) || 1685 (xvdi_add_event_handler(dip, XS_HP_STATE, xdb_hp_state_change, 1686 NULL) != DDI_SUCCESS)) 1687 goto errout3; 1688 1689 /* 1690 * Kick-off hotplug script 1691 */ 1692 if (xvdi_post_event(dip, XEN_HP_ADD) != DDI_SUCCESS) { 1693 cmn_err(CE_WARN, "xdb@%s: failed to start hotplug script", 1694 ddi_get_name_addr(dip)); 1695 goto errout3; 1696 } 1697 1698 /* 1699 * start waiting for hotplug event and otherend state event 1700 * mainly for debugging, frontend will not take any op seeing this 1701 */ 1702 (void) xvdi_switch_state(dip, XBT_NULL, XenbusStateInitWait); 1703 1704 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: attached!", 1705 ddi_get_name_addr(dip))); 1706 return (DDI_SUCCESS); 1707 1708 errout3: 1709 ASSERT(vdp->xs_hp_connected && vdp->xs_if_connected); 1710 1711 xvdi_remove_event_handler(dip, NULL); 1712 1713 /* Disconnect from the backend */ 1714 mutex_enter(&vdp->xs_cbmutex); 1715 mutex_enter(&vdp->xs_iomutex); 1716 vdp->xs_send_buf = B_FALSE; 1717 cv_broadcast(&vdp->xs_iocv); 1718 mutex_exit(&vdp->xs_iomutex); 1719 mutex_exit(&vdp->xs_cbmutex); 1720 1721 /* wait for all io to dtrain and destroy io taskq */ 1722 ddi_taskq_destroy(vdp->xs_iotaskq); 1723 1724 /* tear down block-configure watch */ 1725 mutex_enter(&vdp->xs_cbmutex); 1726 xvdi_remove_xb_watch_handlers(dip); 1727 mutex_exit(&vdp->xs_cbmutex); 1728 1729 errout2: 1730 /* remove kstats */ 1731 kstat_delete(vdp->xs_kstats); 1732 1733 errout1: 1734 /* free up driver state */ 1735 ddi_set_driver_private(dip, NULL); 1736 cv_destroy(&vdp->xs_iocv); 1737 cv_destroy(&vdp->xs_ionumcv); 1738 mutex_destroy(&vdp->xs_cbmutex); 1739 mutex_destroy(&vdp->xs_iomutex); 1740 ddi_soft_state_free(xdb_statep, instance); 1741 1742 return (DDI_FAILURE); 1743 } 1744 1745 /*ARGSUSED*/ 1746 static int 1747 xdb_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1748 { 1749 int instance = ddi_get_instance(dip); 1750 xdb_t *vdp = XDB_INST2SOFTS(instance); 1751 1752 switch (cmd) { 1753 case DDI_SUSPEND: 1754 return (DDI_FAILURE); 1755 case DDI_DETACH: 1756 break; 1757 default: 1758 return (DDI_FAILURE); 1759 } 1760 1761 /* DDI_DETACH handling */ 1762 1763 /* refuse to detach if we're still in use by the frontend */ 1764 mutex_enter(&vdp->xs_iomutex); 1765 if (vdp->xs_if_connected) { 1766 mutex_exit(&vdp->xs_iomutex); 1767 return (DDI_FAILURE); 1768 } 1769 vdp->xs_send_buf = B_FALSE; 1770 cv_broadcast(&vdp->xs_iocv); 1771 mutex_exit(&vdp->xs_iomutex); 1772 1773 xvdi_remove_event_handler(dip, NULL); 1774 (void) xvdi_post_event(dip, XEN_HP_REMOVE); 1775 1776 ddi_taskq_destroy(vdp->xs_iotaskq); 1777 1778 mutex_enter(&vdp->xs_cbmutex); 1779 xvdi_remove_xb_watch_handlers(dip); 1780 mutex_exit(&vdp->xs_cbmutex); 1781 1782 cv_destroy(&vdp->xs_iocv); 1783 cv_destroy(&vdp->xs_ionumcv); 1784 mutex_destroy(&vdp->xs_cbmutex); 1785 mutex_destroy(&vdp->xs_iomutex); 1786 kstat_delete(vdp->xs_kstats); 1787 ddi_set_driver_private(dip, NULL); 1788 ddi_soft_state_free(xdb_statep, instance); 1789 1790 XDB_DBPRINT(XDB_DBG_INFO, (CE_NOTE, "xdb@%s: detached!", 1791 ddi_get_name_addr(dip))); 1792 return (DDI_SUCCESS); 1793 } 1794 1795 static struct dev_ops xdb_dev_ops = { 1796 DEVO_REV, /* devo_rev */ 1797 0, /* devo_refcnt */ 1798 ddi_getinfo_1to1, /* devo_getinfo */ 1799 nulldev, /* devo_identify */ 1800 nulldev, /* devo_probe */ 1801 xdb_attach, /* devo_attach */ 1802 xdb_detach, /* devo_detach */ 1803 nodev, /* devo_reset */ 1804 NULL, /* devo_cb_ops */ 1805 NULL, /* devo_bus_ops */ 1806 NULL, /* power */ 1807 ddi_quiesce_not_needed, /* quiesce */ 1808 }; 1809 1810 /* 1811 * Module linkage information for the kernel. 1812 */ 1813 static struct modldrv modldrv = { 1814 &mod_driverops, /* Type of module. */ 1815 "vbd backend driver", /* Name of the module */ 1816 &xdb_dev_ops /* driver ops */ 1817 }; 1818 1819 static struct modlinkage xdb_modlinkage = { 1820 MODREV_1, 1821 &modldrv, 1822 NULL 1823 }; 1824 1825 int 1826 _init(void) 1827 { 1828 int rv; 1829 1830 if ((rv = ddi_soft_state_init((void **)&xdb_statep, 1831 sizeof (xdb_t), 0)) == 0) 1832 if ((rv = mod_install(&xdb_modlinkage)) != 0) 1833 ddi_soft_state_fini((void **)&xdb_statep); 1834 return (rv); 1835 } 1836 1837 int 1838 _fini(void) 1839 { 1840 int rv; 1841 1842 if ((rv = mod_remove(&xdb_modlinkage)) != 0) 1843 return (rv); 1844 ddi_soft_state_fini((void **)&xdb_statep); 1845 return (rv); 1846 } 1847 1848 int 1849 _info(struct modinfo *modinfop) 1850 { 1851 return (mod_info(&xdb_modlinkage, modinfop)); 1852 } 1853 1854 static int 1855 xdb_get_request(xdb_t *vdp, blkif_request_t *req) 1856 { 1857 void *src = xvdi_ring_get_request(vdp->xs_ring); 1858 1859 if (src == NULL) 1860 return (0); 1861 1862 switch (vdp->xs_blk_protocol) { 1863 case BLKIF_PROTOCOL_NATIVE: 1864 (void) memcpy(req, src, sizeof (*req)); 1865 break; 1866 case BLKIF_PROTOCOL_X86_32: 1867 blkif_get_x86_32_req(req, src); 1868 break; 1869 case BLKIF_PROTOCOL_X86_64: 1870 blkif_get_x86_64_req(req, src); 1871 break; 1872 default: 1873 cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d", 1874 ddi_get_name_addr(vdp->xs_dip), 1875 vdp->xs_blk_protocol); 1876 } 1877 return (1); 1878 } 1879 1880 static int 1881 xdb_push_response(xdb_t *vdp, uint64_t id, uint8_t op, uint16_t status) 1882 { 1883 ddi_acc_handle_t acchdl = vdp->xs_ring_hdl; 1884 blkif_response_t *rsp = xvdi_ring_get_response(vdp->xs_ring); 1885 blkif_x86_32_response_t *rsp_32 = (blkif_x86_32_response_t *)rsp; 1886 blkif_x86_64_response_t *rsp_64 = (blkif_x86_64_response_t *)rsp; 1887 1888 ASSERT(rsp); 1889 1890 switch (vdp->xs_blk_protocol) { 1891 case BLKIF_PROTOCOL_NATIVE: 1892 ddi_put64(acchdl, &rsp->id, id); 1893 ddi_put8(acchdl, &rsp->operation, op); 1894 ddi_put16(acchdl, (uint16_t *)&rsp->status, 1895 status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); 1896 break; 1897 case BLKIF_PROTOCOL_X86_32: 1898 ddi_put64(acchdl, &rsp_32->id, id); 1899 ddi_put8(acchdl, &rsp_32->operation, op); 1900 ddi_put16(acchdl, (uint16_t *)&rsp_32->status, 1901 status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); 1902 break; 1903 case BLKIF_PROTOCOL_X86_64: 1904 ddi_put64(acchdl, &rsp_64->id, id); 1905 ddi_put8(acchdl, &rsp_64->operation, op); 1906 ddi_put16(acchdl, (uint16_t *)&rsp_64->status, 1907 status == 0 ? BLKIF_RSP_OKAY : BLKIF_RSP_ERROR); 1908 break; 1909 default: 1910 cmn_err(CE_PANIC, "xdb@%s: unrecognised protocol: %d", 1911 ddi_get_name_addr(vdp->xs_dip), 1912 vdp->xs_blk_protocol); 1913 } 1914 1915 return (xvdi_ring_push_response(vdp->xs_ring)); 1916 } 1917 1918 static void 1919 blkif_get_x86_32_req(blkif_request_t *dst, blkif_x86_32_request_t *src) 1920 { 1921 int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; 1922 dst->operation = src->operation; 1923 dst->nr_segments = src->nr_segments; 1924 dst->handle = src->handle; 1925 dst->id = src->id; 1926 dst->sector_number = src->sector_number; 1927 if (n > src->nr_segments) 1928 n = src->nr_segments; 1929 for (i = 0; i < n; i++) 1930 dst->seg[i] = src->seg[i]; 1931 } 1932 1933 static void 1934 blkif_get_x86_64_req(blkif_request_t *dst, blkif_x86_64_request_t *src) 1935 { 1936 int i, n = BLKIF_MAX_SEGMENTS_PER_REQUEST; 1937 dst->operation = src->operation; 1938 dst->nr_segments = src->nr_segments; 1939 dst->handle = src->handle; 1940 dst->id = src->id; 1941 dst->sector_number = src->sector_number; 1942 if (n > src->nr_segments) 1943 n = src->nr_segments; 1944 for (i = 0; i < n; i++) 1945 dst->seg[i] = src->seg[i]; 1946 } 1947