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