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