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 */
30
31 /*
32 * Xen virtual device driver interfaces
33 */
34
35 /*
36 * todo:
37 * + name space clean up:
38 * xvdi_* - public xen interfaces, for use by all leaf drivers
39 * xd_* - public xen data structures
40 * i_xvdi_* - implementation private functions
41 * xendev_* - xendev driver interfaces, both internal and in cb_ops/bus_ops
42 * + add mdb dcmds to dump ring status
43 * + implement xvdi_xxx to wrap xenbus_xxx read/write function
44 * + convert (xendev_ring_t *) into xvdi_ring_handle_t
45 */
46 #include <sys/conf.h>
47 #include <sys/param.h>
48 #include <sys/kmem.h>
49 #include <vm/seg_kmem.h>
50 #include <sys/debug.h>
51 #include <sys/modctl.h>
52 #include <sys/autoconf.h>
53 #include <sys/ddi_impldefs.h>
54 #include <sys/ddi_subrdefs.h>
55 #include <sys/ddi.h>
56 #include <sys/sunddi.h>
57 #include <sys/sunndi.h>
58 #include <sys/sunldi.h>
59 #include <sys/fs/dv_node.h>
60 #include <sys/avintr.h>
61 #include <sys/psm.h>
62 #include <sys/spl.h>
63 #include <sys/promif.h>
64 #include <sys/list.h>
65 #include <sys/bootconf.h>
66 #include <sys/bootsvcs.h>
67 #include <sys/bootinfo.h>
68 #include <sys/note.h>
69 #include <sys/sysmacros.h>
70 #ifdef XPV_HVM_DRIVER
71 #include <sys/xpv_support.h>
72 #include <sys/hypervisor.h>
73 #include <public/grant_table.h>
74 #include <public/xen.h>
75 #include <public/io/xenbus.h>
76 #include <public/io/xs_wire.h>
77 #include <public/event_channel.h>
78 #include <public/io/xenbus.h>
79 #else /* XPV_HVM_DRIVER */
80 #include <sys/hypervisor.h>
81 #include <sys/xen_mmu.h>
82 #include <xen/sys/xenbus_impl.h>
83 #include <sys/evtchn_impl.h>
84 #endif /* XPV_HVM_DRIVER */
85 #include <sys/gnttab.h>
86 #include <xen/sys/xendev.h>
87 #include <vm/hat_i86.h>
88 #include <sys/scsi/generic/inquiry.h>
89 #include <util/sscanf.h>
90 #include <xen/public/io/xs_wire.h>
91
92
93 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
94 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
95 ((ch) >= 'A' && (ch) <= 'F'))
96
97 static void xvdi_ring_init_sring(xendev_ring_t *);
98 static void xvdi_ring_init_front_ring(xendev_ring_t *, size_t, size_t);
99 #ifndef XPV_HVM_DRIVER
100 static void xvdi_ring_init_back_ring(xendev_ring_t *, size_t, size_t);
101 #endif
102 static void xvdi_reinit_ring(dev_info_t *, grant_ref_t *, xendev_ring_t *);
103
104 static int i_xvdi_add_watches(dev_info_t *);
105 static void i_xvdi_rem_watches(dev_info_t *);
106
107 static int i_xvdi_add_watch_oestate(dev_info_t *);
108 static void i_xvdi_rem_watch_oestate(dev_info_t *);
109 static void i_xvdi_oestate_cb(struct xenbus_device *, XenbusState);
110 static void i_xvdi_oestate_handler(void *);
111
112 static int i_xvdi_add_watch_hpstate(dev_info_t *);
113 static void i_xvdi_rem_watch_hpstate(dev_info_t *);
114 static void i_xvdi_hpstate_cb(struct xenbus_watch *, const char **,
115 unsigned int);
116 static void i_xvdi_hpstate_handler(void *);
117
118 static int i_xvdi_add_watch_bepath(dev_info_t *);
119 static void i_xvdi_rem_watch_bepath(dev_info_t *);
120 static void i_xvdi_bepath_cb(struct xenbus_watch *, const char **,
121 unsigned in);
122
123 static void xendev_offline_device(void *);
124
125 static void i_xvdi_probe_path_cb(struct xenbus_watch *, const char **,
126 unsigned int);
127 static void i_xvdi_probe_path_handler(void *);
128
129 typedef struct oestate_evt {
130 dev_info_t *dip;
131 XenbusState state;
132 } i_oestate_evt_t;
133
134 typedef struct xd_cfg {
135 xendev_devclass_t devclass;
136 char *xsdev;
137 char *xs_path_fe;
138 char *xs_path_be;
139 char *node_fe;
140 char *node_be;
141 char *device_type;
142 int xd_ipl;
143 int flags;
144 } i_xd_cfg_t;
145
146 #define XD_DOM_ZERO 0x01 /* dom0 only. */
147 #define XD_DOM_GUEST 0x02 /* Guest domains (i.e. non-dom0). */
148 #define XD_DOM_IO 0x04 /* IO domains. */
149
150 #define XD_DOM_ALL (XD_DOM_ZERO | XD_DOM_GUEST)
151
152 static i_xd_cfg_t xdci[] = {
153 #ifndef XPV_HVM_DRIVER
154 { XEN_CONSOLE, NULL, NULL, NULL, "xencons", NULL,
155 "console", IPL_CONS, XD_DOM_ALL, },
156 #endif
157
158 { XEN_VNET, "vif", "device/vif", "backend/vif", "xnf", "xnb",
159 "network", IPL_VIF, XD_DOM_ALL, },
160
161 { XEN_VBLK, "vbd", "device/vbd", "backend/vbd", "xdf", "xdb",
162 "block", IPL_VBD, XD_DOM_ALL, },
163
164 { XEN_BLKTAP, "tap", NULL, "backend/tap", NULL, "xpvtap",
165 "block", IPL_VBD, XD_DOM_ALL, },
166
167 #ifndef XPV_HVM_DRIVER
168 { XEN_XENBUS, NULL, NULL, NULL, "xenbus", NULL,
169 NULL, 0, XD_DOM_ALL, },
170
171 { XEN_DOMCAPS, NULL, NULL, NULL, "domcaps", NULL,
172 NULL, 0, XD_DOM_ALL, },
173
174 { XEN_BALLOON, NULL, NULL, NULL, "balloon", NULL,
175 NULL, 0, XD_DOM_ALL, },
176 #endif
177
178 { XEN_EVTCHN, NULL, NULL, NULL, "evtchn", NULL,
179 NULL, 0, XD_DOM_ZERO, },
180
181 { XEN_PRIVCMD, NULL, NULL, NULL, "privcmd", NULL,
182 NULL, 0, XD_DOM_ZERO, },
183 };
184 #define NXDC (sizeof (xdci) / sizeof (xdci[0]))
185
186 static void i_xvdi_enum_fe(dev_info_t *, i_xd_cfg_t *);
187 static void i_xvdi_enum_be(dev_info_t *, i_xd_cfg_t *);
188 static void i_xvdi_enum_worker(dev_info_t *, i_xd_cfg_t *, char *);
189
190 /*
191 * Xen device channel device access and DMA attributes
192 */
193 static ddi_device_acc_attr_t xendev_dc_accattr = {
194 DDI_DEVICE_ATTR_V0, DDI_NEVERSWAP_ACC, DDI_STRICTORDER_ACC
195 };
196
197 static ddi_dma_attr_t xendev_dc_dmaattr = {
198 DMA_ATTR_V0, /* version of this structure */
199 0, /* lowest usable address */
200 0xffffffffffffffffULL, /* highest usable address */
201 0x7fffffff, /* maximum DMAable byte count */
202 MMU_PAGESIZE, /* alignment in bytes */
203 0x7ff, /* bitmap of burst sizes */
204 1, /* minimum transfer */
205 0xffffffffU, /* maximum transfer */
206 0xffffffffffffffffULL, /* maximum segment length */
207 1, /* maximum number of segments */
208 1, /* granularity */
209 0, /* flags (reserved) */
210 };
211
212 static dev_info_t *xendev_dip = NULL;
213
214 #define XVDI_DBG_STATE 0x01
215 #define XVDI_DBG_PROBE 0x02
216
217 #ifdef DEBUG
218 int i_xvdi_debug = 0;
219
220 #define XVDI_DPRINTF(flag, format, ...) \
221 { \
222 if (i_xvdi_debug & (flag)) \
223 prom_printf((format), __VA_ARGS__); \
224 }
225 #else
226 #define XVDI_DPRINTF(flag, format, ...)
227 #endif /* DEBUG */
228
229 static i_xd_cfg_t *
230 i_xvdi_devclass2cfg(xendev_devclass_t devclass)
231 {
232 i_xd_cfg_t *xdcp;
233 int i;
234
235 for (i = 0, xdcp = xdci; i < NXDC; i++, xdcp++)
236 if (xdcp->devclass == devclass)
237 return (xdcp);
238
239 return (NULL);
240 }
241
242 int
243 xvdi_init_dev(dev_info_t *dip)
244 {
245 xendev_devclass_t devcls;
246 int vdevnum;
247 domid_t domid;
248 struct xendev_ppd *pdp;
249 i_xd_cfg_t *xdcp;
250 boolean_t backend;
251 char xsnamebuf[TYPICALMAXPATHLEN];
252 char *xsname;
253 void *prop_str;
254 unsigned int prop_len;
255 char unitaddr[8];
256
257 devcls = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
258 DDI_PROP_DONTPASS, "devclass", XEN_INVAL);
259 vdevnum = ddi_prop_get_int(DDI_DEV_T_ANY, dip,
260 DDI_PROP_DONTPASS, "vdev", VDEV_NOXS);
261 domid = (domid_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip,
262 DDI_PROP_DONTPASS, "domain", DOMID_SELF);
263
264 backend = (domid != DOMID_SELF);
265 xdcp = i_xvdi_devclass2cfg(devcls);
266 if (xdcp->device_type != NULL)
267 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
268 "device_type", xdcp->device_type);
269
270 pdp = kmem_zalloc(sizeof (*pdp), KM_SLEEP);
271 pdp->xd_domain = domid;
272 pdp->xd_vdevnum = vdevnum;
273 pdp->xd_devclass = devcls;
274 pdp->xd_evtchn = INVALID_EVTCHN;
275 list_create(&pdp->xd_xb_watches, sizeof (xd_xb_watches_t),
276 offsetof(xd_xb_watches_t, xxw_list));
277 mutex_init(&pdp->xd_evt_lk, NULL, MUTEX_DRIVER, NULL);
278 mutex_init(&pdp->xd_ndi_lk, NULL, MUTEX_DRIVER, NULL);
279 ddi_set_parent_data(dip, pdp);
280
281 /*
282 * devices that do not need to interact with xenstore
283 */
284 if (vdevnum == VDEV_NOXS) {
285 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
286 "unit-address", "0");
287 if (devcls == XEN_CONSOLE)
288 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
289 "pm-hardware-state", "needs-suspend-resume");
290 return (DDI_SUCCESS);
291 }
292
293 /*
294 * PV devices that need to probe xenstore
295 */
296
297 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
298 "pm-hardware-state", "needs-suspend-resume");
299
300 xsname = xsnamebuf;
301 if (!backend)
302 (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
303 "%s/%d", xdcp->xs_path_fe, vdevnum);
304 else
305 (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
306 "%s/%d/%d", xdcp->xs_path_be, domid, vdevnum);
307 if ((xenbus_read_driver_state(xsname) >= XenbusStateClosing)) {
308 /* Don't try to init a dev that may be closing */
309 mutex_destroy(&pdp->xd_ndi_lk);
310 mutex_destroy(&pdp->xd_evt_lk);
311 kmem_free(pdp, sizeof (*pdp));
312 ddi_set_parent_data(dip, NULL);
313 return (DDI_FAILURE);
314 }
315
316 pdp->xd_xsdev.nodename = i_ddi_strdup(xsname, KM_SLEEP);
317 pdp->xd_xsdev.devicetype = xdcp->xsdev;
318 pdp->xd_xsdev.frontend = (backend ? 0 : 1);
319 pdp->xd_xsdev.data = dip;
320 pdp->xd_xsdev.otherend_id = (backend ? domid : -1);
321 if (i_xvdi_add_watches(dip) != DDI_SUCCESS) {
322 cmn_err(CE_WARN, "xvdi_init_dev: "
323 "cannot add watches for %s", xsname);
324 xvdi_uninit_dev(dip);
325 return (DDI_FAILURE);
326 }
327
328 if (backend)
329 return (DDI_SUCCESS);
330
331 /*
332 * The unit-address for frontend devices is the name of the
333 * of the xenstore node containing the device configuration
334 * and is contained in the 'vdev' property.
335 * VIF devices are named using an incrementing integer.
336 * VBD devices are either named using the 16-bit dev_t value
337 * for linux 'hd' and 'xvd' devices, or a simple integer value
338 * in the range 0..767. 768 is the base value of the linux
339 * dev_t namespace, the dev_t value for 'hda'.
340 */
341 (void) snprintf(unitaddr, sizeof (unitaddr), "%d", vdevnum);
342 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "unit-address",
343 unitaddr);
344
345 switch (devcls) {
346 case XEN_VNET:
347 if (xenbus_read(XBT_NULL, xsname, "mac", (void *)&prop_str,
348 &prop_len) != 0)
349 break;
350 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip, "mac",
351 prop_str);
352 kmem_free(prop_str, prop_len);
353 break;
354 case XEN_VBLK:
355 /*
356 * cache a copy of the otherend name
357 * for ease of observeability
358 */
359 if (xenbus_read(XBT_NULL, pdp->xd_xsdev.otherend, "dev",
360 &prop_str, &prop_len) != 0)
361 break;
362 (void) ndi_prop_update_string(DDI_DEV_T_NONE, dip,
363 "dev-address", prop_str);
364 kmem_free(prop_str, prop_len);
365 break;
366 default:
367 break;
368 }
369
370 return (DDI_SUCCESS);
371 }
372
373 void
374 xvdi_uninit_dev(dev_info_t *dip)
375 {
376 struct xendev_ppd *pdp = ddi_get_parent_data(dip);
377
378 if (pdp != NULL) {
379 /* Remove any registered callbacks. */
380 xvdi_remove_event_handler(dip, NULL);
381
382 /* Remove any registered watches. */
383 i_xvdi_rem_watches(dip);
384
385 /* tell other end to close */
386 if (pdp->xd_xsdev.otherend_id != (domid_t)-1)
387 (void) xvdi_switch_state(dip, XBT_NULL,
388 XenbusStateClosed);
389
390 if (pdp->xd_xsdev.nodename != NULL)
391 kmem_free((char *)(pdp->xd_xsdev.nodename),
392 strlen(pdp->xd_xsdev.nodename) + 1);
393
394 ddi_set_parent_data(dip, NULL);
395
396 mutex_destroy(&pdp->xd_ndi_lk);
397 mutex_destroy(&pdp->xd_evt_lk);
398 kmem_free(pdp, sizeof (*pdp));
399 }
400 }
401
402 /*
403 * Bind the event channel for this device instance.
404 * Currently we only support one evtchn per device instance.
405 */
406 int
407 xvdi_bind_evtchn(dev_info_t *dip, evtchn_port_t evtchn)
408 {
409 struct xendev_ppd *pdp;
410 domid_t oeid;
411 int r;
412
413 pdp = ddi_get_parent_data(dip);
414 ASSERT(pdp != NULL);
415 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
416
417 mutex_enter(&pdp->xd_evt_lk);
418 if (pdp->xd_devclass == XEN_CONSOLE) {
419 if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
420 pdp->xd_evtchn = xen_info->console.domU.evtchn;
421 } else {
422 pdp->xd_evtchn = INVALID_EVTCHN;
423 mutex_exit(&pdp->xd_evt_lk);
424 return (DDI_SUCCESS);
425 }
426 } else {
427 oeid = pdp->xd_xsdev.otherend_id;
428 if (oeid == (domid_t)-1) {
429 mutex_exit(&pdp->xd_evt_lk);
430 return (DDI_FAILURE);
431 }
432
433 if ((r = xen_bind_interdomain(oeid, evtchn, &pdp->xd_evtchn))) {
434 xvdi_dev_error(dip, r, "bind event channel");
435 mutex_exit(&pdp->xd_evt_lk);
436 return (DDI_FAILURE);
437 }
438 }
439 #ifndef XPV_HVM_DRIVER
440 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
441 #endif
442 mutex_exit(&pdp->xd_evt_lk);
443
444 return (DDI_SUCCESS);
445 }
446
447 /*
448 * Allocate an event channel for this device instance.
449 * Currently we only support one evtchn per device instance.
450 */
451 int
452 xvdi_alloc_evtchn(dev_info_t *dip)
453 {
454 struct xendev_ppd *pdp;
455 domid_t oeid;
456 int rv;
457
458 pdp = ddi_get_parent_data(dip);
459 ASSERT(pdp != NULL);
460 ASSERT(pdp->xd_evtchn == INVALID_EVTCHN);
461
462 mutex_enter(&pdp->xd_evt_lk);
463 if (pdp->xd_devclass == XEN_CONSOLE) {
464 if (!DOMAIN_IS_INITDOMAIN(xen_info)) {
465 pdp->xd_evtchn = xen_info->console.domU.evtchn;
466 } else {
467 pdp->xd_evtchn = INVALID_EVTCHN;
468 mutex_exit(&pdp->xd_evt_lk);
469 return (DDI_SUCCESS);
470 }
471 } else {
472 oeid = pdp->xd_xsdev.otherend_id;
473 if (oeid == (domid_t)-1) {
474 mutex_exit(&pdp->xd_evt_lk);
475 return (DDI_FAILURE);
476 }
477
478 if ((rv = xen_alloc_unbound_evtchn(oeid, &pdp->xd_evtchn))) {
479 xvdi_dev_error(dip, rv, "bind event channel");
480 mutex_exit(&pdp->xd_evt_lk);
481 return (DDI_FAILURE);
482 }
483 }
484 #ifndef XPV_HVM_DRIVER
485 pdp->xd_ispec.intrspec_vec = ec_bind_evtchn_to_irq(pdp->xd_evtchn);
486 #endif
487 mutex_exit(&pdp->xd_evt_lk);
488
489 return (DDI_SUCCESS);
490 }
491
492 /*
493 * Unbind the event channel for this device instance.
494 * Currently we only support one evtchn per device instance.
495 */
496 void
497 xvdi_free_evtchn(dev_info_t *dip)
498 {
499 struct xendev_ppd *pdp;
500
501 pdp = ddi_get_parent_data(dip);
502 ASSERT(pdp != NULL);
503
504 mutex_enter(&pdp->xd_evt_lk);
505 if (pdp->xd_evtchn != INVALID_EVTCHN) {
506 #ifndef XPV_HVM_DRIVER
507 ec_unbind_irq(pdp->xd_ispec.intrspec_vec);
508 pdp->xd_ispec.intrspec_vec = 0;
509 #endif
510 pdp->xd_evtchn = INVALID_EVTCHN;
511 }
512 mutex_exit(&pdp->xd_evt_lk);
513 }
514
515 #ifndef XPV_HVM_DRIVER
516 /*
517 * Map an inter-domain communication ring for a virtual device.
518 * This is used by backend drivers.
519 */
520 int
521 xvdi_map_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
522 grant_ref_t gref, xendev_ring_t **ringpp)
523 {
524 domid_t oeid;
525 gnttab_map_grant_ref_t mapop;
526 gnttab_unmap_grant_ref_t unmapop;
527 caddr_t ringva;
528 ddi_acc_hdl_t *ap;
529 ddi_acc_impl_t *iap;
530 xendev_ring_t *ring;
531 int err;
532 char errstr[] = "mapping in ring buffer";
533
534 ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
535 oeid = xvdi_get_oeid(dip);
536
537 /* alloc va in backend dom for ring buffer */
538 ringva = vmem_xalloc(heap_arena, PAGESIZE, PAGESIZE,
539 0, 0, 0, 0, VM_SLEEP);
540
541 /* map in ring page */
542 hat_prepare_mapping(kas.a_hat, ringva, NULL);
543 mapop.host_addr = (uint64_t)(uintptr_t)ringva;
544 mapop.flags = GNTMAP_host_map;
545 mapop.ref = gref;
546 mapop.dom = oeid;
547 err = xen_map_gref(GNTTABOP_map_grant_ref, &mapop, 1, B_FALSE);
548 if (err) {
549 xvdi_fatal_error(dip, err, errstr);
550 goto errout1;
551 }
552
553 if (mapop.status != 0) {
554 xvdi_fatal_error(dip, err, errstr);
555 goto errout2;
556 }
557 ring->xr_vaddr = ringva;
558 ring->xr_grant_hdl = mapop.handle;
559 ring->xr_gref = gref;
560
561 /*
562 * init an acc handle and associate it w/ this ring
563 * this is only for backend drivers. we get the memory by calling
564 * vmem_xalloc(), instead of calling any ddi function, so we have
565 * to init an acc handle by ourselves
566 */
567 ring->xr_acc_hdl = impl_acc_hdl_alloc(KM_SLEEP, NULL);
568 ap = impl_acc_hdl_get(ring->xr_acc_hdl);
569 ap->ah_vers = VERS_ACCHDL;
570 ap->ah_dip = dip;
571 ap->ah_xfermodes = DDI_DMA_CONSISTENT;
572 ap->ah_acc = xendev_dc_accattr;
573 iap = (ddi_acc_impl_t *)ap->ah_platform_private;
574 iap->ahi_acc_attr |= DDI_ACCATTR_CPU_VADDR;
575 impl_acc_hdl_init(ap);
576 ap->ah_offset = 0;
577 ap->ah_len = (off_t)PAGESIZE;
578 ap->ah_addr = ring->xr_vaddr;
579
580 /* init backend ring */
581 xvdi_ring_init_back_ring(ring, nentry, entrysize);
582
583 *ringpp = ring;
584
585 return (DDI_SUCCESS);
586
587 errout2:
588 /* unmap ring page */
589 unmapop.host_addr = (uint64_t)(uintptr_t)ringva;
590 unmapop.handle = ring->xr_grant_hdl;
591 unmapop.dev_bus_addr = NULL;
592 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
593 hat_release_mapping(kas.a_hat, ringva);
594 errout1:
595 vmem_xfree(heap_arena, ringva, PAGESIZE);
596 kmem_free(ring, sizeof (xendev_ring_t));
597 return (DDI_FAILURE);
598 }
599
600 /*
601 * Unmap a ring for a virtual device.
602 * This is used by backend drivers.
603 */
604 void
605 xvdi_unmap_ring(xendev_ring_t *ring)
606 {
607 gnttab_unmap_grant_ref_t unmapop;
608
609 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
610
611 impl_acc_hdl_free(ring->xr_acc_hdl);
612 unmapop.host_addr = (uint64_t)(uintptr_t)ring->xr_vaddr;
613 unmapop.handle = ring->xr_grant_hdl;
614 unmapop.dev_bus_addr = NULL;
615 (void) HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &unmapop, 1);
616 hat_release_mapping(kas.a_hat, ring->xr_vaddr);
617 vmem_xfree(heap_arena, ring->xr_vaddr, PAGESIZE);
618 kmem_free(ring, sizeof (xendev_ring_t));
619 }
620 #endif /* XPV_HVM_DRIVER */
621
622 /*
623 * Re-initialise an inter-domain communications ring for the backend domain.
624 * ring will be re-initialized after re-grant succeed
625 * ring will be freed if fails to re-grant access to backend domain
626 * so, don't keep useful data in the ring
627 * used only in frontend driver
628 */
629 static void
630 xvdi_reinit_ring(dev_info_t *dip, grant_ref_t *gref, xendev_ring_t *ringp)
631 {
632 paddr_t rpaddr;
633 maddr_t rmaddr;
634
635 ASSERT((ringp != NULL) && (ringp->xr_paddr != 0));
636 rpaddr = ringp->xr_paddr;
637
638 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? rpaddr : pa_to_ma(rpaddr);
639 gnttab_grant_foreign_access_ref(ringp->xr_gref, xvdi_get_oeid(dip),
640 rmaddr >> PAGESHIFT, 0);
641 *gref = ringp->xr_gref;
642
643 /* init frontend ring */
644 xvdi_ring_init_sring(ringp);
645 xvdi_ring_init_front_ring(ringp, ringp->xr_sring.fr.nr_ents,
646 ringp->xr_entry_size);
647 }
648
649 /*
650 * allocate Xen inter-domain communications ring for Xen virtual devices
651 * used only in frontend driver
652 * if *ringpp is not NULL, we'll simply re-init it
653 */
654 int
655 xvdi_alloc_ring(dev_info_t *dip, size_t nentry, size_t entrysize,
656 grant_ref_t *gref, xendev_ring_t **ringpp)
657 {
658 size_t len;
659 xendev_ring_t *ring;
660 ddi_dma_cookie_t dma_cookie;
661 uint_t ncookies;
662 grant_ref_t ring_gref;
663 domid_t oeid;
664 maddr_t rmaddr;
665
666 if (*ringpp) {
667 xvdi_reinit_ring(dip, gref, *ringpp);
668 return (DDI_SUCCESS);
669 }
670
671 *ringpp = ring = kmem_zalloc(sizeof (xendev_ring_t), KM_SLEEP);
672 oeid = xvdi_get_oeid(dip);
673
674 /*
675 * Allocate page for this ring buffer
676 */
677 if (ddi_dma_alloc_handle(dip, &xendev_dc_dmaattr, DDI_DMA_SLEEP,
678 0, &ring->xr_dma_hdl) != DDI_SUCCESS)
679 goto err;
680
681 if (ddi_dma_mem_alloc(ring->xr_dma_hdl, PAGESIZE,
682 &xendev_dc_accattr, DDI_DMA_CONSISTENT, DDI_DMA_SLEEP, 0,
683 &ring->xr_vaddr, &len, &ring->xr_acc_hdl) != DDI_SUCCESS) {
684 ddi_dma_free_handle(&ring->xr_dma_hdl);
685 goto err;
686 }
687
688 if (ddi_dma_addr_bind_handle(ring->xr_dma_hdl, NULL,
689 ring->xr_vaddr, len, DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
690 DDI_DMA_SLEEP, 0, &dma_cookie, &ncookies) != DDI_DMA_MAPPED) {
691 ddi_dma_mem_free(&ring->xr_acc_hdl);
692 ring->xr_vaddr = NULL;
693 ddi_dma_free_handle(&ring->xr_dma_hdl);
694 goto err;
695 }
696 ASSERT(ncookies == 1);
697 ring->xr_paddr = dma_cookie.dmac_laddress;
698 rmaddr = DOMAIN_IS_INITDOMAIN(xen_info) ? ring->xr_paddr :
699 pa_to_ma(ring->xr_paddr);
700
701 if ((ring_gref = gnttab_grant_foreign_access(oeid,
702 rmaddr >> PAGESHIFT, 0)) == (grant_ref_t)-1) {
703 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
704 ddi_dma_mem_free(&ring->xr_acc_hdl);
705 ring->xr_vaddr = NULL;
706 ddi_dma_free_handle(&ring->xr_dma_hdl);
707 goto err;
708 }
709 *gref = ring->xr_gref = ring_gref;
710
711 /* init frontend ring */
712 xvdi_ring_init_sring(ring);
713 xvdi_ring_init_front_ring(ring, nentry, entrysize);
714
715 return (DDI_SUCCESS);
716
717 err:
718 kmem_free(ring, sizeof (xendev_ring_t));
719 return (DDI_FAILURE);
720 }
721
722 /*
723 * Release ring buffers allocated for Xen devices
724 * used for frontend driver
725 */
726 void
727 xvdi_free_ring(xendev_ring_t *ring)
728 {
729 ASSERT((ring != NULL) && (ring->xr_vaddr != NULL));
730
731 (void) gnttab_end_foreign_access_ref(ring->xr_gref, 0);
732 (void) ddi_dma_unbind_handle(ring->xr_dma_hdl);
733 ddi_dma_mem_free(&ring->xr_acc_hdl);
734 ddi_dma_free_handle(&ring->xr_dma_hdl);
735 kmem_free(ring, sizeof (xendev_ring_t));
736 }
737
738 dev_info_t *
739 xvdi_create_dev(dev_info_t *parent, xendev_devclass_t devclass,
740 domid_t dom, int vdev)
741 {
742 dev_info_t *dip;
743 boolean_t backend;
744 i_xd_cfg_t *xdcp;
745 char xsnamebuf[TYPICALMAXPATHLEN];
746 char *type, *node = NULL, *xsname = NULL;
747 unsigned int tlen;
748 int ret;
749
750 ASSERT(DEVI_BUSY_OWNED(parent));
751
752 backend = (dom != DOMID_SELF);
753 xdcp = i_xvdi_devclass2cfg(devclass);
754 ASSERT(xdcp != NULL);
755
756 if (vdev != VDEV_NOXS) {
757 if (!backend) {
758 (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
759 "%s/%d", xdcp->xs_path_fe, vdev);
760 xsname = xsnamebuf;
761 node = xdcp->node_fe;
762 } else {
763 (void) snprintf(xsnamebuf, sizeof (xsnamebuf),
764 "%s/%d/%d", xdcp->xs_path_be, dom, vdev);
765 xsname = xsnamebuf;
766 node = xdcp->node_be;
767 }
768 } else {
769 node = xdcp->node_fe;
770 }
771
772 /* Must have a driver to use. */
773 if (node == NULL)
774 return (NULL);
775
776 /*
777 * We need to check the state of this device before we go
778 * further, otherwise we'll end up with a dead loop if
779 * anything goes wrong.
780 */
781 if ((xsname != NULL) &&
782 (xenbus_read_driver_state(xsname) >= XenbusStateClosing))
783 return (NULL);
784
785 ndi_devi_alloc_sleep(parent, node, DEVI_SID_NODEID, &dip);
786
787 /*
788 * Driver binding uses the compatible property _before_ the
789 * node name, so we set the node name to the 'model' of the
790 * device (i.e. 'xnb' or 'xdb') and, if 'type' is present,
791 * encode both the model and the type in a compatible property
792 * (i.e. 'xnb,netfront' or 'xnb,SUNW_mac'). This allows a
793 * driver binding based on the <model,type> pair _before_ a
794 * binding based on the node name.
795 */
796 if ((xsname != NULL) &&
797 (xenbus_read(XBT_NULL, xsname, "type", (void *)&type, &tlen)
798 == 0)) {
799 size_t clen;
800 char *c[1];
801
802 clen = strlen(node) + strlen(type) + 2;
803 c[0] = kmem_alloc(clen, KM_SLEEP);
804 (void) snprintf(c[0], clen, "%s,%s", node, type);
805
806 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE,
807 dip, "compatible", (char **)c, 1);
808
809 kmem_free(c[0], clen);
810 kmem_free(type, tlen);
811 }
812
813 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "devclass", devclass);
814 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "domain", dom);
815 (void) ndi_prop_update_int(DDI_DEV_T_NONE, dip, "vdev", vdev);
816
817 if (i_ddi_devi_attached(parent))
818 ret = ndi_devi_online(dip, 0);
819 else
820 ret = ndi_devi_bind_driver(dip, 0);
821 if (ret != NDI_SUCCESS)
822 (void) ndi_devi_offline(dip, NDI_DEVI_REMOVE);
823
824 return (dip);
825 }
826
827 /*
828 * xendev_enum_class()
829 */
830 void
831 xendev_enum_class(dev_info_t *parent, xendev_devclass_t devclass)
832 {
833 boolean_t dom0 = DOMAIN_IS_INITDOMAIN(xen_info);
834 boolean_t domU = !dom0;
835 i_xd_cfg_t *xdcp;
836
837 xdcp = i_xvdi_devclass2cfg(devclass);
838 ASSERT(xdcp != NULL);
839
840 if (dom0 && !(xdcp->flags & XD_DOM_ZERO))
841 return;
842
843 if (domU && !(xdcp->flags & XD_DOM_GUEST))
844 return;
845
846 if (xdcp->xsdev == NULL) {
847 int circ;
848
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, &circ);
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, circ);
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, circ;
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, &circ);
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, circ);
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, circ;
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, &circ);
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, circ);
2420
2421 done:
2422 kmem_free(path, strlen(path) + 1);
2423 }