xref: /openbmc/qemu/hw/xen/xen-legacy-backend.c (revision 64552b6b)
1 /*
2  *  xen backend driver infrastructure
3  *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; under version 2 of the License.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, see <http://www.gnu.org/licenses/>.
16  *
17  *  Contributions after 2012-01-13 are licensed under the terms of the
18  *  GNU GPL, version 2 or (at your option) any later version.
19  */
20 
21 /*
22  * TODO: add some xenbus / xenstore concepts overview here.
23  */
24 
25 #include "qemu/osdep.h"
26 #include <sys/signal.h>
27 
28 #include "hw/hw.h"
29 #include "hw/sysbus.h"
30 #include "hw/boards.h"
31 #include "qemu/log.h"
32 #include "qapi/error.h"
33 #include "hw/xen/xen-legacy-backend.h"
34 #include "hw/xen/xen_pvdev.h"
35 #include "monitor/qdev.h"
36 
37 DeviceState *xen_sysdev;
38 BusState *xen_sysbus;
39 
40 /* ------------------------------------------------------------- */
41 
42 /* public */
43 struct xs_handle *xenstore;
44 const char *xen_protocol;
45 
46 /* private */
47 static bool xen_feature_grant_copy;
48 static int debug;
49 
50 int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node,
51                           const char *val)
52 {
53     return xenstore_write_str(xendev->be, node, val);
54 }
55 
56 int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node,
57                           int ival)
58 {
59     return xenstore_write_int(xendev->be, node, ival);
60 }
61 
62 int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node,
63                             int64_t ival)
64 {
65     return xenstore_write_int64(xendev->be, node, ival);
66 }
67 
68 char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node)
69 {
70     return xenstore_read_str(xendev->be, node);
71 }
72 
73 int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node,
74                          int *ival)
75 {
76     return xenstore_read_int(xendev->be, node, ival);
77 }
78 
79 char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node)
80 {
81     return xenstore_read_str(xendev->fe, node);
82 }
83 
84 int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node,
85                          int *ival)
86 {
87     return xenstore_read_int(xendev->fe, node, ival);
88 }
89 
90 int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node,
91                             uint64_t *uval)
92 {
93     return xenstore_read_uint64(xendev->fe, node, uval);
94 }
95 
96 /* ------------------------------------------------------------- */
97 
98 int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state)
99 {
100     int rc;
101 
102     rc = xenstore_write_be_int(xendev, "state", state);
103     if (rc < 0) {
104         return rc;
105     }
106     xen_pv_printf(xendev, 1, "backend state: %s -> %s\n",
107                   xenbus_strstate(xendev->be_state), xenbus_strstate(state));
108     xendev->be_state = state;
109     return 0;
110 }
111 
112 void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev,
113                                unsigned int nr_refs)
114 {
115     assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
116 
117     if (xengnttab_set_max_grants(xendev->gnttabdev, nr_refs)) {
118         xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
119                       strerror(errno));
120     }
121 }
122 
123 void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs,
124                             unsigned int nr_refs, int prot)
125 {
126     void *ptr;
127 
128     assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
129 
130     ptr = xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_refs,
131                                           xen_domid, refs, prot);
132     if (!ptr) {
133         xen_pv_printf(xendev, 0,
134                       "xengnttab_map_domain_grant_refs failed: %s\n",
135                       strerror(errno));
136     }
137 
138     return ptr;
139 }
140 
141 void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr,
142                              unsigned int nr_refs)
143 {
144     assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
145 
146     if (xengnttab_unmap(xendev->gnttabdev, ptr, nr_refs)) {
147         xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
148                       strerror(errno));
149     }
150 }
151 
152 static int compat_copy_grant_refs(struct XenLegacyDevice *xendev,
153                                   bool to_domain,
154                                   XenGrantCopySegment segs[],
155                                   unsigned int nr_segs)
156 {
157     uint32_t *refs = g_new(uint32_t, nr_segs);
158     int prot = to_domain ? PROT_WRITE : PROT_READ;
159     void *pages;
160     unsigned int i;
161 
162     for (i = 0; i < nr_segs; i++) {
163         XenGrantCopySegment *seg = &segs[i];
164 
165         refs[i] = to_domain ?
166             seg->dest.foreign.ref : seg->source.foreign.ref;
167     }
168 
169     pages = xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_segs,
170                                             xen_domid, refs, prot);
171     if (!pages) {
172         xen_pv_printf(xendev, 0,
173                       "xengnttab_map_domain_grant_refs failed: %s\n",
174                       strerror(errno));
175         g_free(refs);
176         return -1;
177     }
178 
179     for (i = 0; i < nr_segs; i++) {
180         XenGrantCopySegment *seg = &segs[i];
181         void *page = pages + (i * XC_PAGE_SIZE);
182 
183         if (to_domain) {
184             memcpy(page + seg->dest.foreign.offset, seg->source.virt,
185                    seg->len);
186         } else {
187             memcpy(seg->dest.virt, page + seg->source.foreign.offset,
188                    seg->len);
189         }
190     }
191 
192     if (xengnttab_unmap(xendev->gnttabdev, pages, nr_segs)) {
193         xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
194                       strerror(errno));
195     }
196 
197     g_free(refs);
198     return 0;
199 }
200 
201 int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev,
202                            bool to_domain,
203                            XenGrantCopySegment segs[],
204                            unsigned int nr_segs)
205 {
206     xengnttab_grant_copy_segment_t *xengnttab_segs;
207     unsigned int i;
208     int rc;
209 
210     assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
211 
212     if (!xen_feature_grant_copy) {
213         return compat_copy_grant_refs(xendev, to_domain, segs, nr_segs);
214     }
215 
216     xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
217 
218     for (i = 0; i < nr_segs; i++) {
219         XenGrantCopySegment *seg = &segs[i];
220         xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
221 
222         if (to_domain) {
223             xengnttab_seg->flags = GNTCOPY_dest_gref;
224             xengnttab_seg->dest.foreign.domid = xen_domid;
225             xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
226             xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
227             xengnttab_seg->source.virt = seg->source.virt;
228         } else {
229             xengnttab_seg->flags = GNTCOPY_source_gref;
230             xengnttab_seg->source.foreign.domid = xen_domid;
231             xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
232             xengnttab_seg->source.foreign.offset =
233                 seg->source.foreign.offset;
234             xengnttab_seg->dest.virt = seg->dest.virt;
235         }
236 
237         xengnttab_seg->len = seg->len;
238     }
239 
240     rc = xengnttab_grant_copy(xendev->gnttabdev, nr_segs, xengnttab_segs);
241 
242     if (rc) {
243         xen_pv_printf(xendev, 0, "xengnttab_copy failed: %s\n",
244                       strerror(errno));
245     }
246 
247     for (i = 0; i < nr_segs; i++) {
248         xengnttab_grant_copy_segment_t *xengnttab_seg =
249             &xengnttab_segs[i];
250 
251         if (xengnttab_seg->status != GNTST_okay) {
252             xen_pv_printf(xendev, 0, "segment[%u] status: %d\n", i,
253                           xengnttab_seg->status);
254             rc = -1;
255         }
256     }
257 
258     g_free(xengnttab_segs);
259     return rc;
260 }
261 
262 /*
263  * get xen backend device, allocate a new one if it doesn't exist.
264  */
265 static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom,
266                                                  int dev,
267                                                  struct XenDevOps *ops)
268 {
269     struct XenLegacyDevice *xendev;
270 
271     xendev = xen_pv_find_xendev(type, dom, dev);
272     if (xendev) {
273         return xendev;
274     }
275 
276     /* init new xendev */
277     xendev = g_malloc0(ops->size);
278     object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
279     OBJECT(xendev)->free = g_free;
280     qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
281     qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
282     qdev_init_nofail(DEVICE(xendev));
283     object_unref(OBJECT(xendev));
284 
285     xendev->type  = type;
286     xendev->dom   = dom;
287     xendev->dev   = dev;
288     xendev->ops   = ops;
289 
290     snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
291              xendev->type, xendev->dom, xendev->dev);
292     snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
293              xendev->type, xendev->dev);
294 
295     xendev->debug      = debug;
296     xendev->local_port = -1;
297 
298     xendev->evtchndev = xenevtchn_open(NULL, 0);
299     if (xendev->evtchndev == NULL) {
300         xen_pv_printf(NULL, 0, "can't open evtchn device\n");
301         qdev_unplug(DEVICE(xendev), NULL);
302         return NULL;
303     }
304     qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev));
305 
306     xen_pv_insert_xendev(xendev);
307 
308     if (xendev->ops->alloc) {
309         xendev->ops->alloc(xendev);
310     }
311 
312     return xendev;
313 }
314 
315 
316 /*
317  * Sync internal data structures on xenstore updates.
318  * Node specifies the changed field.  node = NULL means
319  * update all fields (used for initialization).
320  */
321 static void xen_be_backend_changed(struct XenLegacyDevice *xendev,
322                                    const char *node)
323 {
324     if (node == NULL  ||  strcmp(node, "online") == 0) {
325         if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
326             xendev->online = 0;
327         }
328     }
329 
330     if (node) {
331         xen_pv_printf(xendev, 2, "backend update: %s\n", node);
332         if (xendev->ops->backend_changed) {
333             xendev->ops->backend_changed(xendev, node);
334         }
335     }
336 }
337 
338 static void xen_be_frontend_changed(struct XenLegacyDevice *xendev,
339                                     const char *node)
340 {
341     int fe_state;
342 
343     if (node == NULL  ||  strcmp(node, "state") == 0) {
344         if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
345             fe_state = XenbusStateUnknown;
346         }
347         if (xendev->fe_state != fe_state) {
348             xen_pv_printf(xendev, 1, "frontend state: %s -> %s\n",
349                           xenbus_strstate(xendev->fe_state),
350                           xenbus_strstate(fe_state));
351         }
352         xendev->fe_state = fe_state;
353     }
354     if (node == NULL  ||  strcmp(node, "protocol") == 0) {
355         g_free(xendev->protocol);
356         xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
357         if (xendev->protocol) {
358             xen_pv_printf(xendev, 1, "frontend protocol: %s\n",
359                           xendev->protocol);
360         }
361     }
362 
363     if (node) {
364         xen_pv_printf(xendev, 2, "frontend update: %s\n", node);
365         if (xendev->ops->frontend_changed) {
366             xendev->ops->frontend_changed(xendev, node);
367         }
368     }
369 }
370 
371 /* ------------------------------------------------------------- */
372 /* Check for possible state transitions and perform them.        */
373 
374 /*
375  * Initial xendev setup.  Read frontend path, register watch for it.
376  * Should succeed once xend finished setting up the backend device.
377  *
378  * Also sets initial state (-> Initializing) when done.  Which
379  * only affects the xendev->be_state variable as xenbus should
380  * already be put into that state by xend.
381  */
382 static int xen_be_try_setup(struct XenLegacyDevice *xendev)
383 {
384     char token[XEN_BUFSIZE];
385     int be_state;
386 
387     if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
388         xen_pv_printf(xendev, 0, "reading backend state failed\n");
389         return -1;
390     }
391 
392     if (be_state != XenbusStateInitialising) {
393         xen_pv_printf(xendev, 0, "initial backend state is wrong (%s)\n",
394                       xenbus_strstate(be_state));
395         return -1;
396     }
397 
398     xendev->fe = xenstore_read_be_str(xendev, "frontend");
399     if (xendev->fe == NULL) {
400         xen_pv_printf(xendev, 0, "reading frontend path failed\n");
401         return -1;
402     }
403 
404     /* setup frontend watch */
405     snprintf(token, sizeof(token), "fe:%p", xendev);
406     if (!xs_watch(xenstore, xendev->fe, token)) {
407         xen_pv_printf(xendev, 0, "watching frontend path (%s) failed\n",
408                       xendev->fe);
409         return -1;
410     }
411     xen_be_set_state(xendev, XenbusStateInitialising);
412 
413     xen_be_backend_changed(xendev, NULL);
414     xen_be_frontend_changed(xendev, NULL);
415     return 0;
416 }
417 
418 /*
419  * Try initialize xendev.  Prepare everything the backend can do
420  * without synchronizing with the frontend.  Fakes hotplug-status.  No
421  * hotplug involved here because this is about userspace drivers, thus
422  * there are kernel backend devices which could invoke hotplug.
423  *
424  * Goes to InitWait on success.
425  */
426 static int xen_be_try_init(struct XenLegacyDevice *xendev)
427 {
428     int rc = 0;
429 
430     if (!xendev->online) {
431         xen_pv_printf(xendev, 1, "not online\n");
432         return -1;
433     }
434 
435     if (xendev->ops->init) {
436         rc = xendev->ops->init(xendev);
437     }
438     if (rc != 0) {
439         xen_pv_printf(xendev, 1, "init() failed\n");
440         return rc;
441     }
442 
443     xenstore_write_be_str(xendev, "hotplug-status", "connected");
444     xen_be_set_state(xendev, XenbusStateInitWait);
445     return 0;
446 }
447 
448 /*
449  * Try to initialise xendev.  Depends on the frontend being ready
450  * for it (shared ring and evtchn info in xenstore, state being
451  * Initialised or Connected).
452  *
453  * Goes to Connected on success.
454  */
455 static int xen_be_try_initialise(struct XenLegacyDevice *xendev)
456 {
457     int rc = 0;
458 
459     if (xendev->fe_state != XenbusStateInitialised  &&
460         xendev->fe_state != XenbusStateConnected) {
461         if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
462             xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
463         } else {
464             xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
465             return -1;
466         }
467     }
468 
469     if (xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
470         xendev->gnttabdev = xengnttab_open(NULL, 0);
471         if (xendev->gnttabdev == NULL) {
472             xen_pv_printf(NULL, 0, "can't open gnttab device\n");
473             return -1;
474         }
475     } else {
476         xendev->gnttabdev = NULL;
477     }
478 
479     if (xendev->ops->initialise) {
480         rc = xendev->ops->initialise(xendev);
481     }
482     if (rc != 0) {
483         xen_pv_printf(xendev, 0, "initialise() failed\n");
484         return rc;
485     }
486 
487     xen_be_set_state(xendev, XenbusStateConnected);
488     return 0;
489 }
490 
491 /*
492  * Try to let xendev know that it is connected.  Depends on the
493  * frontend being Connected.  Note that this may be called more
494  * than once since the backend state is not modified.
495  */
496 static void xen_be_try_connected(struct XenLegacyDevice *xendev)
497 {
498     if (!xendev->ops->connected) {
499         return;
500     }
501 
502     if (xendev->fe_state != XenbusStateConnected) {
503         if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
504             xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
505         } else {
506             xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
507             return;
508         }
509     }
510 
511     xendev->ops->connected(xendev);
512 }
513 
514 /*
515  * Teardown connection.
516  *
517  * Goes to Closed when done.
518  */
519 static void xen_be_disconnect(struct XenLegacyDevice *xendev,
520                               enum xenbus_state state)
521 {
522     if (xendev->be_state != XenbusStateClosing &&
523         xendev->be_state != XenbusStateClosed  &&
524         xendev->ops->disconnect) {
525         xendev->ops->disconnect(xendev);
526     }
527     if (xendev->gnttabdev) {
528         xengnttab_close(xendev->gnttabdev);
529         xendev->gnttabdev = NULL;
530     }
531     if (xendev->be_state != state) {
532         xen_be_set_state(xendev, state);
533     }
534 }
535 
536 /*
537  * Try to reset xendev, for reconnection by another frontend instance.
538  */
539 static int xen_be_try_reset(struct XenLegacyDevice *xendev)
540 {
541     if (xendev->fe_state != XenbusStateInitialising) {
542         return -1;
543     }
544 
545     xen_pv_printf(xendev, 1, "device reset (for re-connect)\n");
546     xen_be_set_state(xendev, XenbusStateInitialising);
547     return 0;
548 }
549 
550 /*
551  * state change dispatcher function
552  */
553 void xen_be_check_state(struct XenLegacyDevice *xendev)
554 {
555     int rc = 0;
556 
557     /* frontend may request shutdown from almost anywhere */
558     if (xendev->fe_state == XenbusStateClosing ||
559         xendev->fe_state == XenbusStateClosed) {
560         xen_be_disconnect(xendev, xendev->fe_state);
561         return;
562     }
563 
564     /* check for possible backend state transitions */
565     for (;;) {
566         switch (xendev->be_state) {
567         case XenbusStateUnknown:
568             rc = xen_be_try_setup(xendev);
569             break;
570         case XenbusStateInitialising:
571             rc = xen_be_try_init(xendev);
572             break;
573         case XenbusStateInitWait:
574             rc = xen_be_try_initialise(xendev);
575             break;
576         case XenbusStateConnected:
577             /* xendev->be_state doesn't change */
578             xen_be_try_connected(xendev);
579             rc = -1;
580             break;
581         case XenbusStateClosed:
582             rc = xen_be_try_reset(xendev);
583             break;
584         default:
585             rc = -1;
586         }
587         if (rc != 0) {
588             break;
589         }
590     }
591 }
592 
593 /* ------------------------------------------------------------- */
594 
595 static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
596 {
597     struct XenLegacyDevice *xendev;
598     char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
599     char **dev = NULL;
600     unsigned int cdev, j;
601 
602     /* setup watch */
603     snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
604     snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
605     if (!xs_watch(xenstore, path, token)) {
606         xen_pv_printf(NULL, 0, "xen be: watching backend path (%s) failed\n",
607                       path);
608         return -1;
609     }
610 
611     /* look for backends */
612     dev = xs_directory(xenstore, 0, path, &cdev);
613     if (!dev) {
614         return 0;
615     }
616     for (j = 0; j < cdev; j++) {
617         xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
618         if (xendev == NULL) {
619             continue;
620         }
621         xen_be_check_state(xendev);
622     }
623     free(dev);
624     return 0;
625 }
626 
627 void xenstore_update_be(char *watch, char *type, int dom,
628                         struct XenDevOps *ops)
629 {
630     struct XenLegacyDevice *xendev;
631     char path[XEN_BUFSIZE], *bepath;
632     unsigned int len, dev;
633 
634     len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
635     if (strncmp(path, watch, len) != 0) {
636         return;
637     }
638     if (sscanf(watch + len, "/%u/%255s", &dev, path) != 2) {
639         strcpy(path, "");
640         if (sscanf(watch + len, "/%u", &dev) != 1) {
641             dev = -1;
642         }
643     }
644     if (dev == -1) {
645         return;
646     }
647 
648     xendev = xen_be_get_xendev(type, dom, dev, ops);
649     if (xendev != NULL) {
650         bepath = xs_read(xenstore, 0, xendev->be, &len);
651         if (bepath == NULL) {
652             xen_pv_del_xendev(xendev);
653         } else {
654             free(bepath);
655             xen_be_backend_changed(xendev, path);
656             xen_be_check_state(xendev);
657         }
658     }
659 }
660 
661 void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev)
662 {
663     char *node;
664     unsigned int len;
665 
666     len = strlen(xendev->fe);
667     if (strncmp(xendev->fe, watch, len) != 0) {
668         return;
669     }
670     if (watch[len] != '/') {
671         return;
672     }
673     node = watch + len + 1;
674 
675     xen_be_frontend_changed(xendev, node);
676     xen_be_check_state(xendev);
677 }
678 /* -------------------------------------------------------------------- */
679 
680 int xen_be_init(void)
681 {
682     xengnttab_handle *gnttabdev;
683 
684     xenstore = xs_daemon_open();
685     if (!xenstore) {
686         xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
687         return -1;
688     }
689 
690     qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);
691 
692     if (xen_xc == NULL || xen_fmem == NULL) {
693         /* Check if xen_init() have been called */
694         goto err;
695     }
696 
697     gnttabdev = xengnttab_open(NULL, 0);
698     if (gnttabdev != NULL) {
699         if (xengnttab_grant_copy(gnttabdev, 0, NULL) == 0) {
700             xen_feature_grant_copy = true;
701         }
702         xengnttab_close(gnttabdev);
703     }
704 
705     xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
706     qdev_init_nofail(xen_sysdev);
707     xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
708     qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort);
709 
710     return 0;
711 
712 err:
713     qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
714     xs_daemon_close(xenstore);
715     xenstore = NULL;
716 
717     return -1;
718 }
719 
720 static void xen_set_dynamic_sysbus(void)
721 {
722     Object *machine = qdev_get_machine();
723     ObjectClass *oc = object_get_class(machine);
724     MachineClass *mc = MACHINE_CLASS(oc);
725 
726     machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV);
727 }
728 
729 int xen_be_register(const char *type, struct XenDevOps *ops)
730 {
731     char path[50];
732     int rc;
733 
734     if (ops->backend_register) {
735         rc = ops->backend_register();
736         if (rc) {
737             return rc;
738         }
739     }
740 
741     snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
742              type);
743     xenstore_mkdir(path, XS_PERM_NONE);
744 
745     return xenstore_scan(type, xen_domid, ops);
746 }
747 
748 void xen_be_register_common(void)
749 {
750     xen_set_dynamic_sysbus();
751 
752     xen_be_register("console", &xen_console_ops);
753     xen_be_register("vkbd", &xen_kbdmouse_ops);
754 #ifdef CONFIG_VIRTFS
755     xen_be_register("9pfs", &xen_9pfs_ops);
756 #endif
757 #ifdef CONFIG_USB_LIBUSB
758     xen_be_register("qusb", &xen_usb_ops);
759 #endif
760 }
761 
762 int xen_be_bind_evtchn(struct XenLegacyDevice *xendev)
763 {
764     if (xendev->local_port != -1) {
765         return 0;
766     }
767     xendev->local_port = xenevtchn_bind_interdomain
768         (xendev->evtchndev, xendev->dom, xendev->remote_port);
769     if (xendev->local_port == -1) {
770         xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
771         return -1;
772     }
773     xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
774     qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
775                         xen_pv_evtchn_event, NULL, xendev);
776     return 0;
777 }
778 
779 
780 static Property xendev_properties[] = {
781     DEFINE_PROP_END_OF_LIST(),
782 };
783 
784 static void xendev_class_init(ObjectClass *klass, void *data)
785 {
786     DeviceClass *dc = DEVICE_CLASS(klass);
787 
788     dc->props = xendev_properties;
789     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
790     /* xen-backend devices can be plugged/unplugged dynamically */
791     dc->user_creatable = true;
792 }
793 
794 static const TypeInfo xendev_type_info = {
795     .name          = TYPE_XENBACKEND,
796     .parent        = TYPE_XENSYSDEV,
797     .class_init    = xendev_class_init,
798     .instance_size = sizeof(struct XenLegacyDevice),
799 };
800 
801 static void xen_sysbus_class_init(ObjectClass *klass, void *data)
802 {
803     HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
804 
805     hc->unplug = qdev_simple_device_unplug_cb;
806 }
807 
808 static const TypeInfo xensysbus_info = {
809     .name       = TYPE_XENSYSBUS,
810     .parent     = TYPE_BUS,
811     .class_init = xen_sysbus_class_init,
812     .interfaces = (InterfaceInfo[]) {
813         { TYPE_HOTPLUG_HANDLER },
814         { }
815     }
816 };
817 
818 static Property xen_sysdev_properties[] = {
819     {/* end of property list */},
820 };
821 
822 static void xen_sysdev_class_init(ObjectClass *klass, void *data)
823 {
824     DeviceClass *dc = DEVICE_CLASS(klass);
825 
826     dc->props = xen_sysdev_properties;
827     dc->bus_type = TYPE_XENSYSBUS;
828 }
829 
830 static const TypeInfo xensysdev_info = {
831     .name          = TYPE_XENSYSDEV,
832     .parent        = TYPE_SYS_BUS_DEVICE,
833     .instance_size = sizeof(SysBusDevice),
834     .class_init    = xen_sysdev_class_init,
835 };
836 
837 static void xenbe_register_types(void)
838 {
839     type_register_static(&xensysbus_info);
840     type_register_static(&xensysdev_info);
841     type_register_static(&xendev_type_info);
842 }
843 
844 type_init(xenbe_register_types)
845