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