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