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