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