xref: /openbmc/qemu/hw/xen/xen-legacy-backend.c (revision 354908ce)
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_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
282     qdev_realize(DEVICE(xendev), xen_sysbus, &error_fatal);
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_new(TYPE_XENSYSDEV);
706     sysbus_realize_and_unref(SYS_BUS_DEVICE(xen_sysdev), &error_fatal);
707     xen_sysbus = qbus_create(TYPE_XENSYSBUS, 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     device_class_set_props(dc, 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     device_class_set_props(dc, 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