1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include <sys/signal.h>
27
28#include "hw/hw.h"
29#include "hw/sysbus.h"
30#include "hw/boards.h"
31#include "qemu/log.h"
32#include "qapi/error.h"
33#include "hw/xen/xen_backend.h"
34#include "hw/xen/xen_pvdev.h"
35#include "monitor/qdev.h"
36
37#include <xen/grant_table.h>
38
39DeviceState *xen_sysdev;
40BusState *xen_sysbus;
41
42
43
44
45struct xs_handle *xenstore = NULL;
46const char *xen_protocol;
47
48
49static int debug;
50
51int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
52{
53 return xenstore_write_str(xendev->be, node, val);
54}
55
56int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
57{
58 return xenstore_write_int(xendev->be, node, ival);
59}
60
61int xenstore_write_be_int64(struct XenDevice *xendev, const char *node, int64_t ival)
62{
63 return xenstore_write_int64(xendev->be, node, ival);
64}
65
66char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
67{
68 return xenstore_read_str(xendev->be, node);
69}
70
71int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
72{
73 return xenstore_read_int(xendev->be, node, ival);
74}
75
76char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
77{
78 return xenstore_read_str(xendev->fe, node);
79}
80
81int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
82{
83 return xenstore_read_int(xendev->fe, node, ival);
84}
85
86int xenstore_read_fe_uint64(struct XenDevice *xendev, const char *node,
87 uint64_t *uval)
88{
89 return xenstore_read_uint64(xendev->fe, node, uval);
90}
91
92
93
94int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
95{
96 int rc;
97
98 rc = xenstore_write_be_int(xendev, "state", state);
99 if (rc < 0) {
100 return rc;
101 }
102 xen_pv_printf(xendev, 1, "backend state: %s -> %s\n",
103 xenbus_strstate(xendev->be_state), xenbus_strstate(state));
104 xendev->be_state = state;
105 return 0;
106}
107
108
109
110
111static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
112 struct XenDevOps *ops)
113{
114 struct XenDevice *xendev;
115
116 xendev = xen_pv_find_xendev(type, dom, dev);
117 if (xendev) {
118 return xendev;
119 }
120
121
122 xendev = g_malloc0(ops->size);
123 object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
124 OBJECT(xendev)->free = g_free;
125 qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
126 qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
127 qdev_init_nofail(DEVICE(xendev));
128 object_unref(OBJECT(xendev));
129
130 xendev->type = type;
131 xendev->dom = dom;
132 xendev->dev = dev;
133 xendev->ops = ops;
134
135 snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
136 xendev->type, xendev->dom, xendev->dev);
137 snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
138 xendev->type, xendev->dev);
139
140 xendev->debug = debug;
141 xendev->local_port = -1;
142
143 xendev->evtchndev = xenevtchn_open(NULL, 0);
144 if (xendev->evtchndev == NULL) {
145 xen_pv_printf(NULL, 0, "can't open evtchn device\n");
146 qdev_unplug(DEVICE(xendev), NULL);
147 return NULL;
148 }
149 qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev));
150
151 if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
152 xendev->gnttabdev = xengnttab_open(NULL, 0);
153 if (xendev->gnttabdev == NULL) {
154 xen_pv_printf(NULL, 0, "can't open gnttab device\n");
155 xenevtchn_close(xendev->evtchndev);
156 qdev_unplug(DEVICE(xendev), NULL);
157 return NULL;
158 }
159 } else {
160 xendev->gnttabdev = NULL;
161 }
162
163 xen_pv_insert_xendev(xendev);
164
165 if (xendev->ops->alloc) {
166 xendev->ops->alloc(xendev);
167 }
168
169 return xendev;
170}
171
172
173
174
175
176
177
178static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
179{
180 if (node == NULL || strcmp(node, "online") == 0) {
181 if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
182 xendev->online = 0;
183 }
184 }
185
186 if (node) {
187 xen_pv_printf(xendev, 2, "backend update: %s\n", node);
188 if (xendev->ops->backend_changed) {
189 xendev->ops->backend_changed(xendev, node);
190 }
191 }
192}
193
194static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
195{
196 int fe_state;
197
198 if (node == NULL || strcmp(node, "state") == 0) {
199 if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
200 fe_state = XenbusStateUnknown;
201 }
202 if (xendev->fe_state != fe_state) {
203 xen_pv_printf(xendev, 1, "frontend state: %s -> %s\n",
204 xenbus_strstate(xendev->fe_state),
205 xenbus_strstate(fe_state));
206 }
207 xendev->fe_state = fe_state;
208 }
209 if (node == NULL || strcmp(node, "protocol") == 0) {
210 g_free(xendev->protocol);
211 xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
212 if (xendev->protocol) {
213 xen_pv_printf(xendev, 1, "frontend protocol: %s\n",
214 xendev->protocol);
215 }
216 }
217
218 if (node) {
219 xen_pv_printf(xendev, 2, "frontend update: %s\n", node);
220 if (xendev->ops->frontend_changed) {
221 xendev->ops->frontend_changed(xendev, node);
222 }
223 }
224}
225
226
227
228
229
230
231
232
233
234
235
236
237static int xen_be_try_setup(struct XenDevice *xendev)
238{
239 char token[XEN_BUFSIZE];
240 int be_state;
241
242 if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
243 xen_pv_printf(xendev, 0, "reading backend state failed\n");
244 return -1;
245 }
246
247 if (be_state != XenbusStateInitialising) {
248 xen_pv_printf(xendev, 0, "initial backend state is wrong (%s)\n",
249 xenbus_strstate(be_state));
250 return -1;
251 }
252
253 xendev->fe = xenstore_read_be_str(xendev, "frontend");
254 if (xendev->fe == NULL) {
255 xen_pv_printf(xendev, 0, "reading frontend path failed\n");
256 return -1;
257 }
258
259
260 snprintf(token, sizeof(token), "fe:%p", xendev);
261 if (!xs_watch(xenstore, xendev->fe, token)) {
262 xen_pv_printf(xendev, 0, "watching frontend path (%s) failed\n",
263 xendev->fe);
264 return -1;
265 }
266 xen_be_set_state(xendev, XenbusStateInitialising);
267
268 xen_be_backend_changed(xendev, NULL);
269 xen_be_frontend_changed(xendev, NULL);
270 return 0;
271}
272
273
274
275
276
277
278
279
280
281static int xen_be_try_init(struct XenDevice *xendev)
282{
283 int rc = 0;
284
285 if (!xendev->online) {
286 xen_pv_printf(xendev, 1, "not online\n");
287 return -1;
288 }
289
290 if (xendev->ops->init) {
291 rc = xendev->ops->init(xendev);
292 }
293 if (rc != 0) {
294 xen_pv_printf(xendev, 1, "init() failed\n");
295 return rc;
296 }
297
298 xenstore_write_be_str(xendev, "hotplug-status", "connected");
299 xen_be_set_state(xendev, XenbusStateInitWait);
300 return 0;
301}
302
303
304
305
306
307
308
309
310static int xen_be_try_initialise(struct XenDevice *xendev)
311{
312 int rc = 0;
313
314 if (xendev->fe_state != XenbusStateInitialised &&
315 xendev->fe_state != XenbusStateConnected) {
316 if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
317 xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
318 } else {
319 xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
320 return -1;
321 }
322 }
323
324 if (xendev->ops->initialise) {
325 rc = xendev->ops->initialise(xendev);
326 }
327 if (rc != 0) {
328 xen_pv_printf(xendev, 0, "initialise() failed\n");
329 return rc;
330 }
331
332 xen_be_set_state(xendev, XenbusStateConnected);
333 return 0;
334}
335
336
337
338
339
340
341static void xen_be_try_connected(struct XenDevice *xendev)
342{
343 if (!xendev->ops->connected) {
344 return;
345 }
346
347 if (xendev->fe_state != XenbusStateConnected) {
348 if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
349 xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
350 } else {
351 xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
352 return;
353 }
354 }
355
356 xendev->ops->connected(xendev);
357}
358
359
360
361
362
363
364static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
365{
366 if (xendev->be_state != XenbusStateClosing &&
367 xendev->be_state != XenbusStateClosed &&
368 xendev->ops->disconnect) {
369 xendev->ops->disconnect(xendev);
370 }
371 if (xendev->be_state != state) {
372 xen_be_set_state(xendev, state);
373 }
374}
375
376
377
378
379static int xen_be_try_reset(struct XenDevice *xendev)
380{
381 if (xendev->fe_state != XenbusStateInitialising) {
382 return -1;
383 }
384
385 xen_pv_printf(xendev, 1, "device reset (for re-connect)\n");
386 xen_be_set_state(xendev, XenbusStateInitialising);
387 return 0;
388}
389
390
391
392
393void xen_be_check_state(struct XenDevice *xendev)
394{
395 int rc = 0;
396
397
398 if (xendev->fe_state == XenbusStateClosing ||
399 xendev->fe_state == XenbusStateClosed) {
400 xen_be_disconnect(xendev, xendev->fe_state);
401 return;
402 }
403
404
405 for (;;) {
406 switch (xendev->be_state) {
407 case XenbusStateUnknown:
408 rc = xen_be_try_setup(xendev);
409 break;
410 case XenbusStateInitialising:
411 rc = xen_be_try_init(xendev);
412 break;
413 case XenbusStateInitWait:
414 rc = xen_be_try_initialise(xendev);
415 break;
416 case XenbusStateConnected:
417
418 xen_be_try_connected(xendev);
419 rc = -1;
420 break;
421 case XenbusStateClosed:
422 rc = xen_be_try_reset(xendev);
423 break;
424 default:
425 rc = -1;
426 }
427 if (rc != 0) {
428 break;
429 }
430 }
431}
432
433
434
435static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
436{
437 struct XenDevice *xendev;
438 char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
439 char **dev = NULL;
440 unsigned int cdev, j;
441
442
443 snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
444 snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
445 if (!xs_watch(xenstore, path, token)) {
446 xen_pv_printf(NULL, 0, "xen be: watching backend path (%s) failed\n",
447 path);
448 return -1;
449 }
450
451
452 dev = xs_directory(xenstore, 0, path, &cdev);
453 if (!dev) {
454 return 0;
455 }
456 for (j = 0; j < cdev; j++) {
457 xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
458 if (xendev == NULL) {
459 continue;
460 }
461 xen_be_check_state(xendev);
462 }
463 free(dev);
464 return 0;
465}
466
467void xenstore_update_be(char *watch, char *type, int dom,
468 struct XenDevOps *ops)
469{
470 struct XenDevice *xendev;
471 char path[XEN_BUFSIZE], *bepath;
472 unsigned int len, dev;
473
474 len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
475 if (strncmp(path, watch, len) != 0) {
476 return;
477 }
478 if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
479 strcpy(path, "");
480 if (sscanf(watch+len, "/%u", &dev) != 1) {
481 dev = -1;
482 }
483 }
484 if (dev == -1) {
485 return;
486 }
487
488 xendev = xen_be_get_xendev(type, dom, dev, ops);
489 if (xendev != NULL) {
490 bepath = xs_read(xenstore, 0, xendev->be, &len);
491 if (bepath == NULL) {
492 xen_pv_del_xendev(xendev);
493 } else {
494 free(bepath);
495 xen_be_backend_changed(xendev, path);
496 xen_be_check_state(xendev);
497 }
498 }
499}
500
501void xenstore_update_fe(char *watch, struct XenDevice *xendev)
502{
503 char *node;
504 unsigned int len;
505
506 len = strlen(xendev->fe);
507 if (strncmp(xendev->fe, watch, len) != 0) {
508 return;
509 }
510 if (watch[len] != '/') {
511 return;
512 }
513 node = watch + len + 1;
514
515 xen_be_frontend_changed(xendev, node);
516 xen_be_check_state(xendev);
517}
518
519
520int xen_be_init(void)
521{
522 xenstore = xs_daemon_open();
523 if (!xenstore) {
524 xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
525 return -1;
526 }
527
528 qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);
529
530 if (xen_xc == NULL || xen_fmem == NULL) {
531
532 goto err;
533 }
534
535 xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
536 qdev_init_nofail(xen_sysdev);
537 xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
538 qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort);
539
540 return 0;
541
542err:
543 qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
544 xs_daemon_close(xenstore);
545 xenstore = NULL;
546
547 return -1;
548}
549
550static void xen_set_dynamic_sysbus(void)
551{
552 Object *machine = qdev_get_machine();
553 ObjectClass *oc = object_get_class(machine);
554 MachineClass *mc = MACHINE_CLASS(oc);
555
556 mc->has_dynamic_sysbus = true;
557}
558
559int xen_be_register(const char *type, struct XenDevOps *ops)
560{
561 char path[50];
562 int rc;
563
564 if (ops->backend_register) {
565 rc = ops->backend_register();
566 if (rc) {
567 return rc;
568 }
569 }
570
571 snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
572 type);
573 xenstore_mkdir(path, XS_PERM_NONE);
574
575 return xenstore_scan(type, xen_domid, ops);
576}
577
578void xen_be_register_common(void)
579{
580 xen_set_dynamic_sysbus();
581
582 xen_be_register("console", &xen_console_ops);
583 xen_be_register("vkbd", &xen_kbdmouse_ops);
584 xen_be_register("qdisk", &xen_blkdev_ops);
585#ifdef CONFIG_VIRTFS
586 xen_be_register("9pfs", &xen_9pfs_ops);
587#endif
588#ifdef CONFIG_USB_LIBUSB
589 xen_be_register("qusb", &xen_usb_ops);
590#endif
591}
592
593int xen_be_bind_evtchn(struct XenDevice *xendev)
594{
595 if (xendev->local_port != -1) {
596 return 0;
597 }
598 xendev->local_port = xenevtchn_bind_interdomain
599 (xendev->evtchndev, xendev->dom, xendev->remote_port);
600 if (xendev->local_port == -1) {
601 xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
602 return -1;
603 }
604 xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
605 qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
606 xen_pv_evtchn_event, NULL, xendev);
607 return 0;
608}
609
610
611static Property xendev_properties[] = {
612 DEFINE_PROP_END_OF_LIST(),
613};
614
615static void xendev_class_init(ObjectClass *klass, void *data)
616{
617 DeviceClass *dc = DEVICE_CLASS(klass);
618
619 dc->props = xendev_properties;
620 set_bit(DEVICE_CATEGORY_MISC, dc->categories);
621
622 dc->user_creatable = true;
623}
624
625static const TypeInfo xendev_type_info = {
626 .name = TYPE_XENBACKEND,
627 .parent = TYPE_XENSYSDEV,
628 .class_init = xendev_class_init,
629 .instance_size = sizeof(struct XenDevice),
630};
631
632static void xen_sysbus_class_init(ObjectClass *klass, void *data)
633{
634 HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
635
636 hc->unplug = qdev_simple_device_unplug_cb;
637}
638
639static const TypeInfo xensysbus_info = {
640 .name = TYPE_XENSYSBUS,
641 .parent = TYPE_BUS,
642 .class_init = xen_sysbus_class_init,
643 .interfaces = (InterfaceInfo[]) {
644 { TYPE_HOTPLUG_HANDLER },
645 { }
646 }
647};
648
649static int xen_sysdev_init(SysBusDevice *dev)
650{
651 return 0;
652}
653
654static Property xen_sysdev_properties[] = {
655 {},
656};
657
658static void xen_sysdev_class_init(ObjectClass *klass, void *data)
659{
660 DeviceClass *dc = DEVICE_CLASS(klass);
661 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
662
663 k->init = xen_sysdev_init;
664 dc->props = xen_sysdev_properties;
665 dc->bus_type = TYPE_XENSYSBUS;
666}
667
668static const TypeInfo xensysdev_info = {
669 .name = TYPE_XENSYSDEV,
670 .parent = TYPE_SYS_BUS_DEVICE,
671 .instance_size = sizeof(SysBusDevice),
672 .class_init = xen_sysdev_class_init,
673};
674
675static void xenbe_register_types(void)
676{
677 type_register_static(&xensysbus_info);
678 type_register_static(&xensysdev_info);
679 type_register_static(&xendev_type_info);
680}
681
682type_init(xenbe_register_types)
683