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