]> git.proxmox.com Git - mirror_qemu.git/blob - hw/xen/xen-bus.c
xen / notify: introduce a new XenWatchList abstraction
[mirror_qemu.git] / hw / xen / xen-bus.c
1 /*
2 * Copyright (c) 2018 Citrix Systems Inc.
3 *
4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
5 * See the COPYING file in the top-level directory.
6 */
7
8 #include "qemu/osdep.h"
9 #include "qemu/main-loop.h"
10 #include "qemu/module.h"
11 #include "qemu/uuid.h"
12 #include "hw/qdev-properties.h"
13 #include "hw/sysbus.h"
14 #include "hw/xen/xen.h"
15 #include "hw/xen/xen-backend.h"
16 #include "hw/xen/xen-bus.h"
17 #include "hw/xen/xen-bus-helper.h"
18 #include "monitor/monitor.h"
19 #include "qapi/error.h"
20 #include "qapi/qmp/qdict.h"
21 #include "sysemu/sysemu.h"
22 #include "trace.h"
23
24 static char *xen_device_get_backend_path(XenDevice *xendev)
25 {
26 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
27 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
28 const char *type = object_get_typename(OBJECT(xendev));
29 const char *backend = xendev_class->backend;
30
31 if (!backend) {
32 backend = type;
33 }
34
35 return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
36 xenbus->backend_id, backend, xendev->frontend_id,
37 xendev->name);
38 }
39
40 static char *xen_device_get_frontend_path(XenDevice *xendev)
41 {
42 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
43 const char *type = object_get_typename(OBJECT(xendev));
44 const char *device = xendev_class->device;
45
46 if (!device) {
47 device = type;
48 }
49
50 return g_strdup_printf("/local/domain/%u/device/%s/%s",
51 xendev->frontend_id, device, xendev->name);
52 }
53
54 static void xen_device_unplug(XenDevice *xendev, Error **errp)
55 {
56 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
57 const char *type = object_get_typename(OBJECT(xendev));
58 Error *local_err = NULL;
59 xs_transaction_t tid;
60
61 trace_xen_device_unplug(type, xendev->name);
62
63 /* Mimic the way the Xen toolstack does an unplug */
64 again:
65 tid = xs_transaction_start(xenbus->xsh);
66 if (tid == XBT_NULL) {
67 error_setg_errno(errp, errno, "failed xs_transaction_start");
68 return;
69 }
70
71 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online",
72 &local_err, "%u", 0);
73 if (local_err) {
74 goto abort;
75 }
76
77 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
78 &local_err, "%u", XenbusStateClosing);
79 if (local_err) {
80 goto abort;
81 }
82
83 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
84 if (errno == EAGAIN) {
85 goto again;
86 }
87
88 error_setg_errno(errp, errno, "failed xs_transaction_end");
89 }
90
91 return;
92
93 abort:
94 /*
95 * We only abort if there is already a failure so ignore any error
96 * from ending the transaction.
97 */
98 xs_transaction_end(xenbus->xsh, tid, true);
99 error_propagate(errp, local_err);
100 }
101
102 static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
103 {
104 XenDevice *xendev = XEN_DEVICE(dev);
105
106 monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
107 indent, "", xendev->name, xendev->frontend_id);
108 }
109
110 static char *xen_bus_get_dev_path(DeviceState *dev)
111 {
112 return xen_device_get_backend_path(XEN_DEVICE(dev));
113 }
114
115 struct XenWatch {
116 char *node, *key;
117 char *token;
118 XenWatchHandler handler;
119 void *opaque;
120 Notifier notifier;
121 };
122
123 static void watch_notify(Notifier *n, void *data)
124 {
125 XenWatch *watch = container_of(n, XenWatch, notifier);
126 const char *token = data;
127
128 if (!strcmp(watch->token, token)) {
129 watch->handler(watch->opaque);
130 }
131 }
132
133 static XenWatch *new_watch(const char *node, const char *key,
134 XenWatchHandler handler, void *opaque)
135 {
136 XenWatch *watch = g_new0(XenWatch, 1);
137 QemuUUID uuid;
138
139 qemu_uuid_generate(&uuid);
140
141 watch->token = qemu_uuid_unparse_strdup(&uuid);
142 watch->node = g_strdup(node);
143 watch->key = g_strdup(key);
144 watch->handler = handler;
145 watch->opaque = opaque;
146 watch->notifier.notify = watch_notify;
147
148 return watch;
149 }
150
151 static void free_watch(XenWatch *watch)
152 {
153 g_free(watch->token);
154 g_free(watch->key);
155 g_free(watch->node);
156
157 g_free(watch);
158 }
159
160 struct XenWatchList {
161 struct xs_handle *xsh;
162 NotifierList notifiers;
163 };
164
165 static void watch_list_event(void *opaque)
166 {
167 XenWatchList *watch_list = opaque;
168 char **v;
169 const char *token;
170
171 v = xs_check_watch(watch_list->xsh);
172 if (!v) {
173 return;
174 }
175
176 token = v[XS_WATCH_TOKEN];
177
178 notifier_list_notify(&watch_list->notifiers, (void *)token);
179
180 free(v);
181 }
182
183 static XenWatchList *watch_list_create(struct xs_handle *xsh)
184 {
185 XenWatchList *watch_list = g_new0(XenWatchList, 1);
186
187 g_assert(xsh);
188
189 watch_list->xsh = xsh;
190 notifier_list_init(&watch_list->notifiers);
191 qemu_set_fd_handler(xs_fileno(watch_list->xsh), watch_list_event, NULL,
192 watch_list);
193
194 return watch_list;
195 }
196
197 static void watch_list_destroy(XenWatchList *watch_list)
198 {
199 g_assert(notifier_list_empty(&watch_list->notifiers));
200 qemu_set_fd_handler(xs_fileno(watch_list->xsh), NULL, NULL, NULL);
201 g_free(watch_list);
202 }
203
204 static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node,
205 const char *key, XenWatchHandler handler,
206 void *opaque, Error **errp)
207 {
208 XenWatch *watch = new_watch(node, key, handler, opaque);
209 Error *local_err = NULL;
210
211 notifier_list_add(&watch_list->notifiers, &watch->notifier);
212
213 xs_node_watch(watch_list->xsh, node, key, watch->token, &local_err);
214 if (local_err) {
215 error_propagate(errp, local_err);
216
217 notifier_remove(&watch->notifier);
218 free_watch(watch);
219
220 return NULL;
221 }
222
223 return watch;
224 }
225
226 static void watch_list_remove(XenWatchList *watch_list, XenWatch *watch,
227 Error **errp)
228 {
229 xs_node_unwatch(watch_list->xsh, watch->node, watch->key, watch->token,
230 errp);
231
232 notifier_remove(&watch->notifier);
233 free_watch(watch);
234 }
235
236 static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
237 const char *key, XenWatchHandler handler,
238 void *opaque, Error **errp)
239 {
240 trace_xen_bus_add_watch(node, key);
241
242 return watch_list_add(xenbus->watch_list, node, key, handler, opaque,
243 errp);
244 }
245
246 static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
247 Error **errp)
248 {
249 trace_xen_bus_remove_watch(watch->node, watch->key);
250
251 watch_list_remove(xenbus->watch_list, watch, errp);
252 }
253
254 static void xen_bus_backend_create(XenBus *xenbus, const char *type,
255 const char *name, char *path,
256 Error **errp)
257 {
258 xs_transaction_t tid;
259 char **key;
260 QDict *opts;
261 unsigned int i, n;
262 Error *local_err = NULL;
263
264 trace_xen_bus_backend_create(type, path);
265
266 again:
267 tid = xs_transaction_start(xenbus->xsh);
268 if (tid == XBT_NULL) {
269 error_setg(errp, "failed xs_transaction_start");
270 return;
271 }
272
273 key = xs_directory(xenbus->xsh, tid, path, &n);
274 if (!key) {
275 if (!xs_transaction_end(xenbus->xsh, tid, true)) {
276 error_setg_errno(errp, errno, "failed xs_transaction_end");
277 }
278 return;
279 }
280
281 opts = qdict_new();
282 for (i = 0; i < n; i++) {
283 char *val;
284
285 /*
286 * Assume anything found in the xenstore backend area, other than
287 * the keys created for a generic XenDevice, are parameters
288 * to be used to configure the backend.
289 */
290 if (!strcmp(key[i], "state") ||
291 !strcmp(key[i], "online") ||
292 !strcmp(key[i], "frontend") ||
293 !strcmp(key[i], "frontend-id") ||
294 !strcmp(key[i], "hotplug-status"))
295 continue;
296
297 if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
298 &val) == 1) {
299 qdict_put_str(opts, key[i], val);
300 free(val);
301 }
302 }
303
304 free(key);
305
306 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
307 qobject_unref(opts);
308
309 if (errno == EAGAIN) {
310 goto again;
311 }
312
313 error_setg_errno(errp, errno, "failed xs_transaction_end");
314 return;
315 }
316
317 xen_backend_device_create(xenbus, type, name, opts, &local_err);
318 qobject_unref(opts);
319
320 if (local_err) {
321 error_propagate_prepend(errp, local_err,
322 "failed to create '%s' device '%s': ",
323 type, name);
324 }
325 }
326
327 static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
328 {
329 char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
330 char **backend;
331 unsigned int i, n;
332
333 trace_xen_bus_type_enumerate(type);
334
335 backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
336 if (!backend) {
337 goto out;
338 }
339
340 for (i = 0; i < n; i++) {
341 char *backend_path = g_strdup_printf("%s/%s", domain_path,
342 backend[i]);
343 enum xenbus_state backend_state;
344
345 if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
346 NULL, "%u", &backend_state) != 1)
347 backend_state = XenbusStateUnknown;
348
349 if (backend_state == XenbusStateInitialising) {
350 Error *local_err = NULL;
351
352 xen_bus_backend_create(xenbus, type, backend[i], backend_path,
353 &local_err);
354 if (local_err) {
355 error_report_err(local_err);
356 }
357 }
358
359 g_free(backend_path);
360 }
361
362 free(backend);
363
364 out:
365 g_free(domain_path);
366 }
367
368 static void xen_bus_enumerate(void *opaque)
369 {
370 XenBus *xenbus = opaque;
371 char **type;
372 unsigned int i, n;
373
374 trace_xen_bus_enumerate();
375
376 type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
377 if (!type) {
378 return;
379 }
380
381 for (i = 0; i < n; i++) {
382 xen_bus_type_enumerate(xenbus, type[i]);
383 }
384
385 free(type);
386 }
387
388 static void xen_bus_unrealize(BusState *bus, Error **errp)
389 {
390 XenBus *xenbus = XEN_BUS(bus);
391
392 trace_xen_bus_unrealize();
393
394 if (xenbus->backend_watch) {
395 xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL);
396 xenbus->backend_watch = NULL;
397 }
398
399 if (xenbus->watch_list) {
400 watch_list_destroy(xenbus->watch_list);
401 xenbus->watch_list = NULL;
402 }
403
404 if (xenbus->xsh) {
405 xs_close(xenbus->xsh);
406 }
407 }
408
409 static void xen_bus_realize(BusState *bus, Error **errp)
410 {
411 XenBus *xenbus = XEN_BUS(bus);
412 unsigned int domid;
413 Error *local_err = NULL;
414
415 trace_xen_bus_realize();
416
417 xenbus->xsh = xs_open(0);
418 if (!xenbus->xsh) {
419 error_setg_errno(errp, errno, "failed xs_open");
420 goto fail;
421 }
422
423 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
424 "domid", NULL, "%u", &domid) == 1) {
425 xenbus->backend_id = domid;
426 } else {
427 xenbus->backend_id = 0; /* Assume lack of node means dom0 */
428 }
429
430 xenbus->watch_list = watch_list_create(xenbus->xsh);
431
432 module_call_init(MODULE_INIT_XEN_BACKEND);
433
434 xenbus->backend_watch =
435 xen_bus_add_watch(xenbus, "", /* domain root node */
436 "backend", xen_bus_enumerate, xenbus, &local_err);
437 if (local_err) {
438 /* This need not be treated as a hard error so don't propagate */
439 error_reportf_err(local_err,
440 "failed to set up enumeration watch: ");
441 }
442
443 return;
444
445 fail:
446 xen_bus_unrealize(bus, &error_abort);
447 }
448
449 static void xen_bus_unplug_request(HotplugHandler *hotplug,
450 DeviceState *dev,
451 Error **errp)
452 {
453 XenDevice *xendev = XEN_DEVICE(dev);
454
455 xen_device_unplug(xendev, errp);
456 }
457
458 static void xen_bus_class_init(ObjectClass *class, void *data)
459 {
460 BusClass *bus_class = BUS_CLASS(class);
461 HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
462
463 bus_class->print_dev = xen_bus_print_dev;
464 bus_class->get_dev_path = xen_bus_get_dev_path;
465 bus_class->realize = xen_bus_realize;
466 bus_class->unrealize = xen_bus_unrealize;
467
468 hotplug_class->unplug_request = xen_bus_unplug_request;
469 }
470
471 static const TypeInfo xen_bus_type_info = {
472 .name = TYPE_XEN_BUS,
473 .parent = TYPE_BUS,
474 .instance_size = sizeof(XenBus),
475 .class_size = sizeof(XenBusClass),
476 .class_init = xen_bus_class_init,
477 .interfaces = (InterfaceInfo[]) {
478 { TYPE_HOTPLUG_HANDLER },
479 { }
480 },
481 };
482
483 void xen_device_backend_printf(XenDevice *xendev, const char *key,
484 const char *fmt, ...)
485 {
486 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
487 Error *local_err = NULL;
488 va_list ap;
489
490 g_assert(xenbus->xsh);
491
492 va_start(ap, fmt);
493 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
494 &local_err, fmt, ap);
495 va_end(ap);
496
497 if (local_err) {
498 error_report_err(local_err);
499 }
500 }
501
502 static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
503 const char *fmt, ...)
504 {
505 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
506 va_list ap;
507 int rc;
508
509 g_assert(xenbus->xsh);
510
511 va_start(ap, fmt);
512 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
513 NULL, fmt, ap);
514 va_end(ap);
515
516 return rc;
517 }
518
519 void xen_device_backend_set_state(XenDevice *xendev,
520 enum xenbus_state state)
521 {
522 const char *type = object_get_typename(OBJECT(xendev));
523
524 if (xendev->backend_state == state) {
525 return;
526 }
527
528 trace_xen_device_backend_state(type, xendev->name,
529 xs_strstate(state));
530
531 xendev->backend_state = state;
532 xen_device_backend_printf(xendev, "state", "%u", state);
533 }
534
535 enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
536 {
537 return xendev->backend_state;
538 }
539
540 static void xen_device_backend_set_online(XenDevice *xendev, bool online)
541 {
542 const char *type = object_get_typename(OBJECT(xendev));
543
544 if (xendev->backend_online == online) {
545 return;
546 }
547
548 trace_xen_device_backend_online(type, xendev->name, online);
549
550 xendev->backend_online = online;
551 xen_device_backend_printf(xendev, "online", "%u", online);
552 }
553
554 /*
555 * Tell from the state whether the frontend is likely alive,
556 * i.e. it will react to a change of state of the backend.
557 */
558 static bool xen_device_state_is_active(enum xenbus_state state)
559 {
560 switch (state) {
561 case XenbusStateInitWait:
562 case XenbusStateInitialised:
563 case XenbusStateConnected:
564 case XenbusStateClosing:
565 return true;
566 default:
567 return false;
568 }
569 }
570
571 static void xen_device_backend_changed(void *opaque)
572 {
573 XenDevice *xendev = opaque;
574 const char *type = object_get_typename(OBJECT(xendev));
575 enum xenbus_state state;
576 unsigned int online;
577
578 trace_xen_device_backend_changed(type, xendev->name);
579
580 if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
581 state = XenbusStateUnknown;
582 }
583
584 xen_device_backend_set_state(xendev, state);
585
586 if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
587 online = 0;
588 }
589
590 xen_device_backend_set_online(xendev, !!online);
591
592 /*
593 * If the toolstack (or unplug request callback) has set the backend
594 * state to Closing, but there is no active frontend then set the
595 * backend state to Closed.
596 */
597 if (xendev->backend_state == XenbusStateClosing &&
598 !xen_device_state_is_active(xendev->frontend_state)) {
599 xen_device_backend_set_state(xendev, XenbusStateClosed);
600 }
601
602 /*
603 * If a backend is still 'online' then we should leave it alone but,
604 * if a backend is not 'online', then the device should be destroyed
605 * once the state is Closed.
606 */
607 if (!xendev->backend_online &&
608 (xendev->backend_state == XenbusStateClosed ||
609 xendev->backend_state == XenbusStateInitialising ||
610 xendev->backend_state == XenbusStateInitWait ||
611 xendev->backend_state == XenbusStateUnknown)) {
612 Error *local_err = NULL;
613
614 if (!xen_backend_try_device_destroy(xendev, &local_err)) {
615 object_unparent(OBJECT(xendev));
616 }
617
618 if (local_err) {
619 error_report_err(local_err);
620 }
621 }
622 }
623
624 static void xen_device_backend_create(XenDevice *xendev, Error **errp)
625 {
626 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
627 struct xs_permissions perms[2];
628 Error *local_err = NULL;
629
630 xendev->backend_path = xen_device_get_backend_path(xendev);
631
632 perms[0].id = xenbus->backend_id;
633 perms[0].perms = XS_PERM_NONE;
634 perms[1].id = xendev->frontend_id;
635 perms[1].perms = XS_PERM_READ;
636
637 g_assert(xenbus->xsh);
638
639 xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
640 ARRAY_SIZE(perms), &local_err);
641 if (local_err) {
642 error_propagate_prepend(errp, local_err,
643 "failed to create backend: ");
644 return;
645 }
646
647 xendev->backend_state_watch =
648 xen_bus_add_watch(xenbus, xendev->backend_path,
649 "state", xen_device_backend_changed,
650 xendev, &local_err);
651 if (local_err) {
652 error_propagate_prepend(errp, local_err,
653 "failed to watch backend state: ");
654 return;
655 }
656
657 xendev->backend_online_watch =
658 xen_bus_add_watch(xenbus, xendev->backend_path,
659 "online", xen_device_backend_changed,
660 xendev, &local_err);
661 if (local_err) {
662 error_propagate_prepend(errp, local_err,
663 "failed to watch backend online: ");
664 return;
665 }
666 }
667
668 static void xen_device_backend_destroy(XenDevice *xendev)
669 {
670 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
671 Error *local_err = NULL;
672
673 if (xendev->backend_online_watch) {
674 xen_bus_remove_watch(xenbus, xendev->backend_online_watch, NULL);
675 xendev->backend_online_watch = NULL;
676 }
677
678 if (xendev->backend_state_watch) {
679 xen_bus_remove_watch(xenbus, xendev->backend_state_watch, NULL);
680 xendev->backend_state_watch = NULL;
681 }
682
683 if (!xendev->backend_path) {
684 return;
685 }
686
687 g_assert(xenbus->xsh);
688
689 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
690 &local_err);
691 g_free(xendev->backend_path);
692 xendev->backend_path = NULL;
693
694 if (local_err) {
695 error_report_err(local_err);
696 }
697 }
698
699 void xen_device_frontend_printf(XenDevice *xendev, const char *key,
700 const char *fmt, ...)
701 {
702 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
703 Error *local_err = NULL;
704 va_list ap;
705
706 g_assert(xenbus->xsh);
707
708 va_start(ap, fmt);
709 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
710 &local_err, fmt, ap);
711 va_end(ap);
712
713 if (local_err) {
714 error_report_err(local_err);
715 }
716 }
717
718 int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
719 const char *fmt, ...)
720 {
721 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
722 va_list ap;
723 int rc;
724
725 g_assert(xenbus->xsh);
726
727 va_start(ap, fmt);
728 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
729 NULL, fmt, ap);
730 va_end(ap);
731
732 return rc;
733 }
734
735 static void xen_device_frontend_set_state(XenDevice *xendev,
736 enum xenbus_state state,
737 bool publish)
738 {
739 const char *type = object_get_typename(OBJECT(xendev));
740
741 if (xendev->frontend_state == state) {
742 return;
743 }
744
745 trace_xen_device_frontend_state(type, xendev->name,
746 xs_strstate(state));
747
748 xendev->frontend_state = state;
749 if (publish) {
750 xen_device_frontend_printf(xendev, "state", "%u", state);
751 }
752 }
753
754 static void xen_device_frontend_changed(void *opaque)
755 {
756 XenDevice *xendev = opaque;
757 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
758 const char *type = object_get_typename(OBJECT(xendev));
759 enum xenbus_state state;
760
761 trace_xen_device_frontend_changed(type, xendev->name);
762
763 if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
764 state = XenbusStateUnknown;
765 }
766
767 xen_device_frontend_set_state(xendev, state, false);
768
769 if (state == XenbusStateInitialising &&
770 xendev->backend_state == XenbusStateClosed &&
771 xendev->backend_online) {
772 /*
773 * The frontend is re-initializing so switch back to
774 * InitWait.
775 */
776 xen_device_backend_set_state(xendev, XenbusStateInitWait);
777 return;
778 }
779
780 if (xendev_class->frontend_changed) {
781 Error *local_err = NULL;
782
783 xendev_class->frontend_changed(xendev, state, &local_err);
784
785 if (local_err) {
786 error_reportf_err(local_err, "frontend change error: ");
787 }
788 }
789 }
790
791 static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
792 {
793 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
794 struct xs_permissions perms[2];
795 Error *local_err = NULL;
796
797 xendev->frontend_path = xen_device_get_frontend_path(xendev);
798
799 perms[0].id = xendev->frontend_id;
800 perms[0].perms = XS_PERM_NONE;
801 perms[1].id = xenbus->backend_id;
802 perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
803
804 g_assert(xenbus->xsh);
805
806 xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
807 ARRAY_SIZE(perms), &local_err);
808 if (local_err) {
809 error_propagate_prepend(errp, local_err,
810 "failed to create frontend: ");
811 return;
812 }
813
814 xendev->frontend_state_watch =
815 xen_bus_add_watch(xenbus, xendev->frontend_path, "state",
816 xen_device_frontend_changed, xendev, &local_err);
817 if (local_err) {
818 error_propagate_prepend(errp, local_err,
819 "failed to watch frontend state: ");
820 }
821 }
822
823 static void xen_device_frontend_destroy(XenDevice *xendev)
824 {
825 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
826 Error *local_err = NULL;
827
828 if (xendev->frontend_state_watch) {
829 xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL);
830 xendev->frontend_state_watch = NULL;
831 }
832
833 if (!xendev->frontend_path) {
834 return;
835 }
836
837 g_assert(xenbus->xsh);
838
839 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
840 &local_err);
841 g_free(xendev->frontend_path);
842 xendev->frontend_path = NULL;
843
844 if (local_err) {
845 error_report_err(local_err);
846 }
847 }
848
849 void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
850 Error **errp)
851 {
852 if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
853 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
854 }
855 }
856
857 void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
858 unsigned int nr_refs, int prot,
859 Error **errp)
860 {
861 void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
862 xendev->frontend_id, refs,
863 prot);
864
865 if (!map) {
866 error_setg_errno(errp, errno,
867 "xengnttab_map_domain_grant_refs failed");
868 }
869
870 return map;
871 }
872
873 void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
874 unsigned int nr_refs, Error **errp)
875 {
876 if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
877 error_setg_errno(errp, errno, "xengnttab_unmap failed");
878 }
879 }
880
881 static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
882 XenDeviceGrantCopySegment segs[],
883 unsigned int nr_segs, Error **errp)
884 {
885 uint32_t *refs = g_new(uint32_t, nr_segs);
886 int prot = to_domain ? PROT_WRITE : PROT_READ;
887 void *map;
888 unsigned int i;
889
890 for (i = 0; i < nr_segs; i++) {
891 XenDeviceGrantCopySegment *seg = &segs[i];
892
893 refs[i] = to_domain ? seg->dest.foreign.ref :
894 seg->source.foreign.ref;
895 }
896
897 map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
898 xendev->frontend_id, refs,
899 prot);
900 if (!map) {
901 error_setg_errno(errp, errno,
902 "xengnttab_map_domain_grant_refs failed");
903 goto done;
904 }
905
906 for (i = 0; i < nr_segs; i++) {
907 XenDeviceGrantCopySegment *seg = &segs[i];
908 void *page = map + (i * XC_PAGE_SIZE);
909
910 if (to_domain) {
911 memcpy(page + seg->dest.foreign.offset, seg->source.virt,
912 seg->len);
913 } else {
914 memcpy(seg->dest.virt, page + seg->source.foreign.offset,
915 seg->len);
916 }
917 }
918
919 if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
920 error_setg_errno(errp, errno, "xengnttab_unmap failed");
921 }
922
923 done:
924 g_free(refs);
925 }
926
927 void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
928 XenDeviceGrantCopySegment segs[],
929 unsigned int nr_segs, Error **errp)
930 {
931 xengnttab_grant_copy_segment_t *xengnttab_segs;
932 unsigned int i;
933
934 if (!xendev->feature_grant_copy) {
935 compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
936 return;
937 }
938
939 xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
940
941 for (i = 0; i < nr_segs; i++) {
942 XenDeviceGrantCopySegment *seg = &segs[i];
943 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
944
945 if (to_domain) {
946 xengnttab_seg->flags = GNTCOPY_dest_gref;
947 xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
948 xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
949 xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
950 xengnttab_seg->source.virt = seg->source.virt;
951 } else {
952 xengnttab_seg->flags = GNTCOPY_source_gref;
953 xengnttab_seg->source.foreign.domid = xendev->frontend_id;
954 xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
955 xengnttab_seg->source.foreign.offset =
956 seg->source.foreign.offset;
957 xengnttab_seg->dest.virt = seg->dest.virt;
958 }
959
960 xengnttab_seg->len = seg->len;
961 }
962
963 if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
964 error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
965 goto done;
966 }
967
968 for (i = 0; i < nr_segs; i++) {
969 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
970
971 if (xengnttab_seg->status != GNTST_okay) {
972 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
973 break;
974 }
975 }
976
977 done:
978 g_free(xengnttab_segs);
979 }
980
981 struct XenEventChannel {
982 QLIST_ENTRY(XenEventChannel) list;
983 AioContext *ctx;
984 xenevtchn_handle *xeh;
985 evtchn_port_t local_port;
986 XenEventHandler handler;
987 void *opaque;
988 };
989
990 static bool xen_device_poll(void *opaque)
991 {
992 XenEventChannel *channel = opaque;
993
994 return channel->handler(channel->opaque);
995 }
996
997 static void xen_device_event(void *opaque)
998 {
999 XenEventChannel *channel = opaque;
1000 unsigned long port = xenevtchn_pending(channel->xeh);
1001
1002 if (port == channel->local_port) {
1003 xen_device_poll(channel);
1004
1005 xenevtchn_unmask(channel->xeh, port);
1006 }
1007 }
1008
1009 XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
1010 AioContext *ctx,
1011 unsigned int port,
1012 XenEventHandler handler,
1013 void *opaque, Error **errp)
1014 {
1015 XenEventChannel *channel = g_new0(XenEventChannel, 1);
1016 xenevtchn_port_or_error_t local_port;
1017
1018 channel->xeh = xenevtchn_open(NULL, 0);
1019 if (!channel->xeh) {
1020 error_setg_errno(errp, errno, "failed xenevtchn_open");
1021 goto fail;
1022 }
1023
1024 local_port = xenevtchn_bind_interdomain(channel->xeh,
1025 xendev->frontend_id,
1026 port);
1027 if (local_port < 0) {
1028 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
1029 goto fail;
1030 }
1031
1032 channel->local_port = local_port;
1033 channel->handler = handler;
1034 channel->opaque = opaque;
1035
1036 channel->ctx = ctx;
1037 aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1038 xen_device_event, NULL, xen_device_poll, channel);
1039
1040 QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
1041
1042 return channel;
1043
1044 fail:
1045 if (channel->xeh) {
1046 xenevtchn_close(channel->xeh);
1047 }
1048
1049 g_free(channel);
1050
1051 return NULL;
1052 }
1053
1054 void xen_device_notify_event_channel(XenDevice *xendev,
1055 XenEventChannel *channel,
1056 Error **errp)
1057 {
1058 if (!channel) {
1059 error_setg(errp, "bad channel");
1060 return;
1061 }
1062
1063 if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
1064 error_setg_errno(errp, errno, "xenevtchn_notify failed");
1065 }
1066 }
1067
1068 void xen_device_unbind_event_channel(XenDevice *xendev,
1069 XenEventChannel *channel,
1070 Error **errp)
1071 {
1072 if (!channel) {
1073 error_setg(errp, "bad channel");
1074 return;
1075 }
1076
1077 QLIST_REMOVE(channel, list);
1078
1079 aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1080 NULL, NULL, NULL, NULL);
1081
1082 if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
1083 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
1084 }
1085
1086 xenevtchn_close(channel->xeh);
1087 g_free(channel);
1088 }
1089
1090 static void xen_device_unrealize(DeviceState *dev, Error **errp)
1091 {
1092 XenDevice *xendev = XEN_DEVICE(dev);
1093 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1094 const char *type = object_get_typename(OBJECT(xendev));
1095 XenEventChannel *channel, *next;
1096
1097 if (!xendev->name) {
1098 return;
1099 }
1100
1101 trace_xen_device_unrealize(type, xendev->name);
1102
1103 if (xendev->exit.notify) {
1104 qemu_remove_exit_notifier(&xendev->exit);
1105 xendev->exit.notify = NULL;
1106 }
1107
1108 if (xendev_class->unrealize) {
1109 xendev_class->unrealize(xendev, errp);
1110 }
1111
1112 /* Make sure all event channels are cleaned up */
1113 QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
1114 xen_device_unbind_event_channel(xendev, channel, NULL);
1115 }
1116
1117 xen_device_frontend_destroy(xendev);
1118 xen_device_backend_destroy(xendev);
1119
1120 if (xendev->xgth) {
1121 xengnttab_close(xendev->xgth);
1122 xendev->xgth = NULL;
1123 }
1124
1125 g_free(xendev->name);
1126 xendev->name = NULL;
1127 }
1128
1129 static void xen_device_exit(Notifier *n, void *data)
1130 {
1131 XenDevice *xendev = container_of(n, XenDevice, exit);
1132
1133 xen_device_unrealize(DEVICE(xendev), &error_abort);
1134 }
1135
1136 static void xen_device_realize(DeviceState *dev, Error **errp)
1137 {
1138 XenDevice *xendev = XEN_DEVICE(dev);
1139 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1140 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
1141 const char *type = object_get_typename(OBJECT(xendev));
1142 Error *local_err = NULL;
1143
1144 if (xendev->frontend_id == DOMID_INVALID) {
1145 xendev->frontend_id = xen_domid;
1146 }
1147
1148 if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1149 error_setg(errp, "invalid frontend-id");
1150 goto unrealize;
1151 }
1152
1153 if (!xendev_class->get_name) {
1154 error_setg(errp, "get_name method not implemented");
1155 goto unrealize;
1156 }
1157
1158 xendev->name = xendev_class->get_name(xendev, &local_err);
1159 if (local_err) {
1160 error_propagate_prepend(errp, local_err,
1161 "failed to get device name: ");
1162 goto unrealize;
1163 }
1164
1165 trace_xen_device_realize(type, xendev->name);
1166
1167 xendev->xgth = xengnttab_open(NULL, 0);
1168 if (!xendev->xgth) {
1169 error_setg_errno(errp, errno, "failed xengnttab_open");
1170 goto unrealize;
1171 }
1172
1173 xendev->feature_grant_copy =
1174 (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1175
1176 xen_device_backend_create(xendev, &local_err);
1177 if (local_err) {
1178 error_propagate(errp, local_err);
1179 goto unrealize;
1180 }
1181
1182 xen_device_frontend_create(xendev, &local_err);
1183 if (local_err) {
1184 error_propagate(errp, local_err);
1185 goto unrealize;
1186 }
1187
1188 if (xendev_class->realize) {
1189 xendev_class->realize(xendev, &local_err);
1190 if (local_err) {
1191 error_propagate(errp, local_err);
1192 goto unrealize;
1193 }
1194 }
1195
1196 xen_device_backend_printf(xendev, "frontend", "%s",
1197 xendev->frontend_path);
1198 xen_device_backend_printf(xendev, "frontend-id", "%u",
1199 xendev->frontend_id);
1200 xen_device_backend_printf(xendev, "hotplug-status", "connected");
1201
1202 xen_device_backend_set_online(xendev, true);
1203 xen_device_backend_set_state(xendev, XenbusStateInitWait);
1204
1205 xen_device_frontend_printf(xendev, "backend", "%s",
1206 xendev->backend_path);
1207 xen_device_frontend_printf(xendev, "backend-id", "%u",
1208 xenbus->backend_id);
1209
1210 xen_device_frontend_set_state(xendev, XenbusStateInitialising, true);
1211
1212 xendev->exit.notify = xen_device_exit;
1213 qemu_add_exit_notifier(&xendev->exit);
1214 return;
1215
1216 unrealize:
1217 xen_device_unrealize(dev, &error_abort);
1218 }
1219
1220 static Property xen_device_props[] = {
1221 DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1222 DOMID_INVALID),
1223 DEFINE_PROP_END_OF_LIST()
1224 };
1225
1226 static void xen_device_class_init(ObjectClass *class, void *data)
1227 {
1228 DeviceClass *dev_class = DEVICE_CLASS(class);
1229
1230 dev_class->realize = xen_device_realize;
1231 dev_class->unrealize = xen_device_unrealize;
1232 dev_class->props = xen_device_props;
1233 dev_class->bus_type = TYPE_XEN_BUS;
1234 }
1235
1236 static const TypeInfo xen_device_type_info = {
1237 .name = TYPE_XEN_DEVICE,
1238 .parent = TYPE_DEVICE,
1239 .instance_size = sizeof(XenDevice),
1240 .abstract = true,
1241 .class_size = sizeof(XenDeviceClass),
1242 .class_init = xen_device_class_init,
1243 };
1244
1245 typedef struct XenBridge {
1246 SysBusDevice busdev;
1247 } XenBridge;
1248
1249 #define TYPE_XEN_BRIDGE "xen-bridge"
1250
1251 static const TypeInfo xen_bridge_type_info = {
1252 .name = TYPE_XEN_BRIDGE,
1253 .parent = TYPE_SYS_BUS_DEVICE,
1254 .instance_size = sizeof(XenBridge),
1255 };
1256
1257 static void xen_register_types(void)
1258 {
1259 type_register_static(&xen_bridge_type_info);
1260 type_register_static(&xen_bus_type_info);
1261 type_register_static(&xen_device_type_info);
1262 }
1263
1264 type_init(xen_register_types)
1265
1266 void xen_bus_init(void)
1267 {
1268 DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
1269 BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
1270
1271 qdev_init_nofail(dev);
1272 qbus_set_bus_hotplug_handler(bus, &error_abort);
1273 }