Statistics
| Branch: | Revision:

root / hw / xen_backend.c @ 57c83dac

History | View | Annotate | Download (21.1 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, 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;
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
    if (0) {
615
        /* FIXME: detect devices being deleted from xenstore ... */
616
        xen_be_del_xendev(dom, dev);
617
    }
618

    
619
    xendev = xen_be_get_xendev(type, dom, dev, ops);
620
    if (xendev != NULL) {
621
        xen_be_backend_changed(xendev, path);
622
        xen_be_check_state(xendev);
623
    }
624
}
625

    
626
static void xenstore_update_fe(char *watch, struct XenDevice *xendev)
627
{
628
    char *node;
629
    unsigned int len;
630

    
631
    len = strlen(xendev->fe);
632
    if (strncmp(xendev->fe, watch, len) != 0) {
633
        return;
634
    }
635
    if (watch[len] != '/') {
636
        return;
637
    }
638
    node = watch + len + 1;
639

    
640
    xen_be_frontend_changed(xendev, node);
641
    xen_be_check_state(xendev);
642
}
643

    
644
static void xenstore_update(void *unused)
645
{
646
    char **vec = NULL;
647
    intptr_t type, ops, ptr;
648
    unsigned int dom, count;
649

    
650
    vec = xs_read_watch(xenstore, &count);
651
    if (vec == NULL) {
652
        goto cleanup;
653
    }
654

    
655
    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
656
               &type, &dom, &ops) == 3) {
657
        xenstore_update_be(vec[XS_WATCH_PATH], (void*)type, dom, (void*)ops);
658
    }
659
    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
660
        xenstore_update_fe(vec[XS_WATCH_PATH], (void*)ptr);
661
    }
662

    
663
cleanup:
664
    free(vec);
665
}
666

    
667
static void xen_be_evtchn_event(void *opaque)
668
{
669
    struct XenDevice *xendev = opaque;
670
    evtchn_port_t port;
671

    
672
    port = xc_evtchn_pending(xendev->evtchndev);
673
    if (port != xendev->local_port) {
674
        xen_be_printf(xendev, 0, "xc_evtchn_pending returned %d (expected %d)\n",
675
                      port, xendev->local_port);
676
        return;
677
    }
678
    xc_evtchn_unmask(xendev->evtchndev, port);
679

    
680
    if (xendev->ops->event) {
681
        xendev->ops->event(xendev);
682
    }
683
}
684

    
685
/* -------------------------------------------------------------------- */
686

    
687
int xen_be_init(void)
688
{
689
    xenstore = xs_daemon_open();
690
    if (!xenstore) {
691
        xen_be_printf(NULL, 0, "can't connect to xenstored\n");
692
        return -1;
693
    }
694

    
695
    if (qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL) < 0) {
696
        goto err;
697
    }
698

    
699
    if (xen_xc == XC_HANDLER_INITIAL_VALUE) {
700
        /* Check if xen_init() have been called */
701
        goto err;
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
int xen_be_register(const char *type, struct XenDevOps *ops)
714
{
715
    return xenstore_scan(type, xen_domid, ops);
716
}
717

    
718
int xen_be_bind_evtchn(struct XenDevice *xendev)
719
{
720
    if (xendev->local_port != -1) {
721
        return 0;
722
    }
723
    xendev->local_port = xc_evtchn_bind_interdomain
724
        (xendev->evtchndev, xendev->dom, xendev->remote_port);
725
    if (xendev->local_port == -1) {
726
        xen_be_printf(xendev, 0, "xc_evtchn_bind_interdomain failed\n");
727
        return -1;
728
    }
729
    xen_be_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
730
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev),
731
                        xen_be_evtchn_event, NULL, xendev);
732
    return 0;
733
}
734

    
735
void xen_be_unbind_evtchn(struct XenDevice *xendev)
736
{
737
    if (xendev->local_port == -1) {
738
        return;
739
    }
740
    qemu_set_fd_handler(xc_evtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
741
    xc_evtchn_unbind(xendev->evtchndev, xendev->local_port);
742
    xen_be_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
743
    xendev->local_port = -1;
744
}
745

    
746
int xen_be_send_notify(struct XenDevice *xendev)
747
{
748
    return xc_evtchn_notify(xendev->evtchndev, xendev->local_port);
749
}
750

    
751
/*
752
 * msg_level:
753
 *  0 == errors (stderr + logfile).
754
 *  1 == informative debug messages (logfile only).
755
 *  2 == noisy debug messages (logfile only).
756
 *  3 == will flood your log (logfile only).
757
 */
758
void xen_be_printf(struct XenDevice *xendev, int msg_level, const char *fmt, ...)
759
{
760
    va_list args;
761

    
762
    if (xendev) {
763
        if (msg_level > xendev->debug) {
764
            return;
765
        }
766
        qemu_log("xen be: %s: ", xendev->name);
767
        if (msg_level == 0) {
768
            fprintf(stderr, "xen be: %s: ", xendev->name);
769
        }
770
    } else {
771
        if (msg_level > debug) {
772
            return;
773
        }
774
        qemu_log("xen be core: ");
775
        if (msg_level == 0) {
776
            fprintf(stderr, "xen be core: ");
777
        }
778
    }
779
    va_start(args, fmt);
780
    qemu_log_vprintf(fmt, args);
781
    va_end(args);
782
    if (msg_level == 0) {
783
        va_start(args, fmt);
784
        vfprintf(stderr, fmt, args);
785
        va_end(args);
786
    }
787
    qemu_log_flush();
788
}