qemu/hw/xen/xen-bus.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2018  Citrix Systems Inc.
   3 *
   4 * This work is licensed under the terms of the GNU GPL, version 2 or later.
   5 * See the COPYING file in the top-level directory.
   6 */
   7
   8#include "qemu/osdep.h"
   9#include "qemu/main-loop.h"
  10#include "qemu/module.h"
  11#include "qemu/uuid.h"
  12#include "hw/hw.h"
  13#include "hw/sysbus.h"
  14#include "hw/xen/xen.h"
  15#include "hw/xen/xen-backend.h"
  16#include "hw/xen/xen-bus.h"
  17#include "hw/xen/xen-bus-helper.h"
  18#include "monitor/monitor.h"
  19#include "qapi/error.h"
  20#include "qapi/qmp/qdict.h"
  21#include "sysemu/sysemu.h"
  22#include "trace.h"
  23
  24static char *xen_device_get_backend_path(XenDevice *xendev)
  25{
  26    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
  27    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
  28    const char *type = object_get_typename(OBJECT(xendev));
  29    const char *backend = xendev_class->backend;
  30
  31    if (!backend) {
  32        backend = type;
  33    }
  34
  35    return g_strdup_printf("/local/domain/%u/backend/%s/%u/%s",
  36                           xenbus->backend_id, backend, xendev->frontend_id,
  37                           xendev->name);
  38}
  39
  40static char *xen_device_get_frontend_path(XenDevice *xendev)
  41{
  42    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
  43    const char *type = object_get_typename(OBJECT(xendev));
  44    const char *device = xendev_class->device;
  45
  46    if (!device) {
  47        device = type;
  48    }
  49
  50    return g_strdup_printf("/local/domain/%u/device/%s/%s",
  51                           xendev->frontend_id, device, xendev->name);
  52}
  53
  54static void xen_device_unplug(XenDevice *xendev, Error **errp)
  55{
  56    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
  57    const char *type = object_get_typename(OBJECT(xendev));
  58    Error *local_err = NULL;
  59    xs_transaction_t tid;
  60
  61    trace_xen_device_unplug(type, xendev->name);
  62
  63    /* Mimic the way the Xen toolstack does an unplug */
  64again:
  65    tid = xs_transaction_start(xenbus->xsh);
  66    if (tid == XBT_NULL) {
  67        error_setg_errno(errp, errno, "failed xs_transaction_start");
  68        return;
  69    }
  70
  71    xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "online",
  72                   &local_err, "%u", 0);
  73    if (local_err) {
  74        goto abort;
  75    }
  76
  77    xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
  78                   &local_err, "%u", XenbusStateClosing);
  79    if (local_err) {
  80        goto abort;
  81    }
  82
  83    if (!xs_transaction_end(xenbus->xsh, tid, false)) {
  84        if (errno == EAGAIN) {
  85            goto again;
  86        }
  87
  88        error_setg_errno(errp, errno, "failed xs_transaction_end");
  89    }
  90
  91    return;
  92
  93abort:
  94    /*
  95     * We only abort if there is already a failure so ignore any error
  96     * from ending the transaction.
  97     */
  98    xs_transaction_end(xenbus->xsh, tid, true);
  99    error_propagate(errp, local_err);
 100}
 101
 102static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
 103{
 104    XenDevice *xendev = XEN_DEVICE(dev);
 105
 106    monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
 107                   indent, "", xendev->name, xendev->frontend_id);
 108}
 109
 110static char *xen_bus_get_dev_path(DeviceState *dev)
 111{
 112    return xen_device_get_backend_path(XEN_DEVICE(dev));
 113}
 114
 115struct XenWatch {
 116    char *node, *key;
 117    char *token;
 118    XenWatchHandler handler;
 119    void *opaque;
 120    Notifier notifier;
 121};
 122
 123static void watch_notify(Notifier *n, void *data)
 124{
 125    XenWatch *watch = container_of(n, XenWatch, notifier);
 126    const char *token = data;
 127
 128    if (!strcmp(watch->token, token)) {
 129        watch->handler(watch->opaque);
 130    }
 131}
 132
 133static XenWatch *new_watch(const char *node, const char *key,
 134                           XenWatchHandler handler, void *opaque)
 135{
 136    XenWatch *watch = g_new0(XenWatch, 1);
 137    QemuUUID uuid;
 138
 139    qemu_uuid_generate(&uuid);
 140
 141    watch->token = qemu_uuid_unparse_strdup(&uuid);
 142    watch->node = g_strdup(node);
 143    watch->key = g_strdup(key);
 144    watch->handler = handler;
 145    watch->opaque = opaque;
 146    watch->notifier.notify = watch_notify;
 147
 148    return watch;
 149}
 150
 151static void free_watch(XenWatch *watch)
 152{
 153    g_free(watch->token);
 154    g_free(watch->key);
 155    g_free(watch->node);
 156
 157    g_free(watch);
 158}
 159
 160static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
 161                                   const char *key, XenWatchHandler handler,
 162                                   void *opaque, Error **errp)
 163{
 164    XenWatch *watch = new_watch(node, key, handler, opaque);
 165    Error *local_err = NULL;
 166
 167    trace_xen_bus_add_watch(watch->node, watch->key, watch->token);
 168
 169    notifier_list_add(&xenbus->watch_notifiers, &watch->notifier);
 170
 171    xs_node_watch(xenbus->xsh, node, key, watch->token, &local_err);
 172    if (local_err) {
 173        error_propagate(errp, local_err);
 174
 175        notifier_remove(&watch->notifier);
 176        free_watch(watch);
 177
 178        return NULL;
 179    }
 180
 181    return watch;
 182}
 183
 184static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
 185                                 Error **errp)
 186{
 187    trace_xen_bus_remove_watch(watch->node, watch->key, watch->token);
 188
 189    xs_node_unwatch(xenbus->xsh, watch->node, watch->key, watch->token,
 190                    errp);
 191
 192    notifier_remove(&watch->notifier);
 193    free_watch(watch);
 194}
 195
 196static void xen_bus_backend_create(XenBus *xenbus, const char *type,
 197                                   const char *name, char *path,
 198                                   Error **errp)
 199{
 200    xs_transaction_t tid;
 201    char **key;
 202    QDict *opts;
 203    unsigned int i, n;
 204    Error *local_err = NULL;
 205
 206    trace_xen_bus_backend_create(type, path);
 207
 208again:
 209    tid = xs_transaction_start(xenbus->xsh);
 210    if (tid == XBT_NULL) {
 211        error_setg(errp, "failed xs_transaction_start");
 212        return;
 213    }
 214
 215    key = xs_directory(xenbus->xsh, tid, path, &n);
 216    if (!key) {
 217        if (!xs_transaction_end(xenbus->xsh, tid, true)) {
 218            error_setg_errno(errp, errno, "failed xs_transaction_end");
 219        }
 220        return;
 221    }
 222
 223    opts = qdict_new();
 224    for (i = 0; i < n; i++) {
 225        char *val;
 226
 227        /*
 228         * Assume anything found in the xenstore backend area, other than
 229         * the keys created for a generic XenDevice, are parameters
 230         * to be used to configure the backend.
 231         */
 232        if (!strcmp(key[i], "state") ||
 233            !strcmp(key[i], "online") ||
 234            !strcmp(key[i], "frontend") ||
 235            !strcmp(key[i], "frontend-id") ||
 236            !strcmp(key[i], "hotplug-status"))
 237            continue;
 238
 239        if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
 240                          &val) == 1) {
 241            qdict_put_str(opts, key[i], val);
 242            free(val);
 243        }
 244    }
 245
 246    free(key);
 247
 248    if (!xs_transaction_end(xenbus->xsh, tid, false)) {
 249        qobject_unref(opts);
 250
 251        if (errno == EAGAIN) {
 252            goto again;
 253        }
 254
 255        error_setg_errno(errp, errno, "failed xs_transaction_end");
 256        return;
 257    }
 258
 259    xen_backend_device_create(xenbus, type, name, opts, &local_err);
 260    qobject_unref(opts);
 261
 262    if (local_err) {
 263        error_propagate_prepend(errp, local_err,
 264                                "failed to create '%s' device '%s': ",
 265                                type, name);
 266    }
 267}
 268
 269static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
 270{
 271    char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
 272    char **backend;
 273    unsigned int i, n;
 274
 275    trace_xen_bus_type_enumerate(type);
 276
 277    backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
 278    if (!backend) {
 279        goto out;
 280    }
 281
 282    for (i = 0; i < n; i++) {
 283        char *backend_path = g_strdup_printf("%s/%s", domain_path,
 284                                             backend[i]);
 285        enum xenbus_state backend_state;
 286
 287        if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
 288                          NULL, "%u", &backend_state) != 1)
 289            backend_state = XenbusStateUnknown;
 290
 291        if (backend_state == XenbusStateInitialising) {
 292            Error *local_err = NULL;
 293
 294            xen_bus_backend_create(xenbus, type, backend[i], backend_path,
 295                                   &local_err);
 296            if (local_err) {
 297                error_report_err(local_err);
 298            }
 299        }
 300
 301        g_free(backend_path);
 302    }
 303
 304    free(backend);
 305
 306out:
 307    g_free(domain_path);
 308}
 309
 310static void xen_bus_enumerate(void *opaque)
 311{
 312    XenBus *xenbus = opaque;
 313    char **type;
 314    unsigned int i, n;
 315
 316    trace_xen_bus_enumerate();
 317
 318    type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
 319    if (!type) {
 320        return;
 321    }
 322
 323    for (i = 0; i < n; i++) {
 324        xen_bus_type_enumerate(xenbus, type[i]);
 325    }
 326
 327    free(type);
 328}
 329
 330static void xen_bus_unrealize(BusState *bus, Error **errp)
 331{
 332    XenBus *xenbus = XEN_BUS(bus);
 333
 334    trace_xen_bus_unrealize();
 335
 336    if (xenbus->backend_watch) {
 337        xen_bus_remove_watch(xenbus, xenbus->backend_watch, NULL);
 338        xenbus->backend_watch = NULL;
 339    }
 340
 341    if (!xenbus->xsh) {
 342        return;
 343    }
 344
 345    qemu_set_fd_handler(xs_fileno(xenbus->xsh), NULL, NULL, NULL);
 346
 347    xs_close(xenbus->xsh);
 348}
 349
 350static void xen_bus_watch(void *opaque)
 351{
 352    XenBus *xenbus = opaque;
 353    char **v;
 354    const char *token;
 355
 356    g_assert(xenbus->xsh);
 357
 358    v = xs_check_watch(xenbus->xsh);
 359    if (!v) {
 360        return;
 361    }
 362
 363    token = v[XS_WATCH_TOKEN];
 364
 365    trace_xen_bus_watch(token);
 366
 367    notifier_list_notify(&xenbus->watch_notifiers, (void *)token);
 368
 369    free(v);
 370}
 371
 372static void xen_bus_realize(BusState *bus, Error **errp)
 373{
 374    XenBus *xenbus = XEN_BUS(bus);
 375    unsigned int domid;
 376    Error *local_err = NULL;
 377
 378    trace_xen_bus_realize();
 379
 380    xenbus->xsh = xs_open(0);
 381    if (!xenbus->xsh) {
 382        error_setg_errno(errp, errno, "failed xs_open");
 383        goto fail;
 384    }
 385
 386    if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
 387                      "domid", NULL, "%u", &domid) == 1) {
 388        xenbus->backend_id = domid;
 389    } else {
 390        xenbus->backend_id = 0; /* Assume lack of node means dom0 */
 391    }
 392
 393    notifier_list_init(&xenbus->watch_notifiers);
 394    qemu_set_fd_handler(xs_fileno(xenbus->xsh), xen_bus_watch, NULL,
 395                        xenbus);
 396
 397    module_call_init(MODULE_INIT_XEN_BACKEND);
 398
 399    xenbus->backend_watch =
 400        xen_bus_add_watch(xenbus, "", /* domain root node */
 401                          "backend", xen_bus_enumerate, xenbus, &local_err);
 402    if (local_err) {
 403        /* This need not be treated as a hard error so don't propagate */
 404        error_reportf_err(local_err,
 405                          "failed to set up enumeration watch: ");
 406    }
 407
 408    return;
 409
 410fail:
 411    xen_bus_unrealize(bus, &error_abort);
 412}
 413
 414static void xen_bus_unplug_request(HotplugHandler *hotplug,
 415                                   DeviceState *dev,
 416                                   Error **errp)
 417{
 418    XenDevice *xendev = XEN_DEVICE(dev);
 419
 420    xen_device_unplug(xendev, errp);
 421}
 422
 423static void xen_bus_class_init(ObjectClass *class, void *data)
 424{
 425    BusClass *bus_class = BUS_CLASS(class);
 426    HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
 427
 428    bus_class->print_dev = xen_bus_print_dev;
 429    bus_class->get_dev_path = xen_bus_get_dev_path;
 430    bus_class->realize = xen_bus_realize;
 431    bus_class->unrealize = xen_bus_unrealize;
 432
 433    hotplug_class->unplug_request = xen_bus_unplug_request;
 434}
 435
 436static const TypeInfo xen_bus_type_info = {
 437    .name = TYPE_XEN_BUS,
 438    .parent = TYPE_BUS,
 439    .instance_size = sizeof(XenBus),
 440    .class_size = sizeof(XenBusClass),
 441    .class_init = xen_bus_class_init,
 442    .interfaces = (InterfaceInfo[]) {
 443        { TYPE_HOTPLUG_HANDLER },
 444        { }
 445    },
 446};
 447
 448void xen_device_backend_printf(XenDevice *xendev, const char *key,
 449                               const char *fmt, ...)
 450{
 451    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 452    Error *local_err = NULL;
 453    va_list ap;
 454
 455    g_assert(xenbus->xsh);
 456
 457    va_start(ap, fmt);
 458    xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
 459                    &local_err, fmt, ap);
 460    va_end(ap);
 461
 462    if (local_err) {
 463        error_report_err(local_err);
 464    }
 465}
 466
 467static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
 468                                    const char *fmt, ...)
 469{
 470    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 471    va_list ap;
 472    int rc;
 473
 474    g_assert(xenbus->xsh);
 475
 476    va_start(ap, fmt);
 477    rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
 478                        NULL, fmt, ap);
 479    va_end(ap);
 480
 481    return rc;
 482}
 483
 484void xen_device_backend_set_state(XenDevice *xendev,
 485                                  enum xenbus_state state)
 486{
 487    const char *type = object_get_typename(OBJECT(xendev));
 488
 489    if (xendev->backend_state == state) {
 490        return;
 491    }
 492
 493    trace_xen_device_backend_state(type, xendev->name,
 494                                   xs_strstate(state));
 495
 496    xendev->backend_state = state;
 497    xen_device_backend_printf(xendev, "state", "%u", state);
 498}
 499
 500enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
 501{
 502    return xendev->backend_state;
 503}
 504
 505static void xen_device_backend_set_online(XenDevice *xendev, bool online)
 506{
 507    const char *type = object_get_typename(OBJECT(xendev));
 508
 509    if (xendev->backend_online == online) {
 510        return;
 511    }
 512
 513    trace_xen_device_backend_online(type, xendev->name, online);
 514
 515    xendev->backend_online = online;
 516    xen_device_backend_printf(xendev, "online", "%u", online);
 517}
 518
 519static void xen_device_backend_changed(void *opaque)
 520{
 521    XenDevice *xendev = opaque;
 522    const char *type = object_get_typename(OBJECT(xendev));
 523    enum xenbus_state state;
 524    unsigned int online;
 525
 526    trace_xen_device_backend_changed(type, xendev->name);
 527
 528    if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
 529        state = XenbusStateUnknown;
 530    }
 531
 532    xen_device_backend_set_state(xendev, state);
 533
 534    if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
 535        online = 0;
 536    }
 537
 538    xen_device_backend_set_online(xendev, !!online);
 539
 540    /*
 541     * If the toolstack (or unplug request callback) has set the backend
 542     * state to Closing, but there is no active frontend (i.e. the
 543     * state is not Connected) then set the backend state to Closed.
 544     */
 545    if (xendev->backend_state == XenbusStateClosing &&
 546        xendev->frontend_state != XenbusStateConnected) {
 547        xen_device_backend_set_state(xendev, XenbusStateClosed);
 548    }
 549
 550    /*
 551     * If a backend is still 'online' then we should leave it alone but,
 552     * if a backend is not 'online', then the device should be destroyed
 553     * once the state is Closed.
 554     */
 555    if (!xendev->backend_online &&
 556        (xendev->backend_state == XenbusStateClosed ||
 557         xendev->backend_state == XenbusStateInitialising ||
 558         xendev->backend_state == XenbusStateInitWait ||
 559         xendev->backend_state == XenbusStateUnknown)) {
 560        Error *local_err = NULL;
 561
 562        if (!xen_backend_try_device_destroy(xendev, &local_err)) {
 563            object_unparent(OBJECT(xendev));
 564        }
 565
 566        if (local_err) {
 567            error_report_err(local_err);
 568        }
 569    }
 570}
 571
 572static void xen_device_backend_create(XenDevice *xendev, Error **errp)
 573{
 574    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 575    struct xs_permissions perms[2];
 576    Error *local_err = NULL;
 577
 578    xendev->backend_path = xen_device_get_backend_path(xendev);
 579
 580    perms[0].id = xenbus->backend_id;
 581    perms[0].perms = XS_PERM_NONE;
 582    perms[1].id = xendev->frontend_id;
 583    perms[1].perms = XS_PERM_READ;
 584
 585    g_assert(xenbus->xsh);
 586
 587    xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
 588                   ARRAY_SIZE(perms), &local_err);
 589    if (local_err) {
 590        error_propagate_prepend(errp, local_err,
 591                                "failed to create backend: ");
 592        return;
 593    }
 594
 595    xendev->backend_state_watch =
 596        xen_bus_add_watch(xenbus, xendev->backend_path,
 597                          "state", xen_device_backend_changed,
 598                          xendev, &local_err);
 599    if (local_err) {
 600        error_propagate_prepend(errp, local_err,
 601                                "failed to watch backend state: ");
 602        return;
 603    }
 604
 605    xendev->backend_online_watch =
 606        xen_bus_add_watch(xenbus, xendev->backend_path,
 607                          "online", xen_device_backend_changed,
 608                          xendev, &local_err);
 609    if (local_err) {
 610        error_propagate_prepend(errp, local_err,
 611                                "failed to watch backend online: ");
 612        return;
 613    }
 614}
 615
 616static void xen_device_backend_destroy(XenDevice *xendev)
 617{
 618    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 619    Error *local_err = NULL;
 620
 621    if (xendev->backend_online_watch) {
 622        xen_bus_remove_watch(xenbus, xendev->backend_online_watch, NULL);
 623        xendev->backend_online_watch = NULL;
 624    }
 625
 626    if (xendev->backend_state_watch) {
 627        xen_bus_remove_watch(xenbus, xendev->backend_state_watch, NULL);
 628        xendev->backend_state_watch = NULL;
 629    }
 630
 631    if (!xendev->backend_path) {
 632        return;
 633    }
 634
 635    g_assert(xenbus->xsh);
 636
 637    xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
 638                    &local_err);
 639    g_free(xendev->backend_path);
 640    xendev->backend_path = NULL;
 641
 642    if (local_err) {
 643        error_report_err(local_err);
 644    }
 645}
 646
 647void xen_device_frontend_printf(XenDevice *xendev, const char *key,
 648                                const char *fmt, ...)
 649{
 650    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 651    Error *local_err = NULL;
 652    va_list ap;
 653
 654    g_assert(xenbus->xsh);
 655
 656    va_start(ap, fmt);
 657    xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
 658                    &local_err, fmt, ap);
 659    va_end(ap);
 660
 661    if (local_err) {
 662        error_report_err(local_err);
 663    }
 664}
 665
 666int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
 667                              const char *fmt, ...)
 668{
 669    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 670    va_list ap;
 671    int rc;
 672
 673    g_assert(xenbus->xsh);
 674
 675    va_start(ap, fmt);
 676    rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
 677                        NULL, fmt, ap);
 678    va_end(ap);
 679
 680    return rc;
 681}
 682
 683static void xen_device_frontend_set_state(XenDevice *xendev,
 684                                          enum xenbus_state state)
 685{
 686    const char *type = object_get_typename(OBJECT(xendev));
 687
 688    if (xendev->frontend_state == state) {
 689        return;
 690    }
 691
 692    trace_xen_device_frontend_state(type, xendev->name,
 693                                    xs_strstate(state));
 694
 695    xendev->frontend_state = state;
 696    xen_device_frontend_printf(xendev, "state", "%u", state);
 697}
 698
 699static void xen_device_frontend_changed(void *opaque)
 700{
 701    XenDevice *xendev = opaque;
 702    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
 703    const char *type = object_get_typename(OBJECT(xendev));
 704    enum xenbus_state state;
 705
 706    trace_xen_device_frontend_changed(type, xendev->name);
 707
 708    if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
 709        state = XenbusStateUnknown;
 710    }
 711
 712    xen_device_frontend_set_state(xendev, state);
 713
 714    if (state == XenbusStateInitialising &&
 715        xendev->backend_state == XenbusStateClosed &&
 716        xendev->backend_online) {
 717        /*
 718         * The frontend is re-initializing so switch back to
 719         * InitWait.
 720         */
 721        xen_device_backend_set_state(xendev, XenbusStateInitWait);
 722        return;
 723    }
 724
 725    if (xendev_class->frontend_changed) {
 726        Error *local_err = NULL;
 727
 728        xendev_class->frontend_changed(xendev, state, &local_err);
 729
 730        if (local_err) {
 731            error_reportf_err(local_err, "frontend change error: ");
 732        }
 733    }
 734}
 735
 736static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
 737{
 738    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 739    struct xs_permissions perms[2];
 740    Error *local_err = NULL;
 741
 742    xendev->frontend_path = xen_device_get_frontend_path(xendev);
 743
 744    perms[0].id = xendev->frontend_id;
 745    perms[0].perms = XS_PERM_NONE;
 746    perms[1].id = xenbus->backend_id;
 747    perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
 748
 749    g_assert(xenbus->xsh);
 750
 751    xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
 752                   ARRAY_SIZE(perms), &local_err);
 753    if (local_err) {
 754        error_propagate_prepend(errp, local_err,
 755                                "failed to create frontend: ");
 756        return;
 757    }
 758
 759    xendev->frontend_state_watch =
 760        xen_bus_add_watch(xenbus, xendev->frontend_path, "state",
 761                          xen_device_frontend_changed, xendev, &local_err);
 762    if (local_err) {
 763        error_propagate_prepend(errp, local_err,
 764                                "failed to watch frontend state: ");
 765    }
 766}
 767
 768static void xen_device_frontend_destroy(XenDevice *xendev)
 769{
 770    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 771    Error *local_err = NULL;
 772
 773    if (xendev->frontend_state_watch) {
 774        xen_bus_remove_watch(xenbus, xendev->frontend_state_watch, NULL);
 775        xendev->frontend_state_watch = NULL;
 776    }
 777
 778    if (!xendev->frontend_path) {
 779        return;
 780    }
 781
 782    g_assert(xenbus->xsh);
 783
 784    xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
 785                    &local_err);
 786    g_free(xendev->frontend_path);
 787    xendev->frontend_path = NULL;
 788
 789    if (local_err) {
 790        error_report_err(local_err);
 791    }
 792}
 793
 794void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
 795                                   Error **errp)
 796{
 797    if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
 798        error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
 799    }
 800}
 801
 802void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
 803                                unsigned int nr_refs, int prot,
 804                                Error **errp)
 805{
 806    void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
 807                                                xendev->frontend_id, refs,
 808                                                prot);
 809
 810    if (!map) {
 811        error_setg_errno(errp, errno,
 812                         "xengnttab_map_domain_grant_refs failed");
 813    }
 814
 815    return map;
 816}
 817
 818void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
 819                                 unsigned int nr_refs, Error **errp)
 820{
 821    if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
 822        error_setg_errno(errp, errno, "xengnttab_unmap failed");
 823    }
 824}
 825
 826static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
 827                                   XenDeviceGrantCopySegment segs[],
 828                                   unsigned int nr_segs, Error **errp)
 829{
 830    uint32_t *refs = g_new(uint32_t, nr_segs);
 831    int prot = to_domain ? PROT_WRITE : PROT_READ;
 832    void *map;
 833    unsigned int i;
 834
 835    for (i = 0; i < nr_segs; i++) {
 836        XenDeviceGrantCopySegment *seg = &segs[i];
 837
 838        refs[i] = to_domain ? seg->dest.foreign.ref :
 839            seg->source.foreign.ref;
 840    }
 841
 842    map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
 843                                          xendev->frontend_id, refs,
 844                                          prot);
 845    if (!map) {
 846        error_setg_errno(errp, errno,
 847                         "xengnttab_map_domain_grant_refs failed");
 848        goto done;
 849    }
 850
 851    for (i = 0; i < nr_segs; i++) {
 852        XenDeviceGrantCopySegment *seg = &segs[i];
 853        void *page = map + (i * XC_PAGE_SIZE);
 854
 855        if (to_domain) {
 856            memcpy(page + seg->dest.foreign.offset, seg->source.virt,
 857                   seg->len);
 858        } else {
 859            memcpy(seg->dest.virt, page + seg->source.foreign.offset,
 860                   seg->len);
 861        }
 862    }
 863
 864    if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
 865        error_setg_errno(errp, errno, "xengnttab_unmap failed");
 866    }
 867
 868done:
 869    g_free(refs);
 870}
 871
 872void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
 873                                XenDeviceGrantCopySegment segs[],
 874                                unsigned int nr_segs, Error **errp)
 875{
 876    xengnttab_grant_copy_segment_t *xengnttab_segs;
 877    unsigned int i;
 878
 879    if (!xendev->feature_grant_copy) {
 880        compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
 881        return;
 882    }
 883
 884    xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
 885
 886    for (i = 0; i < nr_segs; i++) {
 887        XenDeviceGrantCopySegment *seg = &segs[i];
 888        xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
 889
 890        if (to_domain) {
 891            xengnttab_seg->flags = GNTCOPY_dest_gref;
 892            xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
 893            xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
 894            xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
 895            xengnttab_seg->source.virt = seg->source.virt;
 896        } else {
 897            xengnttab_seg->flags = GNTCOPY_source_gref;
 898            xengnttab_seg->source.foreign.domid = xendev->frontend_id;
 899            xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
 900            xengnttab_seg->source.foreign.offset =
 901                seg->source.foreign.offset;
 902            xengnttab_seg->dest.virt = seg->dest.virt;
 903        }
 904
 905        xengnttab_seg->len = seg->len;
 906    }
 907
 908    if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
 909        error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
 910        goto done;
 911    }
 912
 913    for (i = 0; i < nr_segs; i++) {
 914        xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
 915
 916        if (xengnttab_seg->status != GNTST_okay) {
 917            error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
 918            break;
 919        }
 920    }
 921
 922done:
 923    g_free(xengnttab_segs);
 924}
 925
 926struct XenEventChannel {
 927    QLIST_ENTRY(XenEventChannel) list;
 928    AioContext *ctx;
 929    xenevtchn_handle *xeh;
 930    evtchn_port_t local_port;
 931    XenEventHandler handler;
 932    void *opaque;
 933};
 934
 935static bool xen_device_poll(void *opaque)
 936{
 937    XenEventChannel *channel = opaque;
 938
 939    return channel->handler(channel->opaque);
 940}
 941
 942static void xen_device_event(void *opaque)
 943{
 944    XenEventChannel *channel = opaque;
 945    unsigned long port = xenevtchn_pending(channel->xeh);
 946
 947    if (port == channel->local_port) {
 948        xen_device_poll(channel);
 949
 950        xenevtchn_unmask(channel->xeh, port);
 951    }
 952}
 953
 954XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
 955                                               AioContext *ctx,
 956                                               unsigned int port,
 957                                               XenEventHandler handler,
 958                                               void *opaque, Error **errp)
 959{
 960    XenEventChannel *channel = g_new0(XenEventChannel, 1);
 961    xenevtchn_port_or_error_t local_port;
 962
 963    channel->xeh = xenevtchn_open(NULL, 0);
 964    if (!channel->xeh) {
 965        error_setg_errno(errp, errno, "failed xenevtchn_open");
 966        goto fail;
 967    }
 968
 969    local_port = xenevtchn_bind_interdomain(channel->xeh,
 970                                            xendev->frontend_id,
 971                                            port);
 972    if (local_port < 0) {
 973        error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
 974        goto fail;
 975    }
 976
 977    channel->local_port = local_port;
 978    channel->handler = handler;
 979    channel->opaque = opaque;
 980
 981    channel->ctx = ctx;
 982    aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
 983                       xen_device_event, NULL, xen_device_poll, channel);
 984
 985    QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
 986
 987    return channel;
 988
 989fail:
 990    if (channel->xeh) {
 991        xenevtchn_close(channel->xeh);
 992    }
 993
 994    g_free(channel);
 995
 996    return NULL;
 997}
 998
 999void xen_device_notify_event_channel(XenDevice *xendev,
1000                                     XenEventChannel *channel,
1001                                     Error **errp)
1002{
1003    if (!channel) {
1004        error_setg(errp, "bad channel");
1005        return;
1006    }
1007
1008    if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
1009        error_setg_errno(errp, errno, "xenevtchn_notify failed");
1010    }
1011}
1012
1013void xen_device_unbind_event_channel(XenDevice *xendev,
1014                                     XenEventChannel *channel,
1015                                     Error **errp)
1016{
1017    if (!channel) {
1018        error_setg(errp, "bad channel");
1019        return;
1020    }
1021
1022    QLIST_REMOVE(channel, list);
1023
1024    aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1025                       NULL, NULL, NULL, NULL);
1026
1027    if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
1028        error_setg_errno(errp, errno, "xenevtchn_unbind failed");
1029    }
1030
1031    xenevtchn_close(channel->xeh);
1032    g_free(channel);
1033}
1034
1035static void xen_device_unrealize(DeviceState *dev, Error **errp)
1036{
1037    XenDevice *xendev = XEN_DEVICE(dev);
1038    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1039    const char *type = object_get_typename(OBJECT(xendev));
1040    XenEventChannel *channel, *next;
1041
1042    if (!xendev->name) {
1043        return;
1044    }
1045
1046    trace_xen_device_unrealize(type, xendev->name);
1047
1048    if (xendev->exit.notify) {
1049        qemu_remove_exit_notifier(&xendev->exit);
1050        xendev->exit.notify = NULL;
1051    }
1052
1053    if (xendev_class->unrealize) {
1054        xendev_class->unrealize(xendev, errp);
1055    }
1056
1057    /* Make sure all event channels are cleaned up */
1058    QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
1059        xen_device_unbind_event_channel(xendev, channel, NULL);
1060    }
1061
1062    xen_device_frontend_destroy(xendev);
1063    xen_device_backend_destroy(xendev);
1064
1065    if (xendev->xgth) {
1066        xengnttab_close(xendev->xgth);
1067        xendev->xgth = NULL;
1068    }
1069
1070    g_free(xendev->name);
1071    xendev->name = NULL;
1072}
1073
1074static void xen_device_exit(Notifier *n, void *data)
1075{
1076    XenDevice *xendev = container_of(n, XenDevice, exit);
1077
1078    xen_device_unrealize(DEVICE(xendev), &error_abort);
1079}
1080
1081static void xen_device_realize(DeviceState *dev, Error **errp)
1082{
1083    XenDevice *xendev = XEN_DEVICE(dev);
1084    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1085    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
1086    const char *type = object_get_typename(OBJECT(xendev));
1087    Error *local_err = NULL;
1088
1089    if (xendev->frontend_id == DOMID_INVALID) {
1090        xendev->frontend_id = xen_domid;
1091    }
1092
1093    if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1094        error_setg(errp, "invalid frontend-id");
1095        goto unrealize;
1096    }
1097
1098    if (!xendev_class->get_name) {
1099        error_setg(errp, "get_name method not implemented");
1100        goto unrealize;
1101    }
1102
1103    xendev->name = xendev_class->get_name(xendev, &local_err);
1104    if (local_err) {
1105        error_propagate_prepend(errp, local_err,
1106                                "failed to get device name: ");
1107        goto unrealize;
1108    }
1109
1110    trace_xen_device_realize(type, xendev->name);
1111
1112    xendev->xgth = xengnttab_open(NULL, 0);
1113    if (!xendev->xgth) {
1114        error_setg_errno(errp, errno, "failed xengnttab_open");
1115        goto unrealize;
1116    }
1117
1118    xendev->feature_grant_copy =
1119        (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1120
1121    xen_device_backend_create(xendev, &local_err);
1122    if (local_err) {
1123        error_propagate(errp, local_err);
1124        goto unrealize;
1125    }
1126
1127    xen_device_frontend_create(xendev, &local_err);
1128    if (local_err) {
1129        error_propagate(errp, local_err);
1130        goto unrealize;
1131    }
1132
1133    if (xendev_class->realize) {
1134        xendev_class->realize(xendev, &local_err);
1135        if (local_err) {
1136            error_propagate(errp, local_err);
1137            goto unrealize;
1138        }
1139    }
1140
1141    xen_device_backend_printf(xendev, "frontend", "%s",
1142                              xendev->frontend_path);
1143    xen_device_backend_printf(xendev, "frontend-id", "%u",
1144                              xendev->frontend_id);
1145    xen_device_backend_printf(xendev, "hotplug-status", "connected");
1146
1147    xen_device_backend_set_online(xendev, true);
1148    xen_device_backend_set_state(xendev, XenbusStateInitWait);
1149
1150    xen_device_frontend_printf(xendev, "backend", "%s",
1151                               xendev->backend_path);
1152    xen_device_frontend_printf(xendev, "backend-id", "%u",
1153                               xenbus->backend_id);
1154
1155    xen_device_frontend_set_state(xendev, XenbusStateInitialising);
1156
1157    xendev->exit.notify = xen_device_exit;
1158    qemu_add_exit_notifier(&xendev->exit);
1159    return;
1160
1161unrealize:
1162    xen_device_unrealize(dev, &error_abort);
1163}
1164
1165static Property xen_device_props[] = {
1166    DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1167                       DOMID_INVALID),
1168    DEFINE_PROP_END_OF_LIST()
1169};
1170
1171static void xen_device_class_init(ObjectClass *class, void *data)
1172{
1173    DeviceClass *dev_class = DEVICE_CLASS(class);
1174
1175    dev_class->realize = xen_device_realize;
1176    dev_class->unrealize = xen_device_unrealize;
1177    dev_class->props = xen_device_props;
1178    dev_class->bus_type = TYPE_XEN_BUS;
1179}
1180
1181static const TypeInfo xen_device_type_info = {
1182    .name = TYPE_XEN_DEVICE,
1183    .parent = TYPE_DEVICE,
1184    .instance_size = sizeof(XenDevice),
1185    .abstract = true,
1186    .class_size = sizeof(XenDeviceClass),
1187    .class_init = xen_device_class_init,
1188};
1189
1190typedef struct XenBridge {
1191    SysBusDevice busdev;
1192} XenBridge;
1193
1194#define TYPE_XEN_BRIDGE "xen-bridge"
1195
1196static const TypeInfo xen_bridge_type_info = {
1197    .name = TYPE_XEN_BRIDGE,
1198    .parent = TYPE_SYS_BUS_DEVICE,
1199    .instance_size = sizeof(XenBridge),
1200};
1201
1202static void xen_register_types(void)
1203{
1204    type_register_static(&xen_bridge_type_info);
1205    type_register_static(&xen_bus_type_info);
1206    type_register_static(&xen_device_type_info);
1207}
1208
1209type_init(xen_register_types)
1210
1211void xen_bus_init(void)
1212{
1213    DeviceState *dev = qdev_create(NULL, TYPE_XEN_BRIDGE);
1214    BusState *bus = qbus_create(TYPE_XEN_BUS, dev, NULL);
1215
1216    qdev_init_nofail(dev);
1217    qbus_set_bus_hotplug_handler(bus, &error_abort);
1218}
1219