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