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