xenbus_probe.c revision 1.8 1 /* $NetBSD: xenbus_probe.c,v 1.8 2006/04/09 22:14:13 bouyer Exp $ */
2 /******************************************************************************
3 * Talks to Xen Store to figure out what devices we have.
4 *
5 * Copyright (C) 2005 Rusty Russell, IBM Corporation
6 * Copyright (C) 2005 Mike Wray, Hewlett-Packard
7 * Copyright (C) 2005 XenSource Ltd
8 *
9 * This file may be distributed separately from the Linux kernel, or
10 * incorporated into other software packages, subject to the following license:
11 *
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:
18 *
19 * The above copyright notice and this permission notice shall be included in
20 * all copies or substantial portions of the Software.
21 *
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
28 * IN THE SOFTWARE.
29 */
30
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: xenbus_probe.c,v 1.8 2006/04/09 22:14:13 bouyer Exp $");
33
34 #if 0
35 #define DPRINTK(fmt, args...) \
36 printf("xenbus_probe (%s:%d) " fmt ".\n", __FUNCTION__, __LINE__, ##args)
37 #else
38 #define DPRINTK(fmt, args...) ((void)0)
39 #endif
40
41 #include <sys/types.h>
42 #include <sys/null.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>
48 #include <uvm/uvm.h>
49
50 #if defined(DOM0OPS)
51 #include <sys/dirent.h>
52 #include <sys/stat.h>
53 #include <sys/tree.h>
54 #include <sys/vnode.h>
55 #include <miscfs/specfs/specdev.h>
56 #include <miscfs/kernfs/kernfs.h>
57 #include <machine/kernfs_machdep.h>
58 #endif
59
60 #include <machine/stdarg.h>
61
62 #include <machine/hypervisor.h>
63 #include <machine/xenbus.h>
64 #include <machine/evtchn.h>
65
66 #include "xenbus_comms.h"
67
68 extern struct semaphore xenwatch_mutex;
69
70 #define streq(a, b) (strcmp((a), (b)) == 0)
71
72 static int xenbus_match(struct device *, struct cfdata *, void *);
73 static void xenbus_attach(struct device *, struct device *, void *);
74 static int xenbus_print(void *, const char *);
75
76 static void xenbus_kthread_create(void *);
77 static void xenbus_probe_init(void *);
78
79 static struct xenbus_device *xenbus_lookup_device_path(const char *);
80
81 CFATTACH_DECL(xenbus, sizeof(struct device), xenbus_match, xenbus_attach,
82 NULL, NULL);
83
84 struct device *xenbus_sc;
85
86 SLIST_HEAD(, xenbus_device) xenbus_device_list;
87
88 #if defined(DOM0OPS)
89 static int xsd_mfn_read(void *);
90 static int xsd_port_read(void *);
91
92 static const struct kernfs_fileop xsd_mfn_fileops[] = {
93 { .kf_fileop = KERNFS_FILEOP_READ, .kf_vop = xsd_mfn_read },
94 };
95 static const struct kernfs_fileop xsd_port_fileops[] = {
96 { .kf_fileop = KERNFS_FILEOP_READ, .kf_vop = xsd_port_read },
97 };
98
99 #define XSD_MODE (S_IRUSR)
100 #endif /*DOM0OPS*/
101 int
102 xenbus_match(struct device *parent, struct cfdata *match, void *aux)
103 {
104 struct xenbus_attach_args *xa = (struct xenbus_attach_args *)aux;
105
106 if (strcmp(xa->xa_device, "xenbus") == 0)
107 return 1;
108 return 0;
109 }
110
111 static void
112 xenbus_attach(struct device *parent, struct device *self, void *aux)
113 {
114 aprint_normal(": Xen Virtual Bus Interface\n");
115 xenbus_sc = self;
116 xb_init_comms(self);
117 config_pending_incr();
118 kthread_create(xenbus_kthread_create, NULL);
119 }
120
121 void
122 xenbus_kthread_create(void *unused)
123 {
124 struct proc *p;
125 int err;
126 err = kthread_create1(xenbus_probe_init, NULL, &p, "xenbus_probe");
127 if (err)
128 printf("kthread_create1(xenbus_probe): %d\n", err);
129 }
130
131
132 #if 0
133 static char *kasprintf(const char *fmt, ...);
134
135 static struct notifier_block *xenstore_chain;
136
137 /* If something in array of ids matches this device, return it. */
138 static const struct xenbus_device_id *
139 match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev)
140 {
141 for (; !streq(arr->devicetype, ""); arr++) {
142 if (streq(arr->devicetype, dev->devicetype))
143 return arr;
144 }
145 return NULL;
146 }
147
148 static int xenbus_match_device(struct device *_dev, struct device_driver *_drv)
149 {
150 struct xenbus_driver *drv = to_xenbus_driver(_drv);
151
152 if (!drv->ids)
153 return 0;
154
155 return match_device(drv->ids, to_xenbus_device(_dev)) != NULL;
156 }
157 #endif
158
159 struct xen_bus_type
160 {
161 const char *root;
162 unsigned int levels;
163 };
164
165 #if 0
166 /* device/<type>/<id> => <type>-<id> */
167 static int
168 frontend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
169 {
170 nodename = strchr(nodename, '/');
171 if (!nodename || strlen(nodename + 1) >= BUS_ID_SIZE) {
172 printk(KERN_WARNING "XENBUS: bad frontend %s\n", nodename);
173 return EINVAL;
174 }
175
176 strlcpy(bus_id, nodename + 1, BUS_ID_SIZE);
177 if (!strchr(bus_id, '/')) {
178 printk(KERN_WARNING "XENBUS: bus_id %s no slash\n", bus_id);
179 return EINVAL;
180 }
181 *strchr(bus_id, '/') = '-';
182 return 0;
183 }
184 #endif
185
186 static int
187 read_otherend_details(struct xenbus_device *xendev,
188 const char *id_node, const char *path_node)
189 {
190 int err;
191 char *val, *ep;
192
193 err = xenbus_read(NULL, xendev->xbusd_path, id_node, NULL, &val);
194 if (err) {
195 printf("reading other end details %s from %s\n",
196 id_node, xendev->xbusd_path);
197 xenbus_dev_fatal(xendev, err,
198 "reading other end details %s from %s",
199 id_node, xendev->xbusd_path);
200 return err;
201 }
202 xendev->xbusd_otherend_id = strtoul(val, &ep, 10);
203 if (val[0] == '\0' || *ep != '\0') {
204 printf("reading other end details %s from %s: %s is not a number\n", id_node, xendev->xbusd_path, val);
205 xenbus_dev_fatal(xendev, err,
206 "reading other end details %s from %s: %s is not a number",
207 id_node, xendev->xbusd_path, val);
208 free(val, M_DEVBUF);
209 return EFTYPE;
210 }
211 free(val, M_DEVBUF);
212 err = xenbus_read(NULL, xendev->xbusd_path, path_node, NULL, &val);
213 if (err) {
214 printf("reading other end details %s from %s (%d)\n",
215 path_node, xendev->xbusd_path, err);
216 xenbus_dev_fatal(xendev, err,
217 "reading other end details %s from %s",
218 path_node, xendev->xbusd_path);
219 return err;
220 }
221 DPRINTK("read_otherend_details: read %s/%s returned %s\n",
222 xendev->xbusd_path, path_node, val);
223 xendev->xbusd_otherend = val;
224
225 if (strlen(xendev->xbusd_otherend) == 0 ||
226 !xenbus_exists(NULL, xendev->xbusd_otherend, "")) {
227 printf("missing other end from %s\n", xendev->xbusd_path);
228 xenbus_dev_fatal(xendev, -ENOENT, "missing other end from %s",
229 xendev->xbusd_path);
230 free(xendev->xbusd_otherend, M_DEVBUF);
231 xendev->xbusd_otherend = NULL;
232 return ENOENT;
233 }
234
235 return 0;
236 }
237
238 static int
239 read_backend_details(struct xenbus_device *xendev)
240 {
241 return read_otherend_details(xendev, "backend-id", "backend");
242 }
243
244
245 #if 0 //#ifdef DOM0OPS
246 static int
247 read_frontend_details(struct xenbus_device *xendev)
248 {
249 return read_otherend_details(xendev, "frontend-id", "frontend");
250 }
251 #endif
252
253 #if unused
254 static void
255 free_otherend_details(struct xenbus_device *dev)
256 {
257 free(dev->xbusd_otherend, M_DEVBUF);
258 dev->xbusd_otherend = NULL;
259 }
260 #endif
261
262
263 static void
264 free_otherend_watch(struct xenbus_device *dev)
265 {
266 if (dev->xbusd_otherend_watch.node) {
267 unregister_xenbus_watch(&dev->xbusd_otherend_watch);
268 free(dev->xbusd_otherend_watch.node, M_DEVBUF);
269 dev->xbusd_otherend_watch.node = NULL;
270 }
271 }
272
273 #if 0
274
275 /* Bus type for frontend drivers. */
276 static int xenbus_probe_frontend(const char *type, const char *name);
277 #endif
278 static struct xen_bus_type xenbus_frontend = {
279 .root = "device",
280 .levels = 2, /* device/type/<id> */
281 };
282
283 #if 0
284 /* backend/<type>/<fe-uuid>/<id> => <type>-<fe-domid>-<id> */
285 static int
286 backend_bus_id(char bus_id[BUS_ID_SIZE], const char *nodename)
287 {
288 int domid, err;
289 const char *devid, *type, *frontend;
290 unsigned int typelen;
291
292 type = strchr(nodename, '/');
293 if (!type)
294 return EINVAL;
295 type++;
296 typelen = strcspn(type, "/");
297 if (!typelen || type[typelen] != '/')
298 return EINVAL;
299
300 devid = strrchr(nodename, '/') + 1;
301
302 err = xenbus_gather(NULL, nodename, "frontend-id", "%i", &domid,
303 "frontend", NULL, &frontend,
304 NULL);
305 if (err)
306 return err;
307 if (strlen(frontend) == 0)
308 err = ERANGE;
309
310 if (!err && !xenbus_exists(NULL, frontend, ""))
311 err = ENOENT;
312
313 if (err) {
314 free(frontend, M_DEVBUF);
315 return err;
316 }
317
318 if (snprintf(bus_id, BUS_ID_SIZE,
319 "%.*s-%i-%s", typelen, type, domid, devid) >= BUS_ID_SIZE)
320 return ENOSPC;
321 return 0;
322 }
323
324 static int
325 xenbus_hotplug_backend(struct device *dev, char **envp,
326 int num_envp, char *buffer, int buffer_size)
327 {
328 struct xenbus_device *xdev;
329 struct xenbus_driver *drv = NULL;
330 int i = 0;
331 int length = 0;
332 char *basepath_end;
333 char *frontend_id;
334
335 DPRINTK("");
336
337 if (dev == NULL)
338 return ENODEV;
339
340 xdev = to_xenbus_device(dev);
341 if (xdev == NULL)
342 return ENODEV;
343
344 if (dev->driver)
345 drv = to_xenbus_driver(dev->driver);
346
347 /* stuff we want to pass to /sbin/hotplug */
348 add_hotplug_env_var(envp, num_envp, &i,
349 buffer, buffer_size, &length,
350 "XENBUS_TYPE=%s", xdev->devicetype);
351
352 add_hotplug_env_var(envp, num_envp, &i,
353 buffer, buffer_size, &length,
354 "XENBUS_PATH=%s", xdev->xbusd_path);
355
356 add_hotplug_env_var(envp, num_envp, &i,
357 buffer, buffer_size, &length,
358 "XENBUS_BASE_PATH=%s", xdev->xbusd_path);
359
360 basepath_end = strrchr(envp[i - 1], '/');
361 length -= strlen(basepath_end);
362 *basepath_end = '\0';
363 basepath_end = strrchr(envp[i - 1], '/');
364 length -= strlen(basepath_end);
365 *basepath_end = '\0';
366
367 basepath_end++;
368 frontend_id = kmalloc(strlen(basepath_end) + 1, GFP_KERNEL);
369 strcpy(frontend_id, basepath_end);
370 add_hotplug_env_var(envp, num_envp, &i,
371 buffer, buffer_size, &length,
372 "XENBUS_FRONTEND_ID=%s", frontend_id);
373 free(frontend_id, M_DEVBUF);
374
375 /* terminate, set to next free slot, shrink available space */
376 envp[i] = NULL;
377 envp = &envp[i];
378 num_envp -= i;
379 buffer = &buffer[length];
380 buffer_size -= length;
381
382 if (drv && drv->hotplug)
383 return drv->hotplug(xdev, envp, num_envp, buffer,
384 buffer_size);
385
386 return 0;
387 }
388
389 static int xenbus_probe_backend(const char *type, const char *domid);
390 #endif
391
392 static struct xen_bus_type xenbus_backend = {
393 .root = "backend",
394 .levels = 3, /* backend/type/<frontend>/<id> */
395 };
396
397 static void
398 otherend_changed(struct xenbus_watch *watch,
399 const char **vec, unsigned int len)
400 {
401 struct xenbus_device *xdev = watch->xbw_dev;
402 XenbusState state;
403
404 /* Protect us against watches firing on old details when the otherend
405 details change, say immediately after a resume. */
406 if (!xdev->xbusd_otherend ||
407 strncmp(xdev->xbusd_otherend, vec[XS_WATCH_PATH],
408 strlen(xdev->xbusd_otherend))) {
409 DPRINTK("Ignoring watch at %s", vec[XS_WATCH_PATH]);
410 return;
411 }
412
413 state = xenbus_read_driver_state(xdev->xbusd_otherend);
414
415 DPRINTK("state is %d, %s, %s",
416 state, xdev->xbusd_otherend_watch.node, vec[XS_WATCH_PATH]);
417 if (state == XenbusStateClosed) {
418 int error;
419 error = config_detach(xdev->xbusd_dev, DETACH_FORCE);
420 if (error) {
421 printf("could not detach %s: %d\n",
422 xdev->xbusd_dev->dv_xname, error);
423 return;
424 }
425 xenbus_free_device(xdev);
426 return;
427 }
428 if (xdev->xbusd_otherend_changed)
429 xdev->xbusd_otherend_changed(xdev->xbusd_dev, state);
430 }
431
432 static int
433 talk_to_otherend(struct xenbus_device *dev)
434 {
435 free_otherend_watch(dev);
436
437 return xenbus_watch_path2(dev, dev->xbusd_otherend, "state",
438 &dev->xbusd_otherend_watch,
439 otherend_changed);
440 }
441
442 #if 0
443
444 static int
445 xenbus_dev_probe(struct device *_dev)
446 {
447 struct xenbus_device *dev = to_xenbus_device(_dev);
448 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
449 const struct xenbus_device_id *id;
450 int err;
451
452 DPRINTK("");
453
454 err = talk_to_otherend(dev);
455 if (err) {
456 printk(KERN_WARNING
457 "xenbus_probe: talk_to_otherend on %s failed.\n",
458 dev->xbusd_path);
459 return err;
460 }
461
462 if (!drv->probe) {
463 err = ENODEV;
464 goto fail;
465 }
466
467 id = match_device(drv->ids, dev);
468 if (!id) {
469 err = ENODEV;
470 goto fail;
471 }
472
473 err = drv->probe(dev, id);
474 if (err)
475 goto fail;
476
477 return 0;
478 fail:
479 xenbus_dev_error(dev, err, "xenbus_dev_probe on %s", dev->xbusd_path);
480 xenbus_switch_state(dev, NULL, XenbusStateClosed);
481 return ENODEV;
482
483 }
484
485 static int
486 xenbus_dev_remove(struct device *_dev)
487 {
488 struct xenbus_device *dev = to_xenbus_device(_dev);
489 struct xenbus_driver *drv = to_xenbus_driver(_dev->driver);
490
491 DPRINTK("");
492
493 free_otherend_watch(dev);
494 free_otherend_details(dev);
495
496 if (drv->remove)
497 drv->remove(dev);
498
499 xenbus_switch_state(dev, NULL, XenbusStateClosed);
500 return 0;
501 }
502
503 static int
504 xenbus_register_driver_common(struct xenbus_driver *drv,
505 struct xen_bus_type *bus)
506 {
507 int ret;
508
509 drv->driver.name = drv->name;
510 drv->driver.bus = &bus->bus;
511 drv->driver.owner = drv->owner;
512 drv->driver.probe = xenbus_dev_probe;
513 drv->driver.remove = xenbus_dev_remove;
514
515 down(&xenwatch_mutex);
516 ret = driver_register(&drv->driver);
517 up(&xenwatch_mutex);
518 return ret;
519 }
520
521 int
522 xenbus_register_frontend(struct xenbus_driver *drv)
523 {
524 drv->read_otherend_details = read_backend_details;
525
526 return xenbus_register_driver_common(drv, &xenbus_frontend);
527 }
528
529 int
530 xenbus_register_backend(struct xenbus_driver *drv)
531 {
532 drv->read_otherend_details = read_frontend_details;
533
534 return xenbus_register_driver_common(drv, &xenbus_backend);
535 }
536
537 void
538 xenbus_unregister_driver(struct xenbus_driver *drv)
539 {
540 driver_unregister(&drv->driver);
541 }
542
543 struct xb_find_info
544 {
545 struct xenbus_device *dev;
546 const char *nodename;
547 };
548
549 static int
550 cmp_dev(struct device *dev, void *data)
551 {
552 struct xenbus_device *xendev = to_xenbus_device(dev);
553 struct xb_find_info *info = data;
554
555 if (streq(xendev->xbusd_path, info->nodename)) {
556 info->dev = xendev;
557 get_device(dev);
558 return 1;
559 }
560 return 0;
561 }
562
563 struct xenbus_device *
564 xenbus_device_find(const char *nodename, struct bus_type *bus)
565 {
566 struct xb_find_info info = { .dev = NULL, .nodename = nodename };
567
568 bus_for_each_dev(bus, NULL, &info, cmp_dev);
569 return info.dev;
570 }
571
572 static int
573 cleanup_dev(struct device *dev, void *data)
574 {
575 struct xenbus_device *xendev = to_xenbus_device(dev);
576 struct xb_find_info *info = data;
577 int len = strlen(info->nodename);
578
579 DPRINTK("%s", info->nodename);
580
581 if (!strncmp(xendev->xbusd_path, info->nodename, len)) {
582 info->dev = xendev;
583 get_device(dev);
584 return 1;
585 }
586 return 0;
587 }
588
589 static void
590 xenbus_cleanup_devices(const char *path, struct bus_type *bus)
591 {
592 struct xb_find_info info = { .nodename = path };
593
594 do {
595 info.dev = NULL;
596 bus_for_each_dev(bus, NULL, &info, cleanup_dev);
597 if (info.dev) {
598 device_unregister(&info.dev->dev);
599 put_device(&info.dev->dev);
600 }
601 } while (info.dev);
602 }
603
604 static void
605 xenbus_dev_free(struct xenbus_device *xendev)
606 {
607 free(xendev, M_DEVBUF);
608 }
609
610 static void
611 xenbus_dev_release(struct device *dev)
612 {
613 if (dev) {
614 xenbus_dev_free(to_xenbus_device(dev));
615 }
616 }
617
618 /* Simplified asprintf. */
619 static char *kasprintf(const char *fmt, ...)
620 {
621 va_list ap;
622 unsigned int len;
623 char *p, dummy[1];
624
625 va_start(ap, fmt);
626 /* FIXME: vsnprintf has a bug, NULL should work */
627 len = vsnprintf(dummy, 0, fmt, ap);
628 va_end(ap);
629
630 p = malloc(len + 1, M_DEVBUF, M_NOWAIT);
631 if (!p)
632 return NULL;
633 va_start(ap, fmt);
634 vsprintf(p, fmt, ap);
635 va_end(ap);
636 return p;
637 }
638 #endif
639
640 #if 0
641 static ssize_t
642 xendev_show_nodename(struct device *dev, char *buf)
643 {
644 return sprintf(buf, "%s\n", to_xenbus_device(dev)->nodename);
645 }
646 // XXX implement
647 DEVICE_ATTR(nodename, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_nodename, NULL);
648
649 static ssize_t
650 xendev_show_devtype(struct device *dev, char *buf)
651 {
652 return sprintf(buf, "%s\n", to_xenbus_device(dev)->devicetype);
653 }
654 DEVICE_ATTR(devtype, S_IRUSR | S_IRGRP | S_IROTH, xendev_show_devtype, NULL);
655
656
657 static int
658 xenbus_probe_node(struct xen_bus_type *bus,
659 const char *type,
660 const char *nodename)
661 {
662 #define CHECK_FAIL \
663 do { \
664 if (err) \
665 goto fail; \
666 } \
667 while (0) \
668
669
670 struct xenbus_device *xendev;
671 size_t stringlen;
672 char *tmpstring;
673
674 XenbusState state = xenbus_read_driver_state(nodename);
675
676 printf("xenbus_probe_node %s %s %s %d\n", bus->root, type, nodename, state);
677 if (state != XenbusStateInitialising) {
678 /* Device is not new, so ignore it. This can happen if a
679 device is going away after switching to Closed. */
680 return 0;
681 }
682
683
684 stringlen = strlen(nodename) + 1 + strlen(type) + 1;
685 xendev = malloc(sizeof(*xendev) + stringlen, M_DEVBUF, M_NOWAIT);
686 if (!xendev)
687 return ENOMEM;
688 memset(xendev, 0, sizeof(*xendev));
689
690 /* Copy the strings into the extra space. */
691
692 tmpstring = (char *)(xendev + 1);
693 strcpy(tmpstring, nodename);
694 xendev->nodename = tmpstring;
695
696 tmpstring += strlen(tmpstring) + 1;
697 strcpy(tmpstring, type);
698 xendev->devicetype = tmpstring;
699
700 #if 0
701 xendev->dev.parent = &bus->dev;
702 xendev->dev.bus = &bus->bus;
703 xendev->dev.release = xenbus_dev_release;
704
705 err = bus->get_bus_id(xendev->dev.bus_id, xendev->nodename);
706 CHECK_FAIL;
707
708 /* Register with generic device framework. */
709 err = device_register(&xendev->dev);
710 CHECK_FAIL;
711
712 device_create_file(&xendev->dev, &dev_attr_nodename);
713 device_create_file(&xendev->dev, &dev_attr_devtype);
714
715 #endif
716 return 0;
717
718 #undef CHECK_FAIL
719 #if 0
720 fail:
721 xenbus_dev_free(xendev);
722 return err;
723 #endif
724 }
725 #endif
726
727 #if 0
728 /* device/<typename>/<name> */
729 static int
730 xenbus_probe_frontend(const char *type, const char *name)
731 {
732 char *nodename;
733 int err;
734
735 nodename = kasprintf("%s/%s/%s", xenbus_frontend.root, type, name);
736 if (!nodename)
737 return ENOMEM;
738
739 DPRINTK("%s", nodename);
740
741 err = xenbus_probe_node(&xenbus_frontend, type, nodename);
742 free(nodename, M_DEVBUF);
743 return err;
744 }
745
746 /* backend/<typename>/<frontend-uuid>/<name> */
747 static int
748 xenbus_probe_backend_unit(const char *dir,
749 const char *type,
750 const char *name)
751 {
752 char *nodename;
753 int err;
754
755 nodename = kasprintf("%s/%s", dir, name);
756 if (!nodename)
757 return ENOMEM;
758
759 DPRINTK("%s", nodename);
760
761 err = xenbus_probe_node(&xenbus_backend, type, nodename);
762 free(nodename, M_DEVBUF);
763 return err;
764 }
765
766 /* backend/<typename>/<frontend-domid> */
767 static int
768 xenbus_probe_backend(const char *type, const char *domid)
769 {
770 char *nodename;
771 int err;
772 char **dir;
773 unsigned int i, dir_n = 0;
774
775 DPRINTK("");
776
777 nodename = kasprintf("%s/%s/%s", xenbus_backend.root, type, domid);
778 if (!nodename)
779 return ENOMEM;
780
781 err = xenbus_directory(NULL, nodename, "", &dir_n, &dir);
782 DPRINTK("xenbus_probe_backend err %d dir_n %d", err, dir_n);
783 if (err) {
784 free(nodename, M_DEVBUF);
785 return err;
786 }
787
788 for (i = 0; i < dir_n; i++) {
789 err = xenbus_probe_backend_unit(nodename, type, dir[i]);
790 if (err)
791 break;
792 }
793 free(dir, M_DEVBUF);
794 free(nodename, M_DEVBUF);
795 return err;
796 }
797 #endif
798
799 static struct xenbus_device *
800 xenbus_lookup_device_path(const char *path)
801 {
802 struct xenbus_device *xbusd;
803
804 SLIST_FOREACH(xbusd, &xenbus_device_list, xbusd_entries) {
805 if (strcmp(xbusd->xbusd_path, path) == 0)
806 return xbusd;
807 }
808 return NULL;
809 }
810
811 static int
812 xenbus_probe_device_type(struct xen_bus_type *bus, const char *type)
813 {
814 int err;
815 char **dir;
816 unsigned int dir_n = 0;
817 int i;
818 struct xenbus_device *xbusd;
819 struct xenbusdev_attach_args xa;
820 char *ep;
821
822 DPRINTK("probe %s type %s", bus->root, type);
823 err = xenbus_directory(NULL, bus->root, type, &dir_n, &dir);
824 DPRINTK("directory err %d dir_n %d", err, dir_n);
825 if (err)
826 return err;
827
828 for (i = 0; i < dir_n; i++) {
829 int msize;
830 /*
831 * add size of path to size of xenbus_device. xenbus_device
832 * already has room for one char in xbusd_path.
833 */
834 msize = sizeof(*xbusd) + strlen(bus->root) + strlen(type)
835 + strlen(dir[i]) + 2;
836 xbusd = malloc(msize, M_DEVBUF, M_WAITOK | M_ZERO);
837 if (xbusd == NULL)
838 panic("can't malloc xbusd");
839
840 snprintf(__UNCONST(xbusd->xbusd_path),
841 msize - sizeof(*xbusd) + 1, "%s/%s/%s",
842 bus->root, type, dir[i]);
843 if (xenbus_lookup_device_path(xbusd->xbusd_path) != NULL) {
844 /* device already registered */
845 free(xbusd, M_DEVBUF);
846 continue;
847 }
848
849 xbusd->xbusd_otherend_watch.xbw_dev = xbusd;
850 DPRINTK("xenbus_probe_device_type probe %s\n",
851 xbusd->xbusd_path);
852 xa.xa_xbusd = xbusd;
853 xa.xa_type = type;
854 xa.xa_id = strtoul(dir[i], &ep, 0);
855 if (dir[i][0] == '\0' || *ep != '\0') {
856 printf("xenbus device type %s: id %s is not a number\n",
857 type, dir[i]);
858 err = EFTYPE;
859 free(xbusd, M_DEVBUF);
860 break;
861 }
862 err = read_backend_details(xbusd);
863 if (err != 0) {
864 printf("xenbus: can't get backend details "
865 "for %s (%d)\n", xbusd->xbusd_path, err);
866 break;
867 }
868 xbusd->xbusd_dev = config_found_ia(xenbus_sc, "xenbus", &xa,
869 xenbus_print);
870 if (xbusd->xbusd_dev == NULL)
871 free(xbusd, M_DEVBUF);
872 else {
873 SLIST_INSERT_HEAD(&xenbus_device_list,
874 xbusd, xbusd_entries);
875 talk_to_otherend(xbusd);
876 }
877 }
878 free(dir, M_DEVBUF);
879 return err;
880 }
881
882 static int
883 xenbus_print(void *aux, const char *pnp)
884 {
885 struct xenbusdev_attach_args *xa = aux;
886
887 if (pnp) {
888 if (strcmp(xa->xa_type, "vbd") == 0)
889 aprint_normal("xbd");
890 else if (strcmp(xa->xa_type, "vif") == 0)
891 aprint_normal("xennet");
892 else
893 aprint_normal("unknown type %s", xa->xa_type);
894 aprint_normal(" at %s", pnp);
895 }
896 aprint_normal(" id %d", xa->xa_id);
897 return(UNCONF);
898 }
899
900 static int
901 xenbus_probe_devices(struct xen_bus_type *bus)
902 {
903 int err;
904 char **dir;
905 unsigned int i, dir_n;
906
907 DPRINTK("probe %s", bus->root);
908 err = xenbus_directory(NULL, bus->root, "", &dir_n, &dir);
909 DPRINTK("directory err %d dir_n %d", err, dir_n);
910 if (err)
911 return err;
912
913 for (i = 0; i < dir_n; i++) {
914 err = xenbus_probe_device_type(bus, dir[i]);
915 if (err)
916 break;
917 }
918 free(dir, M_DEVBUF);
919 return err;
920 }
921
922 int
923 xenbus_free_device(struct xenbus_device *xbusd)
924 {
925 KASSERT(xenbus_lookup_device_path(xbusd->xbusd_path) == xbusd);
926 SLIST_REMOVE(&xenbus_device_list, xbusd, xenbus_device, xbusd_entries);
927 free_otherend_watch(xbusd);
928 free(xbusd->xbusd_otherend, M_DEVBUF);
929 xenbus_switch_state(xbusd, NULL, XenbusStateClosed);
930 free(xbusd, M_DEVBUF);
931 return 0;
932 }
933
934 #if 0
935 static unsigned int
936 char_count(const char *str, char c)
937 {
938 unsigned int i, ret = 0;
939
940 for (i = 0; str[i]; i++)
941 if (str[i] == c)
942 ret++;
943 return ret;
944 }
945
946 static int
947 strsep_len(const char *str, char c, unsigned int len)
948 {
949 unsigned int i;
950
951 for (i = 0; str[i]; i++)
952 if (str[i] == c) {
953 if (len == 0)
954 return i;
955 len--;
956 }
957 return (len == 0) ? i : -ERANGE;
958 }
959
960 static void
961 dev_changed(const char *node, struct xen_bus_type *bus)
962 {
963 int exists, rootlen;
964 struct xenbus_device *dev;
965 char type[BUS_ID_SIZE];
966 const char *p, *root;
967
968 if (char_count(node, '/') < 2)
969 return;
970
971 exists = xenbus_exists(NULL, node, "");
972 if (!exists) {
973 xenbus_cleanup_devices(node, &bus->bus);
974 return;
975 }
976
977 /* backend/<type>/... or device/<type>/... */
978 p = strchr(node, '/') + 1;
979 snprintf(type, BUS_ID_SIZE, "%.*s", (int)strcspn(p, "/"), p);
980 type[BUS_ID_SIZE-1] = '\0';
981
982 rootlen = strsep_len(node, '/', bus->levels);
983 if (rootlen < 0)
984 return;
985 root = kasprintf("%.*s", rootlen, node);
986 if (!root)
987 return;
988
989 dev = xenbus_device_find(root, &bus->bus);
990 if (!dev)
991 xenbus_probe_node(bus, type, root);
992 else
993 put_device(&dev->dev);
994
995 free(root, M_DEVBUF);
996 }
997 #endif
998
999 static void
1000 frontend_changed(struct xenbus_watch *watch,
1001 const char **vec, unsigned int len)
1002 {
1003 DPRINTK("");
1004 //printf("frontend_changed %s\n", vec[XS_WATCH_PATH]);
1005 xenbus_probe_devices(&xenbus_frontend);
1006 }
1007
1008 static void
1009 backend_changed(struct xenbus_watch *watch,
1010 const char **vec, unsigned int len)
1011 {
1012 DPRINTK("");
1013
1014 printf("backend_changed %s\n", vec[XS_WATCH_PATH]);
1015 //dev_changed(vec[XS_WATCH_PATH], &xenbus_backend);
1016 }
1017
1018
1019 /* We watch for devices appearing and vanishing. */
1020 static struct xenbus_watch fe_watch;
1021
1022 static struct xenbus_watch be_watch;
1023
1024 #if 0
1025 static int suspend_dev(struct device *dev, void *data)
1026 {
1027 int err = 0;
1028 struct xenbus_driver *drv;
1029 struct xenbus_device *xdev;
1030
1031 DPRINTK("");
1032
1033 if (dev->driver == NULL)
1034 return 0;
1035 drv = to_xenbus_driver(dev->driver);
1036 xdev = container_of(dev, struct xenbus_device, dev);
1037 if (drv->suspend)
1038 err = drv->suspend(xdev);
1039 if (err)
1040 printk(KERN_WARNING
1041 "xenbus: suspend %s failed: %i\n", dev->bus_id, err);
1042 return 0;
1043 }
1044
1045 static int
1046 resume_dev(struct device *dev, void *data)
1047 {
1048 int err;
1049 struct xenbus_driver *drv;
1050 struct xenbus_device *xdev;
1051
1052 DPRINTK("");
1053
1054 if (dev->driver == NULL)
1055 return 0;
1056 drv = to_xenbus_driver(dev->driver);
1057 xdev = container_of(dev, struct xenbus_device, dev);
1058
1059 err = talk_to_otherend(xdev);
1060 if (err) {
1061 printk(KERN_WARNING
1062 "xenbus: resume (talk_to_otherend) %s failed: %i\n",
1063 dev->bus_id, err);
1064 return err;
1065 }
1066
1067 if (drv->resume)
1068 err = drv->resume(xdev);
1069 if (err)
1070 printk(KERN_WARNING
1071 "xenbus: resume %s failed: %i\n", dev->bus_id, err);
1072 return err;
1073 }
1074
1075 void
1076 xenbus_suspend(void)
1077 {
1078 DPRINTK("");
1079
1080 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev);
1081 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, suspend_dev);
1082 xs_suspend();
1083 }
1084
1085 void xenbus_resume(struct device *dev)
1086 {
1087 xb_init_comms(dev);
1088 xs_resume();
1089 bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev);
1090 bus_for_each_dev(&xenbus_backend.bus, NULL, NULL, resume_dev);
1091 }
1092 #endif
1093
1094
1095 /* A flag to determine if xenstored is 'ready' (i.e. has started) */
1096 int xenstored_ready = 0;
1097
1098
1099 #if 0
1100 int
1101 register_xenstore_notifier(struct notifier_block *nb)
1102 {
1103 int ret = 0;
1104
1105 if (xenstored_ready > 0)
1106 ret = nb->notifier_call(nb, 0, NULL);
1107 else
1108 notifier_chain_register(&xenstore_chain, nb);
1109
1110 return ret;
1111 }
1112
1113 void unregister_xenstore_notifier(struct notifier_block *nb)
1114 {
1115 notifier_chain_unregister(&xenstore_chain, nb);
1116 }
1117 #endif
1118
1119
1120
1121 void
1122 xenbus_probe(void *unused)
1123 {
1124 KASSERT((xenstored_ready > 0));
1125
1126 /* Enumerate devices in xenstore. */
1127 xenbus_probe_devices(&xenbus_frontend);
1128 xenbus_probe_devices(&xenbus_backend);
1129
1130 /* Watch for changes. */
1131 fe_watch.node = malloc(strlen("device" + 1), M_DEVBUF, M_NOWAIT);
1132 strcpy(fe_watch.node, "device");
1133 fe_watch.xbw_callback = frontend_changed;
1134 register_xenbus_watch(&fe_watch);
1135 be_watch.node = malloc(strlen("backend" + 1), M_DEVBUF, M_NOWAIT);
1136 strcpy(be_watch.node, "backend");
1137 be_watch.xbw_callback = backend_changed;
1138 register_xenbus_watch(&be_watch);
1139
1140 /* Notify others that xenstore is up */
1141 //notifier_call_chain(&xenstore_chain, 0, NULL);
1142 }
1143
1144 #if defined(DOM0OPS)
1145 #define LD_STRLEN 21 /* a 64bit integer needs 20 digits in base10 */
1146 static int
1147 xsd_mfn_read(void *v)
1148 {
1149 struct vop_read_args /* {
1150 struct vnode *a_vp;
1151 struct uio *a_uio;
1152 int a_ioflag;
1153 struct ucred *a_cred;
1154 } */ *ap = v;
1155 struct uio *uio = ap->a_uio;
1156 int off, error;
1157 size_t len;
1158 char strbuf[LD_STRLEN], *bf;
1159
1160 off = (int)uio->uio_offset;
1161 if (off < 0)
1162 return EINVAL;
1163
1164 len = snprintf(strbuf, sizeof(strbuf), "%ld\n",
1165 xen_start_info.store_mfn);
1166 if (off >= len) {
1167 bf = strbuf;
1168 len = 0;
1169 } else {
1170 bf = &strbuf[off];
1171 len -= off;
1172 }
1173 error = uiomove(bf, len, uio);
1174 return error;
1175 }
1176
1177 static int
1178 xsd_port_read(void *v)
1179 {
1180 struct vop_read_args /* {
1181 struct vnode *a_vp;
1182 struct uio *a_uio;
1183 int a_ioflag;
1184 struct ucred *a_cred;
1185 } */ *ap = v;
1186 struct uio *uio = ap->a_uio;
1187 int off, error;
1188 size_t len;
1189 char strbuf[LD_STRLEN], *bf;
1190
1191 off = (int)uio->uio_offset;
1192 if (off < 0)
1193 return EINVAL;
1194
1195 len = snprintf(strbuf, sizeof(strbuf), "%ld\n",
1196 (long)xen_start_info.store_evtchn);
1197 if (off >= len) {
1198 bf = strbuf;
1199 len = 0;
1200 } else {
1201 bf = &strbuf[off];
1202 len -= off;
1203 }
1204 error = uiomove(bf, len, uio);
1205 return error;
1206 }
1207 #endif /*DOM0OPS*/
1208
1209 static void
1210 xenbus_probe_init(void *unused)
1211 {
1212 int err = 0, dom0;
1213
1214 DPRINTK("");
1215
1216 SLIST_INIT(&xenbus_device_list);
1217
1218 /*
1219 ** Domain0 doesn't have a store_evtchn or store_mfn yet.
1220 */
1221 dom0 = (xen_start_info.store_evtchn == 0);
1222 if (dom0) {
1223 #if defined(DOM0OPS)
1224 vaddr_t page;
1225 paddr_t ma;
1226 evtchn_op_t op = { 0 };
1227 int ret;
1228 kernfs_entry_t *dkt;
1229 kfstype kfst;
1230
1231 /* Allocate page. */
1232 page = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
1233 UVM_KMF_ZERO | UVM_KMF_WIRED);
1234 if (!page)
1235 panic("can't get xenstore page");
1236
1237 (void)pmap_extract_ma(pmap_kernel(), page, &ma);
1238 xen_start_info.store_mfn = ma >> PAGE_SHIFT;
1239 xenstore_interface = (void *)page;
1240
1241 /* Next allocate a local port which xenstored can bind to */
1242 op.cmd = EVTCHNOP_alloc_unbound;
1243 op.u.alloc_unbound.dom = DOMID_SELF;
1244 op.u.alloc_unbound.remote_dom = 0;
1245
1246 ret = HYPERVISOR_event_channel_op(&op);
1247 if (ret)
1248 panic("can't register xenstore event");
1249 xen_start_info.store_evtchn = op.u.alloc_unbound.port;
1250
1251 /* And finally publish the above info in /kern/xen */
1252 kfst = KERNFS_ALLOCTYPE(xsd_mfn_fileops);
1253 KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
1254 KERNFS_INITENTRY(dkt, DT_REG, "xsd_mfn", NULL, kfst, VREG,
1255 XSD_MODE);
1256 kernfs_addentry(kernxen_pkt, dkt);
1257 kfst = KERNFS_ALLOCTYPE(xsd_port_fileops);
1258 KERNFS_ALLOCENTRY(dkt, M_TEMP, M_WAITOK);
1259 KERNFS_INITENTRY(dkt, DT_REG, "xsd_port", NULL, kfst, VREG,
1260 XSD_MODE);
1261 kernfs_addentry(kernxen_pkt, dkt);
1262
1263 #else /* DOM0OPS */
1264 return ; /* can't get a working xenstore in this case */
1265 #endif /* DOM0OPS */
1266 }
1267
1268 /* Initialize the interface to xenstore. */
1269 err = xs_init();
1270 if (err) {
1271 printf("XENBUS: Error initializing xenstore comms: %i\n", err);
1272 kthread_exit(err);
1273 }
1274
1275 if (!dom0) {
1276 xenstored_ready = 1;
1277 xenbus_probe(NULL);
1278 }
1279
1280 DPRINTK("done");
1281 config_pending_decr();
1282 kthread_exit(0);
1283 }
1284
1285 /*
1286 * Local variables:
1287 * c-file-style: "linux"
1288 * indent-tabs-mode: t
1289 * c-indent-level: 8
1290 * c-basic-offset: 8
1291 * tab-width: 8
1292 * End:
1293 */
1294