qemu/hw/xen/xen-legacy-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 "qemu/osdep.h"
  26#include <sys/signal.h>
  27
  28#include "hw/hw.h"
  29#include "hw/sysbus.h"
  30#include "hw/boards.h"
  31#include "qemu/log.h"
  32#include "qapi/error.h"
  33#include "hw/xen/xen-legacy-backend.h"
  34#include "hw/xen/xen_pvdev.h"
  35#include "monitor/qdev.h"
  36
  37#include <xen/grant_table.h>
  38
  39DeviceState *xen_sysdev;
  40BusState *xen_sysbus;
  41
  42/* ------------------------------------------------------------- */
  43
  44/* public */
  45struct xs_handle *xenstore;
  46const char *xen_protocol;
  47
  48/* private */
  49static bool xen_feature_grant_copy;
  50static int debug;
  51
  52int xenstore_write_be_str(struct XenLegacyDevice *xendev, const char *node,
  53                          const char *val)
  54{
  55    return xenstore_write_str(xendev->be, node, val);
  56}
  57
  58int xenstore_write_be_int(struct XenLegacyDevice *xendev, const char *node,
  59                          int ival)
  60{
  61    return xenstore_write_int(xendev->be, node, ival);
  62}
  63
  64int xenstore_write_be_int64(struct XenLegacyDevice *xendev, const char *node,
  65                            int64_t ival)
  66{
  67    return xenstore_write_int64(xendev->be, node, ival);
  68}
  69
  70char *xenstore_read_be_str(struct XenLegacyDevice *xendev, const char *node)
  71{
  72    return xenstore_read_str(xendev->be, node);
  73}
  74
  75int xenstore_read_be_int(struct XenLegacyDevice *xendev, const char *node,
  76                         int *ival)
  77{
  78    return xenstore_read_int(xendev->be, node, ival);
  79}
  80
  81char *xenstore_read_fe_str(struct XenLegacyDevice *xendev, const char *node)
  82{
  83    return xenstore_read_str(xendev->fe, node);
  84}
  85
  86int xenstore_read_fe_int(struct XenLegacyDevice *xendev, const char *node,
  87                         int *ival)
  88{
  89    return xenstore_read_int(xendev->fe, node, ival);
  90}
  91
  92int xenstore_read_fe_uint64(struct XenLegacyDevice *xendev, const char *node,
  93                            uint64_t *uval)
  94{
  95    return xenstore_read_uint64(xendev->fe, node, uval);
  96}
  97
  98/* ------------------------------------------------------------- */
  99
 100int xen_be_set_state(struct XenLegacyDevice *xendev, enum xenbus_state state)
 101{
 102    int rc;
 103
 104    rc = xenstore_write_be_int(xendev, "state", state);
 105    if (rc < 0) {
 106        return rc;
 107    }
 108    xen_pv_printf(xendev, 1, "backend state: %s -> %s\n",
 109                  xenbus_strstate(xendev->be_state), xenbus_strstate(state));
 110    xendev->be_state = state;
 111    return 0;
 112}
 113
 114void xen_be_set_max_grant_refs(struct XenLegacyDevice *xendev,
 115                               unsigned int nr_refs)
 116{
 117    assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
 118
 119    if (xengnttab_set_max_grants(xendev->gnttabdev, nr_refs)) {
 120        xen_pv_printf(xendev, 0, "xengnttab_set_max_grants failed: %s\n",
 121                      strerror(errno));
 122    }
 123}
 124
 125void *xen_be_map_grant_refs(struct XenLegacyDevice *xendev, uint32_t *refs,
 126                            unsigned int nr_refs, int prot)
 127{
 128    void *ptr;
 129
 130    assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
 131
 132    ptr = xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_refs,
 133                                          xen_domid, refs, prot);
 134    if (!ptr) {
 135        xen_pv_printf(xendev, 0,
 136                      "xengnttab_map_domain_grant_refs failed: %s\n",
 137                      strerror(errno));
 138    }
 139
 140    return ptr;
 141}
 142
 143void xen_be_unmap_grant_refs(struct XenLegacyDevice *xendev, void *ptr,
 144                             unsigned int nr_refs)
 145{
 146    assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
 147
 148    if (xengnttab_unmap(xendev->gnttabdev, ptr, nr_refs)) {
 149        xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
 150                      strerror(errno));
 151    }
 152}
 153
 154static int compat_copy_grant_refs(struct XenLegacyDevice *xendev,
 155                                  bool to_domain,
 156                                  XenGrantCopySegment segs[],
 157                                  unsigned int nr_segs)
 158{
 159    uint32_t *refs = g_new(uint32_t, nr_segs);
 160    int prot = to_domain ? PROT_WRITE : PROT_READ;
 161    void *pages;
 162    unsigned int i;
 163
 164    for (i = 0; i < nr_segs; i++) {
 165        XenGrantCopySegment *seg = &segs[i];
 166
 167        refs[i] = to_domain ?
 168            seg->dest.foreign.ref : seg->source.foreign.ref;
 169    }
 170
 171    pages = xengnttab_map_domain_grant_refs(xendev->gnttabdev, nr_segs,
 172                                            xen_domid, refs, prot);
 173    if (!pages) {
 174        xen_pv_printf(xendev, 0,
 175                      "xengnttab_map_domain_grant_refs failed: %s\n",
 176                      strerror(errno));
 177        g_free(refs);
 178        return -1;
 179    }
 180
 181    for (i = 0; i < nr_segs; i++) {
 182        XenGrantCopySegment *seg = &segs[i];
 183        void *page = pages + (i * XC_PAGE_SIZE);
 184
 185        if (to_domain) {
 186            memcpy(page + seg->dest.foreign.offset, seg->source.virt,
 187                   seg->len);
 188        } else {
 189            memcpy(seg->dest.virt, page + seg->source.foreign.offset,
 190                   seg->len);
 191        }
 192    }
 193
 194    if (xengnttab_unmap(xendev->gnttabdev, pages, nr_segs)) {
 195        xen_pv_printf(xendev, 0, "xengnttab_unmap failed: %s\n",
 196                      strerror(errno));
 197    }
 198
 199    g_free(refs);
 200    return 0;
 201}
 202
 203int xen_be_copy_grant_refs(struct XenLegacyDevice *xendev,
 204                           bool to_domain,
 205                           XenGrantCopySegment segs[],
 206                           unsigned int nr_segs)
 207{
 208    xengnttab_grant_copy_segment_t *xengnttab_segs;
 209    unsigned int i;
 210    int rc;
 211
 212    assert(xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV);
 213
 214    if (!xen_feature_grant_copy) {
 215        return compat_copy_grant_refs(xendev, to_domain, segs, nr_segs);
 216    }
 217
 218    xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
 219
 220    for (i = 0; i < nr_segs; i++) {
 221        XenGrantCopySegment *seg = &segs[i];
 222        xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
 223
 224        if (to_domain) {
 225            xengnttab_seg->flags = GNTCOPY_dest_gref;
 226            xengnttab_seg->dest.foreign.domid = xen_domid;
 227            xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
 228            xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
 229            xengnttab_seg->source.virt = seg->source.virt;
 230        } else {
 231            xengnttab_seg->flags = GNTCOPY_source_gref;
 232            xengnttab_seg->source.foreign.domid = xen_domid;
 233            xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
 234            xengnttab_seg->source.foreign.offset =
 235                seg->source.foreign.offset;
 236            xengnttab_seg->dest.virt = seg->dest.virt;
 237        }
 238
 239        xengnttab_seg->len = seg->len;
 240    }
 241
 242    rc = xengnttab_grant_copy(xendev->gnttabdev, nr_segs, xengnttab_segs);
 243
 244    if (rc) {
 245        xen_pv_printf(xendev, 0, "xengnttab_copy failed: %s\n",
 246                      strerror(errno));
 247    }
 248
 249    for (i = 0; i < nr_segs; i++) {
 250        xengnttab_grant_copy_segment_t *xengnttab_seg =
 251            &xengnttab_segs[i];
 252
 253        if (xengnttab_seg->status != GNTST_okay) {
 254            xen_pv_printf(xendev, 0, "segment[%u] status: %d\n", i,
 255                          xengnttab_seg->status);
 256            rc = -1;
 257        }
 258    }
 259
 260    g_free(xengnttab_segs);
 261    return rc;
 262}
 263
 264/*
 265 * get xen backend device, allocate a new one if it doesn't exist.
 266 */
 267static struct XenLegacyDevice *xen_be_get_xendev(const char *type, int dom,
 268                                                 int dev,
 269                                                 struct XenDevOps *ops)
 270{
 271    struct XenLegacyDevice *xendev;
 272
 273    xendev = xen_pv_find_xendev(type, dom, dev);
 274    if (xendev) {
 275        return xendev;
 276    }
 277
 278    /* init new xendev */
 279    xendev = g_malloc0(ops->size);
 280    object_initialize(&xendev->qdev, ops->size, TYPE_XENBACKEND);
 281    OBJECT(xendev)->free = g_free;
 282    qdev_set_parent_bus(DEVICE(xendev), xen_sysbus);
 283    qdev_set_id(DEVICE(xendev), g_strdup_printf("xen-%s-%d", type, dev));
 284    qdev_init_nofail(DEVICE(xendev));
 285    object_unref(OBJECT(xendev));
 286
 287    xendev->type  = type;
 288    xendev->dom   = dom;
 289    xendev->dev   = dev;
 290    xendev->ops   = ops;
 291
 292    snprintf(xendev->be, sizeof(xendev->be), "backend/%s/%d/%d",
 293             xendev->type, xendev->dom, xendev->dev);
 294    snprintf(xendev->name, sizeof(xendev->name), "%s-%d",
 295             xendev->type, xendev->dev);
 296
 297    xendev->debug      = debug;
 298    xendev->local_port = -1;
 299
 300    xendev->evtchndev = xenevtchn_open(NULL, 0);
 301    if (xendev->evtchndev == NULL) {
 302        xen_pv_printf(NULL, 0, "can't open evtchn device\n");
 303        qdev_unplug(DEVICE(xendev), NULL);
 304        return NULL;
 305    }
 306    qemu_set_cloexec(xenevtchn_fd(xendev->evtchndev));
 307
 308    xen_pv_insert_xendev(xendev);
 309
 310    if (xendev->ops->alloc) {
 311        xendev->ops->alloc(xendev);
 312    }
 313
 314    return xendev;
 315}
 316
 317
 318/*
 319 * Sync internal data structures on xenstore updates.
 320 * Node specifies the changed field.  node = NULL means
 321 * update all fields (used for initialization).
 322 */
 323static void xen_be_backend_changed(struct XenLegacyDevice *xendev,
 324                                   const char *node)
 325{
 326    if (node == NULL  ||  strcmp(node, "online") == 0) {
 327        if (xenstore_read_be_int(xendev, "online", &xendev->online) == -1) {
 328            xendev->online = 0;
 329        }
 330    }
 331
 332    if (node) {
 333        xen_pv_printf(xendev, 2, "backend update: %s\n", node);
 334        if (xendev->ops->backend_changed) {
 335            xendev->ops->backend_changed(xendev, node);
 336        }
 337    }
 338}
 339
 340static void xen_be_frontend_changed(struct XenLegacyDevice *xendev,
 341                                    const char *node)
 342{
 343    int fe_state;
 344
 345    if (node == NULL  ||  strcmp(node, "state") == 0) {
 346        if (xenstore_read_fe_int(xendev, "state", &fe_state) == -1) {
 347            fe_state = XenbusStateUnknown;
 348        }
 349        if (xendev->fe_state != fe_state) {
 350            xen_pv_printf(xendev, 1, "frontend state: %s -> %s\n",
 351                          xenbus_strstate(xendev->fe_state),
 352                          xenbus_strstate(fe_state));
 353        }
 354        xendev->fe_state = fe_state;
 355    }
 356    if (node == NULL  ||  strcmp(node, "protocol") == 0) {
 357        g_free(xendev->protocol);
 358        xendev->protocol = xenstore_read_fe_str(xendev, "protocol");
 359        if (xendev->protocol) {
 360            xen_pv_printf(xendev, 1, "frontend protocol: %s\n",
 361                          xendev->protocol);
 362        }
 363    }
 364
 365    if (node) {
 366        xen_pv_printf(xendev, 2, "frontend update: %s\n", node);
 367        if (xendev->ops->frontend_changed) {
 368            xendev->ops->frontend_changed(xendev, node);
 369        }
 370    }
 371}
 372
 373/* ------------------------------------------------------------- */
 374/* Check for possible state transitions and perform them.        */
 375
 376/*
 377 * Initial xendev setup.  Read frontend path, register watch for it.
 378 * Should succeed once xend finished setting up the backend device.
 379 *
 380 * Also sets initial state (-> Initializing) when done.  Which
 381 * only affects the xendev->be_state variable as xenbus should
 382 * already be put into that state by xend.
 383 */
 384static int xen_be_try_setup(struct XenLegacyDevice *xendev)
 385{
 386    char token[XEN_BUFSIZE];
 387    int be_state;
 388
 389    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
 390        xen_pv_printf(xendev, 0, "reading backend state failed\n");
 391        return -1;
 392    }
 393
 394    if (be_state != XenbusStateInitialising) {
 395        xen_pv_printf(xendev, 0, "initial backend state is wrong (%s)\n",
 396                      xenbus_strstate(be_state));
 397        return -1;
 398    }
 399
 400    xendev->fe = xenstore_read_be_str(xendev, "frontend");
 401    if (xendev->fe == NULL) {
 402        xen_pv_printf(xendev, 0, "reading frontend path failed\n");
 403        return -1;
 404    }
 405
 406    /* setup frontend watch */
 407    snprintf(token, sizeof(token), "fe:%p", xendev);
 408    if (!xs_watch(xenstore, xendev->fe, token)) {
 409        xen_pv_printf(xendev, 0, "watching frontend path (%s) failed\n",
 410                      xendev->fe);
 411        return -1;
 412    }
 413    xen_be_set_state(xendev, XenbusStateInitialising);
 414
 415    xen_be_backend_changed(xendev, NULL);
 416    xen_be_frontend_changed(xendev, NULL);
 417    return 0;
 418}
 419
 420/*
 421 * Try initialize xendev.  Prepare everything the backend can do
 422 * without synchronizing with the frontend.  Fakes hotplug-status.  No
 423 * hotplug involved here because this is about userspace drivers, thus
 424 * there are kernel backend devices which could invoke hotplug.
 425 *
 426 * Goes to InitWait on success.
 427 */
 428static int xen_be_try_init(struct XenLegacyDevice *xendev)
 429{
 430    int rc = 0;
 431
 432    if (!xendev->online) {
 433        xen_pv_printf(xendev, 1, "not online\n");
 434        return -1;
 435    }
 436
 437    if (xendev->ops->init) {
 438        rc = xendev->ops->init(xendev);
 439    }
 440    if (rc != 0) {
 441        xen_pv_printf(xendev, 1, "init() failed\n");
 442        return rc;
 443    }
 444
 445    xenstore_write_be_str(xendev, "hotplug-status", "connected");
 446    xen_be_set_state(xendev, XenbusStateInitWait);
 447    return 0;
 448}
 449
 450/*
 451 * Try to initialise xendev.  Depends on the frontend being ready
 452 * for it (shared ring and evtchn info in xenstore, state being
 453 * Initialised or Connected).
 454 *
 455 * Goes to Connected on success.
 456 */
 457static int xen_be_try_initialise(struct XenLegacyDevice *xendev)
 458{
 459    int rc = 0;
 460
 461    if (xendev->fe_state != XenbusStateInitialised  &&
 462        xendev->fe_state != XenbusStateConnected) {
 463        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
 464            xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
 465        } else {
 466            xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
 467            return -1;
 468        }
 469    }
 470
 471    if (xendev->ops->flags & DEVOPS_FLAG_NEED_GNTDEV) {
 472        xendev->gnttabdev = xengnttab_open(NULL, 0);
 473        if (xendev->gnttabdev == NULL) {
 474            xen_pv_printf(NULL, 0, "can't open gnttab device\n");
 475            return -1;
 476        }
 477    } else {
 478        xendev->gnttabdev = NULL;
 479    }
 480
 481    if (xendev->ops->initialise) {
 482        rc = xendev->ops->initialise(xendev);
 483    }
 484    if (rc != 0) {
 485        xen_pv_printf(xendev, 0, "initialise() failed\n");
 486        return rc;
 487    }
 488
 489    xen_be_set_state(xendev, XenbusStateConnected);
 490    return 0;
 491}
 492
 493/*
 494 * Try to let xendev know that it is connected.  Depends on the
 495 * frontend being Connected.  Note that this may be called more
 496 * than once since the backend state is not modified.
 497 */
 498static void xen_be_try_connected(struct XenLegacyDevice *xendev)
 499{
 500    if (!xendev->ops->connected) {
 501        return;
 502    }
 503
 504    if (xendev->fe_state != XenbusStateConnected) {
 505        if (xendev->ops->flags & DEVOPS_FLAG_IGNORE_STATE) {
 506            xen_pv_printf(xendev, 2, "frontend not ready, ignoring\n");
 507        } else {
 508            xen_pv_printf(xendev, 2, "frontend not ready (yet)\n");
 509            return;
 510        }
 511    }
 512
 513    xendev->ops->connected(xendev);
 514}
 515
 516/*
 517 * Teardown connection.
 518 *
 519 * Goes to Closed when done.
 520 */
 521static void xen_be_disconnect(struct XenLegacyDevice *xendev,
 522                              enum xenbus_state state)
 523{
 524    if (xendev->be_state != XenbusStateClosing &&
 525        xendev->be_state != XenbusStateClosed  &&
 526        xendev->ops->disconnect) {
 527        xendev->ops->disconnect(xendev);
 528    }
 529    if (xendev->gnttabdev) {
 530        xengnttab_close(xendev->gnttabdev);
 531        xendev->gnttabdev = NULL;
 532    }
 533    if (xendev->be_state != state) {
 534        xen_be_set_state(xendev, state);
 535    }
 536}
 537
 538/*
 539 * Try to reset xendev, for reconnection by another frontend instance.
 540 */
 541static int xen_be_try_reset(struct XenLegacyDevice *xendev)
 542{
 543    if (xendev->fe_state != XenbusStateInitialising) {
 544        return -1;
 545    }
 546
 547    xen_pv_printf(xendev, 1, "device reset (for re-connect)\n");
 548    xen_be_set_state(xendev, XenbusStateInitialising);
 549    return 0;
 550}
 551
 552/*
 553 * state change dispatcher function
 554 */
 555void xen_be_check_state(struct XenLegacyDevice *xendev)
 556{
 557    int rc = 0;
 558
 559    /* frontend may request shutdown from almost anywhere */
 560    if (xendev->fe_state == XenbusStateClosing ||
 561        xendev->fe_state == XenbusStateClosed) {
 562        xen_be_disconnect(xendev, xendev->fe_state);
 563        return;
 564    }
 565
 566    /* check for possible backend state transitions */
 567    for (;;) {
 568        switch (xendev->be_state) {
 569        case XenbusStateUnknown:
 570            rc = xen_be_try_setup(xendev);
 571            break;
 572        case XenbusStateInitialising:
 573            rc = xen_be_try_init(xendev);
 574            break;
 575        case XenbusStateInitWait:
 576            rc = xen_be_try_initialise(xendev);
 577            break;
 578        case XenbusStateConnected:
 579            /* xendev->be_state doesn't change */
 580            xen_be_try_connected(xendev);
 581            rc = -1;
 582            break;
 583        case XenbusStateClosed:
 584            rc = xen_be_try_reset(xendev);
 585            break;
 586        default:
 587            rc = -1;
 588        }
 589        if (rc != 0) {
 590            break;
 591        }
 592    }
 593}
 594
 595/* ------------------------------------------------------------- */
 596
 597static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
 598{
 599    struct XenLegacyDevice *xendev;
 600    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
 601    char **dev = NULL;
 602    unsigned int cdev, j;
 603
 604    /* setup watch */
 605    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
 606    snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
 607    if (!xs_watch(xenstore, path, token)) {
 608        xen_pv_printf(NULL, 0, "xen be: watching backend path (%s) failed\n",
 609                      path);
 610        return -1;
 611    }
 612
 613    /* look for backends */
 614    dev = xs_directory(xenstore, 0, path, &cdev);
 615    if (!dev) {
 616        return 0;
 617    }
 618    for (j = 0; j < cdev; j++) {
 619        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
 620        if (xendev == NULL) {
 621            continue;
 622        }
 623        xen_be_check_state(xendev);
 624    }
 625    free(dev);
 626    return 0;
 627}
 628
 629void xenstore_update_be(char *watch, char *type, int dom,
 630                        struct XenDevOps *ops)
 631{
 632    struct XenLegacyDevice *xendev;
 633    char path[XEN_BUFSIZE], *bepath;
 634    unsigned int len, dev;
 635
 636    len = snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
 637    if (strncmp(path, watch, len) != 0) {
 638        return;
 639    }
 640    if (sscanf(watch + len, "/%u/%255s", &dev, path) != 2) {
 641        strcpy(path, "");
 642        if (sscanf(watch + len, "/%u", &dev) != 1) {
 643            dev = -1;
 644        }
 645    }
 646    if (dev == -1) {
 647        return;
 648    }
 649
 650    xendev = xen_be_get_xendev(type, dom, dev, ops);
 651    if (xendev != NULL) {
 652        bepath = xs_read(xenstore, 0, xendev->be, &len);
 653        if (bepath == NULL) {
 654            xen_pv_del_xendev(xendev);
 655        } else {
 656            free(bepath);
 657            xen_be_backend_changed(xendev, path);
 658            xen_be_check_state(xendev);
 659        }
 660    }
 661}
 662
 663void xenstore_update_fe(char *watch, struct XenLegacyDevice *xendev)
 664{
 665    char *node;
 666    unsigned int len;
 667
 668    len = strlen(xendev->fe);
 669    if (strncmp(xendev->fe, watch, len) != 0) {
 670        return;
 671    }
 672    if (watch[len] != '/') {
 673        return;
 674    }
 675    node = watch + len + 1;
 676
 677    xen_be_frontend_changed(xendev, node);
 678    xen_be_check_state(xendev);
 679}
 680/* -------------------------------------------------------------------- */
 681
 682int xen_be_init(void)
 683{
 684    xengnttab_handle *gnttabdev;
 685
 686    xenstore = xs_daemon_open();
 687    if (!xenstore) {
 688        xen_pv_printf(NULL, 0, "can't connect to xenstored\n");
 689        return -1;
 690    }
 691
 692    qemu_set_fd_handler(xs_fileno(xenstore), xenstore_update, NULL, NULL);
 693
 694    if (xen_xc == NULL || xen_fmem == NULL) {
 695        /* Check if xen_init() have been called */
 696        goto err;
 697    }
 698
 699    gnttabdev = xengnttab_open(NULL, 0);
 700    if (gnttabdev != NULL) {
 701        if (xengnttab_grant_copy(gnttabdev, 0, NULL) == 0) {
 702            xen_feature_grant_copy = true;
 703        }
 704        xengnttab_close(gnttabdev);
 705    }
 706
 707    xen_sysdev = qdev_create(NULL, TYPE_XENSYSDEV);
 708    qdev_init_nofail(xen_sysdev);
 709    xen_sysbus = qbus_create(TYPE_XENSYSBUS, DEVICE(xen_sysdev), "xen-sysbus");
 710    qbus_set_bus_hotplug_handler(xen_sysbus, &error_abort);
 711
 712    return 0;
 713
 714err:
 715    qemu_set_fd_handler(xs_fileno(xenstore), NULL, NULL, NULL);
 716    xs_daemon_close(xenstore);
 717    xenstore = NULL;
 718
 719    return -1;
 720}
 721
 722static void xen_set_dynamic_sysbus(void)
 723{
 724    Object *machine = qdev_get_machine();
 725    ObjectClass *oc = object_get_class(machine);
 726    MachineClass *mc = MACHINE_CLASS(oc);
 727
 728    machine_class_allow_dynamic_sysbus_dev(mc, TYPE_XENSYSDEV);
 729}
 730
 731int xen_be_register(const char *type, struct XenDevOps *ops)
 732{
 733    char path[50];
 734    int rc;
 735
 736    if (ops->backend_register) {
 737        rc = ops->backend_register();
 738        if (rc) {
 739            return rc;
 740        }
 741    }
 742
 743    snprintf(path, sizeof(path), "device-model/%u/backends/%s", xen_domid,
 744             type);
 745    xenstore_mkdir(path, XS_PERM_NONE);
 746
 747    return xenstore_scan(type, xen_domid, ops);
 748}
 749
 750void xen_be_register_common(void)
 751{
 752    xen_set_dynamic_sysbus();
 753
 754    xen_be_register("console", &xen_console_ops);
 755    xen_be_register("vkbd", &xen_kbdmouse_ops);
 756#ifdef CONFIG_VIRTFS
 757    xen_be_register("9pfs", &xen_9pfs_ops);
 758#endif
 759#ifdef CONFIG_USB_LIBUSB
 760    xen_be_register("qusb", &xen_usb_ops);
 761#endif
 762}
 763
 764int xen_be_bind_evtchn(struct XenLegacyDevice *xendev)
 765{
 766    if (xendev->local_port != -1) {
 767        return 0;
 768    }
 769    xendev->local_port = xenevtchn_bind_interdomain
 770        (xendev->evtchndev, xendev->dom, xendev->remote_port);
 771    if (xendev->local_port == -1) {
 772        xen_pv_printf(xendev, 0, "xenevtchn_bind_interdomain failed\n");
 773        return -1;
 774    }
 775    xen_pv_printf(xendev, 2, "bind evtchn port %d\n", xendev->local_port);
 776    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev),
 777                        xen_pv_evtchn_event, NULL, xendev);
 778    return 0;
 779}
 780
 781
 782static Property xendev_properties[] = {
 783    DEFINE_PROP_END_OF_LIST(),
 784};
 785
 786static void xendev_class_init(ObjectClass *klass, void *data)
 787{
 788    DeviceClass *dc = DEVICE_CLASS(klass);
 789
 790    dc->props = xendev_properties;
 791    set_bit(DEVICE_CATEGORY_MISC, dc->categories);
 792    /* xen-backend devices can be plugged/unplugged dynamically */
 793    dc->user_creatable = true;
 794}
 795
 796static const TypeInfo xendev_type_info = {
 797    .name          = TYPE_XENBACKEND,
 798    .parent        = TYPE_XENSYSDEV,
 799    .class_init    = xendev_class_init,
 800    .instance_size = sizeof(struct XenLegacyDevice),
 801};
 802
 803static void xen_sysbus_class_init(ObjectClass *klass, void *data)
 804{
 805    HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(klass);
 806
 807    hc->unplug = qdev_simple_device_unplug_cb;
 808}
 809
 810static const TypeInfo xensysbus_info = {
 811    .name       = TYPE_XENSYSBUS,
 812    .parent     = TYPE_BUS,
 813    .class_init = xen_sysbus_class_init,
 814    .interfaces = (InterfaceInfo[]) {
 815        { TYPE_HOTPLUG_HANDLER },
 816        { }
 817    }
 818};
 819
 820static Property xen_sysdev_properties[] = {
 821    {/* end of property list */},
 822};
 823
 824static void xen_sysdev_class_init(ObjectClass *klass, void *data)
 825{
 826    DeviceClass *dc = DEVICE_CLASS(klass);
 827
 828    dc->props = xen_sysdev_properties;
 829    dc->bus_type = TYPE_XENSYSBUS;
 830}
 831
 832static const TypeInfo xensysdev_info = {
 833    .name          = TYPE_XENSYSDEV,
 834    .parent        = TYPE_SYS_BUS_DEVICE,
 835    .instance_size = sizeof(SysBusDevice),
 836    .class_init    = xen_sysdev_class_init,
 837};
 838
 839static void xenbe_register_types(void)
 840{
 841    type_register_static(&xensysbus_info);
 842    type_register_static(&xensysdev_info);
 843    type_register_static(&xendev_type_info);
 844}
 845
 846type_init(xenbe_register_types)
 847