]> Git Repo - qemu.git/blob - hw/xen_backend.c
Merge remote-tracking branch 'sstabellini/for_anthony' into staging
[qemu.git] / hw / 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 <stdio.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28 #include <string.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <inttypes.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <sys/mman.h>
35 #include <sys/signal.h>
36
37 #include <xs.h>
38 #include <xenctrl.h>
39 #include <xen/grant_table.h>
40
41 #include "hw.h"
42 #include "qemu-char.h"
43 #include "qemu-log.h"
44 #include "xen_backend.h"
45
46 /* ------------------------------------------------------------- */
47
48 /* public */
49 XenXC xen_xc = XC_HANDLER_INITIAL_VALUE;
50 XenGnttab xen_xcg = XC_HANDLER_INITIAL_VALUE;
51 struct xs_handle *xenstore = NULL;
52 const char *xen_protocol;
53
54 /* private */
55 static QTAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = QTAILQ_HEAD_INITIALIZER(xendevs);
56 static int debug = 0;
57
58 /* ------------------------------------------------------------- */
59
60 int xenstore_write_str(const char *base, const char *node, const char *val)
61 {
62     char abspath[XEN_BUFSIZE];
63
64     snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
65     if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
66         return -1;
67     }
68     return 0;
69 }
70
71 char *xenstore_read_str(const char *base, const char *node)
72 {
73     char abspath[XEN_BUFSIZE];
74     unsigned int len;
75     char *str, *ret = NULL;
76
77     snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
78     str = xs_read(xenstore, 0, abspath, &len);
79     if (str != NULL) {
80         /* move to qemu-allocated memory to make sure
81          * callers can savely g_free() stuff. */
82         ret = g_strdup(str);
83         free(str);
84     }
85     return ret;
86 }
87
88 int xenstore_write_int(const char *base, const char *node, int ival)
89 {
90     char val[32];
91
92     snprintf(val, sizeof(val), "%d", ival);
93     return xenstore_write_str(base, node, val);
94 }
95
96 int xenstore_read_int(const char *base, const char *node, int *ival)
97 {
98     char *val;
99     int rc = -1;
100
101     val = xenstore_read_str(base, node);
102     if (val && 1 == sscanf(val, "%d", ival)) {
103         rc = 0;
104     }
105     g_free(val);
106     return rc;
107 }
108
109 int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
110 {
111     return xenstore_write_str(xendev->be, node, val);
112 }
113
114 int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
115 {
116     return xenstore_write_int(xendev->be, node, ival);
117 }
118
119 char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
120 {
121     return xenstore_read_str(xendev->be, node);
122 }
123
124 int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
125 {
126     return xenstore_read_int(xendev->be, node, ival);
127 }
128
129 char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
130 {
131     return xenstore_read_str(xendev->fe, node);
132 }
133
134 int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
135 {
136     return xenstore_read_int(xendev->fe, node, ival);
137 }
138
139 /* ------------------------------------------------------------- */
140
141 const char *xenbus_strstate(enum xenbus_state state)
142 {
143     static const char *const name[] = {
144         [ XenbusStateUnknown      ] = "Unknown",
145         [ XenbusStateInitialising ] = "Initialising",
146         [ XenbusStateInitWait     ] = "InitWait",
147         [ XenbusStateInitialised  ] = "Initialised",
148         [ XenbusStateConnected    ] = "Connected",
149         [ XenbusStateClosing      ] = "Closing",
150         [ XenbusStateClosed       ] = "Closed",
151     };
152     return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
153 }
154
155 int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
156 {
157     int rc;
158
159     rc = xenstore_write_be_int(xendev, "state", state);
160     if (rc < 0) {
161         return rc;
162     }
163     xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
164                   xenbus_strstate(xendev->be_state), xenbus_strstate(state));
165     xendev->be_state = state;
166     return 0;
167 }
168
169 /* ------------------------------------------------------------- */
170
171 struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
172 {
173     struct XenDevice *xendev;
174
175     QTAILQ_FOREACH(xendev, &xendevs, next) {
176         if (xendev->dom != dom) {
177             continue;
178         }
179         if (xendev->dev != dev) {
180             continue;
181         }
182         if (strcmp(xendev->type, type) != 0) {
183             continue;
184         }
185         return xendev;
186     }
187     return NULL;
188 }
189
190 /*
191  * get xen backend device, allocate a new one if it doesn't exist.
192  */
193 static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
194                                            struct XenDevOps *ops)
195 {
196     struct XenDevice *xendev;
197     char *dom0;
198
199     xendev = xen_be_find_xendev(type, dom, dev);
200     if (xendev) {
201         return xendev;
202     }
203
204     /* init new xendev */
205     xendev = g_malloc0(ops->size);
206     xendev->type  = type;
207     xendev->dom   = dom;
208     xendev->dev   = dev;
209     xendev->ops   = ops;
210
211     dom0 = xs_get_domain_path(xenstore, 0);
212     snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
213              dom0, xendev->type, xendev->dom, xendev->dev);
214     snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
215              xendev->type, xendev->dev);
216     free(dom0);
217
218     xendev->debug      = debug;
219     xendev->local_port = -1;
220
221     xendev->evtchndev = xen_xc_evtchn_open(NULL, 0);
222     if (xendev->evtchndev == XC_HANDLER_INITIAL_VALUE) {
223         xen_be_printf(NULL, 0, "can't open evtchn device\n");
224         g_free(xendev);
225         return NULL;
226     }
227     fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
228
229     if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
230         xendev->gnttabdev = xen_xc_gnttab_open(NULL, 0);
231         if (xendev->gnttabdev == XC_HANDLER_INITIAL_VALUE) {
232             xen_be_printf(NULL, 0, "can't open gnttab device\n");
233             xc_evtchn_close(xendev->evtchndev);
234             g_free(xendev);
235             return NULL;
236         }
237     } else {
238         xendev->gnttabdev = XC_HANDLER_INITIAL_VALUE;
239     }
240
241     QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
242
243     if (xendev->ops->alloc) {
244         xendev->ops->alloc(xendev);
245     }
246
247     return xendev;
248 }
249
250 /*
251  * release xen backend device.
252  */
253 static struct XenDevice *xen_be_del_xendev(int dom, int dev)
254 {
255     struct XenDevice *xendev, *xnext;
256
257     /*
258      * This is pretty much like QTAILQ_FOREACH(xendev, &xendevs, next) but
259      * we save the next pointer in xnext because we might free xendev.
260      */
261     xnext = xendevs.tqh_first;
262     while (xnext) {
263         xendev = xnext;
264         xnext = xendev->next.tqe_next;
265
266         if (xendev->dom != dom) {
267             continue;
268         }
269         if (xendev->dev != dev && dev != -1) {
270             continue;
271         }
272
273         if (xendev->ops->free) {
274             xendev->ops->free(xendev);
275         }
276
277         if (xendev->fe) {
278             char token[XEN_BUFSIZE];
279             snprintf(token, sizeof(token), "fe:%p", xendev);
280             xs_unwatch(xenstore, xendev->fe, token);
281             g_free(xendev->fe);
282         }
283
284         if (xendev->evtchndev != XC_HANDLER_INITIAL_VALUE) {
285             xc_evtchn_close(xendev->evtchndev);
286         }
287         if (xendev->gnttabdev != XC_HANDLER_INITIAL_VALUE) {
288             xc_gnttab_close(xendev->gnttabdev);
289         }
290
291         QTAILQ_REMOVE(&xendevs, xendev, next);
292         g_free(xendev);
293     }
294     return NULL;
295 }
296
297 /*
298  * Sync internal data structures on xenstore updates.
299  * Node specifies the changed field.  node = NULL means
300  * update all fields (used for initialization).
301  */
302 static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
303 {
304     if (node == NULL  ||  strcmp(node, "online") == 0) {
305         if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
306             xendev->online = 0;
307         }
308     }
309
310     if (node) {
311         xen_be_printf(xendev, 2, "backend update: %s\n", node);
312         if (xendev->ops->backend_changed) {
313             xendev->ops->backend_changed(xendev, node);
314         }
315     }
316 }
317
318 static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
319 {
320     int fe_state;
321
322     if (node == NULL  ||  strcmp(node, "state") == 0) {
323         if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
324             fe_state = XenbusStateUnknown;
325         }
326         if (xendev->fe_state != fe_state) {
327             xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
328                           xenbus_strstate(xendev->fe_state),
329                           xenbus_strstate(fe_state));
330         }
331         xendev->fe_state = fe_state;
332     }
333     if (node == NULL  ||  strcmp(node, "protocol") == 0) {
334         g_free(xendev->protocol);
335         xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
336         if (xendev->protocol) {
337             xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
338         }
339     }
340
341     if (node) {
342         xen_be_printf(xendev, 2, "frontend update: %s\n", node);
343         if (xendev->ops->frontend_changed) {
344             xendev->ops->frontend_changed(xendev, node);
345         }
346     }
347 }
348
349 /* ------------------------------------------------------------- */
350 /* Check for possible state transitions and perform them.        */
351
352 /*
353  * Initial xendev setup.  Read frontend path, register watch for it.
354  * Should succeed once xend finished setting up the backend device.
355  *
356  * Also sets initial state (-> Initializing) when done.  Which
357  * only affects the xendev->be_state variable as xenbus should
358  * already be put into that state by xend.
359  */
360 static int xen_be_try_setup(struct XenDevice *xendev)
361 {
362     char token[XEN_BUFSIZE];
363     int be_state;
364
365     if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
366         xen_be_printf(xendev, 0, "reading backend state failed\n");
367         return -1;
368     }
369
370     if (be_state != XenbusStateInitialising) {
371         xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
372                       xenbus_strstate(be_state));
373         return -1;
374     }
375
376     xendev->fe = xenstore_read_be_str(xendev, "frontend");
377     if (xendev->fe == NULL) {
378         xen_be_printf(xendev, 0, "reading frontend path failed\n");
379         return -1;
380     }
381
382     /* setup frontend watch */
383     snprintf(token, sizeof(token), "fe:%p", xendev);
384     if (!xs_watch(xenstore, xendev->fe, token)) {
385         xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
386                       xendev->fe);
387         return -1;
388     }
389     xen_be_set_state(xendev, XenbusStateInitialising);
390
391     xen_be_backend_changed(xendev, NULL);
392     xen_be_frontend_changed(xendev, NULL);
393     return 0;
394 }
395
396 /*
397  * Try initialize xendev.  Prepare everything the backend can do
398  * without synchronizing with the frontend.  Fakes hotplug-status.  No
399  * hotplug involved here because this is about userspace drivers, thus
400  * there are kernel backend devices which could invoke hotplug.
401  *
402  * Goes to InitWait on success.
403  */
404 static int xen_be_try_init(struct XenDevice *xendev)
405 {
406     int rc = 0;
407
408     if (!xendev->online) {
409         xen_be_printf(xendev, 1, "not online\n");
410         return -1;
411     }
412
413     if (xendev->ops->init) {
414         rc = xendev->ops->init(xendev);
415     }
416     if (rc != 0) {
417         xen_be_printf(xendev, 1, "init() failed\n");
418         return rc;
419     }
420
421     xenstore_write_be_str(xendev, "hotplug-status", "connected");
422     xen_be_set_state(xendev, XenbusStateInitWait);
423     return 0;
424 }
425
426 /*
427  * Try to initialise xendev.  Depends on the frontend being ready
428  * for it (shared ring and evtchn info in xenstore, state being
429  * Initialised or Connected).
430  *
431  * Goes to Connected on success.
432  */
433 static int xen_be_try_initialise(struct XenDevice *xendev)
434 {
435     int rc = 0;
436
437     if (xendev->fe_state != XenbusStateInitialised  &&
438         xendev->fe_state != XenbusStateConnected) {
439         if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
440             xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
441         } else {
442             xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
443             return -1;
444         }
445     }
446
447     if (xendev->ops->initialise) {
448         rc = xendev->ops->initialise(xendev);
449     }
450     if (rc != 0) {
451         xen_be_printf(xendev, 0, "initialise() failed\n");
452         return rc;
453     }
454
455     xen_be_set_state(xendev, XenbusStateConnected);
456     return 0;
457 }
458
459 /*
460  * Try to let xendev know that it is connected.  Depends on the
461  * frontend being Connected.  Note that this may be called more
462  * than once since the backend state is not modified.
463  */
464 static void xen_be_try_connected(struct XenDevice *xendev)
465 {
466     if (!xendev->ops->connected) {
467         return;
468     }
469
470     if (xendev->fe_state != XenbusStateConnected) {
471         if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
472             xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
473         } else {
474             xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
475             return;
476         }
477     }
478
479     xendev->ops->connected(xendev);
480 }
481
482 /*
483  * Teardown connection.
484  *
485  * Goes to Closed when done.
486  */
487 static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
488 {
489     if (xendev->be_state != XenbusStateClosing &&
490         xendev->be_state != XenbusStateClosed  &&
491         xendev->ops->disconnect) {
492         xendev->ops->disconnect(xendev);
493     }
494     if (xendev->be_state != state) {
495         xen_be_set_state(xendev, state);
496     }
497 }
498
499 /*
500  * Try to reset xendev, for reconnection by another frontend instance.
501  */
502 static int xen_be_try_reset(struct XenDevice *xendev)
503 {
504     if (xendev->fe_state != XenbusStateInitialising) {
505         return -1;
506     }
507
508     xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
509     xen_be_set_state(xendev, XenbusStateInitialising);
510     return 0;
511 }
512
513 /*
514  * state change dispatcher function
515  */
516 void xen_be_check_state(struct XenDevice *xendev)
517 {
518     int rc = 0;
519
520     /* frontend may request shutdown from almost anywhere */
521     if (xendev->fe_state == XenbusStateClosing ||
522         xendev->fe_state == XenbusStateClosed) {
523         xen_be_disconnect(xendev, xendev->fe_state);
524         return;
525     }
526
527     /* check for possible backend state transitions */
528     for (;;) {
529         switch (xendev->be_state) {
530         case XenbusStateUnknown:
531             rc = xen_be_try_setup(xendev);
532             break;
533         case XenbusStateInitialising:
534             rc = xen_be_try_init(xendev);
535             break;
536         case XenbusStateInitWait:
537             rc = xen_be_try_initialise(xendev);
538             break;
539         case XenbusStateConnected:
540             /* xendev->be_state doesn't change */
541             xen_be_try_connected(xendev);
542             rc = -1;
543             break;
544         case XenbusStateClosed:
545             rc = xen_be_try_reset(xendev);
546             break;
547         default:
548             rc = -1;
549         }
550         if (rc != 0) {
551             break;
552         }
553     }
554 }
555
556 /* ------------------------------------------------------------- */
557
558 static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
559 {
560     struct XenDevice *xendev;
561     char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
562     char **dev = NULL, *dom0;
563     unsigned int cdev, j;
564
565     /* setup watch */
566     dom0 = xs_get_domain_path(xenstore, 0);
567     snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
568     snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
569     free(dom0);
570     if (!xs_watch(xenstore, path, token)) {
571         xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
572         return -1;
573     }
574
575     /* look for backends */
576     dev = xs_directory(xenstore, 0, path, &cdev);
577     if (!dev) {
578         return 0;
579     }
580     for (j = 0; j < cdev; j++) {
581         xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
582         if (xendev == NULL) {
583             continue;
584         }
585         xen_be_check_state(xendev);
586     }
587     free(dev);
588     return 0;
589 }
590
591 static void xenstore_update_be(char *watch, char *type, int dom,
592                                struct XenDevOps *ops)
593 {
594     struct XenDevice *xendev;
595     char path[XEN_BUFSIZE], *dom0, *bepath;
596     unsigned int len, dev;
597
598     dom0 = xs_get_domain_path(xenstore, 0);
599     len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
600     free(dom0);
601     if (strncmp(path, watch, len) != 0) {
602         return;
603     }
604     if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
605         strcpy(path, "");
606         if (sscanf(watch+len, "/%u", &dev) != 1) {
607             dev = -1;
608         }
609     }
610     if (dev == -1) {
611         return;
612     }
613
614     xendev = xen_be_get_xendev(type, dom, dev, ops);
615     if (xendev != NULL) {
616         bepath = xs_read(xenstore, 0, xendev->be, &len);
617         if (bepath == NULL) {
618             xen_be_del_xendev(dom, dev);
619         } else {
620             free(bepath);
621             xen_be_backend_changed(xendev, path);
622             xen_be_check_state(xendev);
623         }
624     }
625 }
626
627 static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
628 {
629     char *node;
630     unsigned int len;
631
632     len = strlen(xendev->fe);
633     if (strncmp(xendev->fe, watch, len) != 0) {
634         return;
635     }
636     if (watch[len] != '/') {
637         return;
638     }
639     node = watch + len + 1;
640
641     xen_be_frontend_changed(xendev, node);
642     xen_be_check_state(xendev);
643 }
644
645 static void xenstore_update(void *unused)
646 {
647     char **vec = NULL;
648     intptr_t type, ops, ptr;
649     unsigned int dom, count;
650
651     vec = xs_read_watch(xenstore, &count);
652     if (vec == NULL) {
653         goto cleanup;
654     }
655
656     if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
657                &type, &dom, &ops) == 3) {
658         xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
659     }
660     if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
661         xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
662     }
663
664 cleanup:
665     free(vec);
666 }
667
668 static void xen_be_evtchn_event(void *opaque)
669 {
670     struct XenDevice *xendev = opaque;
671     evtchn_port_t port;
672
673     port = xc_evtchn_pending(xendev->evtchndev);
674     if (port != xendev->local_port) {
675         xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
676                       port, xendev->local_port);
677         return;
678     }
679     xc_evtchn_unmask(xendev->evtchndev, port);
680
681     if (xendev->ops->event) {
682         xendev->ops->event(xendev);
683     }
684 }
685
686 /* -------------------------------------------------------------------- */
687
688 int xen_be_init(void)
689 {
690     xenstore = xs_daemon_open();
691     if (!xenstore) {
692         xen_be_printf(NULL, 0, "can't connect to xenstored\n");
693         return -1;
694     }
695
696     if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
697         goto err;
698     }
699
700     if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
701         /* Check if xen_init() have been called */
702         goto err;
703     }
704     return 0;
705
706 err:
707     qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
708     xs_daemon_close(xenstore);
709     xenstore = NULL;
710
711     return -1;
712 }
713
714 int xen_be_register(const char *type, struct XenDevOps *ops)
715 {
716     return xenstore_scan(type, xen_domid, ops);
717 }
718
719 int xen_be_bind_evtchn(struct XenDevice *xendev)
720 {
721     if (xendev->local_port != -1) {
722         return 0;
723     }
724     xendev->local_port = xc_evtchn_bind_interdomain
725         (xendev->evtchndev, xendev->dom, xendev->remote_port);
726     if (xendev->local_port == -1) {
727         xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
728         return -1;
729     }
730     xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
731     qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
732                         xen_be_evtchn_event, NULL, xendev);
733     return 0;
734 }
735
736 void xen_be_unbind_evtchn(struct XenDevice *xendev)
737 {
738     if (xendev->local_port == -1) {
739         return;
740     }
741     qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
742     xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
743     xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
744     xendev->local_port = -1;
745 }
746
747 int xen_be_send_notify(struct XenDevice *xendev)
748 {
749     return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
750 }
751
752 /*
753  * msg_level:
754  *  0 == errors (stderr + logfile).
755  *  1 == informative debug messages (logfile only).
756  *  2 == noisy debug messages (logfile only).
757  *  3 == will flood your log (logfile only).
758  */
759 void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
760 {
761     va_list args;
762
763     if (xendev) {
764         if (msg_level > xendev->debug) {
765             return;
766         }
767         qemu_log("xen be: %s: ", xendev->name);
768         if (msg_level == 0) {
769             fprintf(stderr, "xen be: %s: ", xendev->name);
770         }
771     } else {
772         if (msg_level > debug) {
773             return;
774         }
775         qemu_log("xen be core: ");
776         if (msg_level == 0) {
777             fprintf(stderr, "xen be core: ");
778         }
779     }
780     va_start(args, fmt);
781     qemu_log_vprintf(fmt, args);
782     va_end(args);
783     if (msg_level == 0) {
784         va_start(args, fmt);
785         vfprintf(stderr, fmt, args);
786         va_end(args);
787     }
788     qemu_log_flush();
789 }
This page took 0.067807 seconds and 4 git commands to generate.