1 /* $NetBSD: xenbus_probe.c,v 1.22 2008/09/05 13:37:24 tron Exp $ */
2 /******************************************************************************
3 * Talks to Xen Store to figure out what devices we have.
5 * Copyright (C) 2005 Rusty Russell, IBM Corporation
6 * Copyright (C) 2005 Mike Wray, Hewlett-Packard
7 * Copyright (C) 2005 XenSource Ltd
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
12 * Permission is hereby granted, free of charge, to any person obtaining a copy
13 * of this source file (the "Software"), to deal in the Software without
14 * restriction, including without limitation the rights to use, copy, modify,
15 * merge, publish, distribute, sublicense, and/or sell copies of the Software,
16 * and to permit persons to whom the Software is furnished to do so, subject to
17 * the following conditions:
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.22 2008/09/05 13:37:24 tron Exp $");
35 #define DPRINTK(fmt, args...) \
36 printf("xenbus_probe (%s:%d) " fmt ".\n", __func__, __LINE__, ##args)
38 #define DPRINTK(fmt, args...) ((void)0)
41 #include <sys/types.h>
43 #include <sys/errno.h>
44 #include <sys/malloc.h>
45 #include <sys/systm.h>
46 #include <sys/param.h>
47 #include <sys/kthread.h>
50 #include <machine/stdarg.h>
52 #include <xen/hypervisor.h>
53 #include <xen/xenbus.h>
54 #include <xen/evtchn.h>
55 #include <xen/shutdown_xenbus.h>
57 #include "xenbus_comms.h"
59 extern struct semaphore xenwatch_mutex
;
61 #define streq(a, b) (strcmp((a), (b)) == 0)
63 static int xenbus_match(device_t
, cfdata_t
, void *);
64 static void xenbus_attach(device_t
, device_t
, void *);
65 static int xenbus_print(void *, const char *);
67 static void xenbus_probe_init(void *);
69 static struct xenbus_device
*xenbus_lookup_device_path(const char *);
71 CFATTACH_DECL_NEW(xenbus
, 0, xenbus_match
, xenbus_attach
,
76 SLIST_HEAD(, xenbus_device
) xenbus_device_list
;
77 SLIST_HEAD(, xenbus_backend_driver
) xenbus_backend_driver_list
=
78 SLIST_HEAD_INITIALIZER(xenbus_backend_driver
);
81 xenbus_match(device_t parent
, cfdata_t match
, void *aux
)
83 struct xenbus_attach_args
*xa
= (struct xenbus_attach_args
*)aux
;
85 if (strcmp(xa
->xa_device
, "xenbus") == 0)
91 xenbus_attach(device_t parent
, device_t self
, void *aux
)
95 aprint_normal(": Xen Virtual Bus Interface\n");
97 config_pending_incr();
99 err
= kthread_create(PRI_NONE
, 0, NULL
, xenbus_probe_init
, NULL
,
100 NULL
, "xenbus_probe");
102 aprint_error_dev(xenbus_sc
,
103 "kthread_create(xenbus_probe): %d\n", err
);
107 xenbus_backend_register(struct xenbus_backend_driver
*xbakd
)
109 SLIST_INSERT_HEAD(&xenbus_backend_driver_list
, xbakd
, xbakd_entries
);
113 read_otherend_details(struct xenbus_device
*xendev
,
114 const char *id_node
, const char *path_node
)
119 err
= xenbus_read(NULL
, xendev
->xbusd_path
, id_node
, NULL
, &val
);
121 printf("reading other end details %s from %s\n",
122 id_node
, xendev
->xbusd_path
);
123 xenbus_dev_fatal(xendev
, err
,
124 "reading other end details %s from %s",
125 id_node
, xendev
->xbusd_path
);
128 xendev
->xbusd_otherend_id
= strtoul(val
, &ep
, 10);
129 if (val
[0] == '\0' || *ep
!= '\0') {
130 printf("reading other end details %s from %s: %s is not a number\n", id_node
, xendev
->xbusd_path
, val
);
131 xenbus_dev_fatal(xendev
, err
,
132 "reading other end details %s from %s: %s is not a number",
133 id_node
, xendev
->xbusd_path
, val
);
138 err
= xenbus_read(NULL
, xendev
->xbusd_path
, path_node
, NULL
, &val
);
140 printf("reading other end details %s from %s (%d)\n",
141 path_node
, xendev
->xbusd_path
, err
);
142 xenbus_dev_fatal(xendev
, err
,
143 "reading other end details %s from %s",
144 path_node
, xendev
->xbusd_path
);
147 DPRINTK("read_otherend_details: read %s/%s returned %s\n",
148 xendev
->xbusd_path
, path_node
, val
);
149 xendev
->xbusd_otherend
= val
;
151 if (strlen(xendev
->xbusd_otherend
) == 0 ||
152 !xenbus_exists(NULL
, xendev
->xbusd_otherend
, "")) {
153 printf("missing other end from %s\n", xendev
->xbusd_path
);
154 xenbus_dev_fatal(xendev
, -ENOENT
, "missing other end from %s",
156 free(xendev
->xbusd_otherend
, M_DEVBUF
);
157 xendev
->xbusd_otherend
= NULL
;
165 read_backend_details(struct xenbus_device
*xendev
)
167 return read_otherend_details(xendev
, "backend-id", "backend");
172 read_frontend_details(struct xenbus_device
*xendev
)
174 return read_otherend_details(xendev
, "frontend-id", "frontend");
179 free_otherend_details(struct xenbus_device
*dev
)
181 free(dev
->xbusd_otherend
, M_DEVBUF
);
182 dev
->xbusd_otherend
= NULL
;
188 free_otherend_watch(struct xenbus_device
*dev
)
190 if (dev
->xbusd_otherend_watch
.node
) {
191 unregister_xenbus_watch(&dev
->xbusd_otherend_watch
);
192 free(dev
->xbusd_otherend_watch
.node
, M_DEVBUF
);
193 dev
->xbusd_otherend_watch
.node
= NULL
;
198 otherend_changed(struct xenbus_watch
*watch
,
199 const char **vec
, unsigned int len
)
201 struct xenbus_device
*xdev
= watch
->xbw_dev
;
204 /* Protect us against watches firing on old details when the otherend
205 details change, say immediately after a resume. */
206 if (!xdev
->xbusd_otherend
||
207 strncmp(xdev
->xbusd_otherend
, vec
[XS_WATCH_PATH
],
208 strlen(xdev
->xbusd_otherend
))) {
209 DPRINTK("Ignoring watch at %s", vec
[XS_WATCH_PATH
]);
213 state
= xenbus_read_driver_state(xdev
->xbusd_otherend
);
215 DPRINTK("state is %d, %s, %s",
216 state
, xdev
->xbusd_otherend_watch
.node
, vec
[XS_WATCH_PATH
]);
217 if (state
== XenbusStateClosed
) {
219 if (xdev
->xbusd_type
== XENBUS_BACKEND_DEVICE
) {
220 error
= xdev
->xbusd_u
.b
.b_detach(
221 xdev
->xbusd_u
.b
.b_cookie
);
223 printf("could not detach %s: %d\n",
224 xdev
->xbusd_path
, error
);
228 error
= config_detach(xdev
->xbusd_u
.f
.f_dev
,
231 printf("could not detach %s: %d\n",
232 device_xname(xdev
->xbusd_u
.f
.f_dev
), error
);
236 xenbus_free_device(xdev
);
239 if (xdev
->xbusd_otherend_changed
)
240 xdev
->xbusd_otherend_changed(
241 (xdev
->xbusd_type
== XENBUS_BACKEND_DEVICE
) ?
242 xdev
->xbusd_u
.b
.b_cookie
: xdev
->xbusd_u
.f
.f_dev
, state
);
246 talk_to_otherend(struct xenbus_device
*dev
)
248 free_otherend_watch(dev
);
250 return xenbus_watch_path2(dev
, dev
->xbusd_otherend
, "state",
251 &dev
->xbusd_otherend_watch
,
255 static struct xenbus_device
*
256 xenbus_lookup_device_path(const char *path
)
258 struct xenbus_device
*xbusd
;
260 SLIST_FOREACH(xbusd
, &xenbus_device_list
, xbusd_entries
) {
261 if (strcmp(xbusd
->xbusd_path
, path
) == 0)
268 xenbus_probe_device_type(const char *path
, const char *type
,
269 int (*create
)(struct xenbus_device
*))
274 unsigned int dir_n
= 0;
275 struct xenbus_device
*xbusd
;
276 struct xenbusdev_attach_args xa
;
279 DPRINTK("probe %s type %s", path
, type
);
280 err
= xenbus_directory(NULL
, path
, "", &dir_n
, &dir
);
281 DPRINTK("directory err %d dir_n %d", err
, dir_n
);
285 for (i
= 0; i
< dir_n
; i
++) {
287 * add size of path to size of xenbus_device. xenbus_device
288 * already has room for one char in xbusd_path.
290 msize
= sizeof(*xbusd
) + strlen(path
) + strlen(dir
[i
]) + 2;
291 xbusd
= malloc(msize
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
293 panic("can't malloc xbusd");
295 snprintf(__UNCONST(xbusd
->xbusd_path
),
296 msize
- sizeof(*xbusd
) + 1, "%s/%s", path
, dir
[i
]);
297 if (xenbus_lookup_device_path(xbusd
->xbusd_path
) != NULL
) {
298 /* device already registered */
299 free(xbusd
, M_DEVBUF
);
302 err
= xenbus_read_ul(NULL
, xbusd
->xbusd_path
, "state",
305 printf("xenbus: can't get state "
306 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
307 free(xbusd
, M_DEVBUF
);
310 if (state
!= XenbusStateInitialising
) {
311 /* device is not new */
312 free(xbusd
, M_DEVBUF
);
316 xbusd
->xbusd_otherend_watch
.xbw_dev
= xbusd
;
317 DPRINTK("xenbus_probe_device_type probe %s\n",
319 if (create
!= NULL
) {
320 xbusd
->xbusd_type
= XENBUS_BACKEND_DEVICE
;
321 err
= read_frontend_details(xbusd
);
323 printf("xenbus: can't get frontend details "
324 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
328 free(xbusd
, M_DEVBUF
);
332 xbusd
->xbusd_type
= XENBUS_FRONTEND_DEVICE
;
335 xa
.xa_id
= strtoul(dir
[i
], &ep
, 0);
336 if (dir
[i
][0] == '\0' || *ep
!= '\0') {
337 printf("xenbus device type %s: id %s is not a"
338 " number\n", type
, dir
[i
]);
340 free(xbusd
, M_DEVBUF
);
343 err
= read_backend_details(xbusd
);
345 printf("xenbus: can't get backend details "
346 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
349 xbusd
->xbusd_u
.f
.f_dev
= config_found_ia(xenbus_sc
,
350 "xenbus", &xa
, xenbus_print
);
351 if (xbusd
->xbusd_u
.f
.f_dev
== NULL
) {
352 free(xbusd
, M_DEVBUF
);
356 SLIST_INSERT_HEAD(&xenbus_device_list
,
357 xbusd
, xbusd_entries
);
358 talk_to_otherend(xbusd
);
365 xenbus_print(void *aux
, const char *pnp
)
367 struct xenbusdev_attach_args
*xa
= aux
;
370 if (strcmp(xa
->xa_type
, "vbd") == 0)
371 aprint_normal("xbd");
372 else if (strcmp(xa
->xa_type
, "vif") == 0)
373 aprint_normal("xennet");
375 aprint_normal("unknown type %s", xa
->xa_type
);
376 aprint_normal(" at %s", pnp
);
378 aprint_normal(" id %d", xa
->xa_id
);
383 xenbus_probe_frontends(void)
387 unsigned int i
, dir_n
;
390 DPRINTK("probe device");
391 err
= xenbus_directory(NULL
, "device", "", &dir_n
, &dir
);
392 DPRINTK("directory err %d dir_n %d", err
, dir_n
);
396 for (i
= 0; i
< dir_n
; i
++) {
397 snprintf(path
, sizeof(path
), "device/%s", dir
[i
]);
398 err
= xenbus_probe_device_type(path
, dir
[i
], NULL
);
407 xenbus_probe_backends(void)
410 char **dirt
, **dirid
;
411 unsigned int type
, id
, dirt_n
, dirid_n
;
413 struct xenbus_backend_driver
*xbakd
;
415 DPRINTK("probe backend");
416 err
= xenbus_directory(NULL
, "backend", "", &dirt_n
, &dirt
);
417 DPRINTK("directory err %d dirt_n %d", err
, dirt_n
);
421 for (type
= 0; type
< dirt_n
; type
++) {
422 SLIST_FOREACH(xbakd
, &xenbus_backend_driver_list
,
424 if (strcmp(dirt
[type
], xbakd
->xbakd_type
) == 0)
429 err
= xenbus_directory(NULL
, "backend", dirt
[type
],
431 DPRINTK("directory backend/%s err %d dirid_n %d",
432 dirt
[type
], err
, dirid_n
);
434 free(dirt
, M_DEVBUF
); /* to be checked */
437 for (id
= 0; id
< dirid_n
; id
++) {
438 snprintf(path
, sizeof(path
), "backend/%s/%s",
439 dirt
[type
], dirid
[id
]);
440 err
= xenbus_probe_device_type(path
, dirt
[type
],
441 xbakd
->xbakd_create
);
445 free(dirid
, M_DEVBUF
);
447 free(dirt
, M_DEVBUF
);
452 xenbus_free_device(struct xenbus_device
*xbusd
)
454 KASSERT(xenbus_lookup_device_path(xbusd
->xbusd_path
) == xbusd
);
455 SLIST_REMOVE(&xenbus_device_list
, xbusd
, xenbus_device
, xbusd_entries
);
456 free_otherend_watch(xbusd
);
457 free(xbusd
->xbusd_otherend
, M_DEVBUF
);
458 xenbus_switch_state(xbusd
, NULL
, XenbusStateClosed
);
459 free(xbusd
, M_DEVBUF
);
464 frontend_changed(struct xenbus_watch
*watch
,
465 const char **vec
, unsigned int len
)
467 DPRINTK("frontend_changed %s\n", vec
[XS_WATCH_PATH
]);
468 xenbus_probe_frontends();
472 backend_changed(struct xenbus_watch
*watch
,
473 const char **vec
, unsigned int len
)
475 DPRINTK("backend_changed %s\n", vec
[XS_WATCH_PATH
]);
476 xenbus_probe_backends();
480 /* We watch for devices appearing and vanishing. */
481 static struct xenbus_watch fe_watch
;
483 static struct xenbus_watch be_watch
;
485 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
486 int xenstored_ready
= 0;
489 xenbus_probe(void *unused
)
491 KASSERT((xenstored_ready
> 0));
493 /* Enumerate devices in xenstore. */
494 xenbus_probe_frontends();
495 xenbus_probe_backends();
497 /* Watch for changes. */
498 fe_watch
.node
= malloc(strlen("device" + 1), M_DEVBUF
, M_NOWAIT
);
499 strcpy(fe_watch
.node
, "device");
500 fe_watch
.xbw_callback
= frontend_changed
;
501 register_xenbus_watch(&fe_watch
);
502 be_watch
.node
= malloc(strlen("backend" + 1), M_DEVBUF
, M_NOWAIT
);
503 strcpy(be_watch
.node
, "backend");
504 be_watch
.xbw_callback
= backend_changed
;
505 register_xenbus_watch(&be_watch
);
506 shutdown_xenbus_setup();
508 /* Notify others that xenstore is up */
509 //notifier_call_chain(&xenstore_chain, 0, NULL);
513 xenbus_probe_init(void *unused
)
521 SLIST_INIT(&xenbus_device_list
);
524 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
526 dom0
= xendomain_is_dom0();
530 evtchn_op_t op
= { .cmd
= 0 };
533 page
= uvm_km_alloc(kernel_map
, PAGE_SIZE
, 0,
534 UVM_KMF_ZERO
| UVM_KMF_WIRED
);
536 panic("can't get xenstore page");
538 (void)pmap_extract_ma(pmap_kernel(), page
, &ma
);
539 xen_start_info
.store_mfn
= ma
>> PAGE_SHIFT
;
540 xenstore_interface
= (void *)page
;
542 /* Next allocate a local port which xenstored can bind to */
543 op
.cmd
= EVTCHNOP_alloc_unbound
;
544 op
.u
.alloc_unbound
.dom
= DOMID_SELF
;
545 op
.u
.alloc_unbound
.remote_dom
= 0;
547 err
= HYPERVISOR_event_channel_op(&op
);
549 aprint_error_dev(xenbus_sc
,
550 "can't register xenstore event\n");
554 xen_start_info
.store_evtchn
= op
.u
.alloc_unbound
.port
;
556 /* And finally publish the above info in /kern/xen */
557 xenbus_kernfs_init();
561 kthread_exit(0); /* can't get a working xenstore in this case */
565 /* register event handler */
566 xb_init_comms(xenbus_sc
);
568 /* Initialize the interface to xenstore. */
571 aprint_error_dev(xenbus_sc
,
572 "Error initializing xenstore comms: %i\n", err
);
582 config_pending_decr();
587 while (xenstored_ready
== 0) {
588 tsleep(&xenstored_ready
, PRIBIO
, "xsready", 0);
598 uvm_km_free(kernel_map
, page
, PAGE_SIZE
,
599 UVM_KMF_ZERO
| UVM_KMF_WIRED
);
605 * c-file-style: "linux"
606 * indent-tabs-mode: t