Statistics
| Branch: | Revision:

root / hw / xen_backend.c @ d94f9486

History | View | Annotate | Download (18.5 kB)

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, write to the Free Software Foundation, Inc.,
16
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
 */
18

    
19
/*
20
 * TODO: add some xenbus / xenstore concepts overview here.
21
 */
22

    
23
#include <stdio.h>
24
#include <stdlib.h>
25
#include <stdarg.h>
26
#include <string.h>
27
#include <unistd.h>
28
#include <fcntl.h>
29
#include <inttypes.h>
30
#include <sys/types.h>
31
#include <sys/stat.h>
32
#include <sys/mman.h>
33
#include <sys/signal.h>
34

    
35
#include <xs.h>
36
#include <xenctrl.h>
37
#include <xen/grant_table.h>
38

    
39
#include "hw.h"
40
#include "qemu-char.h"
41
#include "xen_backend.h"
42

    
43
/* ------------------------------------------------------------- */
44

    
45
/* public */
46
int xen_xc;
47
struct xs_handle *xenstore = NULL;
48

    
49
/* private */
50
static TAILQ_HEAD(XenDeviceHead, XenDevice) xendevs = TAILQ_HEAD_INITIALIZER(xendevs);
51
static int debug = 0;
52

    
53
/* ------------------------------------------------------------- */
54

    
55
int xenstore_write_str(const char *base, const char *node, const char *val)
56
{
57
    char abspath[XEN_BUFSIZE];
58

    
59
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
60
    if (!xs_write(xenstore, 0, abspath, val, strlen(val)))
61
        return -1;
62
    return 0;
63
}
64

    
65
char *xenstore_read_str(const char *base, const char *node)
66
{
67
    char abspath[XEN_BUFSIZE];
68
    unsigned int len;
69
    char *str, *ret = NULL;
70

    
71
    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
72
    str = xs_read(xenstore, 0, abspath, &len);
73
    if (str != NULL) {
74
        /* move to qemu-allocated memory to make sure
75
         * callers can savely qemu_free() stuff. */
76
        ret = qemu_strdup(str);
77
        free(str);
78
    }
79
    return ret;
80
}
81

    
82
int xenstore_write_int(const char *base, const char *node, int ival)
83
{
84
    char val[32];
85

    
86
    snprintf(val, sizeof(val), "%d", ival);
87
    return xenstore_write_str(base, node, val);
88
}
89

    
90
int xenstore_read_int(const char *base, const char *node, int *ival)
91
{
92
    char *val;
93
    int rc = -1;
94

    
95
    val = xenstore_read_str(base, node);
96
    if (val && 1 == sscanf(val, "%d", ival))
97
        rc = 0;
98
    qemu_free(val);
99
    return rc;
100
}
101

    
102
int xenstore_write_be_str(struct XenDevice *xendev, const char *node, const char *val)
103
{
104
    return xenstore_write_str(xendev->be, node, val);
105
}
106

    
107
int xenstore_write_be_int(struct XenDevice *xendev, const char *node, int ival)
108
{
109
    return xenstore_write_int(xendev->be, node, ival);
110
}
111

    
112
char *xenstore_read_be_str(struct XenDevice *xendev, const char *node)
113
{
114
    return xenstore_read_str(xendev->be, node);
115
}
116

    
117
int xenstore_read_be_int(struct XenDevice *xendev, const char *node, int *ival)
118
{
119
    return xenstore_read_int(xendev->be, node, ival);
120
}
121

    
122
char *xenstore_read_fe_str(struct XenDevice *xendev, const char *node)
123
{
124
    return xenstore_read_str(xendev->fe, node);
125
}
126

    
127
int xenstore_read_fe_int(struct XenDevice *xendev, const char *node, int *ival)
128
{
129
    return xenstore_read_int(xendev->fe, node, ival);
130
}
131

    
132
/* ------------------------------------------------------------- */
133

    
134
const char *xenbus_strstate(enum xenbus_state state)
135
{
136
        static const char *const name[] = {
137
                [ XenbusStateUnknown      ] = "Unknown",
138
                [ XenbusStateInitialising ] = "Initialising",
139
                [ XenbusStateInitWait     ] = "InitWait",
140
                [ XenbusStateInitialised  ] = "Initialised",
141
                [ XenbusStateConnected    ] = "Connected",
142
                [ XenbusStateClosing      ] = "Closing",
143
                [ XenbusStateClosed          ] = "Closed",
144
        };
145
        return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
146
}
147

    
148
int xen_be_set_state(struct XenDevice *xendev, enum xenbus_state state)
149
{
150
    int rc;
151

    
152
    rc = xenstore_write_be_int(xendev, "state", state);
153
    if (rc < 0)
154
        return rc;
155
    xen_be_printf(xendev, 1, "backend state: %s -> %s\n",
156
                  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
157
    xendev->be_state = state;
158
    return 0;
159
}
160

    
161
/* ------------------------------------------------------------- */
162

    
163
struct XenDevice *xen_be_find_xendev(const char *type, int dom, int dev)
164
{
165
    struct XenDevice *xendev;
166

    
167
    TAILQ_FOREACH(xendev, &xendevs, next) {
168
        if (xendev->dom != dom)
169
            continue;
170
        if (xendev->dev != dev)
171
            continue;
172
        if (strcmp(xendev->type, type) != 0)
173
            continue;
174
        return xendev;
175
    }
176
    return NULL;
177
}
178

    
179
/*
180
 * get xen backend device, allocate a new one if it doesn't exist.
181
 */
182
static struct XenDevice *xen_be_get_xendev(const char *type, int dom, int dev,
183
                                           struct XenDevOps *ops)
184
{
185
    struct XenDevice *xendev;
186
    char *dom0;
187

    
188
    xendev = xen_be_find_xendev(type, dom, dev);
189
    if (xendev)
190
        return xendev;
191

    
192
    /* init new xendev */
193
    xendev = qemu_mallocz(ops->size);
194
    xendev->type  = type;
195
    xendev->dom   = dom;
196
    xendev->dev   = dev;
197
    xendev->ops   = ops;
198

    
199
    dom0 = xs_get_domain_path(xenstore, 0);
200
    snprintf(xendev->be, sizeof(xendev->be), "%s/backend/%s/%d/%d",
201
             dom0, xendev->type, xendev->dom, xendev->dev);
202
    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
203
             xendev->type, xendev->dev);
204
    free(dom0);
205

    
206
    xendev->debug      = debug;
207
    xendev->local_port = -1;
208

    
209
    xendev->evtchndev = xc_evtchn_open();
210
    if (xendev->evtchndev < 0) {
211
        xen_be_printf(NULL, 0, "can't open evtchn device\n");
212
        qemu_free(xendev);
213
        return NULL;
214
    }
215
    fcntl(xc_evtchn_fd(xendev->evtchndev), F_SETFD, FD_CLOEXEC);
216

    
217
    if (ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
218
        xendev->gnttabdev = xc_gnttab_open();
219
        if (xendev->gnttabdev < 0) {
220
            xen_be_printf(NULL, 0, "can't open gnttab device\n");
221
            xc_evtchn_close(xendev->evtchndev);
222
            qemu_free(xendev);
223
            return NULL;
224
        }
225
    } else {
226
        xendev->gnttabdev = -1;
227
    }
228

    
229
    TAILQ_INSERT_TAIL(&xendevs, xendev, next);
230

    
231
    if (xendev->ops->alloc)
232
        xendev->ops->alloc(xendev);
233

    
234
    return xendev;
235
}
236

    
237
/*
238
 * release xen backend device.
239
 */
240
static struct XenDevice *xen_be_del_xendev(int dom, int dev)
241
{
242
    struct XenDevice *xendev, *xnext;
243

    
244
    /*
245
     * This is pretty much like TAILQ_FOREACH(xendev, &xendevs, next) but
246
     * we save the next pointer in xnext because we might free xendev.
247
     */
248
    xnext = xendevs.tqh_first;
249
    while (xnext) {
250
        xendev = xnext;
251
        xnext = xendev->next.tqe_next;
252

    
253
        if (xendev->dom != dom)
254
            continue;
255
        if (xendev->dev != dev && dev != -1)
256
            continue;
257

    
258
        if (xendev->ops->free)
259
            xendev->ops->free(xendev);
260

    
261
        if (xendev->fe) {
262
            char token[XEN_BUFSIZE];
263
            snprintf(token, sizeof(token), "fe:%p", xendev);
264
            xs_unwatch(xenstore, xendev->fe, token);
265
            qemu_free(xendev->fe);
266
        }
267

    
268
        if (xendev->evtchndev >= 0)
269
            xc_evtchn_close(xendev->evtchndev);
270
        if (xendev->gnttabdev >= 0)
271
            xc_gnttab_close(xendev->gnttabdev);
272

    
273
        TAILQ_REMOVE(&xendevs, xendev, next);
274
        qemu_free(xendev);
275
    }
276
    return NULL;
277
}
278

    
279
/*
280
 * Sync internal data structures on xenstore updates.
281
 * Node specifies the changed field.  node = NULL means
282
 * update all fields (used for initialization).
283
 */
284
static void xen_be_backend_changed(struct XenDevice *xendev, const char *node)
285
{
286
    if (node == NULL  ||  strcmp(node, "online") == 0) {
287
        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1)
288
            xendev->online = 0;
289
    }
290

    
291
    if (node) {
292
        xen_be_printf(xendev, 2, "backend update: %s\n", node);
293
        if (xendev->ops->backend_changed)
294
            xendev->ops->backend_changed(xendev, node);
295
    }
296
}
297

    
298
static void xen_be_frontend_changed(struct XenDevice *xendev, const char *node)
299
{
300
    int fe_state;
301

    
302
    if (node == NULL  ||  strcmp(node, "state") == 0) {
303
        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1)
304
            fe_state = XenbusStateUnknown;
305
        if (xendev->fe_state != fe_state)
306
            xen_be_printf(xendev, 1, "frontend state: %s -> %s\n",
307
                          xenbus_strstate(xendev->fe_state),
308
                          xenbus_strstate(fe_state));
309
        xendev->fe_state = fe_state;
310
    }
311
    if (node == NULL  ||  strcmp(node, "protocol") == 0) {
312
        qemu_free(xendev->protocol);
313
        xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
314
        if (xendev->protocol)
315
            xen_be_printf(xendev, 1, "frontend protocol: %s\n", xendev->protocol);
316
    }
317

    
318
    if (node) {
319
        xen_be_printf(xendev, 2, "frontend update: %s\n", node);
320
        if (xendev->ops->frontend_changed)
321
            xendev->ops->frontend_changed(xendev, node);
322
    }
323
}
324

    
325
/* ------------------------------------------------------------- */
326
/* Check for possible state transitions and perform them.        */
327

    
328
/*
329
 * Initial xendev setup.  Read frontend path, register watch for it.
330
 * Should succeed once xend finished setting up the backend device.
331
 *
332
 * Also sets initial state (-> Initializing) when done.  Which
333
 * only affects the xendev->be_state variable as xenbus should
334
 * already be put into that state by xend.
335
 */
336
static int xen_be_try_setup(struct XenDevice *xendev)
337
{
338
    char token[XEN_BUFSIZE];
339
    int be_state;
340

    
341
    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
342
        xen_be_printf(xendev, 0, "reading backend state failed\n");
343
        return -1;
344
    }
345

    
346
    if (be_state != XenbusStateInitialising) {
347
        xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
348
                      xenbus_strstate(be_state));
349
        return -1;
350
    }
351

    
352
    xendev->fe = xenstore_read_be_str(xendev, "frontend");
353
    if (xendev->fe == NULL) {
354
        xen_be_printf(xendev, 0, "reading frontend path failed\n");
355
        return -1;
356
    }
357

    
358
    /* setup frontend watch */
359
    snprintf(token, sizeof(token), "fe:%p", xendev);
360
    if (!xs_watch(xenstore, xendev->fe, token)) {
361
        xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
362
                      xendev->fe);
363
        return -1;
364
    }
365
    xen_be_set_state(xendev, XenbusStateInitialising);
366

    
367
    xen_be_backend_changed(xendev, NULL);
368
    xen_be_frontend_changed(xendev, NULL);
369
    return 0;
370
}
371

    
372
/*
373
 * Try initialize xendev.  Prepare everything the backend can do
374
 * without synchronizing with the frontend.  Fakes hotplug-status.  No
375
 * hotplug involved here because this is about userspace drivers, thus
376
 * there are kernel backend devices which could invoke hotplug.
377
 *
378
 * Goes to InitWait on success.
379
 */
380
static int xen_be_try_init(struct XenDevice *xendev)
381
{
382
    int rc = 0;
383

    
384
    if (!xendev->online) {
385
        xen_be_printf(xendev, 1, "not online\n");
386
        return -1;
387
    }
388

    
389
    if (xendev->ops->init)
390
        rc = xendev->ops->init(xendev);
391
    if (rc != 0) {
392
        xen_be_printf(xendev, 1, "init() failed\n");
393
        return rc;
394
    }
395

    
396
    xenstore_write_be_str(xendev, "hotplug-status", "connected");
397
    xen_be_set_state(xendev, XenbusStateInitWait);
398
    return 0;
399
}
400

    
401
/*
402
 * Try to connect xendev.  Depends on the frontend being ready
403
 * for it (shared ring and evtchn info in xenstore, state being
404
 * Initialised or Connected).
405
 *
406
 * Goes to Connected on success.
407
 */
408
static int xen_be_try_connect(struct XenDevice *xendev)
409
{
410
    int rc = 0;
411

    
412
    if (xendev->fe_state != XenbusStateInitialised  &&
413
        xendev->fe_state != XenbusStateConnected) {
414
        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
415
            xen_be_printf(xendev, 2, "frontend not ready, ignoring\n");
416
        } else {
417
            xen_be_printf(xendev, 2, "frontend not ready (yet)\n");
418
            return -1;
419
        }
420
    }
421

    
422
    if (xendev->ops->connect)
423
        rc = xendev->ops->connect(xendev);
424
    if (rc != 0) {
425
        xen_be_printf(xendev, 0, "connect() failed\n");
426
        return rc;
427
    }
428

    
429
    xen_be_set_state(xendev, XenbusStateConnected);
430
    return 0;
431
}
432

    
433
/*
434
 * Teardown connection.
435
 *
436
 * Goes to Closed when done.
437
 */
438
static void xen_be_disconnect(struct XenDevice *xendev, enum xenbus_state state)
439
{
440
    if (xendev->be_state != XenbusStateClosing &&
441
        xendev->be_state != XenbusStateClosed  &&
442
        xendev->ops->disconnect)
443
        xendev->ops->disconnect(xendev);
444
    if (xendev->be_state != state)
445
        xen_be_set_state(xendev, state);
446
}
447

    
448
/*
449
 * Try to reset xendev, for reconnection by another frontend instance.
450
 */
451
static int xen_be_try_reset(struct XenDevice *xendev)
452
{
453
    if (xendev->fe_state != XenbusStateInitialising)
454
        return -1;
455

    
456
    xen_be_printf(xendev, 1, "device reset (for re-connect)\n");
457
    xen_be_set_state(xendev, XenbusStateInitialising);
458
    return 0;
459
}
460

    
461
/*
462
 * state change dispatcher function
463
 */
464
void xen_be_check_state(struct XenDevice *xendev)
465
{
466
    int rc = 0;
467

    
468
    /* frontend may request shutdown from almost anywhere */
469
    if (xendev->fe_state == XenbusStateClosing ||
470
        xendev->fe_state == XenbusStateClosed) {
471
        xen_be_disconnect(xendev, xendev->fe_state);
472
        return;
473
    }
474

    
475
    /* check for possible backend state transitions */
476
    for (;;) {
477
        switch (xendev->be_state) {
478
        case XenbusStateUnknown:
479
            rc = xen_be_try_setup(xendev);
480
            break;
481
        case XenbusStateInitialising:
482
            rc = xen_be_try_init(xendev);
483
            break;
484
        case XenbusStateInitWait:
485
            rc = xen_be_try_connect(xendev);
486
            break;
487
        case XenbusStateClosed:
488
            rc = xen_be_try_reset(xendev);
489
            break;
490
        default:
491
            rc = -1;
492
        }
493
        if (rc != 0)
494
            break;
495
    }
496
}
497

    
498
/* ------------------------------------------------------------- */
499

    
500
static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
501
{
502
    struct XenDevice *xendev;
503
    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
504
    char **dev = NULL, *dom0;
505
    unsigned int cdev, j;
506

    
507
    /* setup watch */
508
    dom0 = xs_get_domain_path(xenstore, 0);
509
    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
510
    snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
511
    free(dom0);
512
    if (!xs_watch(xenstore, path, token)) {
513
        xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
514
        return -1;
515
    }
516

    
517
    /* look for backends */
518
    dev = xs_directory(xenstore, 0, path, &cdev);
519
    if (!dev)
520
        return 0;
521
    for (j = 0; j < cdev; j++) {
522
        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
523
        if (xendev == NULL)
524
            continue;
525
        xen_be_check_state(xendev);
526
    }
527
    free(dev);
528
    return 0;
529
}
530

    
531
static void xenstore_update_be(char *watch, char *type, int dom,
532
                               struct XenDevOps *ops)
533
{
534
    struct XenDevice *xendev;
535
    char path[XEN_BUFSIZE], *dom0;
536
    unsigned int len, dev;
537

    
538
    dom0 = xs_get_domain_path(xenstore, 0);
539
    len = snprintf(path, sizeof(path), "%s/backend/%s/%d", dom0, type, dom);
540
    free(dom0);
541
    if (strncmp(path, watch, len) != 0)
542
        return;
543
    if (sscanf(watch+len, "/%u/%255s", &dev, path) != 2) {
544
        strcpy(path, "");
545
        if (sscanf(watch+len, "/%u", &dev) != 1)
546
            dev = -1;
547
    }
548
    if (dev == -1)
549
        return;
550

    
551
    if (0) {
552
        /* FIXME: detect devices being deleted from xenstore ... */
553
        xen_be_del_xendev(dom, dev);
554
    }
555

    
556
    xendev = xen_be_get_xendev(type, dom, dev, ops);
557
    if (xendev != NULL) {
558
        xen_be_backend_changed(xendev, path);
559
        xen_be_check_state(xendev);
560
    }
561
}
562

    
563
static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
564
{
565
    char *node;
566
    unsigned int len;
567

    
568
    len = strlen(xendev->fe);
569
    if (strncmp(xendev->fe, watch, len) != 0)
570
        return;
571
    if (watch[len] != '/')
572
        return;
573
    node = watch + len + 1;
574

    
575
    xen_be_frontend_changed(xendev, node);
576
    xen_be_check_state(xendev);
577
}
578

    
579
static void xenstore_update(void *unused)
580
{
581
    char **vec = NULL;
582
    intptr_t type, ops, ptr;
583
    unsigned int dom, count;
584

    
585
    vec = xs_read_watch(xenstore, &count);
586
    if (vec == NULL)
587
        goto cleanup;
588

    
589
    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
590
               &type, &dom, &ops) == 3)
591
        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
592
    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1)
593
        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
594

    
595
cleanup:
596
    qemu_free(vec);
597
}
598

    
599
static void xen_be_evtchn_event(void *opaque)
600
{
601
    struct XenDevice *xendev = opaque;
602
    evtchn_port_t port;
603

    
604
    port = xc_evtchn_pending(xendev->evtchndev);
605
    if (port != xendev->local_port) {
606
        xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
607
                      port, xendev->local_port);
608
        return;
609
    }
610
    xc_evtchn_unmask(xendev->evtchndev, port);
611

    
612
    if (xendev->ops->event)
613
        xendev->ops->event(xendev);
614
}
615

    
616
/* -------------------------------------------------------------------- */
617

    
618
int xen_be_init(void)
619
{
620
    xenstore = xs_daemon_open();
621
    if (!xenstore) {
622
        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
623
        return -1;
624
    }
625

    
626
    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
627
        goto err;
628

    
629
    xen_xc = xc_interface_open();
630
    if (xen_xc == -1) {
631
        xen_be_printf(NULL, 0, "can't open xen interface\n");
632
        goto err;
633
    }
634
    return 0;
635

    
636
err:
637
    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
638
    xs_daemon_close(xenstore);
639
    xenstore = NULL;
640

    
641
    return -1;
642
}
643

    
644
int xen_be_register(const char *type, struct XenDevOps *ops)
645
{
646
    return xenstore_scan(type, xen_domid, ops);
647
}
648

    
649
int xen_be_bind_evtchn(struct XenDevice *xendev)
650
{
651
    if (xendev->local_port != -1)
652
        return 0;
653
    xendev->local_port = xc_evtchn_bind_interdomain
654
        (xendev->evtchndev, xendev->dom, xendev->remote_port);
655
    if (xendev->local_port == -1) {
656
        xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
657
        return -1;
658
    }
659
    xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
660
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
661
                        xen_be_evtchn_event, NULL, xendev);
662
    return 0;
663
}
664

    
665
void xen_be_unbind_evtchn(struct XenDevice *xendev)
666
{
667
    if (xendev->local_port == -1)
668
        return;
669
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
670
    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
671
    xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
672
    xendev->local_port = -1;
673
}
674

    
675
int xen_be_send_notify(struct XenDevice *xendev)
676
{
677
    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
678
}
679

    
680
/*
681
 * msg_level:
682
 *  0 == errors (stderr + logfile).
683
 *  1 == informative debug messages (logfile only).
684
 *  2 == noisy debug messages (logfile only).
685
 *  3 == will flood your log (logfile only).
686
 */
687
void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
688
{
689
    va_list args;
690

    
691
    if (xendev) {
692
        if (msg_level > xendev->debug)
693
            return;
694
        qemu_log("xen be: %s: ", xendev->name);
695
        if (msg_level == 0)
696
            fprintf(stderr, "xen be: %s: ", xendev->name);
697
    } else {
698
        if (msg_level > debug)
699
            return;
700
        qemu_log("xen be core: ");
701
        if (msg_level == 0)
702
            fprintf(stderr, "xen be core: ");
703
    }
704
    va_start(args, fmt);
705
    qemu_log_vprintf(fmt, args);
706
    va_end(args);
707
    if (msg_level == 0) {
708
        va_start(args, fmt);
709
        vfprintf(stderr, fmt, args);
710
        va_end(args);
711
    }
712
    qemu_log_flush();
713
}