xen: add a mechanism to automatically create XenDevice-s...
[qemu.git] / hw / xen / xen-bus.c
blob3aeccec69c007dc65c7934dd172c404f26b94457
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/uuid.h"
11 #include "hw/hw.h"
12 #include "hw/sysbus.h"
13 #include "hw/xen/xen.h"
14 #include "hw/xen/xen-backend.h"
15 #include "hw/xen/xen-bus.h"
16 #include "hw/xen/xen-bus-helper.h"
17 #include "monitor/monitor.h"
18 #include "qapi/error.h"
19 #include "qapi/qmp/qdict.h"
20 #include "sysemu/sysemu.h"
21 #include "trace.h"
23 static char *xen_device_get_backend_path(XenDevice *xendev)
25 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
26 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
27 const char *type = object_get_typename(OBJECT(xendev));
28 const char *backend = xendev_class->backend;
30 if (!backend) {
31 backend = type;
34 return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
35 xenbus->backend_id, backend, xendev->frontend_id,
36 xendev->name);
39 static char *xen_device_get_frontend_path(XenDevice *xendev)
41 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
42 const char *type = object_get_typename(OBJECT(xendev));
43 const char *device = xendev_class->device;
45 if (!device) {
46 device = type;
49 return g_strdup_printf("/local/domain/%u/device/%s/%s",
50 xendev->frontend_id, device, xendev->name);
53 static void xen_device_unplug(XenDevice *xendev, Error **errp)
55 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
56 const char *type = object_get_typename(OBJECT(xendev));
57 Error *local_err = NULL;
58 xs_transaction_t tid;
60 trace_xen_device_unplug(type, xendev->name);
62 /* Mimic the way the Xen toolstack does an unplug */
63 again:
64 tid = xs_transaction_start(xenbus->xsh);
65 if (tid == XBT_NULL) {
66 error_setg_errno(errp, errno, "failed xs_transaction_start");
67 return;
70 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online",
71 &local_err, "%u", 0);
72 if (local_err) {
73 goto abort;
76 xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
77 &local_err, "%u", XenbusStateClosing);
78 if (local_err) {
79 goto abort;
82 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
83 if (errno == EAGAIN) {
84 goto again;
87 error_setg_errno(errp, errno, "failed xs_transaction_end");
90 return;
92 abort:
94 * We only abort if there is already a failure so ignore any error
95 * from ending the transaction.
97 xs_transaction_end(xenbus->xsh, tid, true);
98 error_propagate(errp, local_err);
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 static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
160 const char *key, XenWatchHandler handler,
161 void *opaque, Error **errp)
163 XenWatch *watch = new_watch(node, key, handler, opaque);
164 Error *local_err = NULL;
166 trace_xen_bus_add_watch(watch->node, watch->key, watch->token);
168 notifier_list_add(&xenbus->watch_notifiers, &watch->notifier);
170 xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err);
171 if (local_err) {
172 error_propagate(errp, local_err);
174 notifier_remove(&watch->notifier);
175 free_watch(watch);
177 return NULL;
180 return watch;
183 static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
184 Error **errp)
186 trace_xen_bus_remove_watch(watch->node, watch->key, watch->token);
188 xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token,
189 errp);
191 notifier_remove(&watch->notifier);
192 free_watch(watch);
195 static void xen_bus_backend_create(XenBus *xenbus, const char *type,
196 const char *name, char *path,
197 Error **errp)
199 xs_transaction_t tid;
200 char **key;
201 QDict *opts;
202 unsigned int i, n;
203 Error *local_err = NULL;
205 trace_xen_bus_backend_create(type, path);
207 again:
208 tid = xs_transaction_start(xenbus->xsh);
209 if (tid == XBT_NULL) {
210 error_setg(errp, "failed xs_transaction_start");
211 return;
214 key = xs_directory(xenbus->xsh, tid, path, &n);
215 if (!key) {
216 if (!xs_transaction_end(xenbus->xsh, tid, true)) {
217 error_setg_errno(errp, errno, "failed xs_transaction_end");
219 return;
222 opts = qdict_new();
223 for (i = 0; i < n; i++) {
224 char *val;
227 * Assume anything found in the xenstore backend area, other than
228 * the keys created for a generic XenDevice, are parameters
229 * to be used to configure the backend.
231 if (!strcmp(key[i], "state") ||
232 !strcmp(key[i], "online") ||
233 !strcmp(key[i], "frontend") ||
234 !strcmp(key[i], "frontend-id") ||
235 !strcmp(key[i], "hotplug-status"))
236 continue;
238 if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
239 &val) == 1) {
240 qdict_put_str(opts, key[i], val);
241 free(val);
245 free(key);
247 if (!xs_transaction_end(xenbus->xsh, tid, false)) {
248 qobject_unref(opts);
250 if (errno == EAGAIN) {
251 goto again;
254 error_setg_errno(errp, errno, "failed xs_transaction_end");
255 return;
258 xen_backend_device_create(xenbus, type, name, opts, &local_err);
259 qobject_unref(opts);
261 if (local_err) {
262 error_propagate_prepend(errp, local_err,
263 "failed to create '%s' device '%s': ",
264 type, name);
268 static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
270 char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
271 char **backend;
272 unsigned int i, n;
274 trace_xen_bus_type_enumerate(type);
276 backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
277 if (!backend) {
278 goto out;
281 for (i = 0; i < n; i++) {
282 char *backend_path = g_strdup_printf("%s/%s", domain_path,
283 backend[i]);
284 enum xenbus_state backend_state;
286 if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
287 NULL, "%u", &backend_state) != 1)
288 backend_state = XenbusStateUnknown;
290 if (backend_state == XenbusStateInitialising) {
291 Error *local_err = NULL;
293 xen_bus_backend_create(xenbus, type, backend[i], backend_path,
294 &local_err);
295 if (local_err) {
296 error_report_err(local_err);
300 g_free(backend_path);
303 free(backend);
305 out:
306 g_free(domain_path);
309 static void xen_bus_enumerate(void *opaque)
311 XenBus *xenbus = opaque;
312 char **type;
313 unsigned int i, n;
315 trace_xen_bus_enumerate();
317 type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
318 if (!type) {
319 return;
322 for (i = 0; i < n; i++) {
323 xen_bus_type_enumerate(xenbus, type[i]);
326 free(type);
329 static void xen_bus_unrealize(BusState *bus, Error **errp)
331 XenBus *xenbus = XEN_BUS(bus);
333 trace_xen_bus_unrealize();
335 if (xenbus->backend_watch) {
336 xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL);
337 xenbus->backend_watch = NULL;
340 if (!xenbus->xsh) {
341 return;
344 qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL);
346 xs_close(xenbus->xsh);
349 static void xen_bus_watch(void *opaque)
351 XenBus *xenbus = opaque;
352 char **v;
353 const char *token;
355 g_assert(xenbus->xsh);
357 v = xs_check_watch(xenbus->xsh);
358 if (!v) {
359 return;
362 token = v[XS_WATCH_TOKEN];
364 trace_xen_bus_watch(token);
366 notifier_list_notify(&xenbus->watch_notifiers, (void *)token);
368 free(v);
371 static void xen_bus_realize(BusState *bus, Error **errp)
373 XenBus *xenbus = XEN_BUS(bus);
374 unsigned int domid;
375 Error *local_err = NULL;
377 trace_xen_bus_realize();
379 xenbus->xsh = xs_open(0);
380 if (!xenbus->xsh) {
381 error_setg_errno(errp, errno, "failed xs_open");
382 goto fail;
385 if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
386 "domid", NULL, "%u", &domid) == 1) {
387 xenbus->backend_id = domid;
388 } else {
389 xenbus->backend_id = 0; /* Assume lack of node means dom0 */
392 notifier_list_init(&xenbus->watch_notifiers);
393 qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL,
394 xenbus);
396 module_call_init(MODULE_INIT_XEN_BACKEND);
398 xenbus->backend_watch =
399 xen_bus_add_watch(xenbus, "", /* domain root node */
400 "backend", xen_bus_enumerate, xenbus, &local_err);
401 if (local_err) {
402 /* This need not be treated as a hard error so don't propagate */
403 error_reportf_err(local_err,
404 "failed to set up enumeration watch: ");
407 return;
409 fail:
410 xen_bus_unrealize(bus, &error_abort);
413 static void xen_bus_unplug_request(HotplugHandler *hotplug,
414 DeviceState *dev,
415 Error **errp)
417 XenDevice *xendev = XEN_DEVICE(dev);
419 xen_device_unplug(xendev, errp);
422 static void xen_bus_class_init(ObjectClass *class, void *data)
424 BusClass *bus_class = BUS_CLASS(class);
425 HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
427 bus_class->print_dev = xen_bus_print_dev;
428 bus_class->get_dev_path = xen_bus_get_dev_path;
429 bus_class->realize = xen_bus_realize;
430 bus_class->unrealize = xen_bus_unrealize;
432 hotplug_class->unplug_request = xen_bus_unplug_request;
435 static const TypeInfo xen_bus_type_info = {
436 .name = TYPE_XEN_BUS,
437 .parent = TYPE_BUS,
438 .instance_size = sizeof(XenBus),
439 .class_size = sizeof(XenBusClass),
440 .class_init = xen_bus_class_init,
441 .interfaces = (InterfaceInfo[]) {
442 { TYPE_HOTPLUG_HANDLER },
447 void xen_device_backend_printf(XenDevice *xendev, const char *key,
448 const char *fmt, ...)
450 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
451 Error *local_err = NULL;
452 va_list ap;
454 g_assert(xenbus->xsh);
456 va_start(ap, fmt);
457 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
458 &local_err, fmt, ap);
459 va_end(ap);
461 if (local_err) {
462 error_report_err(local_err);
466 static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
467 const char *fmt, ...)
469 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
470 va_list ap;
471 int rc;
473 g_assert(xenbus->xsh);
475 va_start(ap, fmt);
476 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
477 NULL, fmt, ap);
478 va_end(ap);
480 return rc;
483 void xen_device_backend_set_state(XenDevice *xendev,
484 enum xenbus_state state)
486 const char *type = object_get_typename(OBJECT(xendev));
488 if (xendev->backend_state == state) {
489 return;
492 trace_xen_device_backend_state(type, xendev->name,
493 xs_strstate(state));
495 xendev->backend_state = state;
496 xen_device_backend_printf(xendev, "state", "%u", state);
499 enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
501 return xendev->backend_state;
504 static void xen_device_backend_set_online(XenDevice *xendev, bool online)
506 const char *type = object_get_typename(OBJECT(xendev));
508 if (xendev->backend_online == online) {
509 return;
512 trace_xen_device_backend_online(type, xendev->name, online);
514 xendev->backend_online = online;
515 xen_device_backend_printf(xendev, "online", "%u", online);
518 static void xen_device_backend_changed(void *opaque)
520 XenDevice *xendev = opaque;
521 const char *type = object_get_typename(OBJECT(xendev));
522 enum xenbus_state state;
523 unsigned int online;
525 trace_xen_device_backend_changed(type, xendev->name);
527 if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
528 state = XenbusStateUnknown;
531 xen_device_backend_set_state(xendev, state);
533 if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
534 online = 0;
537 xen_device_backend_set_online(xendev, !!online);
540 * If the toolstack (or unplug request callback) has set the backend
541 * state to Closing, but there is no active frontend (i.e. the
542 * state is not Connected) then set the backend state to Closed.
544 if (xendev->backend_state == XenbusStateClosing &&
545 xendev->frontend_state != XenbusStateConnected) {
546 xen_device_backend_set_state(xendev, XenbusStateClosed);
550 * If a backend is still 'online' then its state should be cycled
551 * back round to InitWait in order for a new frontend instance to
552 * connect. This may happen when, for example, a frontend driver is
553 * re-installed or updated.
554 * If a backend is not 'online' then the device should be destroyed.
556 if (xendev->backend_online &&
557 xendev->backend_state == XenbusStateClosed) {
558 xen_device_backend_set_state(xendev, XenbusStateInitWait);
559 } else if (!xendev->backend_online &&
560 (xendev->backend_state == XenbusStateClosed ||
561 xendev->backend_state == XenbusStateInitialising ||
562 xendev->backend_state == XenbusStateInitWait ||
563 xendev->backend_state == XenbusStateUnknown)) {
564 Error *local_err = NULL;
566 if (!xen_backend_try_device_destroy(xendev, &local_err)) {
567 object_unparent(OBJECT(xendev));
570 if (local_err) {
571 error_report_err(local_err);
576 static void xen_device_backend_create(XenDevice *xendev, Error **errp)
578 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
579 struct xs_permissions perms[2];
580 Error *local_err = NULL;
582 xendev->backend_path = xen_device_get_backend_path(xendev);
584 perms[0].id = xenbus->backend_id;
585 perms[0].perms = XS_PERM_NONE;
586 perms[1].id = xendev->frontend_id;
587 perms[1].perms = XS_PERM_READ;
589 g_assert(xenbus->xsh);
591 xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
592 ARRAY_SIZE(perms), &local_err);
593 if (local_err) {
594 error_propagate_prepend(errp, local_err,
595 "failed to create backend: ");
596 return;
599 xendev->backend_state_watch =
600 xen_bus_add_watch(xenbus, xendev->backend_path,
601 "state", xen_device_backend_changed,
602 xendev, &local_err);
603 if (local_err) {
604 error_propagate_prepend(errp, local_err,
605 "failed to watch backend state: ");
606 return;
609 xendev->backend_online_watch =
610 xen_bus_add_watch(xenbus, xendev->backend_path,
611 "online", xen_device_backend_changed,
612 xendev, &local_err);
613 if (local_err) {
614 error_propagate_prepend(errp, local_err,
615 "failed to watch backend online: ");
616 return;
620 static void xen_device_backend_destroy(XenDevice *xendev)
622 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
623 Error *local_err = NULL;
625 if (xendev->backend_online_watch) {
626 xen_bus_remove_watch(xenbus, xendev->backend_online_watch, NULL);
627 xendev->backend_online_watch = NULL;
630 if (xendev->backend_state_watch) {
631 xen_bus_remove_watch(xenbus, xendev->backend_state_watch, NULL);
632 xendev->backend_state_watch = NULL;
635 if (!xendev->backend_path) {
636 return;
639 g_assert(xenbus->xsh);
641 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
642 &local_err);
643 g_free(xendev->backend_path);
644 xendev->backend_path = NULL;
646 if (local_err) {
647 error_report_err(local_err);
651 void xen_device_frontend_printf(XenDevice *xendev, const char *key,
652 const char *fmt, ...)
654 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
655 Error *local_err = NULL;
656 va_list ap;
658 g_assert(xenbus->xsh);
660 va_start(ap, fmt);
661 xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
662 &local_err, fmt, ap);
663 va_end(ap);
665 if (local_err) {
666 error_report_err(local_err);
670 int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
671 const char *fmt, ...)
673 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
674 va_list ap;
675 int rc;
677 g_assert(xenbus->xsh);
679 va_start(ap, fmt);
680 rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
681 NULL, fmt, ap);
682 va_end(ap);
684 return rc;
687 static void xen_device_frontend_set_state(XenDevice *xendev,
688 enum xenbus_state state)
690 const char *type = object_get_typename(OBJECT(xendev));
692 if (xendev->frontend_state == state) {
693 return;
696 trace_xen_device_frontend_state(type, xendev->name,
697 xs_strstate(state));
699 xendev->frontend_state = state;
700 xen_device_frontend_printf(xendev, "state", "%u", state);
703 static void xen_device_frontend_changed(void *opaque)
705 XenDevice *xendev = opaque;
706 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
707 const char *type = object_get_typename(OBJECT(xendev));
708 enum xenbus_state state;
710 trace_xen_device_frontend_changed(type, xendev->name);
712 if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
713 state = XenbusStateUnknown;
716 xen_device_frontend_set_state(xendev, state);
718 if (xendev_class->frontend_changed) {
719 Error *local_err = NULL;
721 xendev_class->frontend_changed(xendev, state, &local_err);
723 if (local_err) {
724 error_reportf_err(local_err, "frontend change error: ");
729 static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
731 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
732 struct xs_permissions perms[2];
733 Error *local_err = NULL;
735 xendev->frontend_path = xen_device_get_frontend_path(xendev);
737 perms[0].id = xendev->frontend_id;
738 perms[0].perms = XS_PERM_NONE;
739 perms[1].id = xenbus->backend_id;
740 perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
742 g_assert(xenbus->xsh);
744 xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
745 ARRAY_SIZE(perms), &local_err);
746 if (local_err) {
747 error_propagate_prepend(errp, local_err,
748 "failed to create frontend: ");
749 return;
752 xendev->frontend_state_watch =
753 xen_bus_add_watch(xenbus, xendev->frontend_path, "state",
754 xen_device_frontend_changed, xendev, &local_err);
755 if (local_err) {
756 error_propagate_prepend(errp, local_err,
757 "failed to watch frontend state: ");
761 static void xen_device_frontend_destroy(XenDevice *xendev)
763 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
764 Error *local_err = NULL;
766 if (xendev->frontend_state_watch) {
767 xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL);
768 xendev->frontend_state_watch = NULL;
771 if (!xendev->frontend_path) {
772 return;
775 g_assert(xenbus->xsh);
777 xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
778 &local_err);
779 g_free(xendev->frontend_path);
780 xendev->frontend_path = NULL;
782 if (local_err) {
783 error_report_err(local_err);
787 void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
788 Error **errp)
790 if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
791 error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
795 void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
796 unsigned int nr_refs, int prot,
797 Error **errp)
799 void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
800 xendev->frontend_id, refs,
801 prot);
803 if (!map) {
804 error_setg_errno(errp, errno,
805 "xengnttab_map_domain_grant_refs failed");
808 return map;
811 void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
812 unsigned int nr_refs, Error **errp)
814 if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
815 error_setg_errno(errp, errno, "xengnttab_unmap failed");
819 static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
820 XenDeviceGrantCopySegment segs[],
821 unsigned int nr_segs, Error **errp)
823 uint32_t *refs = g_new(uint32_t, nr_segs);
824 int prot = to_domain ? PROT_WRITE : PROT_READ;
825 void *map;
826 unsigned int i;
828 for (i = 0; i < nr_segs; i++) {
829 XenDeviceGrantCopySegment *seg = &segs[i];
831 refs[i] = to_domain ? seg->dest.foreign.ref :
832 seg->source.foreign.ref;
835 map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
836 xendev->frontend_id, refs,
837 prot);
838 if (!map) {
839 error_setg_errno(errp, errno,
840 "xengnttab_map_domain_grant_refs failed");
841 goto done;
844 for (i = 0; i < nr_segs; i++) {
845 XenDeviceGrantCopySegment *seg = &segs[i];
846 void *page = map + (i * XC_PAGE_SIZE);
848 if (to_domain) {
849 memcpy(page + seg->dest.foreign.offset, seg->source.virt,
850 seg->len);
851 } else {
852 memcpy(seg->dest.virt, page + seg->source.foreign.offset,
853 seg->len);
857 if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
858 error_setg_errno(errp, errno, "xengnttab_unmap failed");
861 done:
862 g_free(refs);
865 void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
866 XenDeviceGrantCopySegment segs[],
867 unsigned int nr_segs, Error **errp)
869 xengnttab_grant_copy_segment_t *xengnttab_segs;
870 unsigned int i;
872 if (!xendev->feature_grant_copy) {
873 compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
874 return;
877 xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
879 for (i = 0; i < nr_segs; i++) {
880 XenDeviceGrantCopySegment *seg = &segs[i];
881 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
883 if (to_domain) {
884 xengnttab_seg->flags = GNTCOPY_dest_gref;
885 xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
886 xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
887 xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
888 xengnttab_seg->source.virt = seg->source.virt;
889 } else {
890 xengnttab_seg->flags = GNTCOPY_source_gref;
891 xengnttab_seg->source.foreign.domid = xendev->frontend_id;
892 xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
893 xengnttab_seg->source.foreign.offset =
894 seg->source.foreign.offset;
895 xengnttab_seg->dest.virt = seg->dest.virt;
898 xengnttab_seg->len = seg->len;
901 if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
902 error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
903 goto done;
906 for (i = 0; i < nr_segs; i++) {
907 xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
909 if (xengnttab_seg->status != GNTST_okay) {
910 error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
911 break;
915 done:
916 g_free(xengnttab_segs);
919 struct XenEventChannel {
920 evtchn_port_t local_port;
921 XenEventHandler handler;
922 void *opaque;
923 Notifier notifier;
926 static void event_notify(Notifier *n, void *data)
928 XenEventChannel *channel = container_of(n, XenEventChannel, notifier);
929 unsigned long port = (unsigned long)data;
931 if (port == channel->local_port) {
932 channel->handler(channel->opaque);
936 XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
937 unsigned int port,
938 XenEventHandler handler,
939 void *opaque, Error **errp)
941 XenEventChannel *channel = g_new0(XenEventChannel, 1);
942 xenevtchn_port_or_error_t local_port;
944 local_port = xenevtchn_bind_interdomain(xendev->xeh,
945 xendev->frontend_id,
946 port);
947 if (local_port < 0) {
948 error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
950 g_free(channel);
951 return NULL;
954 channel->local_port = local_port;
955 channel->handler = handler;
956 channel->opaque = opaque;
957 channel->notifier.notify = event_notify;
959 notifier_list_add(&xendev->event_notifiers, &channel->notifier);
961 return channel;
964 void xen_device_notify_event_channel(XenDevice *xendev,
965 XenEventChannel *channel,
966 Error **errp)
968 if (!channel) {
969 error_setg(errp, "bad channel");
970 return;
973 if (xenevtchn_notify(xendev->xeh, channel->local_port) < 0) {
974 error_setg_errno(errp, errno, "xenevtchn_notify failed");
978 void xen_device_unbind_event_channel(XenDevice *xendev,
979 XenEventChannel *channel,
980 Error **errp)
982 if (!channel) {
983 error_setg(errp, "bad channel");
984 return;
987 notifier_remove(&channel->notifier);
989 if (xenevtchn_unbind(xendev->xeh, channel->local_port) < 0) {
990 error_setg_errno(errp, errno, "xenevtchn_unbind failed");
993 g_free(channel);
996 static void xen_device_unrealize(DeviceState *dev, Error **errp)
998 XenDevice *xendev = XEN_DEVICE(dev);
999 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1000 const char *type = object_get_typename(OBJECT(xendev));
1002 if (!xendev->name) {
1003 return;
1006 trace_xen_device_unrealize(type, xendev->name);
1008 if (xendev->exit.notify) {
1009 qemu_remove_exit_notifier(&xendev->exit);
1010 xendev->exit.notify = NULL;
1013 if (xendev_class->unrealize) {
1014 xendev_class->unrealize(xendev, errp);
1017 xen_device_frontend_destroy(xendev);
1018 xen_device_backend_destroy(xendev);
1020 if (xendev->xeh) {
1021 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), NULL, NULL, NULL);
1022 xenevtchn_close(xendev->xeh);
1023 xendev->xeh = NULL;
1026 if (xendev->xgth) {
1027 xengnttab_close(xendev->xgth);
1028 xendev->xgth = NULL;
1031 g_free(xendev->name);
1032 xendev->name = NULL;
1035 static void xen_device_exit(Notifier *n, void *data)
1037 XenDevice *xendev = container_of(n, XenDevice, exit);
1039 xen_device_unrealize(DEVICE(xendev), &error_abort);
1042 static void xen_device_event(void *opaque)
1044 XenDevice *xendev = opaque;
1045 unsigned long port = xenevtchn_pending(xendev->xeh);
1047 notifier_list_notify(&xendev->event_notifiers, (void *)port);
1049 xenevtchn_unmask(xendev->xeh, port);
1052 static void xen_device_realize(DeviceState *dev, Error **errp)
1054 XenDevice *xendev = XEN_DEVICE(dev);
1055 XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1056 XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
1057 const char *type = object_get_typename(OBJECT(xendev));
1058 Error *local_err = NULL;
1060 if (xendev->frontend_id == DOMID_INVALID) {
1061 xendev->frontend_id = xen_domid;
1064 if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1065 error_setg(errp, "invalid frontend-id");
1066 goto unrealize;
1069 if (!xendev_class->get_name) {
1070 error_setg(errp, "get_name method not implemented");
1071 goto unrealize;
1074 xendev->name = xendev_class->get_name(xendev, &local_err);
1075 if (local_err) {
1076 error_propagate_prepend(errp, local_err,
1077 "failed to get device name: ");
1078 goto unrealize;
1081 trace_xen_device_realize(type, xendev->name);
1083 xendev->xgth = xengnttab_open(NULL, 0);
1084 if (!xendev->xgth) {
1085 error_setg_errno(errp, errno, "failed xengnttab_open");
1086 goto unrealize;
1089 xendev->feature_grant_copy =
1090 (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1092 xendev->xeh = xenevtchn_open(NULL, 0);
1093 if (!xendev->xeh) {
1094 error_setg_errno(errp, errno, "failed xenevtchn_open");
1095 goto unrealize;
1098 notifier_list_init(&xendev->event_notifiers);
1099 qemu_set_fd_handler(xenevtchn_fd(xendev->xeh), xen_device_event, NULL,
1100 xendev);
1102 xen_device_backend_create(xendev, &local_err);
1103 if (local_err) {
1104 error_propagate(errp, local_err);
1105 goto unrealize;
1108 xen_device_frontend_create(xendev, &local_err);
1109 if (local_err) {
1110 error_propagate(errp, local_err);
1111 goto unrealize;
1114 if (xendev_class->realize) {
1115 xendev_class->realize(xendev, &local_err);
1116 if (local_err) {
1117 error_propagate(errp, local_err);
1118 goto unrealize;
1122 xen_device_backend_printf(xendev, "frontend", "%s",
1123 xendev->frontend_path);
1124 xen_device_backend_printf(xendev, "frontend-id", "%u",
1125 xendev->frontend_id);
1126 xen_device_backend_printf(xendev, "hotplug-status", "connected");
1128 xen_device_backend_set_online(xendev, true);
1129 xen_device_backend_set_state(xendev, XenbusStateInitWait);
1131 xen_device_frontend_printf(xendev, "backend", "%s",
1132 xendev->backend_path);
1133 xen_device_frontend_printf(xendev, "backend-id", "%u",
1134 xenbus->backend_id);
1136 xen_device_frontend_set_state(xendev, XenbusStateInitialising);
1138 xendev->exit.notify = xen_device_exit;
1139 qemu_add_exit_notifier(&xendev->exit);
1140 return;
1142 unrealize:
1143 xen_device_unrealize(dev, &error_abort);
1146 static Property xen_device_props[] = {
1147 DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1148 DOMID_INVALID),
1149 DEFINE_PROP_END_OF_LIST()
1152 static void xen_device_class_init(ObjectClass *class, void *data)
1154 DeviceClass *dev_class = DEVICE_CLASS(class);
1156 dev_class->realize = xen_device_realize;
1157 dev_class->unrealize = xen_device_unrealize;
1158 dev_class->props = xen_device_props;
1159 dev_class->bus_type = TYPE_XEN_BUS;
1162 static const TypeInfo xen_device_type_info = {
1163 .name = TYPE_XEN_DEVICE,
1164 .parent = TYPE_DEVICE,
1165 .instance_size = sizeof(XenDevice),
1166 .abstract = true,
1167 .class_size = sizeof(XenDeviceClass),
1168 .class_init = xen_device_class_init,
1171 typedef struct XenBridge {
1172 SysBusDevice busdev;
1173 } XenBridge;
1175 #define TYPE_XEN_BRIDGE "xen-bridge"
1177 static const TypeInfo xen_bridge_type_info = {
1178 .name = TYPE_XEN_BRIDGE,
1179 .parent = TYPE_SYS_BUS_DEVICE,
1180 .instance_size = sizeof(XenBridge),
1183 static void xen_register_types(void)
1185 type_register_static(&xen_bridge_type_info);
1186 type_register_static(&xen_bus_type_info);
1187 type_register_static(&xen_device_type_info);
1190 type_init(xen_register_types)
1192 void xen_bus_init(void)
1194 DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
1195 BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
1197 qdev_init_nofail(dev);
1198 qbus_set_bus_hotplug_handler(bus, &error_abort);