1 /* $NetBSD: xenbus_probe.c,v 1.26 2008/10/29 13:53:15 cegger 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.26 2008/10/29 13:53:15 cegger 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/xen.h> /* for xendomain_is_dom0() */
53 #include <xen/hypervisor.h>
54 #include <xen/xenbus.h>
55 #include <xen/evtchn.h>
56 #include <xen/shutdown_xenbus.h>
58 #include "xenbus_comms.h"
60 extern struct semaphore xenwatch_mutex
;
62 #define streq(a, b) (strcmp((a), (b)) == 0)
64 static int xenbus_match(device_t
, cfdata_t
, void *);
65 static void xenbus_attach(device_t
, device_t
, void *);
66 static int xenbus_print(void *, const char *);
68 static void xenbus_probe_init(void *);
70 static struct xenbus_device
*xenbus_lookup_device_path(const char *);
72 CFATTACH_DECL_NEW(xenbus
, 0, xenbus_match
, xenbus_attach
,
77 SLIST_HEAD(, xenbus_device
) xenbus_device_list
;
78 SLIST_HEAD(, xenbus_backend_driver
) xenbus_backend_driver_list
=
79 SLIST_HEAD_INITIALIZER(xenbus_backend_driver
);
82 xenbus_match(device_t parent
, cfdata_t match
, void *aux
)
84 struct xenbus_attach_args
*xa
= (struct xenbus_attach_args
*)aux
;
86 if (strcmp(xa
->xa_device
, "xenbus") == 0)
92 xenbus_attach(device_t parent
, device_t self
, void *aux
)
96 aprint_normal(": Xen Virtual Bus Interface\n");
98 config_pending_incr();
100 err
= kthread_create(PRI_NONE
, 0, NULL
, xenbus_probe_init
, NULL
,
101 NULL
, "xenbus_probe");
103 aprint_error_dev(xenbus_dev
,
104 "kthread_create(xenbus_probe): %d\n", err
);
108 xenbus_backend_register(struct xenbus_backend_driver
*xbakd
)
110 SLIST_INSERT_HEAD(&xenbus_backend_driver_list
, xbakd
, xbakd_entries
);
114 read_otherend_details(struct xenbus_device
*xendev
,
115 const char *id_node
, const char *path_node
)
120 err
= xenbus_read(NULL
, xendev
->xbusd_path
, id_node
, NULL
, &val
);
122 printf("reading other end details %s from %s\n",
123 id_node
, xendev
->xbusd_path
);
124 xenbus_dev_fatal(xendev
, err
,
125 "reading other end details %s from %s",
126 id_node
, xendev
->xbusd_path
);
129 xendev
->xbusd_otherend_id
= strtoul(val
, &ep
, 10);
130 if (val
[0] == '\0' || *ep
!= '\0') {
131 printf("reading other end details %s from %s: %s is not a number\n", id_node
, xendev
->xbusd_path
, val
);
132 xenbus_dev_fatal(xendev
, err
,
133 "reading other end details %s from %s: %s is not a number",
134 id_node
, xendev
->xbusd_path
, val
);
139 err
= xenbus_read(NULL
, xendev
->xbusd_path
, path_node
, NULL
, &val
);
141 printf("reading other end details %s from %s (%d)\n",
142 path_node
, xendev
->xbusd_path
, err
);
143 xenbus_dev_fatal(xendev
, err
,
144 "reading other end details %s from %s",
145 path_node
, xendev
->xbusd_path
);
148 DPRINTK("read_otherend_details: read %s/%s returned %s\n",
149 xendev
->xbusd_path
, path_node
, val
);
150 xendev
->xbusd_otherend
= val
;
152 if (strlen(xendev
->xbusd_otherend
) == 0 ||
153 !xenbus_exists(NULL
, xendev
->xbusd_otherend
, "")) {
154 printf("missing other end from %s\n", xendev
->xbusd_path
);
155 xenbus_dev_fatal(xendev
, -ENOENT
, "missing other end from %s",
157 free(xendev
->xbusd_otherend
, M_DEVBUF
);
158 xendev
->xbusd_otherend
= NULL
;
166 read_backend_details(struct xenbus_device
*xendev
)
168 return read_otherend_details(xendev
, "backend-id", "backend");
173 read_frontend_details(struct xenbus_device
*xendev
)
175 return read_otherend_details(xendev
, "frontend-id", "frontend");
180 free_otherend_details(struct xenbus_device
*dev
)
182 free(dev
->xbusd_otherend
, M_DEVBUF
);
183 dev
->xbusd_otherend
= NULL
;
189 free_otherend_watch(struct xenbus_device
*dev
)
191 if (dev
->xbusd_otherend_watch
.node
) {
192 unregister_xenbus_watch(&dev
->xbusd_otherend_watch
);
193 free(dev
->xbusd_otherend_watch
.node
, M_DEVBUF
);
194 dev
->xbusd_otherend_watch
.node
= NULL
;
199 otherend_changed(struct xenbus_watch
*watch
,
200 const char **vec
, unsigned int len
)
202 struct xenbus_device
*xdev
= watch
->xbw_dev
;
205 /* Protect us against watches firing on old details when the otherend
206 details change, say immediately after a resume. */
207 if (!xdev
->xbusd_otherend
||
208 strncmp(xdev
->xbusd_otherend
, vec
[XS_WATCH_PATH
],
209 strlen(xdev
->xbusd_otherend
))) {
210 DPRINTK("Ignoring watch at %s", vec
[XS_WATCH_PATH
]);
214 state
= xenbus_read_driver_state(xdev
->xbusd_otherend
);
216 DPRINTK("state is %d, %s, %s",
217 state
, xdev
->xbusd_otherend_watch
.node
, vec
[XS_WATCH_PATH
]);
218 if (state
== XenbusStateClosed
) {
220 if (xdev
->xbusd_type
== XENBUS_BACKEND_DEVICE
) {
221 error
= xdev
->xbusd_u
.b
.b_detach(
222 xdev
->xbusd_u
.b
.b_cookie
);
224 printf("could not detach %s: %d\n",
225 xdev
->xbusd_path
, error
);
229 error
= config_detach(xdev
->xbusd_u
.f
.f_dev
,
232 printf("could not detach %s: %d\n",
233 device_xname(xdev
->xbusd_u
.f
.f_dev
), error
);
237 xenbus_free_device(xdev
);
240 if (xdev
->xbusd_otherend_changed
)
241 xdev
->xbusd_otherend_changed(
242 (xdev
->xbusd_type
== XENBUS_BACKEND_DEVICE
) ?
243 xdev
->xbusd_u
.b
.b_cookie
: xdev
->xbusd_u
.f
.f_dev
, state
);
247 talk_to_otherend(struct xenbus_device
*dev
)
249 free_otherend_watch(dev
);
251 return xenbus_watch_path2(dev
, dev
->xbusd_otherend
, "state",
252 &dev
->xbusd_otherend_watch
,
256 static struct xenbus_device
*
257 xenbus_lookup_device_path(const char *path
)
259 struct xenbus_device
*xbusd
;
261 SLIST_FOREACH(xbusd
, &xenbus_device_list
, xbusd_entries
) {
262 if (strcmp(xbusd
->xbusd_path
, path
) == 0)
269 xenbus_probe_device_type(const char *path
, const char *type
,
270 int (*create
)(struct xenbus_device
*))
275 unsigned int dir_n
= 0;
276 struct xenbus_device
*xbusd
;
277 struct xenbusdev_attach_args xa
;
280 DPRINTK("probe %s type %s", path
, type
);
281 err
= xenbus_directory(NULL
, path
, "", &dir_n
, &dir
);
282 DPRINTK("directory err %d dir_n %d", err
, dir_n
);
286 for (i
= 0; i
< dir_n
; i
++) {
288 * add size of path to size of xenbus_device. xenbus_device
289 * already has room for one char in xbusd_path.
291 msize
= sizeof(*xbusd
) + strlen(path
) + strlen(dir
[i
]) + 2;
292 xbusd
= malloc(msize
, M_DEVBUF
, M_WAITOK
| M_ZERO
);
294 panic("can't malloc xbusd");
296 snprintf(__UNCONST(xbusd
->xbusd_path
),
297 msize
- sizeof(*xbusd
) + 1, "%s/%s", path
, dir
[i
]);
298 if (xenbus_lookup_device_path(xbusd
->xbusd_path
) != NULL
) {
299 /* device already registered */
300 free(xbusd
, M_DEVBUF
);
303 err
= xenbus_read_ul(NULL
, xbusd
->xbusd_path
, "state",
306 printf("xenbus: can't get state "
307 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
308 free(xbusd
, M_DEVBUF
);
311 if (state
!= XenbusStateInitialising
) {
312 /* device is not new */
313 free(xbusd
, M_DEVBUF
);
317 xbusd
->xbusd_otherend_watch
.xbw_dev
= xbusd
;
318 DPRINTK("xenbus_probe_device_type probe %s\n",
320 if (create
!= NULL
) {
321 xbusd
->xbusd_type
= XENBUS_BACKEND_DEVICE
;
322 err
= read_frontend_details(xbusd
);
324 printf("xenbus: can't get frontend details "
325 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
329 free(xbusd
, M_DEVBUF
);
333 xbusd
->xbusd_type
= XENBUS_FRONTEND_DEVICE
;
336 xa
.xa_id
= strtoul(dir
[i
], &ep
, 0);
337 if (dir
[i
][0] == '\0' || *ep
!= '\0') {
338 printf("xenbus device type %s: id %s is not a"
339 " number\n", type
, dir
[i
]);
341 free(xbusd
, M_DEVBUF
);
344 err
= read_backend_details(xbusd
);
346 printf("xenbus: can't get backend details "
347 "for %s (%d)\n", xbusd
->xbusd_path
, err
);
350 xbusd
->xbusd_u
.f
.f_dev
= config_found_ia(xenbus_dev
,
351 "xenbus", &xa
, xenbus_print
);
352 if (xbusd
->xbusd_u
.f
.f_dev
== NULL
) {
353 free(xbusd
, M_DEVBUF
);
357 SLIST_INSERT_HEAD(&xenbus_device_list
,
358 xbusd
, xbusd_entries
);
359 talk_to_otherend(xbusd
);
366 xenbus_print(void *aux
, const char *pnp
)
368 struct xenbusdev_attach_args
*xa
= aux
;
371 if (strcmp(xa
->xa_type
, "vbd") == 0)
372 aprint_normal("xbd");
373 else if (strcmp(xa
->xa_type
, "vif") == 0)
374 aprint_normal("xennet");
376 aprint_normal("unknown type %s", xa
->xa_type
);
377 aprint_normal(" at %s", pnp
);
379 aprint_normal(" id %d", xa
->xa_id
);
384 xenbus_probe_frontends(void)
388 unsigned int i
, dir_n
;
391 DPRINTK("probe device");
392 err
= xenbus_directory(NULL
, "device", "", &dir_n
, &dir
);
393 DPRINTK("directory err %d dir_n %d", err
, dir_n
);
397 for (i
= 0; i
< dir_n
; i
++) {
399 * console is configured through xen_start_info when
400 * xencons is attaching to hypervisor, so avoid console
401 * probing when configuring xenbus devices
403 if (strcmp(dir
[i
], "console") == 0)
406 snprintf(path
, sizeof(path
), "device/%s", dir
[i
]);
407 err
= xenbus_probe_device_type(path
, dir
[i
], NULL
);
416 xenbus_probe_backends(void)
419 char **dirt
, **dirid
;
420 unsigned int type
, id
, dirt_n
, dirid_n
;
422 struct xenbus_backend_driver
*xbakd
;
424 DPRINTK("probe backend");
425 err
= xenbus_directory(NULL
, "backend", "", &dirt_n
, &dirt
);
426 DPRINTK("directory err %d dirt_n %d", err
, dirt_n
);
430 for (type
= 0; type
< dirt_n
; type
++) {
431 SLIST_FOREACH(xbakd
, &xenbus_backend_driver_list
,
433 if (strcmp(dirt
[type
], xbakd
->xbakd_type
) == 0)
438 err
= xenbus_directory(NULL
, "backend", dirt
[type
],
440 DPRINTK("directory backend/%s err %d dirid_n %d",
441 dirt
[type
], err
, dirid_n
);
443 free(dirt
, M_DEVBUF
); /* to be checked */
446 for (id
= 0; id
< dirid_n
; id
++) {
447 snprintf(path
, sizeof(path
), "backend/%s/%s",
448 dirt
[type
], dirid
[id
]);
449 err
= xenbus_probe_device_type(path
, dirt
[type
],
450 xbakd
->xbakd_create
);
454 free(dirid
, M_DEVBUF
);
456 free(dirt
, M_DEVBUF
);
461 xenbus_free_device(struct xenbus_device
*xbusd
)
463 KASSERT(xenbus_lookup_device_path(xbusd
->xbusd_path
) == xbusd
);
464 SLIST_REMOVE(&xenbus_device_list
, xbusd
, xenbus_device
, xbusd_entries
);
465 free_otherend_watch(xbusd
);
466 free(xbusd
->xbusd_otherend
, M_DEVBUF
);
467 xenbus_switch_state(xbusd
, NULL
, XenbusStateClosed
);
468 free(xbusd
, M_DEVBUF
);
473 frontend_changed(struct xenbus_watch
*watch
,
474 const char **vec
, unsigned int len
)
476 DPRINTK("frontend_changed %s\n", vec
[XS_WATCH_PATH
]);
477 xenbus_probe_frontends();
481 backend_changed(struct xenbus_watch
*watch
,
482 const char **vec
, unsigned int len
)
484 DPRINTK("backend_changed %s\n", vec
[XS_WATCH_PATH
]);
485 xenbus_probe_backends();
489 /* We watch for devices appearing and vanishing. */
490 static struct xenbus_watch fe_watch
;
492 static struct xenbus_watch be_watch
;
494 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
495 int xenstored_ready
= 0;
498 xenbus_probe(void *unused
)
500 KASSERT((xenstored_ready
> 0));
502 /* Enumerate devices in xenstore. */
503 xenbus_probe_frontends();
504 xenbus_probe_backends();
506 /* Watch for changes. */
507 fe_watch
.node
= malloc(strlen("device" + 1), M_DEVBUF
, M_NOWAIT
);
508 strcpy(fe_watch
.node
, "device");
509 fe_watch
.xbw_callback
= frontend_changed
;
510 register_xenbus_watch(&fe_watch
);
511 be_watch
.node
= malloc(strlen("backend" + 1), M_DEVBUF
, M_NOWAIT
);
512 strcpy(be_watch
.node
, "backend");
513 be_watch
.xbw_callback
= backend_changed
;
514 register_xenbus_watch(&be_watch
);
515 shutdown_xenbus_setup();
517 /* Notify others that xenstore is up */
518 //notifier_call_chain(&xenstore_chain, 0, NULL);
522 xenbus_probe_init(void *unused
)
530 SLIST_INIT(&xenbus_device_list
);
533 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
535 dom0
= xendomain_is_dom0();
539 evtchn_op_t op
= { .cmd
= 0 };
542 page
= uvm_km_alloc(kernel_map
, PAGE_SIZE
, 0,
543 UVM_KMF_ZERO
| UVM_KMF_WIRED
);
545 panic("can't get xenstore page");
547 (void)pmap_extract_ma(pmap_kernel(), page
, &ma
);
548 xen_start_info
.store_mfn
= ma
>> PAGE_SHIFT
;
549 xenstore_interface
= (void *)page
;
551 /* Next allocate a local port which xenstored can bind to */
552 op
.cmd
= EVTCHNOP_alloc_unbound
;
553 op
.u
.alloc_unbound
.dom
= DOMID_SELF
;
554 op
.u
.alloc_unbound
.remote_dom
= 0;
556 err
= HYPERVISOR_event_channel_op(&op
);
558 aprint_error_dev(xenbus_dev
,
559 "can't register xenstore event\n");
563 xen_start_info
.store_evtchn
= op
.u
.alloc_unbound
.port
;
565 /* And finally publish the above info in /kern/xen */
566 xenbus_kernfs_init();
570 kthread_exit(0); /* can't get a working xenstore in this case */
574 /* register event handler */
575 xb_init_comms(xenbus_dev
);
577 /* Initialize the interface to xenstore. */
578 err
= xs_init(xenbus_dev
);
580 aprint_error_dev(xenbus_dev
,
581 "Error initializing xenstore comms: %i\n", err
);
591 config_pending_decr();
596 while (xenstored_ready
== 0) {
597 tsleep(&xenstored_ready
, PRIBIO
, "xsready", 0);
607 uvm_km_free(kernel_map
, page
, PAGE_SIZE
,
608 UVM_KMF_ZERO
| UVM_KMF_WIRED
);
614 * c-file-style: "linux"
615 * indent-tabs-mode: t