hw/mips/cps: Expose input clock and connect it to CPU cores
[qemu/ar7.git] / hw / xen / xen-bus.c
blob9ce1c9540b9e9a39f4a194410ff619e72b03c86c
1 /*
2 * Copyright (c) 2018 Citrix Systems Inc.
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 */
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"
24 static char *xen_device_get_backend_path(XenDevice *xendev)
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;
31 if (!backend) {
32 backend = type;
35 return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
36 xenbus->backend_id, backend, xendev->frontend_id,
37 xendev->name);
40 static char *xen_device_get_frontend_path(XenDevice *xendev)
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;
46 if (!device) {
47 device = type;
50 return g_strdup_printf("/local/domain/%u/device/%s/%s",
51 xendev->frontend_id, device, xendev->name);
54 static void xen_device_unplug(XenDevice *xendev, Error **errp)
56 ERRP_GUARD();
57 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
58 const char *type = object_get_typename(OBJECT(xendev));
59 xs_transaction_t tid;
61 trace_xen_device_unplug(type, xendev->name);
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;
71 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online",
72 errp, "%u", 0);
73 if (*errp) {
74 goto abort;
77 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
78 errp, "%u", XenbusStateClosing);
79 if (*errp) {
80 goto abort;
83 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
84 if (errno == EAGAIN) {
85 goto again;
88 error_setg_errno(errp, errno, "failed xs_transaction_end");
91 return;
93 abort:
95 * We only abort if there is already a failure so ignore any error
96 * from ending the transaction.
98 xs_transaction_end(xenbus->xsh, tid, true);
101 static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
103 XenDevice *xendev = XEN_DEVICE(dev);
105 monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
106 indent, "", xendev->name, xendev->frontend_id);
109 static char *xen_bus_get_dev_path(DeviceState *dev)
111 return xen_device_get_backend_path(XEN_DEVICE(dev));
114 struct XenWatch {
115 char *node, *key;
116 char *token;
117 XenWatchHandler handler;
118 void *opaque;
119 Notifier notifier;
122 static void watch_notify(Notifier *n, void *data)
124 XenWatch *watch = container_of(n, XenWatch, notifier);
125 const char *token = data;
127 if (!strcmp(watch->token, token)) {
128 watch->handler(watch->opaque);
132 static XenWatch *new_watch(const char *node, const char *key,
133 XenWatchHandler handler, void *opaque)
135 XenWatch *watch = g_new0(XenWatch, 1);
136 QemuUUID uuid;
138 qemu_uuid_generate(&uuid);
140 watch->token = qemu_uuid_unparse_strdup(&uuid);
141 watch->node = g_strdup(node);
142 watch->key = g_strdup(key);
143 watch->handler = handler;
144 watch->opaque = opaque;
145 watch->notifier.notify = watch_notify;
147 return watch;
150 static void free_watch(XenWatch *watch)
152 g_free(watch->token);
153 g_free(watch->key);
154 g_free(watch->node);
156 g_free(watch);
159 struct XenWatchList {
160 struct xs_handle *xsh;
161 NotifierList notifiers;
164 static void watch_list_event(void *opaque)
166 XenWatchList *watch_list = opaque;
167 char **v;
168 const char *token;
170 v = xs_check_watch(watch_list->xsh);
171 if (!v) {
172 return;
175 token = v[XS_WATCH_TOKEN];
177 notifier_list_notify(&watch_list->notifiers, (void *)token);
179 free(v);
182 static XenWatchList *watch_list_create(struct xs_handle *xsh)
184 XenWatchList *watch_list = g_new0(XenWatchList, 1);
186 g_assert(xsh);
188 watch_list->xsh = xsh;
189 notifier_list_init(&watch_list->notifiers);
190 qemu_set_fd_handler(xs_fileno(watch_list->xsh), watch_list_event, NULL,
191 watch_list);
193 return watch_list;
196 static void watch_list_destroy(XenWatchList *watch_list)
198 g_assert(notifier_list_empty(&watch_list->notifiers));
199 qemu_set_fd_handler(xs_fileno(watch_list->xsh), NULL, NULL, NULL);
200 g_free(watch_list);
203 static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node,
204 const char *key, XenWatchHandler handler,
205 void *opaque, Error **errp)
207 ERRP_GUARD();
208 XenWatch *watch = new_watch(node, key, handler, opaque);
210 notifier_list_add(&watch_list->notifiers, &watch->notifier);
212 xs_node_watch(watch_list->xsh, node, key, watch->token, errp);
213 if (*errp) {
214 notifier_remove(&watch->notifier);
215 free_watch(watch);
217 return NULL;
220 return watch;
223 static void watch_list_remove(XenWatchList *watch_list, XenWatch *watch,
224 Error **errp)
226 xs_node_unwatch(watch_list->xsh, watch->node, watch->key, watch->token,
227 errp);
229 notifier_remove(&watch->notifier);
230 free_watch(watch);
233 static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
234 const char *key, XenWatchHandler handler,
235 Error **errp)
237 trace_xen_bus_add_watch(node, key);
239 return watch_list_add(xenbus->watch_list, node, key, handler, xenbus,
240 errp);
243 static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
244 Error **errp)
246 trace_xen_bus_remove_watch(watch->node, watch->key);
248 watch_list_remove(xenbus->watch_list, watch, errp);
251 static void xen_bus_backend_create(XenBus *xenbus, const char *type,
252 const char *name, char *path,
253 Error **errp)
255 ERRP_GUARD();
256 xs_transaction_t tid;
257 char **key;
258 QDict *opts;
259 unsigned int i, n;
261 trace_xen_bus_backend_create(type, path);
263 again:
264 tid = xs_transaction_start(xenbus->xsh);
265 if (tid == XBT_NULL) {
266 error_setg(errp, "failed xs_transaction_start");
267 return;
270 key = xs_directory(xenbus->xsh, tid, path, &n);
271 if (!key) {
272 if (!xs_transaction_end(xenbus->xsh, tid, true)) {
273 error_setg_errno(errp, errno, "failed xs_transaction_end");
275 return;
278 opts = qdict_new();
279 for (i = 0; i < n; i++) {
280 char *val;
283 * Assume anything found in the xenstore backend area, other than
284 * the keys created for a generic XenDevice, are parameters
285 * to be used to configure the backend.
287 if (!strcmp(key[i], "state") ||
288 !strcmp(key[i], "online") ||
289 !strcmp(key[i], "frontend") ||
290 !strcmp(key[i], "frontend-id") ||
291 !strcmp(key[i], "hotplug-status"))
292 continue;
294 if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
295 &val) == 1) {
296 qdict_put_str(opts, key[i], val);
297 free(val);
301 free(key);
303 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
304 qobject_unref(opts);
306 if (errno == EAGAIN) {
307 goto again;
310 error_setg_errno(errp, errno, "failed xs_transaction_end");
311 return;
314 xen_backend_device_create(xenbus, type, name, opts, errp);
315 qobject_unref(opts);
317 if (*errp) {
318 error_prepend(errp, "failed to create '%s' device '%s': ", type, name);
322 static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
324 char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
325 char **backend;
326 unsigned int i, n;
328 trace_xen_bus_type_enumerate(type);
330 backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
331 if (!backend) {
332 goto out;
335 for (i = 0; i < n; i++) {
336 char *backend_path = g_strdup_printf("%s/%s", domain_path,
337 backend[i]);
338 enum xenbus_state state;
339 unsigned int online;
341 if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
342 NULL, "%u", &state) != 1)
343 state = XenbusStateUnknown;
345 if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "online",
346 NULL, "%u", &online) != 1)
347 online = 0;
349 if (online && state == XenbusStateInitialising) {
350 Error *local_err = NULL;
352 xen_bus_backend_create(xenbus, type, backend[i], backend_path,
353 &local_err);
354 if (local_err) {
355 error_report_err(local_err);
359 g_free(backend_path);
362 free(backend);
364 out:
365 g_free(domain_path);
368 static void xen_bus_enumerate(XenBus *xenbus)
370 char **type;
371 unsigned int i, n;
373 trace_xen_bus_enumerate();
375 type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
376 if (!type) {
377 return;
380 for (i = 0; i < n; i++) {
381 xen_bus_type_enumerate(xenbus, type[i]);
384 free(type);
387 static void xen_bus_device_cleanup(XenDevice *xendev)
389 const char *type = object_get_typename(OBJECT(xendev));
390 Error *local_err = NULL;
392 trace_xen_bus_device_cleanup(type, xendev->name);
394 g_assert(!xendev->backend_online);
396 if (!xen_backend_try_device_destroy(xendev, &local_err)) {
397 object_unparent(OBJECT(xendev));
400 if (local_err) {
401 error_report_err(local_err);
405 static void xen_bus_cleanup(XenBus *xenbus)
407 XenDevice *xendev, *next;
409 trace_xen_bus_cleanup();
411 QLIST_FOREACH_SAFE(xendev, &xenbus->inactive_devices, list, next) {
412 g_assert(xendev->inactive);
413 QLIST_REMOVE(xendev, list);
414 xen_bus_device_cleanup(xendev);
418 static void xen_bus_backend_changed(void *opaque)
420 XenBus *xenbus = opaque;
422 xen_bus_enumerate(xenbus);
423 xen_bus_cleanup(xenbus);
426 static void xen_bus_unrealize(BusState *bus)
428 XenBus *xenbus = XEN_BUS(bus);
430 trace_xen_bus_unrealize();
432 if (xenbus->backend_watch) {
433 xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL);
434 xenbus->backend_watch = NULL;
437 if (xenbus->watch_list) {
438 watch_list_destroy(xenbus->watch_list);
439 xenbus->watch_list = NULL;
442 if (xenbus->xsh) {
443 xs_close(xenbus->xsh);
447 static void xen_bus_realize(BusState *bus, Error **errp)
449 XenBus *xenbus = XEN_BUS(bus);
450 unsigned int domid;
451 Error *local_err = NULL;
453 trace_xen_bus_realize();
455 xenbus->xsh = xs_open(0);
456 if (!xenbus->xsh) {
457 error_setg_errno(errp, errno, "failed xs_open");
458 goto fail;
461 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
462 "domid", NULL, "%u", &domid) == 1) {
463 xenbus->backend_id = domid;
464 } else {
465 xenbus->backend_id = 0; /* Assume lack of node means dom0 */
468 xenbus->watch_list = watch_list_create(xenbus->xsh);
470 module_call_init(MODULE_INIT_XEN_BACKEND);
472 xenbus->backend_watch =
473 xen_bus_add_watch(xenbus, "", /* domain root node */
474 "backend", xen_bus_backend_changed, &local_err);
475 if (local_err) {
476 /* This need not be treated as a hard error so don't propagate */
477 error_reportf_err(local_err,
478 "failed to set up enumeration watch: ");
481 return;
483 fail:
484 xen_bus_unrealize(bus);
487 static void xen_bus_unplug_request(HotplugHandler *hotplug,
488 DeviceState *dev,
489 Error **errp)
491 XenDevice *xendev = XEN_DEVICE(dev);
493 xen_device_unplug(xendev, errp);
496 static void xen_bus_class_init(ObjectClass *class, void *data)
498 BusClass *bus_class = BUS_CLASS(class);
499 HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
501 bus_class->print_dev = xen_bus_print_dev;
502 bus_class->get_dev_path = xen_bus_get_dev_path;
503 bus_class->realize = xen_bus_realize;
504 bus_class->unrealize = xen_bus_unrealize;
506 hotplug_class->unplug_request = xen_bus_unplug_request;
509 static const TypeInfo xen_bus_type_info = {
510 .name = TYPE_XEN_BUS,
511 .parent = TYPE_BUS,
512 .instance_size = sizeof(XenBus),
513 .class_size = sizeof(XenBusClass),
514 .class_init = xen_bus_class_init,
515 .interfaces = (InterfaceInfo[]) {
516 { TYPE_HOTPLUG_HANDLER },
521 void xen_device_backend_printf(XenDevice *xendev, const char *key,
522 const char *fmt, ...)
524 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
525 Error *local_err = NULL;
526 va_list ap;
528 g_assert(xenbus->xsh);
530 va_start(ap, fmt);
531 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
532 &local_err, fmt, ap);
533 va_end(ap);
535 if (local_err) {
536 error_report_err(local_err);
540 static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
541 const char *fmt, ...)
543 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
544 va_list ap;
545 int rc;
547 g_assert(xenbus->xsh);
549 va_start(ap, fmt);
550 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
551 NULL, fmt, ap);
552 va_end(ap);
554 return rc;
557 void xen_device_backend_set_state(XenDevice *xendev,
558 enum xenbus_state state)
560 const char *type = object_get_typename(OBJECT(xendev));
562 if (xendev->backend_state == state) {
563 return;
566 trace_xen_device_backend_state(type, xendev->name,
567 xs_strstate(state));
569 xendev->backend_state = state;
570 xen_device_backend_printf(xendev, "state", "%u", state);
573 enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
575 return xendev->backend_state;
578 static void xen_device_backend_set_online(XenDevice *xendev, bool online)
580 const char *type = object_get_typename(OBJECT(xendev));
582 if (xendev->backend_online == online) {
583 return;
586 trace_xen_device_backend_online(type, xendev->name, online);
588 xendev->backend_online = online;
589 xen_device_backend_printf(xendev, "online", "%u", online);
593 * Tell from the state whether the frontend is likely alive,
594 * i.e. it will react to a change of state of the backend.
596 static bool xen_device_frontend_is_active(XenDevice *xendev)
598 switch (xendev->frontend_state) {
599 case XenbusStateInitWait:
600 case XenbusStateInitialised:
601 case XenbusStateConnected:
602 case XenbusStateClosing:
603 return true;
604 default:
605 return false;
609 static void xen_device_backend_changed(void *opaque)
611 XenDevice *xendev = opaque;
612 const char *type = object_get_typename(OBJECT(xendev));
613 enum xenbus_state state;
614 unsigned int online;
616 trace_xen_device_backend_changed(type, xendev->name);
618 if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
619 state = XenbusStateUnknown;
622 xen_device_backend_set_state(xendev, state);
624 if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
625 online = 0;
628 xen_device_backend_set_online(xendev, !!online);
631 * If the toolstack (or unplug request callback) has set the backend
632 * state to Closing, but there is no active frontend then set the
633 * backend state to Closed.
635 if (state == XenbusStateClosing &&
636 !xen_device_frontend_is_active(xendev)) {
637 xen_device_backend_set_state(xendev, XenbusStateClosed);
641 * If a backend is still 'online' then we should leave it alone but,
642 * if a backend is not 'online', then the device is a candidate
643 * for destruction. Hence add it to the 'inactive' list to be cleaned
644 * by xen_bus_cleanup().
646 if (!online &&
647 (state == XenbusStateClosed || state == XenbusStateInitialising ||
648 state == XenbusStateInitWait || state == XenbusStateUnknown) &&
649 !xendev->inactive) {
650 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
652 xendev->inactive = true;
653 QLIST_INSERT_HEAD(&xenbus->inactive_devices, xendev, list);
656 * Re-write the state to cause a XenBus backend_watch notification,
657 * resulting in a call to xen_bus_cleanup().
659 xen_device_backend_printf(xendev, "state", "%u", state);
663 static XenWatch *xen_device_add_watch(XenDevice *xendev, const char *node,
664 const char *key,
665 XenWatchHandler handler,
666 Error **errp)
668 const char *type = object_get_typename(OBJECT(xendev));
670 trace_xen_device_add_watch(type, xendev->name, node, key);
672 return watch_list_add(xendev->watch_list, node, key, handler, xendev,
673 errp);
676 static void xen_device_remove_watch(XenDevice *xendev, XenWatch *watch,
677 Error **errp)
679 const char *type = object_get_typename(OBJECT(xendev));
681 trace_xen_device_remove_watch(type, xendev->name, watch->node,
682 watch->key);
684 watch_list_remove(xendev->watch_list, watch, errp);
688 static void xen_device_backend_create(XenDevice *xendev, Error **errp)
690 ERRP_GUARD();
691 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
692 struct xs_permissions perms[2];
694 xendev->backend_path = xen_device_get_backend_path(xendev);
696 perms[0].id = xenbus->backend_id;
697 perms[0].perms = XS_PERM_NONE;
698 perms[1].id = xendev->frontend_id;
699 perms[1].perms = XS_PERM_READ;
701 g_assert(xenbus->xsh);
703 xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
704 ARRAY_SIZE(perms), errp);
705 if (*errp) {
706 error_prepend(errp, "failed to create backend: ");
707 return;
710 xendev->backend_state_watch =
711 xen_device_add_watch(xendev, xendev->backend_path,
712 "state", xen_device_backend_changed,
713 errp);
714 if (*errp) {
715 error_prepend(errp, "failed to watch backend state: ");
716 return;
719 xendev->backend_online_watch =
720 xen_device_add_watch(xendev, xendev->backend_path,
721 "online", xen_device_backend_changed,
722 errp);
723 if (*errp) {
724 error_prepend(errp, "failed to watch backend online: ");
725 return;
729 static void xen_device_backend_destroy(XenDevice *xendev)
731 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
732 Error *local_err = NULL;
734 if (xendev->backend_online_watch) {
735 xen_device_remove_watch(xendev, xendev->backend_online_watch, NULL);
736 xendev->backend_online_watch = NULL;
739 if (xendev->backend_state_watch) {
740 xen_device_remove_watch(xendev, xendev->backend_state_watch, NULL);
741 xendev->backend_state_watch = NULL;
744 if (!xendev->backend_path) {
745 return;
748 g_assert(xenbus->xsh);
750 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
751 &local_err);
752 g_free(xendev->backend_path);
753 xendev->backend_path = NULL;
755 if (local_err) {
756 error_report_err(local_err);
760 void xen_device_frontend_printf(XenDevice *xendev, const char *key,
761 const char *fmt, ...)
763 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
764 Error *local_err = NULL;
765 va_list ap;
767 g_assert(xenbus->xsh);
769 va_start(ap, fmt);
770 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
771 &local_err, fmt, ap);
772 va_end(ap);
774 if (local_err) {
775 error_report_err(local_err);
779 int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
780 const char *fmt, ...)
782 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
783 va_list ap;
784 int rc;
786 g_assert(xenbus->xsh);
788 va_start(ap, fmt);
789 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
790 NULL, fmt, ap);
791 va_end(ap);
793 return rc;
796 static void xen_device_frontend_set_state(XenDevice *xendev,
797 enum xenbus_state state,
798 bool publish)
800 const char *type = object_get_typename(OBJECT(xendev));
802 if (xendev->frontend_state == state) {
803 return;
806 trace_xen_device_frontend_state(type, xendev->name,
807 xs_strstate(state));
809 xendev->frontend_state = state;
810 if (publish) {
811 xen_device_frontend_printf(xendev, "state", "%u", state);
815 static void xen_device_frontend_changed(void *opaque)
817 XenDevice *xendev = opaque;
818 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
819 const char *type = object_get_typename(OBJECT(xendev));
820 enum xenbus_state state;
822 trace_xen_device_frontend_changed(type, xendev->name);
824 if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
825 state = XenbusStateUnknown;
828 xen_device_frontend_set_state(xendev, state, false);
830 if (state == XenbusStateInitialising &&
831 xendev->backend_state == XenbusStateClosed &&
832 xendev->backend_online) {
834 * The frontend is re-initializing so switch back to
835 * InitWait.
837 xen_device_backend_set_state(xendev, XenbusStateInitWait);
838 return;
841 if (xendev_class->frontend_changed) {
842 Error *local_err = NULL;
844 xendev_class->frontend_changed(xendev, state, &local_err);
846 if (local_err) {
847 error_reportf_err(local_err, "frontend change error: ");
852 static bool xen_device_frontend_exists(XenDevice *xendev)
854 enum xenbus_state state;
856 return (xen_device_frontend_scanf(xendev, "state", "%u", &state) == 1);
859 static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
861 ERRP_GUARD();
862 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
863 struct xs_permissions perms[2];
865 xendev->frontend_path = xen_device_get_frontend_path(xendev);
868 * The frontend area may have already been created by a legacy
869 * toolstack.
871 if (!xen_device_frontend_exists(xendev)) {
872 perms[0].id = xendev->frontend_id;
873 perms[0].perms = XS_PERM_NONE;
874 perms[1].id = xenbus->backend_id;
875 perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
877 g_assert(xenbus->xsh);
879 xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
880 ARRAY_SIZE(perms), errp);
881 if (*errp) {
882 error_prepend(errp, "failed to create frontend: ");
883 return;
887 xendev->frontend_state_watch =
888 xen_device_add_watch(xendev, xendev->frontend_path, "state",
889 xen_device_frontend_changed, errp);
890 if (*errp) {
891 error_prepend(errp, "failed to watch frontend state: ");
895 static void xen_device_frontend_destroy(XenDevice *xendev)
897 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
898 Error *local_err = NULL;
900 if (xendev->frontend_state_watch) {
901 xen_device_remove_watch(xendev, xendev->frontend_state_watch,
902 NULL);
903 xendev->frontend_state_watch = NULL;
906 if (!xendev->frontend_path) {
907 return;
910 g_assert(xenbus->xsh);
912 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
913 &local_err);
914 g_free(xendev->frontend_path);
915 xendev->frontend_path = NULL;
917 if (local_err) {
918 error_report_err(local_err);
922 void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
923 Error **errp)
925 if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
926 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
930 void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
931 unsigned int nr_refs, int prot,
932 Error **errp)
934 void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
935 xendev->frontend_id, refs,
936 prot);
938 if (!map) {
939 error_setg_errno(errp, errno,
940 "xengnttab_map_domain_grant_refs failed");
943 return map;
946 void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
947 unsigned int nr_refs, Error **errp)
949 if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
950 error_setg_errno(errp, errno, "xengnttab_unmap failed");
954 static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
955 XenDeviceGrantCopySegment segs[],
956 unsigned int nr_segs, Error **errp)
958 uint32_t *refs = g_new(uint32_t, nr_segs);
959 int prot = to_domain ? PROT_WRITE : PROT_READ;
960 void *map;
961 unsigned int i;
963 for (i = 0; i < nr_segs; i++) {
964 XenDeviceGrantCopySegment *seg = &segs[i];
966 refs[i] = to_domain ? seg->dest.foreign.ref :
967 seg->source.foreign.ref;
970 map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
971 xendev->frontend_id, refs,
972 prot);
973 if (!map) {
974 error_setg_errno(errp, errno,
975 "xengnttab_map_domain_grant_refs failed");
976 goto done;
979 for (i = 0; i < nr_segs; i++) {
980 XenDeviceGrantCopySegment *seg = &segs[i];
981 void *page = map + (i * XC_PAGE_SIZE);
983 if (to_domain) {
984 memcpy(page + seg->dest.foreign.offset, seg->source.virt,
985 seg->len);
986 } else {
987 memcpy(seg->dest.virt, page + seg->source.foreign.offset,
988 seg->len);
992 if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
993 error_setg_errno(errp, errno, "xengnttab_unmap failed");
996 done:
997 g_free(refs);
1000 void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
1001 XenDeviceGrantCopySegment segs[],
1002 unsigned int nr_segs, Error **errp)
1004 xengnttab_grant_copy_segment_t *xengnttab_segs;
1005 unsigned int i;
1007 if (!xendev->feature_grant_copy) {
1008 compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
1009 return;
1012 xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
1014 for (i = 0; i < nr_segs; i++) {
1015 XenDeviceGrantCopySegment *seg = &segs[i];
1016 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
1018 if (to_domain) {
1019 xengnttab_seg->flags = GNTCOPY_dest_gref;
1020 xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
1021 xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
1022 xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
1023 xengnttab_seg->source.virt = seg->source.virt;
1024 } else {
1025 xengnttab_seg->flags = GNTCOPY_source_gref;
1026 xengnttab_seg->source.foreign.domid = xendev->frontend_id;
1027 xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
1028 xengnttab_seg->source.foreign.offset =
1029 seg->source.foreign.offset;
1030 xengnttab_seg->dest.virt = seg->dest.virt;
1033 xengnttab_seg->len = seg->len;
1036 if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
1037 error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
1038 goto done;
1041 for (i = 0; i < nr_segs; i++) {
1042 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
1044 if (xengnttab_seg->status != GNTST_okay) {
1045 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
1046 break;
1050 done:
1051 g_free(xengnttab_segs);
1054 struct XenEventChannel {
1055 QLIST_ENTRY(XenEventChannel) list;
1056 AioContext *ctx;
1057 xenevtchn_handle *xeh;
1058 evtchn_port_t local_port;
1059 XenEventHandler handler;
1060 void *opaque;
1063 static bool xen_device_poll(void *opaque)
1065 XenEventChannel *channel = opaque;
1067 return channel->handler(channel->opaque);
1070 static void xen_device_event(void *opaque)
1072 XenEventChannel *channel = opaque;
1073 unsigned long port = xenevtchn_pending(channel->xeh);
1075 if (port == channel->local_port) {
1076 xen_device_poll(channel);
1078 xenevtchn_unmask(channel->xeh, port);
1082 void xen_device_set_event_channel_context(XenDevice *xendev,
1083 XenEventChannel *channel,
1084 AioContext *ctx,
1085 Error **errp)
1087 if (!channel) {
1088 error_setg(errp, "bad channel");
1089 return;
1092 if (channel->ctx)
1093 aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1094 NULL, NULL, NULL, NULL);
1096 channel->ctx = ctx;
1097 aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1098 xen_device_event, NULL, xen_device_poll, channel);
1101 XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
1102 unsigned int port,
1103 XenEventHandler handler,
1104 void *opaque, Error **errp)
1106 XenEventChannel *channel = g_new0(XenEventChannel, 1);
1107 xenevtchn_port_or_error_t local_port;
1109 channel->xeh = xenevtchn_open(NULL, 0);
1110 if (!channel->xeh) {
1111 error_setg_errno(errp, errno, "failed xenevtchn_open");
1112 goto fail;
1115 local_port = xenevtchn_bind_interdomain(channel->xeh,
1116 xendev->frontend_id,
1117 port);
1118 if (local_port < 0) {
1119 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
1120 goto fail;
1123 channel->local_port = local_port;
1124 channel->handler = handler;
1125 channel->opaque = opaque;
1127 /* Only reason for failure is a NULL channel */
1128 xen_device_set_event_channel_context(xendev, channel,
1129 qemu_get_aio_context(),
1130 &error_abort);
1132 QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
1134 return channel;
1136 fail:
1137 if (channel->xeh) {
1138 xenevtchn_close(channel->xeh);
1141 g_free(channel);
1143 return NULL;
1146 void xen_device_notify_event_channel(XenDevice *xendev,
1147 XenEventChannel *channel,
1148 Error **errp)
1150 if (!channel) {
1151 error_setg(errp, "bad channel");
1152 return;
1155 if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
1156 error_setg_errno(errp, errno, "xenevtchn_notify failed");
1160 void xen_device_unbind_event_channel(XenDevice *xendev,
1161 XenEventChannel *channel,
1162 Error **errp)
1164 if (!channel) {
1165 error_setg(errp, "bad channel");
1166 return;
1169 QLIST_REMOVE(channel, list);
1171 aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1172 NULL, NULL, NULL, NULL);
1174 if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
1175 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
1178 xenevtchn_close(channel->xeh);
1179 g_free(channel);
1182 static void xen_device_unrealize(DeviceState *dev)
1184 XenDevice *xendev = XEN_DEVICE(dev);
1185 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1186 const char *type = object_get_typename(OBJECT(xendev));
1187 XenEventChannel *channel, *next;
1189 if (!xendev->name) {
1190 return;
1193 trace_xen_device_unrealize(type, xendev->name);
1195 if (xendev->exit.notify) {
1196 qemu_remove_exit_notifier(&xendev->exit);
1197 xendev->exit.notify = NULL;
1200 if (xendev_class->unrealize) {
1201 xendev_class->unrealize(xendev);
1204 /* Make sure all event channels are cleaned up */
1205 QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
1206 xen_device_unbind_event_channel(xendev, channel, NULL);
1209 xen_device_frontend_destroy(xendev);
1210 xen_device_backend_destroy(xendev);
1212 if (xendev->xgth) {
1213 xengnttab_close(xendev->xgth);
1214 xendev->xgth = NULL;
1217 if (xendev->watch_list) {
1218 watch_list_destroy(xendev->watch_list);
1219 xendev->watch_list = NULL;
1222 if (xendev->xsh) {
1223 xs_close(xendev->xsh);
1224 xendev->xsh = NULL;
1227 g_free(xendev->name);
1228 xendev->name = NULL;
1231 static void xen_device_exit(Notifier *n, void *data)
1233 XenDevice *xendev = container_of(n, XenDevice, exit);
1235 xen_device_unrealize(DEVICE(xendev));
1238 static void xen_device_realize(DeviceState *dev, Error **errp)
1240 ERRP_GUARD();
1241 XenDevice *xendev = XEN_DEVICE(dev);
1242 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1243 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
1244 const char *type = object_get_typename(OBJECT(xendev));
1246 if (xendev->frontend_id == DOMID_INVALID) {
1247 xendev->frontend_id = xen_domid;
1250 if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1251 error_setg(errp, "invalid frontend-id");
1252 goto unrealize;
1255 if (!xendev_class->get_name) {
1256 error_setg(errp, "get_name method not implemented");
1257 goto unrealize;
1260 xendev->name = xendev_class->get_name(xendev, errp);
1261 if (*errp) {
1262 error_prepend(errp, "failed to get device name: ");
1263 goto unrealize;
1266 trace_xen_device_realize(type, xendev->name);
1268 xendev->xsh = xs_open(0);
1269 if (!xendev->xsh) {
1270 error_setg_errno(errp, errno, "failed xs_open");
1271 goto unrealize;
1274 xendev->watch_list = watch_list_create(xendev->xsh);
1276 xendev->xgth = xengnttab_open(NULL, 0);
1277 if (!xendev->xgth) {
1278 error_setg_errno(errp, errno, "failed xengnttab_open");
1279 goto unrealize;
1282 xendev->feature_grant_copy =
1283 (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1285 xen_device_backend_create(xendev, errp);
1286 if (*errp) {
1287 goto unrealize;
1290 xen_device_frontend_create(xendev, errp);
1291 if (*errp) {
1292 goto unrealize;
1295 if (xendev_class->realize) {
1296 xendev_class->realize(xendev, errp);
1297 if (*errp) {
1298 goto unrealize;
1302 xen_device_backend_printf(xendev, "frontend", "%s",
1303 xendev->frontend_path);
1304 xen_device_backend_printf(xendev, "frontend-id", "%u",
1305 xendev->frontend_id);
1306 xen_device_backend_printf(xendev, "hotplug-status", "connected");
1308 xen_device_backend_set_online(xendev, true);
1309 xen_device_backend_set_state(xendev, XenbusStateInitWait);
1311 if (!xen_device_frontend_exists(xendev)) {
1312 xen_device_frontend_printf(xendev, "backend", "%s",
1313 xendev->backend_path);
1314 xen_device_frontend_printf(xendev, "backend-id", "%u",
1315 xenbus->backend_id);
1317 xen_device_frontend_set_state(xendev, XenbusStateInitialising, true);
1320 xendev->exit.notify = xen_device_exit;
1321 qemu_add_exit_notifier(&xendev->exit);
1322 return;
1324 unrealize:
1325 xen_device_unrealize(dev);
1328 static Property xen_device_props[] = {
1329 DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1330 DOMID_INVALID),
1331 DEFINE_PROP_END_OF_LIST()
1334 static void xen_device_class_init(ObjectClass *class, void *data)
1336 DeviceClass *dev_class = DEVICE_CLASS(class);
1338 dev_class->realize = xen_device_realize;
1339 dev_class->unrealize = xen_device_unrealize;
1340 device_class_set_props(dev_class, xen_device_props);
1341 dev_class->bus_type = TYPE_XEN_BUS;
1344 static const TypeInfo xen_device_type_info = {
1345 .name = TYPE_XEN_DEVICE,
1346 .parent = TYPE_DEVICE,
1347 .instance_size = sizeof(XenDevice),
1348 .abstract = true,
1349 .class_size = sizeof(XenDeviceClass),
1350 .class_init = xen_device_class_init,
1353 typedef struct XenBridge {
1354 SysBusDevice busdev;
1355 } XenBridge;
1357 #define TYPE_XEN_BRIDGE "xen-bridge"
1359 static const TypeInfo xen_bridge_type_info = {
1360 .name = TYPE_XEN_BRIDGE,
1361 .parent = TYPE_SYS_BUS_DEVICE,
1362 .instance_size = sizeof(XenBridge),
1365 static void xen_register_types(void)
1367 type_register_static(&xen_bridge_type_info);
1368 type_register_static(&xen_bus_type_info);
1369 type_register_static(&xen_device_type_info);
1372 type_init(xen_register_types)
1374 void xen_bus_init(void)
1376 DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE);
1377 BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
1379 sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1380 qbus_set_bus_hotplug_handler(bus);