Statistics
| Branch: | Revision:

root / hw / xen_backend.c @ cae4956e

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 "qemu-log.h"
42
#include "xen_backend.h"
43

    
44
/* ------------------------------------------------------------- */
45

    
46
/* public */
47
int xen_xc;
48
struct xs_handle *xenstore = NULL;
49
const char *xen_protocol;
50

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

    
55
/* ------------------------------------------------------------- */
56

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
134
/* ------------------------------------------------------------- */
135

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

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

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

    
163
/* ------------------------------------------------------------- */
164

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

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

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

    
190
    xendev = xen_be_find_xendev(type, dom, dev);
191
    if (xendev)
192
        return xendev;
193

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

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

    
208
    xendev->debug      = debug;
209
    xendev->local_port = -1;
210

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

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

    
231
    TAILQ_INSERT_TAIL(&xendevs, xendev, next);
232

    
233
    if (xendev->ops->alloc)
234
        xendev->ops->alloc(xendev);
235

    
236
    return xendev;
237
}
238

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

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

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

    
260
        if (xendev->ops->free)
261
            xendev->ops->free(xendev);
262

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

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

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

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

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

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

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

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

    
327
/* ------------------------------------------------------------- */
328
/* Check for possible state transitions and perform them.        */
329

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

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

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

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

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

    
369
    xen_be_backend_changed(xendev, NULL);
370
    xen_be_frontend_changed(xendev, NULL);
371
    return 0;
372
}
373

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

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

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

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

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

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

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

    
431
    xen_be_set_state(xendev, XenbusStateConnected);
432
    return 0;
433
}
434

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

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

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

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

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

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

    
500
/* ------------------------------------------------------------- */
501

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

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

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

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

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

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

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

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

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

    
577
    xen_be_frontend_changed(xendev, node);
578
    xen_be_check_state(xendev);
579
}
580

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

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

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

    
597
cleanup:
598
    qemu_free(vec);
599
}
600

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

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

    
614
    if (xendev->ops->event)
615
        xendev->ops->event(xendev);
616
}
617

    
618
/* -------------------------------------------------------------------- */
619

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

    
628
    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0)
629
        goto err;
630

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

    
638
err:
639
    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
640
    xs_daemon_close(xenstore);
641
    xenstore = NULL;
642

    
643
    return -1;
644
}
645

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

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

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

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

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

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