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 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Xen virtual device driver interfaces 31 */ 32 33 /* 34 * todo: 35 * + name space clean up: 36 * xvdi_* - public xen interfaces, for use by all leaf drivers 37 * xd_* - public xen data structures 38 * i_xvdi_* - implementation private functions 39 * xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops 40 * + add mdb dcmds to dump ring status 41 * + implement xvdi_xxx to wrap xenbus_xxx read/write function 42 * + convert (xendev_ring_t *) into xvdi_ring_handle_t 43 */ 44 #include <sys/conf.h> 45 #include <sys/param.h> 46 #include <sys/kmem.h> 47 #include <vm/seg_kmem.h> 48 #include <sys/debug.h> 49 #include <sys/modctl.h> 50 #include <sys/autoconf.h> 51 #include <sys/ddi_impldefs.h> 52 #include <sys/ddi_subrdefs.h> 53 #include <sys/ddi.h> 54 #include <sys/sunddi.h> 55 #include <sys/sunndi.h> 56 #include <sys/sunldi.h> 57 #include <sys/fs/dv_node.h> 58 #include <sys/avintr.h> 59 #include <sys/psm.h> 60 #include <sys/spl.h> 61 #include <sys/promif.h> 62 #include <sys/list.h> 63 #include <sys/bootconf.h> 64 #include <sys/bootsvcs.h> 65 #include <sys/bootinfo.h> 66 #include <sys/note.h> 67 #ifdef XPV_HVM_DRIVER 68 #include <sys/xpv_support.h> 69 #include <sys/hypervisor.h> 70 #include <public/grant_table.h> 71 #include <public/xen.h> 72 #include <public/io/xenbus.h> 73 #include <public/io/xs_wire.h> 74 #include <public/event_channel.h> 75 #include <public/io/xenbus.h> 76 #else /* XPV_HVM_DRIVER */ 77 #include <sys/hypervisor.h> 78 #include <sys/xen_mmu.h> 79 #include <xen/sys/xenbus_impl.h> 80 #include <sys/evtchn_impl.h> 81 #endif /* XPV_HVM_DRIVER */ 82 #include <sys/gnttab.h> 83 #include <xen/sys/xendev.h> 84 #include <vm/hat_i86.h> 85 #include <sys/scsi/generic/inquiry.h> 86 #include <util/sscanf.h> 87 #include <xen/public/io/xs_wire.h> 88 89 90 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9') 91 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \ 92 ((ch) >= 'A' && (ch) <= 'F')) 93 94 static void xvdi_ring_init_sring(xendev_ring_t *); 95 static void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t); 96 #ifndef XPV_HVM_DRIVER 97 static void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t); 98 #endif 99 static void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *); 100 101 static int i_xvdi_add_watches(dev_info_t *); 102 static void i_xvdi_rem_watches(dev_info_t *); 103 104 static int i_xvdi_add_watch_oestate(dev_info_t *); 105 static void i_xvdi_rem_watch_oestate(dev_info_t *); 106 static void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState); 107 static void i_xvdi_oestate_handler(void *); 108 109 static int i_xvdi_add_watch_hpstate(dev_info_t *); 110 static void i_xvdi_rem_watch_hpstate(dev_info_t *); 111 static void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **, 112 unsigned int); 113 static void i_xvdi_hpstate_handler(void *); 114 115 static int i_xvdi_add_watch_bepath(dev_info_t *); 116 static void i_xvdi_rem_watch_bepath(dev_info_t *); 117 static void i_xvdi_bepath_cb(struct xenbus_watch *, const char **, 118 unsigned in); 119 120 static void xendev_offline_device(void *); 121 122 static void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **, 123 unsigned int); 124 static void i_xvdi_probe_path_handler(void *); 125 126 typedef struct xd_cfg { 127 xendev_devclass_t devclass; 128 char *xsdev; 129 char *xs_path_fe; 130 char *xs_path_be; 131 char *node_fe; 132 char *node_be; 133 char *device_type; 134 int xd_ipl; 135 int flags; 136 } i_xd_cfg_t; 137 138 #define XD_DOM_ZERO 0x01 /* dom0 only. */ 139 #define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */ 140 #define XD_DOM_IO 0x04 /* IO domains. */ 141 142 #define XD_DOM_ALL (XD_DOM_ZERO | XD_DOM_GUEST) 143 144 static i_xd_cfg_t xdci[] = { 145 { XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL, 146 "console", IPL_CONS, XD_DOM_ALL, }, 147 148 { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb", 149 "network", IPL_VIF, XD_DOM_ALL, }, 150 151 { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb", 152 "block", IPL_VBD, XD_DOM_ALL, }, 153 154 { XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL, 155 NULL, 0, XD_DOM_ALL, }, 156 157 { XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL, 158 NULL, 0, XD_DOM_ALL, }, 159 160 { XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL, 161 NULL, 0, XD_DOM_ALL, }, 162 163 { XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL, 164 NULL, 0, XD_DOM_ZERO, }, 165 166 { XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL, 167 NULL, 0, XD_DOM_ZERO, }, 168 }; 169 #define NXDC (sizeof (xdci) / sizeof (xdci[0])) 170 171 static void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *); 172 static void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *); 173 static void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *); 174 175 /* 176 * Xen device channel device access and DMA attributes 177 */ 178 static ddi_device_acc_attr_t xendev_dc_accattr = { 179 DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC 180 }; 181 182 static ddi_dma_attr_t xendev_dc_dmaattr = { 183 DMA_ATTR_V0, /* version of this structure */ 184 0, /* lowest usable address */ 185 0xffffffffffffffffULL, /* highest usable address */ 186 0x7fffffff, /* maximum DMAable byte count */ 187 MMU_PAGESIZE, /* alignment in bytes */ 188 0x7ff, /* bitmap of burst sizes */ 189 1, /* minimum transfer */ 190 0xffffffffU, /* maximum transfer */ 191 0xffffffffffffffffULL, /* maximum segment length */ 192 1, /* maximum number of segments */ 193 1, /* granularity */ 194 0, /* flags (reserved) */ 195 }; 196 197 static dev_info_t *xendev_dip = NULL; 198 199 #define XVDI_DBG_STATE 0x01 200 #define XVDI_DBG_PROBE 0x02 201 202 #ifdef DEBUG 203 int i_xvdi_debug = 0; 204 205 #define XVDI_DPRINTF(flag, format, ...) \ 206 { \ 207 if (i_xvdi_debug & (flag)) \ 208 prom_printf((format), __VA_ARGS__); \ 209 } 210 #else 211 #define XVDI_DPRINTF(flag, format, ...) 212 #endif /* DEBUG */ 213 214 static i_xd_cfg_t * 215 i_xvdi_devclass2cfg(xendev_devclass_t devclass) 216 { 217 i_xd_cfg_t *xdcp; 218 int i; 219 220 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) 221 if (xdcp->devclass == devclass) 222 return (xdcp); 223 224 return (NULL); 225 } 226 227 int 228 xvdi_init_dev(dev_info_t *dip) 229 { 230 xendev_devclass_t devcls; 231 int vdevnum; 232 domid_t domid; 233 struct xendev_ppd *pdp; 234 i_xd_cfg_t *xdcp; 235 boolean_t backend; 236 char xsnamebuf[TYPICALMAXPATHLEN]; 237 char *xsname; 238 void *prop_str; 239 unsigned int prop_len; 240 char unitaddr[8]; 241 242 devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 243 DDI_PROP_DONTPASS, "devclass", XEN_INVAL); 244 vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 245 DDI_PROP_DONTPASS, "vdev", VDEV_NOXS); 246 domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, 247 DDI_PROP_DONTPASS, "domain", DOMID_SELF); 248 249 backend = (domid != DOMID_SELF); 250 xdcp = i_xvdi_devclass2cfg(devcls); 251 if (xdcp->device_type != NULL) 252 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 253 "device_type", xdcp->device_type); 254 255 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP); 256 pdp->xd_domain = domid; 257 pdp->xd_vdevnum = vdevnum; 258 pdp->xd_devclass = devcls; 259 pdp->xd_evtchn = INVALID_EVTCHN; 260 mutex_init(&pdp->xd_lk, NULL, MUTEX_DRIVER, NULL); 261 ddi_set_parent_data(dip, pdp); 262 263 /* 264 * devices that do not need to interact with xenstore 265 */ 266 if (vdevnum == VDEV_NOXS) { 267 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 268 "unit-address", "0"); 269 if (devcls == XEN_CONSOLE) 270 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 271 "pm-hardware-state", "needs-suspend-resume"); 272 return (DDI_SUCCESS); 273 } 274 275 /* 276 * PV devices that need to probe xenstore 277 */ 278 279 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 280 "pm-hardware-state", "needs-suspend-resume"); 281 282 xsname = xsnamebuf; 283 if (!backend) 284 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 285 "%s/%d", xdcp->xs_path_fe, vdevnum); 286 else 287 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 288 "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum); 289 if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) { 290 /* Don't try to init a dev that may be closing */ 291 mutex_destroy(&pdp->xd_lk); 292 kmem_free(pdp, sizeof (*pdp)); 293 ddi_set_parent_data(dip, NULL); 294 return (DDI_FAILURE); 295 } 296 297 pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP); 298 pdp->xd_xsdev.devicetype = xdcp->xsdev; 299 pdp->xd_xsdev.frontend = (backend ? 0 : 1); 300 pdp->xd_xsdev.data = dip; 301 pdp->xd_xsdev.otherend_id = (backend ? domid : -1); 302 if (i_xvdi_add_watches(dip) != DDI_SUCCESS) { 303 cmn_err(CE_WARN, "xvdi_init_dev: " 304 "cannot add watches for %s", xsname); 305 xvdi_uninit_dev(dip); 306 return (DDI_FAILURE); 307 } 308 309 if (backend) 310 return (DDI_SUCCESS); 311 312 /* 313 * The unit-address for frontend devices is the name of the 314 * of the xenstore node containing the device configuration 315 * and is contained in the 'vdev' property. 316 * VIF devices are named using an incrementing integer. 317 * VBD devices are either named using the 16-bit dev_t value 318 * for linux 'hd' and 'xvd' devices, or a simple integer value 319 * in the range 0..767. 768 is the base value of the linux 320 * dev_t namespace, the dev_t value for 'hda'. 321 */ 322 (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum); 323 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address", 324 unitaddr); 325 326 switch (devcls) { 327 case XEN_VNET: 328 if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str, 329 &prop_len) != 0) 330 break; 331 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac", 332 prop_str); 333 kmem_free(prop_str, prop_len); 334 break; 335 case XEN_VBLK: 336 /* 337 * cache a copy of the otherend name 338 * for ease of observeability 339 */ 340 if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, "dev", 341 &prop_str, &prop_len) != 0) 342 break; 343 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, 344 "dev-address", prop_str); 345 kmem_free(prop_str, prop_len); 346 break; 347 default: 348 break; 349 } 350 351 return (DDI_SUCCESS); 352 } 353 354 void 355 xvdi_uninit_dev(dev_info_t *dip) 356 { 357 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 358 359 if (pdp != NULL) { 360 /* Remove any registered callbacks. */ 361 xvdi_remove_event_handler(dip, NULL); 362 363 /* Remove any registered watches. */ 364 i_xvdi_rem_watches(dip); 365 366 /* tell other end to close */ 367 if (pdp->xd_xsdev.otherend_id != (domid_t)-1) 368 (void) xvdi_switch_state(dip, XBT_NULL, 369 XenbusStateClosed); 370 371 if (pdp->xd_xsdev.nodename != NULL) 372 kmem_free((char *)(pdp->xd_xsdev.nodename), 373 strlen(pdp->xd_xsdev.nodename) + 1); 374 375 ddi_set_parent_data(dip, NULL); 376 377 mutex_destroy(&pdp->xd_lk); 378 kmem_free(pdp, sizeof (*pdp)); 379 } 380 } 381 382 /* 383 * Bind the event channel for this device instance. 384 * Currently we only support one evtchn per device instance. 385 */ 386 int 387 xvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn) 388 { 389 struct xendev_ppd *pdp; 390 domid_t oeid; 391 int r; 392 393 pdp = ddi_get_parent_data(dip); 394 ASSERT(pdp != NULL); 395 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); 396 397 mutex_enter(&pdp->xd_lk); 398 if (pdp->xd_devclass == XEN_CONSOLE) { 399 if (!DOMAIN_IS_INITDOMAIN(xen_info)) { 400 pdp->xd_evtchn = xen_info->console.domU.evtchn; 401 } else { 402 pdp->xd_evtchn = INVALID_EVTCHN; 403 mutex_exit(&pdp->xd_lk); 404 return (DDI_SUCCESS); 405 } 406 } else { 407 oeid = pdp->xd_xsdev.otherend_id; 408 if (oeid == (domid_t)-1) { 409 mutex_exit(&pdp->xd_lk); 410 return (DDI_FAILURE); 411 } 412 413 if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) { 414 xvdi_dev_error(dip, r, "bind event channel"); 415 mutex_exit(&pdp->xd_lk); 416 return (DDI_FAILURE); 417 } 418 } 419 #ifndef XPV_HVM_DRIVER 420 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); 421 #endif 422 mutex_exit(&pdp->xd_lk); 423 424 return (DDI_SUCCESS); 425 } 426 427 /* 428 * Allocate an event channel for this device instance. 429 * Currently we only support one evtchn per device instance. 430 */ 431 int 432 xvdi_alloc_evtchn(dev_info_t *dip) 433 { 434 struct xendev_ppd *pdp; 435 domid_t oeid; 436 int rv; 437 438 pdp = ddi_get_parent_data(dip); 439 ASSERT(pdp != NULL); 440 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN); 441 442 mutex_enter(&pdp->xd_lk); 443 if (pdp->xd_devclass == XEN_CONSOLE) { 444 if (!DOMAIN_IS_INITDOMAIN(xen_info)) { 445 pdp->xd_evtchn = xen_info->console.domU.evtchn; 446 } else { 447 pdp->xd_evtchn = INVALID_EVTCHN; 448 mutex_exit(&pdp->xd_lk); 449 return (DDI_SUCCESS); 450 } 451 } else { 452 oeid = pdp->xd_xsdev.otherend_id; 453 if (oeid == (domid_t)-1) { 454 mutex_exit(&pdp->xd_lk); 455 return (DDI_FAILURE); 456 } 457 458 if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) { 459 xvdi_dev_error(dip, rv, "bind event channel"); 460 mutex_exit(&pdp->xd_lk); 461 return (DDI_FAILURE); 462 } 463 } 464 #ifndef XPV_HVM_DRIVER 465 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn); 466 #endif 467 mutex_exit(&pdp->xd_lk); 468 469 return (DDI_SUCCESS); 470 } 471 472 /* 473 * Unbind the event channel for this device instance. 474 * Currently we only support one evtchn per device instance. 475 */ 476 void 477 xvdi_free_evtchn(dev_info_t *dip) 478 { 479 struct xendev_ppd *pdp; 480 481 pdp = ddi_get_parent_data(dip); 482 ASSERT(pdp != NULL); 483 484 mutex_enter(&pdp->xd_lk); 485 if (pdp->xd_evtchn != INVALID_EVTCHN) { 486 #ifndef XPV_HVM_DRIVER 487 ec_unbind_irq(pdp->xd_ispec.intrspec_vec); 488 pdp->xd_ispec.intrspec_vec = 0; 489 #endif 490 pdp->xd_evtchn = INVALID_EVTCHN; 491 } 492 mutex_exit(&pdp->xd_lk); 493 } 494 495 #ifndef XPV_HVM_DRIVER 496 /* 497 * Map an inter-domain communication ring for a virtual device. 498 * This is used by backend drivers. 499 */ 500 int 501 xvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize, 502 grant_ref_t gref, xendev_ring_t **ringpp) 503 { 504 domid_t oeid; 505 gnttab_map_grant_ref_t mapop; 506 gnttab_unmap_grant_ref_t unmapop; 507 caddr_t ringva; 508 ddi_acc_hdl_t *ap; 509 ddi_acc_impl_t *iap; 510 xendev_ring_t *ring; 511 int err; 512 char errstr[] = "mapping in ring buffer"; 513 514 ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); 515 oeid = xvdi_get_oeid(dip); 516 517 /* alloc va in backend dom for ring buffer */ 518 ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE, 519 0, 0, 0, 0, VM_SLEEP); 520 521 /* map in ring page */ 522 hat_prepare_mapping(kas.a_hat, ringva); 523 mapop.host_addr = (uint64_t)(uintptr_t)ringva; 524 mapop.flags = GNTMAP_host_map; 525 mapop.ref = gref; 526 mapop.dom = oeid; 527 err = HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &mapop, 1); 528 if (err) { 529 xvdi_fatal_error(dip, err, errstr); 530 goto errout1; 531 } 532 533 if (mapop.status != 0) { 534 xvdi_fatal_error(dip, err, errstr); 535 goto errout2; 536 } 537 ring->xr_vaddr = ringva; 538 ring->xr_grant_hdl = mapop.handle; 539 ring->xr_gref = gref; 540 541 /* 542 * init an acc handle and associate it w/ this ring 543 * this is only for backend drivers. we get the memory by calling 544 * vmem_xalloc(), instead of calling any ddi function, so we have 545 * to init an acc handle by ourselves 546 */ 547 ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL); 548 ap = impl_acc_hdl_get(ring->xr_acc_hdl); 549 ap->ah_vers = VERS_ACCHDL; 550 ap->ah_dip = dip; 551 ap->ah_xfermodes = DDI_DMA_CONSISTENT; 552 ap->ah_acc = xendev_dc_accattr; 553 iap = (ddi_acc_impl_t *)ap->ah_platform_private; 554 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR; 555 impl_acc_hdl_init(ap); 556 ap->ah_offset = 0; 557 ap->ah_len = (off_t)PAGESIZE; 558 ap->ah_addr = ring->xr_vaddr; 559 560 /* init backend ring */ 561 xvdi_ring_init_back_ring(ring, nentry, entrysize); 562 563 *ringpp = ring; 564 565 return (DDI_SUCCESS); 566 567 errout2: 568 /* unmap ring page */ 569 unmapop.host_addr = (uint64_t)(uintptr_t)ringva; 570 unmapop.handle = ring->xr_grant_hdl; 571 unmapop.dev_bus_addr = NULL; 572 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); 573 hat_release_mapping(kas.a_hat, ringva); 574 errout1: 575 vmem_xfree(heap_arena, ringva, PAGESIZE); 576 kmem_free(ring, sizeof (xendev_ring_t)); 577 return (DDI_FAILURE); 578 } 579 580 /* 581 * Unmap a ring for a virtual device. 582 * This is used by backend drivers. 583 */ 584 void 585 xvdi_unmap_ring(xendev_ring_t *ring) 586 { 587 gnttab_unmap_grant_ref_t unmapop; 588 589 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); 590 591 impl_acc_hdl_free(ring->xr_acc_hdl); 592 unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr; 593 unmapop.handle = ring->xr_grant_hdl; 594 unmapop.dev_bus_addr = NULL; 595 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1); 596 hat_release_mapping(kas.a_hat, ring->xr_vaddr); 597 vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE); 598 kmem_free(ring, sizeof (xendev_ring_t)); 599 } 600 #endif /* XPV_HVM_DRIVER */ 601 602 /* 603 * Re-initialise an inter-domain communications ring for the backend domain. 604 * ring will be re-initialized after re-grant succeed 605 * ring will be freed if fails to re-grant access to backend domain 606 * so, don't keep useful data in the ring 607 * used only in frontend driver 608 */ 609 static void 610 xvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp) 611 { 612 paddr_t rpaddr; 613 maddr_t rmaddr; 614 615 ASSERT((ringp != NULL) && (ringp->xr_paddr != 0)); 616 rpaddr = ringp->xr_paddr; 617 618 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr); 619 gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip), 620 rmaddr >> PAGESHIFT, 0); 621 *gref = ringp->xr_gref; 622 623 /* init frontend ring */ 624 xvdi_ring_init_sring(ringp); 625 xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents, 626 ringp->xr_entry_size); 627 } 628 629 /* 630 * allocate Xen inter-domain communications ring for Xen virtual devices 631 * used only in frontend driver 632 * if *ringpp is not NULL, we'll simply re-init it 633 */ 634 int 635 xvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize, 636 grant_ref_t *gref, xendev_ring_t **ringpp) 637 { 638 size_t len; 639 xendev_ring_t *ring; 640 ddi_dma_cookie_t dma_cookie; 641 uint_t ncookies; 642 grant_ref_t ring_gref; 643 domid_t oeid; 644 maddr_t rmaddr; 645 646 if (*ringpp) { 647 xvdi_reinit_ring(dip, gref, *ringpp); 648 return (DDI_SUCCESS); 649 } 650 651 *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP); 652 oeid = xvdi_get_oeid(dip); 653 654 /* 655 * Allocate page for this ring buffer 656 */ 657 if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP, 658 0, &ring->xr_dma_hdl) != DDI_SUCCESS) 659 goto err; 660 661 if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE, 662 &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0, 663 &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) { 664 ddi_dma_free_handle(&ring->xr_dma_hdl); 665 goto err; 666 } 667 668 if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL, 669 ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT, 670 DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) { 671 ddi_dma_mem_free(&ring->xr_acc_hdl); 672 ring->xr_vaddr = NULL; 673 ddi_dma_free_handle(&ring->xr_dma_hdl); 674 goto err; 675 } 676 ASSERT(ncookies == 1); 677 ring->xr_paddr = dma_cookie.dmac_laddress; 678 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr : 679 pa_to_ma(ring->xr_paddr); 680 681 if ((ring_gref = gnttab_grant_foreign_access(oeid, 682 rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) { 683 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); 684 ddi_dma_mem_free(&ring->xr_acc_hdl); 685 ring->xr_vaddr = NULL; 686 ddi_dma_free_handle(&ring->xr_dma_hdl); 687 goto err; 688 } 689 *gref = ring->xr_gref = ring_gref; 690 691 /* init frontend ring */ 692 xvdi_ring_init_sring(ring); 693 xvdi_ring_init_front_ring(ring, nentry, entrysize); 694 695 return (DDI_SUCCESS); 696 697 err: 698 kmem_free(ring, sizeof (xendev_ring_t)); 699 return (DDI_FAILURE); 700 } 701 702 /* 703 * Release ring buffers allocated for Xen devices 704 * used for frontend driver 705 */ 706 void 707 xvdi_free_ring(xendev_ring_t *ring) 708 { 709 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL)); 710 711 (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0); 712 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl); 713 ddi_dma_mem_free(&ring->xr_acc_hdl); 714 ddi_dma_free_handle(&ring->xr_dma_hdl); 715 kmem_free(ring, sizeof (xendev_ring_t)); 716 } 717 718 dev_info_t * 719 xvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass, 720 domid_t dom, int vdev) 721 { 722 dev_info_t *dip; 723 boolean_t backend; 724 i_xd_cfg_t *xdcp; 725 char xsnamebuf[TYPICALMAXPATHLEN]; 726 char *type, *node = NULL, *xsname = NULL; 727 unsigned int tlen; 728 int ret; 729 730 ASSERT(DEVI_BUSY_OWNED(parent)); 731 732 backend = (dom != DOMID_SELF); 733 xdcp = i_xvdi_devclass2cfg(devclass); 734 ASSERT(xdcp != NULL); 735 736 if (vdev != VDEV_NOXS) { 737 if (!backend) { 738 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 739 "%s/%d", xdcp->xs_path_fe, vdev); 740 xsname = xsnamebuf; 741 node = xdcp->node_fe; 742 } else { 743 (void) snprintf(xsnamebuf, sizeof (xsnamebuf), 744 "%s/%d/%d", xdcp->xs_path_be, dom, vdev); 745 xsname = xsnamebuf; 746 node = xdcp->node_be; 747 } 748 } else { 749 node = xdcp->node_fe; 750 } 751 752 /* Must have a driver to use. */ 753 if (node == NULL) 754 return (NULL); 755 756 /* 757 * We need to check the state of this device before we go 758 * further, otherwise we'll end up with a dead loop if 759 * anything goes wrong. 760 */ 761 if ((xsname != NULL) && 762 (xenbus_read_driver_state(xsname) >= XenbusStateClosing)) 763 return (NULL); 764 765 ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip); 766 767 /* 768 * Driver binding uses the compatible property _before_ the 769 * node name, so we set the node name to the 'model' of the 770 * device (i.e. 'xnb' or 'xdb') and, if 'type' is present, 771 * encode both the model and the type in a compatible property 772 * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac'). This allows a 773 * driver binding based on the <model,type> pair _before_ a 774 * binding based on the node name. 775 */ 776 if ((xsname != NULL) && 777 (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen) 778 == 0)) { 779 size_t clen; 780 char *c[1]; 781 782 clen = strlen(node) + strlen(type) + 2; 783 c[0] = kmem_alloc(clen, KM_SLEEP); 784 (void) snprintf(c[0], clen, "%s,%s", node, type); 785 786 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, 787 dip, "compatible", (char **)c, 1); 788 789 kmem_free(c[0], clen); 790 kmem_free(type, tlen); 791 } 792 793 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass); 794 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom); 795 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev); 796 797 if (i_ddi_devi_attached(parent)) 798 ret = ndi_devi_online(dip, 0); 799 else 800 ret = ndi_devi_bind_driver(dip, 0); 801 if (ret != NDI_SUCCESS) 802 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); 803 804 return (dip); 805 } 806 807 /* 808 * xendev_enum_class() 809 */ 810 void 811 xendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass) 812 { 813 boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); 814 boolean_t domU = !dom0; 815 i_xd_cfg_t *xdcp; 816 817 xdcp = i_xvdi_devclass2cfg(devclass); 818 ASSERT(xdcp != NULL); 819 820 if (dom0 && !(xdcp->flags & XD_DOM_ZERO)) 821 return; 822 823 if (domU && !(xdcp->flags & XD_DOM_GUEST)) 824 return; 825 826 if (xdcp->xsdev == NULL) { 827 int circ; 828 829 /* 830 * Don't need to probe this kind of device from the 831 * store, just create one if it doesn't exist. 832 */ 833 834 ndi_devi_enter(parent, &circ); 835 if (xvdi_find_dev(parent, devclass, DOMID_SELF, VDEV_NOXS) 836 == NULL) 837 (void) xvdi_create_dev(parent, devclass, 838 DOMID_SELF, VDEV_NOXS); 839 ndi_devi_exit(parent, circ); 840 } else { 841 /* 842 * Probe this kind of device from the store, both 843 * frontend and backend. 844 */ 845 846 i_xvdi_enum_fe(parent, xdcp); 847 i_xvdi_enum_be(parent, xdcp); 848 } 849 } 850 851 /* 852 * xendev_enum_all() 853 */ 854 void 855 xendev_enum_all(dev_info_t *parent, boolean_t store_unavailable) 856 { 857 int i; 858 i_xd_cfg_t *xdcp; 859 boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info); 860 861 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { 862 /* 863 * Dom0 relies on watchpoints to create non-soft 864 * devices - don't attempt to iterate over the store. 865 */ 866 if (dom0 && (xdcp->xsdev != NULL)) 867 continue; 868 869 /* 870 * If the store is not yet available, don't attempt to 871 * iterate. 872 */ 873 if (store_unavailable && (xdcp->xsdev != NULL)) 874 continue; 875 876 xendev_enum_class(parent, xdcp->devclass); 877 } 878 } 879 880 xendev_devclass_t 881 xendev_nodename_to_devclass(char *nodename) 882 { 883 int i; 884 i_xd_cfg_t *xdcp; 885 886 /* 887 * This relies on the convention that variants of a base 888 * driver share the same prefix and that there are no drivers 889 * which share a common prefix with the name of any other base 890 * drivers. 891 * 892 * So for a base driver 'xnb' (which is the name listed in 893 * xdci) the variants all begin with the string 'xnb' (in fact 894 * they are 'xnbe', 'xnbo' and 'xnbu') and there are no other 895 * base drivers which have the prefix 'xnb'. 896 */ 897 ASSERT(nodename != NULL); 898 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++) { 899 if (((xdcp->node_fe != NULL) && 900 (strncmp(nodename, xdcp->node_fe, 901 strlen(xdcp->node_fe)) == 0)) || 902 ((xdcp->node_be != NULL) && 903 (strncmp(nodename, xdcp->node_be, 904 strlen(xdcp->node_be)) == 0))) 905 906 return (xdcp->devclass); 907 } 908 return (XEN_INVAL); 909 } 910 911 int 912 xendev_devclass_ipl(xendev_devclass_t devclass) 913 { 914 i_xd_cfg_t *xdcp; 915 916 xdcp = i_xvdi_devclass2cfg(devclass); 917 ASSERT(xdcp != NULL); 918 919 return (xdcp->xd_ipl); 920 } 921 922 /* 923 * Determine if a devinfo instance exists of a particular device 924 * class, domain and xenstore virtual device number. 925 */ 926 dev_info_t * 927 xvdi_find_dev(dev_info_t *parent, xendev_devclass_t devclass, 928 domid_t dom, int vdev) 929 { 930 dev_info_t *dip; 931 932 ASSERT(DEVI_BUSY_OWNED(parent)); 933 934 switch (devclass) { 935 case XEN_CONSOLE: 936 case XEN_XENBUS: 937 case XEN_DOMCAPS: 938 case XEN_BALLOON: 939 case XEN_EVTCHN: 940 case XEN_PRIVCMD: 941 /* Console and soft devices have no vdev. */ 942 vdev = VDEV_NOXS; 943 break; 944 default: 945 break; 946 } 947 948 for (dip = ddi_get_child(parent); dip != NULL; 949 dip = ddi_get_next_sibling(dip)) { 950 int *vdevnump, *domidp, *devclsp, vdevnum; 951 uint_t ndomid, nvdevnum, ndevcls; 952 xendev_devclass_t devcls; 953 domid_t domid; 954 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 955 956 if (pdp == NULL) { 957 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 958 DDI_PROP_DONTPASS, "domain", &domidp, &ndomid) != 959 DDI_PROP_SUCCESS) 960 continue; 961 ASSERT(ndomid == 1); 962 domid = (domid_t)*domidp; 963 ddi_prop_free(domidp); 964 965 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 966 DDI_PROP_DONTPASS, "vdev", &vdevnump, &nvdevnum) != 967 DDI_PROP_SUCCESS) 968 continue; 969 ASSERT(nvdevnum == 1); 970 vdevnum = *vdevnump; 971 ddi_prop_free(vdevnump); 972 973 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, 974 DDI_PROP_DONTPASS, "devclass", &devclsp, 975 &ndevcls) != DDI_PROP_SUCCESS) 976 continue; 977 ASSERT(ndevcls == 1); 978 devcls = (xendev_devclass_t)*devclsp; 979 ddi_prop_free(devclsp); 980 } else { 981 domid = pdp->xd_domain; 982 vdevnum = pdp->xd_vdevnum; 983 devcls = pdp->xd_devclass; 984 } 985 986 if ((domid == dom) && (vdevnum == vdev) && (devcls == devclass)) 987 return (dip); 988 } 989 return (NULL); 990 } 991 992 int 993 xvdi_get_evtchn(dev_info_t *xdip) 994 { 995 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 996 997 ASSERT(pdp != NULL); 998 return (pdp->xd_evtchn); 999 } 1000 1001 int 1002 xvdi_get_vdevnum(dev_info_t *xdip) 1003 { 1004 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1005 1006 ASSERT(pdp != NULL); 1007 return (pdp->xd_vdevnum); 1008 } 1009 1010 char * 1011 xvdi_get_xsname(dev_info_t *xdip) 1012 { 1013 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1014 1015 ASSERT(pdp != NULL); 1016 return ((char *)(pdp->xd_xsdev.nodename)); 1017 } 1018 1019 char * 1020 xvdi_get_oename(dev_info_t *xdip) 1021 { 1022 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1023 1024 ASSERT(pdp != NULL); 1025 if (pdp->xd_devclass == XEN_CONSOLE) 1026 return (NULL); 1027 return ((char *)(pdp->xd_xsdev.otherend)); 1028 } 1029 1030 struct xenbus_device * 1031 xvdi_get_xsd(dev_info_t *xdip) 1032 { 1033 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1034 1035 ASSERT(pdp != NULL); 1036 return (&pdp->xd_xsdev); 1037 } 1038 1039 domid_t 1040 xvdi_get_oeid(dev_info_t *xdip) 1041 { 1042 struct xendev_ppd *pdp = ddi_get_parent_data(xdip); 1043 1044 ASSERT(pdp != NULL); 1045 if (pdp->xd_devclass == XEN_CONSOLE) 1046 return ((domid_t)-1); 1047 return ((domid_t)(pdp->xd_xsdev.otherend_id)); 1048 } 1049 1050 void 1051 xvdi_dev_error(dev_info_t *dip, int errno, char *errstr) 1052 { 1053 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1054 1055 ASSERT(pdp != NULL); 1056 xenbus_dev_error(&pdp->xd_xsdev, errno, errstr); 1057 } 1058 1059 void 1060 xvdi_fatal_error(dev_info_t *dip, int errno, char *errstr) 1061 { 1062 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1063 1064 ASSERT(pdp != NULL); 1065 xenbus_dev_fatal(&pdp->xd_xsdev, errno, errstr); 1066 } 1067 1068 static void 1069 i_xvdi_oestate_handler(void *arg) 1070 { 1071 dev_info_t *dip = arg; 1072 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1073 XenbusState oestate = pdp->xd_xsdev.otherend_state; 1074 ddi_eventcookie_t evc; 1075 1076 mutex_enter(&pdp->xd_lk); 1077 1078 if (pdp->xd_oe_ehid != NULL) { 1079 /* send notification to driver */ 1080 if (ddi_get_eventcookie(dip, XS_OE_STATE, 1081 &evc) == DDI_SUCCESS) { 1082 mutex_exit(&pdp->xd_lk); 1083 (void) ndi_post_event(dip, dip, evc, &oestate); 1084 mutex_enter(&pdp->xd_lk); 1085 } 1086 } else { 1087 /* 1088 * take default action, if driver hasn't registered its 1089 * event handler yet 1090 */ 1091 if (oestate == XenbusStateClosing) { 1092 (void) xvdi_switch_state(dip, XBT_NULL, 1093 XenbusStateClosed); 1094 } else if (oestate == XenbusStateClosed) { 1095 (void) xvdi_switch_state(dip, XBT_NULL, 1096 XenbusStateClosed); 1097 (void) xvdi_post_event(dip, XEN_HP_REMOVE); 1098 } 1099 } 1100 1101 mutex_exit(&pdp->xd_lk); 1102 1103 /* 1104 * We'll try to remove the devinfo node of this device if the 1105 * other end has closed. 1106 */ 1107 if (oestate == XenbusStateClosed) 1108 (void) ddi_taskq_dispatch(DEVI(ddi_get_parent(dip))->devi_taskq, 1109 xendev_offline_device, dip, DDI_SLEEP); 1110 } 1111 1112 static void 1113 i_xvdi_hpstate_handler(void *arg) 1114 { 1115 dev_info_t *dip = (dev_info_t *)arg; 1116 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1117 ddi_eventcookie_t evc; 1118 char *hp_status; 1119 unsigned int hpl; 1120 1121 mutex_enter(&pdp->xd_lk); 1122 if ((ddi_get_eventcookie(dip, XS_HP_STATE, &evc) == DDI_SUCCESS) && 1123 (xenbus_read(XBT_NULL, pdp->xd_hp_watch.node, "", 1124 (void *)&hp_status, &hpl) == 0)) { 1125 1126 xendev_hotplug_state_t new_state = Unrecognized; 1127 1128 if (strcmp(hp_status, "connected") == 0) 1129 new_state = Connected; 1130 1131 mutex_exit(&pdp->xd_lk); 1132 1133 (void) ndi_post_event(dip, dip, evc, &new_state); 1134 kmem_free(hp_status, hpl); 1135 return; 1136 } 1137 mutex_exit(&pdp->xd_lk); 1138 } 1139 1140 void 1141 xvdi_notify_oe(dev_info_t *dip) 1142 { 1143 struct xendev_ppd *pdp; 1144 1145 pdp = ddi_get_parent_data(dip); 1146 ASSERT(pdp->xd_evtchn != INVALID_EVTCHN); 1147 ec_notify_via_evtchn(pdp->xd_evtchn); 1148 } 1149 1150 static void 1151 i_xvdi_bepath_cb(struct xenbus_watch *w, const char **vec, unsigned int len) 1152 { 1153 dev_info_t *dip = (dev_info_t *)w->dev; 1154 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1155 char *be = NULL; 1156 unsigned int bel; 1157 1158 ASSERT(len > XS_WATCH_PATH); 1159 ASSERT(vec[XS_WATCH_PATH] != NULL); 1160 1161 /* 1162 * If the backend is not the same as that we already stored, 1163 * re-set our watch for its' state. 1164 */ 1165 if ((xenbus_read(XBT_NULL, "", vec[XS_WATCH_PATH], (void *)be, &bel) 1166 == 0) && (strcmp(be, pdp->xd_xsdev.otherend) != 0)) 1167 (void) i_xvdi_add_watch_oestate(dip); 1168 1169 if (be != NULL) { 1170 ASSERT(bel > 0); 1171 kmem_free(be, bel); 1172 } 1173 } 1174 1175 static int 1176 i_xvdi_add_watch_oestate(dev_info_t *dip) 1177 { 1178 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1179 1180 ASSERT(pdp != NULL); 1181 ASSERT(pdp->xd_xsdev.nodename != NULL); 1182 ASSERT(mutex_owned(&pdp->xd_lk)); 1183 1184 /* 1185 * Create taskq for delivering other end state change event to 1186 * this device later. 1187 * 1188 * Set nthreads to 1 to make sure that events can be delivered 1189 * in order. 1190 * 1191 * Note: It is _not_ guaranteed that driver can see every 1192 * xenstore change under the path that it is watching. If two 1193 * changes happen consecutively in a very short amount of 1194 * time, it is likely that the driver will see only the last 1195 * one. 1196 */ 1197 if (pdp->xd_oe_taskq == NULL) 1198 if ((pdp->xd_oe_taskq = ddi_taskq_create(dip, 1199 "xendev_oe_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) 1200 return (DDI_FAILURE); 1201 1202 /* 1203 * Watch for changes to the XenbusState of otherend. 1204 */ 1205 pdp->xd_xsdev.otherend_state = XenbusStateUnknown; 1206 pdp->xd_xsdev.otherend_changed = i_xvdi_oestate_cb; 1207 1208 if (talk_to_otherend(&pdp->xd_xsdev) != 0) { 1209 i_xvdi_rem_watch_oestate(dip); 1210 return (DDI_FAILURE); 1211 } 1212 1213 return (DDI_SUCCESS); 1214 } 1215 1216 static void 1217 i_xvdi_rem_watch_oestate(dev_info_t *dip) 1218 { 1219 struct xendev_ppd *pdp; 1220 struct xenbus_device *dev; 1221 1222 pdp = ddi_get_parent_data(dip); 1223 ASSERT(pdp != NULL); 1224 ASSERT(mutex_owned(&pdp->xd_lk)); 1225 1226 dev = &pdp->xd_xsdev; 1227 1228 /* Unwatch for changes to XenbusState of otherend */ 1229 if (dev->otherend_watch.node != NULL) { 1230 mutex_exit(&pdp->xd_lk); 1231 unregister_xenbus_watch(&dev->otherend_watch); 1232 mutex_enter(&pdp->xd_lk); 1233 } 1234 1235 /* make sure no event handler is running */ 1236 if (pdp->xd_oe_taskq != NULL) { 1237 mutex_exit(&pdp->xd_lk); 1238 ddi_taskq_destroy(pdp->xd_oe_taskq); 1239 mutex_enter(&pdp->xd_lk); 1240 pdp->xd_oe_taskq = NULL; 1241 } 1242 1243 /* clean up */ 1244 dev->otherend_state = XenbusStateUnknown; 1245 dev->otherend_id = (domid_t)-1; 1246 if (dev->otherend_watch.node != NULL) 1247 kmem_free((void *)dev->otherend_watch.node, 1248 strlen(dev->otherend_watch.node) + 1); 1249 dev->otherend_watch.node = NULL; 1250 if (dev->otherend != NULL) 1251 kmem_free((void *)dev->otherend, strlen(dev->otherend) + 1); 1252 dev->otherend = NULL; 1253 } 1254 1255 static int 1256 i_xvdi_add_watch_hpstate(dev_info_t *dip) 1257 { 1258 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1259 1260 ASSERT(pdp != NULL); 1261 ASSERT(pdp->xd_xsdev.frontend == 0); 1262 ASSERT(mutex_owned(&pdp->xd_lk)); 1263 1264 /* 1265 * Create taskq for delivering hotplug status change event to 1266 * this device later. 1267 * 1268 * Set nthreads to 1 to make sure that events can be delivered 1269 * in order. 1270 * 1271 * Note: It is _not_ guaranteed that driver can see every 1272 * hotplug status change under the path that it is 1273 * watching. If two changes happen consecutively in a very 1274 * short amount of time, it is likely that the driver only 1275 * sees the last one. 1276 */ 1277 if (pdp->xd_hp_taskq == NULL) 1278 if ((pdp->xd_hp_taskq = ddi_taskq_create(dip, 1279 "xendev_hp_taskq", 1, TASKQ_DEFAULTPRI, 0)) == NULL) 1280 return (DDI_FAILURE); 1281 1282 if (pdp->xd_hp_watch.node == NULL) { 1283 size_t len; 1284 char *path; 1285 1286 ASSERT(pdp->xd_xsdev.nodename != NULL); 1287 1288 len = strlen(pdp->xd_xsdev.nodename) + 1289 strlen("/hotplug-status") + 1; 1290 path = kmem_alloc(len, KM_SLEEP); 1291 (void) snprintf(path, len, "%s/hotplug-status", 1292 pdp->xd_xsdev.nodename); 1293 1294 pdp->xd_hp_watch.node = path; 1295 pdp->xd_hp_watch.callback = i_xvdi_hpstate_cb; 1296 pdp->xd_hp_watch.dev = (struct xenbus_device *)dip; /* yuck! */ 1297 if (register_xenbus_watch(&pdp->xd_hp_watch) != 0) { 1298 i_xvdi_rem_watch_hpstate(dip); 1299 return (DDI_FAILURE); 1300 } 1301 } 1302 1303 return (DDI_SUCCESS); 1304 } 1305 1306 static void 1307 i_xvdi_rem_watch_hpstate(dev_info_t *dip) 1308 { 1309 struct xendev_ppd *pdp; 1310 pdp = ddi_get_parent_data(dip); 1311 1312 ASSERT(pdp != NULL); 1313 ASSERT(pdp->xd_xsdev.frontend == 0); 1314 ASSERT(mutex_owned(&pdp->xd_lk)); 1315 1316 /* Unwatch for changes to "hotplug-status" node for backend device. */ 1317 if (pdp->xd_hp_watch.node != NULL) { 1318 mutex_exit(&pdp->xd_lk); 1319 unregister_xenbus_watch(&pdp->xd_hp_watch); 1320 mutex_enter(&pdp->xd_lk); 1321 } 1322 1323 /* Make sure no event handler is running. */ 1324 if (pdp->xd_hp_taskq != NULL) { 1325 mutex_exit(&pdp->xd_lk); 1326 ddi_taskq_destroy(pdp->xd_hp_taskq); 1327 mutex_enter(&pdp->xd_lk); 1328 pdp->xd_hp_taskq = NULL; 1329 } 1330 1331 /* Clean up. */ 1332 if (pdp->xd_hp_watch.node != NULL) { 1333 kmem_free((void *)pdp->xd_hp_watch.node, 1334 strlen(pdp->xd_hp_watch.node) + 1); 1335 pdp->xd_hp_watch.node = NULL; 1336 } 1337 } 1338 1339 static int 1340 i_xvdi_add_watches(dev_info_t *dip) 1341 { 1342 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1343 1344 ASSERT(pdp != NULL); 1345 1346 mutex_enter(&pdp->xd_lk); 1347 1348 if (i_xvdi_add_watch_oestate(dip) != DDI_SUCCESS) { 1349 mutex_exit(&pdp->xd_lk); 1350 return (DDI_FAILURE); 1351 } 1352 1353 if (pdp->xd_xsdev.frontend == 1) { 1354 /* 1355 * Frontend devices must watch for the backend path 1356 * changing. 1357 */ 1358 if (i_xvdi_add_watch_bepath(dip) != DDI_SUCCESS) 1359 goto unwatch_and_fail; 1360 } else { 1361 /* 1362 * Backend devices must watch for hotplug events. 1363 */ 1364 if (i_xvdi_add_watch_hpstate(dip) != DDI_SUCCESS) 1365 goto unwatch_and_fail; 1366 } 1367 1368 mutex_exit(&pdp->xd_lk); 1369 1370 return (DDI_SUCCESS); 1371 1372 unwatch_and_fail: 1373 i_xvdi_rem_watch_oestate(dip); 1374 mutex_exit(&pdp->xd_lk); 1375 1376 return (DDI_FAILURE); 1377 } 1378 1379 static void 1380 i_xvdi_rem_watches(dev_info_t *dip) 1381 { 1382 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1383 1384 ASSERT(pdp != NULL); 1385 1386 mutex_enter(&pdp->xd_lk); 1387 1388 i_xvdi_rem_watch_oestate(dip); 1389 1390 if (pdp->xd_xsdev.frontend == 1) 1391 i_xvdi_rem_watch_bepath(dip); 1392 else 1393 i_xvdi_rem_watch_hpstate(dip); 1394 1395 mutex_exit(&pdp->xd_lk); 1396 } 1397 1398 static int 1399 i_xvdi_add_watch_bepath(dev_info_t *dip) 1400 { 1401 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1402 1403 ASSERT(pdp != NULL); 1404 ASSERT(pdp->xd_xsdev.frontend == 1); 1405 1406 /* 1407 * Frontend devices need to watch for the backend path changing. 1408 */ 1409 if (pdp->xd_bepath_watch.node == NULL) { 1410 size_t len; 1411 char *path; 1412 1413 ASSERT(pdp->xd_xsdev.nodename != NULL); 1414 1415 len = strlen(pdp->xd_xsdev.nodename) + strlen("/backend") + 1; 1416 path = kmem_alloc(len, KM_SLEEP); 1417 (void) snprintf(path, len, "%s/backend", 1418 pdp->xd_xsdev.nodename); 1419 1420 pdp->xd_bepath_watch.node = path; 1421 pdp->xd_bepath_watch.callback = i_xvdi_bepath_cb; 1422 pdp->xd_bepath_watch.dev = (struct xenbus_device *)dip; 1423 if (register_xenbus_watch(&pdp->xd_bepath_watch) != 0) { 1424 kmem_free(path, len); 1425 pdp->xd_bepath_watch.node = NULL; 1426 return (DDI_FAILURE); 1427 } 1428 } 1429 1430 return (DDI_SUCCESS); 1431 } 1432 1433 static void 1434 i_xvdi_rem_watch_bepath(dev_info_t *dip) 1435 { 1436 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1437 1438 ASSERT(pdp != NULL); 1439 ASSERT(pdp->xd_xsdev.frontend == 1); 1440 ASSERT(mutex_owned(&pdp->xd_lk)); 1441 1442 if (pdp->xd_bepath_watch.node != NULL) { 1443 mutex_exit(&pdp->xd_lk); 1444 unregister_xenbus_watch(&pdp->xd_bepath_watch); 1445 mutex_enter(&pdp->xd_lk); 1446 1447 kmem_free((void *)(pdp->xd_bepath_watch.node), 1448 strlen(pdp->xd_bepath_watch.node) + 1); 1449 pdp->xd_bepath_watch.node = NULL; 1450 } 1451 } 1452 1453 int 1454 xvdi_switch_state(dev_info_t *dip, xenbus_transaction_t xbt, 1455 XenbusState newState) 1456 { 1457 int rv; 1458 struct xendev_ppd *pdp; 1459 1460 pdp = ddi_get_parent_data(dip); 1461 ASSERT(pdp != NULL); 1462 1463 XVDI_DPRINTF(XVDI_DBG_STATE, 1464 "xvdi_switch_state: dip 0x%p moves to %d", 1465 (void *)dip, newState); 1466 1467 rv = xenbus_switch_state(&pdp->xd_xsdev, xbt, newState); 1468 if (rv > 0) 1469 cmn_err(CE_WARN, "xvdi_switch_state: change state failed"); 1470 1471 return (rv); 1472 } 1473 1474 /* 1475 * Notify hotplug script running in userland 1476 */ 1477 int 1478 xvdi_post_event(dev_info_t *dip, xendev_hotplug_cmd_t hpc) 1479 { 1480 struct xendev_ppd *pdp; 1481 nvlist_t *attr_list = NULL; 1482 i_xd_cfg_t *xdcp; 1483 sysevent_id_t eid; 1484 int err; 1485 char devname[256]; /* XXPV dme: ? */ 1486 1487 pdp = ddi_get_parent_data(dip); 1488 ASSERT(pdp != NULL); 1489 1490 xdcp = i_xvdi_devclass2cfg(pdp->xd_devclass); 1491 ASSERT(xdcp != NULL); 1492 1493 (void) snprintf(devname, sizeof (devname) - 1, "%s%d", 1494 ddi_driver_name(dip), ddi_get_instance(dip)); 1495 1496 err = nvlist_alloc(&attr_list, NV_UNIQUE_NAME, KM_NOSLEEP); 1497 if (err != DDI_SUCCESS) 1498 goto failure; 1499 1500 err = nvlist_add_int32(attr_list, "domain", pdp->xd_domain); 1501 if (err != DDI_SUCCESS) 1502 goto failure; 1503 err = nvlist_add_int32(attr_list, "vdev", pdp->xd_vdevnum); 1504 if (err != DDI_SUCCESS) 1505 goto failure; 1506 err = nvlist_add_string(attr_list, "devclass", xdcp->xsdev); 1507 if (err != DDI_SUCCESS) 1508 goto failure; 1509 err = nvlist_add_string(attr_list, "device", devname); 1510 if (err != DDI_SUCCESS) 1511 goto failure; 1512 err = nvlist_add_string(attr_list, "fob", 1513 ((pdp->xd_xsdev.frontend == 1) ? "frontend" : "backend")); 1514 if (err != DDI_SUCCESS) 1515 goto failure; 1516 1517 switch (hpc) { 1518 case XEN_HP_ADD: 1519 err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", 1520 "add", attr_list, &eid, DDI_NOSLEEP); 1521 break; 1522 case XEN_HP_REMOVE: 1523 err = ddi_log_sysevent(dip, DDI_VENDOR_SUNW, "EC_xendev", 1524 "remove", attr_list, &eid, DDI_NOSLEEP); 1525 break; 1526 default: 1527 err = DDI_FAILURE; 1528 goto failure; 1529 } 1530 1531 failure: 1532 if (attr_list != NULL) 1533 nvlist_free(attr_list); 1534 1535 return (err); 1536 } 1537 1538 /* ARGSUSED */ 1539 static void 1540 i_xvdi_probe_path_cb(struct xenbus_watch *w, const char **vec, 1541 unsigned int len) 1542 { 1543 char *path; 1544 1545 if (xendev_dip == NULL) 1546 xendev_dip = ddi_find_devinfo("xpvd", -1, 0); 1547 1548 path = i_ddi_strdup((char *)vec[XS_WATCH_PATH], KM_SLEEP); 1549 1550 (void) ddi_taskq_dispatch(DEVI(xendev_dip)->devi_taskq, 1551 i_xvdi_probe_path_handler, (void *)path, DDI_SLEEP); 1552 } 1553 1554 static void 1555 i_xvdi_watch_device(char *path) 1556 { 1557 struct xenbus_watch *w; 1558 1559 ASSERT(path != NULL); 1560 1561 w = kmem_zalloc(sizeof (*w), KM_SLEEP); 1562 w->node = path; 1563 w->callback = &i_xvdi_probe_path_cb; 1564 w->dev = NULL; 1565 1566 if (register_xenbus_watch(w) != 0) { 1567 cmn_err(CE_WARN, "i_xvdi_watch_device: " 1568 "cannot set watch on %s", path); 1569 kmem_free(w, sizeof (*w)); 1570 return; 1571 } 1572 } 1573 1574 void 1575 xvdi_watch_devices(int newstate) 1576 { 1577 int devclass; 1578 1579 /* 1580 * Watch for devices being created in the store. 1581 */ 1582 if (newstate == XENSTORE_DOWN) 1583 return; 1584 for (devclass = 0; devclass < NXDC; devclass++) { 1585 if (xdci[devclass].xs_path_fe != NULL) 1586 i_xvdi_watch_device(xdci[devclass].xs_path_fe); 1587 if (xdci[devclass].xs_path_be != NULL) 1588 i_xvdi_watch_device(xdci[devclass].xs_path_be); 1589 } 1590 } 1591 1592 /* 1593 * Iterate over the store looking for backend devices to create. 1594 */ 1595 static void 1596 i_xvdi_enum_be(dev_info_t *parent, i_xd_cfg_t *xdcp) 1597 { 1598 char **domains; 1599 unsigned int ndomains; 1600 int ldomains, i; 1601 1602 if ((domains = xenbus_directory(XBT_NULL, xdcp->xs_path_be, "", 1603 &ndomains)) == NULL) 1604 return; 1605 1606 for (i = 0, ldomains = 0; i < ndomains; i++) { 1607 ldomains += strlen(domains[i]) + 1 + sizeof (char *); 1608 1609 i_xvdi_enum_worker(parent, xdcp, domains[i]); 1610 } 1611 kmem_free(domains, ldomains); 1612 } 1613 1614 /* 1615 * Iterate over the store looking for frontend devices to create. 1616 */ 1617 static void 1618 i_xvdi_enum_fe(dev_info_t *parent, i_xd_cfg_t *xdcp) 1619 { 1620 i_xvdi_enum_worker(parent, xdcp, NULL); 1621 } 1622 1623 static void 1624 i_xvdi_enum_worker(dev_info_t *parent, i_xd_cfg_t *xdcp, 1625 char *domain) 1626 { 1627 char *path, *domain_path, *ep; 1628 char **devices; 1629 unsigned int ndevices; 1630 int ldevices, j, circ; 1631 domid_t dom; 1632 long tmplong; 1633 1634 if (domain == NULL) { 1635 dom = DOMID_SELF; 1636 path = xdcp->xs_path_fe; 1637 domain_path = ""; 1638 } else { 1639 (void) ddi_strtol(domain, &ep, 0, &tmplong); 1640 dom = tmplong; 1641 path = xdcp->xs_path_be; 1642 domain_path = domain; 1643 } 1644 1645 if ((devices = xenbus_directory(XBT_NULL, path, domain_path, 1646 &ndevices)) == NULL) 1647 return; 1648 1649 for (j = 0, ldevices = 0; j < ndevices; j++) { 1650 int vdev; 1651 1652 ldevices += strlen(devices[j]) + 1 + sizeof (char *); 1653 (void) ddi_strtol(devices[j], &ep, 0, &tmplong); 1654 vdev = tmplong; 1655 1656 ndi_devi_enter(parent, &circ); 1657 1658 if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) 1659 (void) xvdi_create_dev(parent, xdcp->devclass, 1660 dom, vdev); 1661 1662 ndi_devi_exit(parent, circ); 1663 } 1664 kmem_free(devices, ldevices); 1665 } 1666 1667 /* 1668 * Leaf drivers should call this in their detach() routine during suspend. 1669 */ 1670 void 1671 xvdi_suspend(dev_info_t *dip) 1672 { 1673 i_xvdi_rem_watches(dip); 1674 } 1675 1676 /* 1677 * Leaf drivers should call this in their attach() routine during resume. 1678 */ 1679 int 1680 xvdi_resume(dev_info_t *dip) 1681 { 1682 return (i_xvdi_add_watches(dip)); 1683 } 1684 1685 /* 1686 * Add event handler for the leaf driver 1687 * to handle event triggered by the change in xenstore 1688 */ 1689 int 1690 xvdi_add_event_handler(dev_info_t *dip, char *name, 1691 void (*evthandler)(dev_info_t *, ddi_eventcookie_t, void *, void *)) 1692 { 1693 ddi_eventcookie_t ecv; 1694 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 1695 ddi_callback_id_t *cbid; 1696 1697 ASSERT(pdp != NULL); 1698 1699 mutex_enter(&pdp->xd_lk); 1700 1701 if (strcmp(name, XS_OE_STATE) == 0) { 1702 ASSERT(pdp->xd_xsdev.otherend != NULL); 1703 1704 cbid = &pdp->xd_oe_ehid; 1705 } else if (strcmp(name, XS_HP_STATE) == 0) { 1706 if (pdp->xd_xsdev.frontend == 1) { 1707 mutex_exit(&pdp->xd_lk); 1708 return (DDI_FAILURE); 1709 } 1710 1711 ASSERT(pdp->xd_hp_watch.node != NULL); 1712 1713 cbid = &pdp->xd_hp_ehid; 1714 } else { 1715 /* Unsupported watch. */ 1716 mutex_exit(&pdp->xd_lk); 1717 return (DDI_FAILURE); 1718 } 1719 1720 /* 1721 * No event handler provided, take default action to handle 1722 * event. 1723 */ 1724 if (evthandler == NULL) { 1725 mutex_exit(&pdp->xd_lk); 1726 return (DDI_SUCCESS); 1727 } 1728 1729 ASSERT(*cbid == NULL); 1730 1731 if (ddi_get_eventcookie(dip, name, &ecv) != DDI_SUCCESS) { 1732 cmn_err(CE_WARN, "failed to find %s cookie for %s@%s", 1733 name, ddi_get_name(dip), ddi_get_name_addr(dip)); 1734 mutex_exit(&pdp->xd_lk); 1735 return (DDI_FAILURE); 1736 } 1737 if (ddi_add_event_handler(dip, ecv, evthandler, NULL, cbid) 1738 != DDI_SUCCESS) { 1739 cmn_err(CE_WARN, "failed to add %s event handler for %s@%s", 1740 name, ddi_get_name(dip), ddi_get_name_addr(dip)); 1741 *cbid = NULL; 1742 mutex_exit(&pdp->xd_lk); 1743 return (DDI_FAILURE); 1744 } 1745 1746 mutex_exit(&pdp->xd_lk); 1747 1748 return (DDI_SUCCESS); 1749 } 1750 1751 /* 1752 * Remove event handler for the leaf driver and unwatch xenstore 1753 * so, driver will not be notified when xenstore entry changed later 1754 */ 1755 void 1756 xvdi_remove_event_handler(dev_info_t *dip, char *name) 1757 { 1758 struct xendev_ppd *pdp; 1759 boolean_t rem_oe = B_FALSE, rem_hp = B_FALSE; 1760 ddi_callback_id_t oeid = NULL, hpid = NULL; 1761 1762 pdp = ddi_get_parent_data(dip); 1763 ASSERT(pdp != NULL); 1764 1765 if (name == NULL) { 1766 rem_oe = B_TRUE; 1767 rem_hp = B_TRUE; 1768 } else if (strcmp(name, XS_OE_STATE) == 0) { 1769 rem_oe = B_TRUE; 1770 } else if (strcmp(name, XS_HP_STATE) == 0) { 1771 rem_hp = B_TRUE; 1772 } else { 1773 cmn_err(CE_WARN, "event %s not supported, cannot remove", name); 1774 return; 1775 } 1776 1777 mutex_enter(&pdp->xd_lk); 1778 1779 if (rem_oe && (pdp->xd_oe_ehid != NULL)) { 1780 oeid = pdp->xd_oe_ehid; 1781 pdp->xd_oe_ehid = NULL; 1782 } 1783 1784 if (rem_hp && (pdp->xd_hp_ehid != NULL)) { 1785 hpid = pdp->xd_hp_ehid; 1786 pdp->xd_hp_ehid = NULL; 1787 } 1788 1789 mutex_exit(&pdp->xd_lk); 1790 1791 if (oeid != NULL) 1792 (void) ddi_remove_event_handler(oeid); 1793 if (hpid != NULL) 1794 (void) ddi_remove_event_handler(hpid); 1795 } 1796 1797 1798 /* 1799 * common ring interfaces 1800 */ 1801 1802 #define FRONT_RING(_ringp) (&(_ringp)->xr_sring.fr) 1803 #define BACK_RING(_ringp) (&(_ringp)->xr_sring.br) 1804 #define GET_RING_SIZE(_ringp) RING_SIZE(FRONT_RING(ringp)) 1805 #define GET_RING_ENTRY_FE(_ringp, _idx) \ 1806 (FRONT_RING(_ringp)->sring->ring + \ 1807 (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) 1808 #define GET_RING_ENTRY_BE(_ringp, _idx) \ 1809 (BACK_RING(_ringp)->sring->ring + \ 1810 (_ringp)->xr_entry_size * ((_idx) & (GET_RING_SIZE(_ringp) - 1))) 1811 1812 unsigned int 1813 xvdi_ring_avail_slots(xendev_ring_t *ringp) 1814 { 1815 comif_ring_fe_t *frp; 1816 comif_ring_be_t *brp; 1817 1818 if (ringp->xr_frontend) { 1819 frp = FRONT_RING(ringp); 1820 return (GET_RING_SIZE(ringp) - 1821 (frp->req_prod_pvt - frp->rsp_cons)); 1822 } else { 1823 brp = BACK_RING(ringp); 1824 return (GET_RING_SIZE(ringp) - 1825 (brp->rsp_prod_pvt - brp->req_cons)); 1826 } 1827 } 1828 1829 int 1830 xvdi_ring_has_unconsumed_requests(xendev_ring_t *ringp) 1831 { 1832 comif_ring_be_t *brp; 1833 1834 ASSERT(!ringp->xr_frontend); 1835 brp = BACK_RING(ringp); 1836 return ((brp->req_cons != 1837 ddi_get32(ringp->xr_acc_hdl, &brp->sring->req_prod)) && 1838 ((brp->req_cons - brp->rsp_prod_pvt) != RING_SIZE(brp))); 1839 } 1840 1841 int 1842 xvdi_ring_has_incomp_request(xendev_ring_t *ringp) 1843 { 1844 comif_ring_fe_t *frp; 1845 1846 ASSERT(ringp->xr_frontend); 1847 frp = FRONT_RING(ringp); 1848 return (frp->req_prod_pvt != 1849 ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); 1850 } 1851 1852 int 1853 xvdi_ring_has_unconsumed_responses(xendev_ring_t *ringp) 1854 { 1855 comif_ring_fe_t *frp; 1856 1857 ASSERT(ringp->xr_frontend); 1858 frp = FRONT_RING(ringp); 1859 return (frp->rsp_cons != 1860 ddi_get32(ringp->xr_acc_hdl, &frp->sring->rsp_prod)); 1861 } 1862 1863 /* NOTE: req_event will be increased as needed */ 1864 void * 1865 xvdi_ring_get_request(xendev_ring_t *ringp) 1866 { 1867 comif_ring_fe_t *frp; 1868 comif_ring_be_t *brp; 1869 1870 if (ringp->xr_frontend) { 1871 /* for frontend ring */ 1872 frp = FRONT_RING(ringp); 1873 if (!RING_FULL(frp)) 1874 return (GET_RING_ENTRY_FE(ringp, frp->req_prod_pvt++)); 1875 else 1876 return (NULL); 1877 } else { 1878 /* for backend ring */ 1879 brp = BACK_RING(ringp); 1880 /* RING_FINAL_CHECK_FOR_REQUESTS() */ 1881 if (xvdi_ring_has_unconsumed_requests(ringp)) 1882 return (GET_RING_ENTRY_BE(ringp, brp->req_cons++)); 1883 else { 1884 ddi_put32(ringp->xr_acc_hdl, &brp->sring->req_event, 1885 brp->req_cons + 1); 1886 membar_enter(); 1887 if (xvdi_ring_has_unconsumed_requests(ringp)) 1888 return (GET_RING_ENTRY_BE(ringp, 1889 brp->req_cons++)); 1890 else 1891 return (NULL); 1892 } 1893 } 1894 } 1895 1896 int 1897 xvdi_ring_push_request(xendev_ring_t *ringp) 1898 { 1899 RING_IDX old, new, reqevt; 1900 comif_ring_fe_t *frp; 1901 1902 /* only frontend should be able to push request */ 1903 ASSERT(ringp->xr_frontend); 1904 1905 /* RING_PUSH_REQUEST_AND_CHECK_NOTIFY() */ 1906 frp = FRONT_RING(ringp); 1907 old = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_prod); 1908 new = frp->req_prod_pvt; 1909 ddi_put32(ringp->xr_acc_hdl, &frp->sring->req_prod, new); 1910 membar_enter(); 1911 reqevt = ddi_get32(ringp->xr_acc_hdl, &frp->sring->req_event); 1912 return ((RING_IDX)(new - reqevt) < (RING_IDX)(new - old)); 1913 } 1914 1915 /* NOTE: rsp_event will be increased as needed */ 1916 void * 1917 xvdi_ring_get_response(xendev_ring_t *ringp) 1918 { 1919 comif_ring_fe_t *frp; 1920 comif_ring_be_t *brp; 1921 1922 if (!ringp->xr_frontend) { 1923 /* for backend ring */ 1924 brp = BACK_RING(ringp); 1925 return (GET_RING_ENTRY_BE(ringp, brp->rsp_prod_pvt++)); 1926 } else { 1927 /* for frontend ring */ 1928 frp = FRONT_RING(ringp); 1929 /* RING_FINAL_CHECK_FOR_RESPONSES() */ 1930 if (xvdi_ring_has_unconsumed_responses(ringp)) 1931 return (GET_RING_ENTRY_FE(ringp, frp->rsp_cons++)); 1932 else { 1933 ddi_put32(ringp->xr_acc_hdl, &frp->sring->rsp_event, 1934 frp->rsp_cons + 1); 1935 membar_enter(); 1936 if (xvdi_ring_has_unconsumed_responses(ringp)) 1937 return (GET_RING_ENTRY_FE(ringp, 1938 frp->rsp_cons++)); 1939 else 1940 return (NULL); 1941 } 1942 } 1943 } 1944 1945 int 1946 xvdi_ring_push_response(xendev_ring_t *ringp) 1947 { 1948 RING_IDX old, new, rspevt; 1949 comif_ring_be_t *brp; 1950 1951 /* only backend should be able to push response */ 1952 ASSERT(!ringp->xr_frontend); 1953 1954 /* RING_PUSH_RESPONSE_AND_CHECK_NOTIFY() */ 1955 brp = BACK_RING(ringp); 1956 old = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_prod); 1957 new = brp->rsp_prod_pvt; 1958 ddi_put32(ringp->xr_acc_hdl, &brp->sring->rsp_prod, new); 1959 membar_enter(); 1960 rspevt = ddi_get32(ringp->xr_acc_hdl, &brp->sring->rsp_event); 1961 return ((RING_IDX)(new - rspevt) < (RING_IDX)(new - old)); 1962 } 1963 1964 static void 1965 xvdi_ring_init_sring(xendev_ring_t *ringp) 1966 { 1967 ddi_acc_handle_t acchdl; 1968 comif_sring_t *xsrp; 1969 int i; 1970 1971 xsrp = (comif_sring_t *)ringp->xr_vaddr; 1972 acchdl = ringp->xr_acc_hdl; 1973 1974 /* shared ring initialization */ 1975 ddi_put32(acchdl, &xsrp->req_prod, 0); 1976 ddi_put32(acchdl, &xsrp->rsp_prod, 0); 1977 ddi_put32(acchdl, &xsrp->req_event, 1); 1978 ddi_put32(acchdl, &xsrp->rsp_event, 1); 1979 for (i = 0; i < sizeof (xsrp->pad); i++) 1980 ddi_put8(acchdl, xsrp->pad + i, 0); 1981 } 1982 1983 static void 1984 xvdi_ring_init_front_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) 1985 { 1986 comif_ring_fe_t *xfrp; 1987 1988 xfrp = &ringp->xr_sring.fr; 1989 xfrp->req_prod_pvt = 0; 1990 xfrp->rsp_cons = 0; 1991 xfrp->nr_ents = nentry; 1992 xfrp->sring = (comif_sring_t *)ringp->xr_vaddr; 1993 1994 ringp->xr_frontend = 1; 1995 ringp->xr_entry_size = entrysize; 1996 } 1997 1998 #ifndef XPV_HVM_DRIVER 1999 static void 2000 xvdi_ring_init_back_ring(xendev_ring_t *ringp, size_t nentry, size_t entrysize) 2001 { 2002 comif_ring_be_t *xbrp; 2003 2004 xbrp = &ringp->xr_sring.br; 2005 xbrp->rsp_prod_pvt = 0; 2006 xbrp->req_cons = 0; 2007 xbrp->nr_ents = nentry; 2008 xbrp->sring = (comif_sring_t *)ringp->xr_vaddr; 2009 2010 ringp->xr_frontend = 0; 2011 ringp->xr_entry_size = entrysize; 2012 } 2013 #endif /* XPV_HVM_DRIVER */ 2014 2015 static void 2016 xendev_offline_device(void *arg) 2017 { 2018 dev_info_t *dip = (dev_info_t *)arg; 2019 char devname[MAXNAMELEN] = {0}; 2020 2021 /* 2022 * This is currently the only chance to delete a devinfo node, which 2023 * is _not_ always successful. 2024 */ 2025 (void) ddi_deviname(dip, devname); 2026 (void) devfs_clean(ddi_get_parent(dip), devname + 1, DV_CLEAN_FORCE); 2027 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE); 2028 } 2029 2030 static void 2031 i_xvdi_oestate_cb(struct xenbus_device *dev, XenbusState oestate) 2032 { 2033 dev_info_t *dip = (dev_info_t *)dev->data; 2034 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 2035 2036 /* 2037 * Don't trigger two consecutive ndi_devi_offline on the same 2038 * dip. 2039 */ 2040 if ((oestate == XenbusStateClosed) && 2041 (dev->otherend_state == XenbusStateClosed)) 2042 return; 2043 2044 dev->otherend_state = oestate; 2045 (void) ddi_taskq_dispatch(pdp->xd_oe_taskq, 2046 i_xvdi_oestate_handler, (void *)dip, DDI_SLEEP); 2047 } 2048 2049 /*ARGSUSED*/ 2050 static void 2051 i_xvdi_hpstate_cb(struct xenbus_watch *w, const char **vec, 2052 unsigned int len) 2053 { 2054 dev_info_t *dip = (dev_info_t *)w->dev; 2055 struct xendev_ppd *pdp = ddi_get_parent_data(dip); 2056 2057 (void) ddi_taskq_dispatch(pdp->xd_hp_taskq, 2058 i_xvdi_hpstate_handler, (void *)dip, DDI_SLEEP); 2059 } 2060 2061 static void 2062 i_xvdi_probe_path_handler(void *arg) 2063 { 2064 dev_info_t *parent; 2065 char *path = arg, *p = NULL; 2066 int i, vdev, circ; 2067 i_xd_cfg_t *xdcp; 2068 boolean_t frontend; 2069 domid_t dom; 2070 2071 for (i = 0, xdcp = &xdci[0]; i < NXDC; i++, xdcp++) { 2072 2073 if ((xdcp->xs_path_fe != NULL) && 2074 (strncmp(path, xdcp->xs_path_fe, strlen(xdcp->xs_path_fe)) 2075 == 0)) { 2076 2077 frontend = B_TRUE; 2078 p = path + strlen(xdcp->xs_path_fe); 2079 break; 2080 } 2081 2082 if ((xdcp->xs_path_be != NULL) && 2083 (strncmp(path, xdcp->xs_path_be, strlen(xdcp->xs_path_be)) 2084 == 0)) { 2085 2086 frontend = B_FALSE; 2087 p = path + strlen(xdcp->xs_path_be); 2088 break; 2089 } 2090 2091 } 2092 2093 if (p == NULL) { 2094 cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " 2095 "unexpected path prefix in %s", path); 2096 goto done; 2097 } 2098 2099 if (frontend) { 2100 dom = DOMID_SELF; 2101 if (sscanf(p, "/%d/", &vdev) != 1) { 2102 XVDI_DPRINTF(XVDI_DBG_PROBE, 2103 "i_xvdi_probe_path_handler: " 2104 "cannot parse frontend path %s", 2105 path); 2106 goto done; 2107 } 2108 } else { 2109 if (sscanf(p, "/%d/%d/", &dom, &vdev) != 2) { 2110 XVDI_DPRINTF(XVDI_DBG_PROBE, 2111 "i_xvdi_probe_path_handler: " 2112 "cannot parse backend path %s", 2113 path); 2114 goto done; 2115 } 2116 } 2117 2118 /* 2119 * This is an oxymoron, so indicates a bogus configuration we 2120 * must check for. 2121 */ 2122 if (vdev == VDEV_NOXS) { 2123 cmn_err(CE_WARN, "i_xvdi_probe_path_handler: " 2124 "invalid path %s", path); 2125 goto done; 2126 } 2127 2128 parent = xendev_dip; 2129 ASSERT(parent != NULL); 2130 2131 ndi_devi_enter(parent, &circ); 2132 2133 if (xvdi_find_dev(parent, xdcp->devclass, dom, vdev) == NULL) { 2134 XVDI_DPRINTF(XVDI_DBG_PROBE, 2135 "i_xvdi_probe_path_handler: create for %s", path); 2136 (void) xvdi_create_dev(parent, xdcp->devclass, dom, vdev); 2137 } else { 2138 XVDI_DPRINTF(XVDI_DBG_PROBE, 2139 "i_xvdi_probe_path_handler: %s already exists", path); 2140 } 2141 2142 ndi_devi_exit(parent, circ); 2143 2144 done: 2145 kmem_free(path, strlen(path) + 1); 2146 } 2147