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/qdev-properties.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    ERRP_GUARD();
  57    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
  58    const char *type = object_get_typename(OBJECT(xendev));
  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                   errp, "%u", 0);
  73    if (*errp) {
  74        goto abort;
  75    }
  76
  77    xs_node_printf(xenbus->xsh, tid, xendev->backend_path, "state",
  78                   errp, "%u", XenbusStateClosing);
  79    if (*errp) {
  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}
 100
 101static void xen_bus_print_dev(Monitor *mon, DeviceState *dev, int indent)
 102{
 103    XenDevice *xendev = XEN_DEVICE(dev);
 104
 105    monitor_printf(mon, "%*sname = '%s' frontend_id = %u\n",
 106                   indent, "", xendev->name, xendev->frontend_id);
 107}
 108
 109static char *xen_bus_get_dev_path(DeviceState *dev)
 110{
 111    return xen_device_get_backend_path(XEN_DEVICE(dev));
 112}
 113
 114struct XenWatch {
 115    char *node, *key;
 116    char *token;
 117    XenWatchHandler handler;
 118    void *opaque;
 119    Notifier notifier;
 120};
 121
 122static void watch_notify(Notifier *n, void *data)
 123{
 124    XenWatch *watch = container_of(n, XenWatch, notifier);
 125    const char *token = data;
 126
 127    if (!strcmp(watch->token, token)) {
 128        watch->handler(watch->opaque);
 129    }
 130}
 131
 132static XenWatch *new_watch(const char *node, const char *key,
 133                           XenWatchHandler handler, void *opaque)
 134{
 135    XenWatch *watch = g_new0(XenWatch, 1);
 136    QemuUUID uuid;
 137
 138    qemu_uuid_generate(&uuid);
 139
 140    watch->token = qemu_uuid_unparse_strdup(&uuid);
 141    watch->node = g_strdup(node);
 142    watch->key = g_strdup(key);
 143    watch->handler = handler;
 144    watch->opaque = opaque;
 145    watch->notifier.notify = watch_notify;
 146
 147    return watch;
 148}
 149
 150static void free_watch(XenWatch *watch)
 151{
 152    g_free(watch->token);
 153    g_free(watch->key);
 154    g_free(watch->node);
 155
 156    g_free(watch);
 157}
 158
 159struct XenWatchList {
 160    struct xs_handle *xsh;
 161    NotifierList notifiers;
 162};
 163
 164static void watch_list_event(void *opaque)
 165{
 166    XenWatchList *watch_list = opaque;
 167    char **v;
 168    const char *token;
 169
 170    v = xs_check_watch(watch_list->xsh);
 171    if (!v) {
 172        return;
 173    }
 174
 175    token = v[XS_WATCH_TOKEN];
 176
 177    notifier_list_notify(&watch_list->notifiers, (void *)token);
 178
 179    free(v);
 180}
 181
 182static XenWatchList *watch_list_create(struct xs_handle *xsh)
 183{
 184    XenWatchList *watch_list = g_new0(XenWatchList, 1);
 185
 186    g_assert(xsh);
 187
 188    watch_list->xsh = xsh;
 189    notifier_list_init(&watch_list->notifiers);
 190    qemu_set_fd_handler(xs_fileno(watch_list->xsh), watch_list_event, NULL,
 191                        watch_list);
 192
 193    return watch_list;
 194}
 195
 196static void watch_list_destroy(XenWatchList *watch_list)
 197{
 198    g_assert(notifier_list_empty(&watch_list->notifiers));
 199    qemu_set_fd_handler(xs_fileno(watch_list->xsh), NULL, NULL, NULL);
 200    g_free(watch_list);
 201}
 202
 203static XenWatch *watch_list_add(XenWatchList *watch_list, const char *node,
 204                                const char *key, XenWatchHandler handler,
 205                                void *opaque, Error **errp)
 206{
 207    ERRP_GUARD();
 208    XenWatch *watch = new_watch(node, key, handler, opaque);
 209
 210    notifier_list_add(&watch_list->notifiers, &watch->notifier);
 211
 212    xs_node_watch(watch_list->xsh, node, key, watch->token, errp);
 213    if (*errp) {
 214        notifier_remove(&watch->notifier);
 215        free_watch(watch);
 216
 217        return NULL;
 218    }
 219
 220    return watch;
 221}
 222
 223static void watch_list_remove(XenWatchList *watch_list, XenWatch *watch,
 224                              Error **errp)
 225{
 226    xs_node_unwatch(watch_list->xsh, watch->node, watch->key, watch->token,
 227                    errp);
 228
 229    notifier_remove(&watch->notifier);
 230    free_watch(watch);
 231}
 232
 233static XenWatch *xen_bus_add_watch(XenBus *xenbus, const char *node,
 234                                   const char *key, XenWatchHandler handler,
 235                                   Error **errp)
 236{
 237    trace_xen_bus_add_watch(node, key);
 238
 239    return watch_list_add(xenbus->watch_list, node, key, handler, xenbus,
 240                          errp);
 241}
 242
 243static void xen_bus_remove_watch(XenBus *xenbus, XenWatch *watch,
 244                                 Error **errp)
 245{
 246    trace_xen_bus_remove_watch(watch->node, watch->key);
 247
 248    watch_list_remove(xenbus->watch_list, watch, errp);
 249}
 250
 251static void xen_bus_backend_create(XenBus *xenbus, const char *type,
 252                                   const char *name, char *path,
 253                                   Error **errp)
 254{
 255    ERRP_GUARD();
 256    xs_transaction_t tid;
 257    char **key;
 258    QDict *opts;
 259    unsigned int i, n;
 260
 261    trace_xen_bus_backend_create(type, path);
 262
 263again:
 264    tid = xs_transaction_start(xenbus->xsh);
 265    if (tid == XBT_NULL) {
 266        error_setg(errp, "failed xs_transaction_start");
 267        return;
 268    }
 269
 270    key = xs_directory(xenbus->xsh, tid, path, &n);
 271    if (!key) {
 272        if (!xs_transaction_end(xenbus->xsh, tid, true)) {
 273            error_setg_errno(errp, errno, "failed xs_transaction_end");
 274        }
 275        return;
 276    }
 277
 278    opts = qdict_new();
 279    for (i = 0; i < n; i++) {
 280        char *val;
 281
 282        /*
 283         * Assume anything found in the xenstore backend area, other than
 284         * the keys created for a generic XenDevice, are parameters
 285         * to be used to configure the backend.
 286         */
 287        if (!strcmp(key[i], "state") ||
 288            !strcmp(key[i], "online") ||
 289            !strcmp(key[i], "frontend") ||
 290            !strcmp(key[i], "frontend-id") ||
 291            !strcmp(key[i], "hotplug-status"))
 292            continue;
 293
 294        if (xs_node_scanf(xenbus->xsh, tid, path, key[i], NULL, "%ms",
 295                          &val) == 1) {
 296            qdict_put_str(opts, key[i], val);
 297            free(val);
 298        }
 299    }
 300
 301    free(key);
 302
 303    if (!xs_transaction_end(xenbus->xsh, tid, false)) {
 304        qobject_unref(opts);
 305
 306        if (errno == EAGAIN) {
 307            goto again;
 308        }
 309
 310        error_setg_errno(errp, errno, "failed xs_transaction_end");
 311        return;
 312    }
 313
 314    xen_backend_device_create(xenbus, type, name, opts, errp);
 315    qobject_unref(opts);
 316
 317    if (*errp) {
 318        error_prepend(errp, "failed to create '%s' device '%s': ", type, name);
 319    }
 320}
 321
 322static void xen_bus_type_enumerate(XenBus *xenbus, const char *type)
 323{
 324    char *domain_path = g_strdup_printf("backend/%s/%u", type, xen_domid);
 325    char **backend;
 326    unsigned int i, n;
 327
 328    trace_xen_bus_type_enumerate(type);
 329
 330    backend = xs_directory(xenbus->xsh, XBT_NULL, domain_path, &n);
 331    if (!backend) {
 332        goto out;
 333    }
 334
 335    for (i = 0; i < n; i++) {
 336        char *backend_path = g_strdup_printf("%s/%s", domain_path,
 337                                             backend[i]);
 338        enum xenbus_state state;
 339        unsigned int online;
 340
 341        if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "state",
 342                          NULL, "%u", &state) != 1)
 343            state = XenbusStateUnknown;
 344
 345        if (xs_node_scanf(xenbus->xsh, XBT_NULL, backend_path, "online",
 346                          NULL, "%u", &online) != 1)
 347            online = 0;
 348
 349        if (online && state == XenbusStateInitialising) {
 350            Error *local_err = NULL;
 351
 352            xen_bus_backend_create(xenbus, type, backend[i], backend_path,
 353                                   &local_err);
 354            if (local_err) {
 355                error_report_err(local_err);
 356            }
 357        }
 358
 359        g_free(backend_path);
 360    }
 361
 362    free(backend);
 363
 364out:
 365    g_free(domain_path);
 366}
 367
 368static void xen_bus_enumerate(XenBus *xenbus)
 369{
 370    char **type;
 371    unsigned int i, n;
 372
 373    trace_xen_bus_enumerate();
 374
 375    type = xs_directory(xenbus->xsh, XBT_NULL, "backend", &n);
 376    if (!type) {
 377        return;
 378    }
 379
 380    for (i = 0; i < n; i++) {
 381        xen_bus_type_enumerate(xenbus, type[i]);
 382    }
 383
 384    free(type);
 385}
 386
 387static void xen_bus_device_cleanup(XenDevice *xendev)
 388{
 389    const char *type = object_get_typename(OBJECT(xendev));
 390    Error *local_err = NULL;
 391
 392    trace_xen_bus_device_cleanup(type, xendev->name);
 393
 394    g_assert(!xendev->backend_online);
 395
 396    if (!xen_backend_try_device_destroy(xendev, &local_err)) {
 397        object_unparent(OBJECT(xendev));
 398    }
 399
 400    if (local_err) {
 401        error_report_err(local_err);
 402    }
 403}
 404
 405static void xen_bus_cleanup(XenBus *xenbus)
 406{
 407    XenDevice *xendev, *next;
 408
 409    trace_xen_bus_cleanup();
 410
 411    QLIST_FOREACH_SAFE(xendev, &xenbus->inactive_devices, list, next) {
 412        g_assert(xendev->inactive);
 413        QLIST_REMOVE(xendev, list);
 414        xen_bus_device_cleanup(xendev);
 415    }
 416}
 417
 418static void xen_bus_backend_changed(void *opaque)
 419{
 420    XenBus *xenbus = opaque;
 421
 422    xen_bus_enumerate(xenbus);
 423    xen_bus_cleanup(xenbus);
 424}
 425
 426static void xen_bus_unrealize(BusState *bus)
 427{
 428    XenBus *xenbus = XEN_BUS(bus);
 429
 430    trace_xen_bus_unrealize();
 431
 432    if (xenbus->backend_watch) {
 433        unsigned int i;
 434
 435        for (i = 0; i < xenbus->backend_types; i++) {
 436            if (xenbus->backend_watch[i]) {
 437                xen_bus_remove_watch(xenbus, xenbus->backend_watch[i], NULL);
 438            }
 439        }
 440
 441        g_free(xenbus->backend_watch);
 442        xenbus->backend_watch = NULL;
 443    }
 444
 445    if (xenbus->watch_list) {
 446        watch_list_destroy(xenbus->watch_list);
 447        xenbus->watch_list = NULL;
 448    }
 449
 450    if (xenbus->xsh) {
 451        xs_close(xenbus->xsh);
 452    }
 453}
 454
 455static void xen_bus_realize(BusState *bus, Error **errp)
 456{
 457    char *key = g_strdup_printf("%u", xen_domid);
 458    XenBus *xenbus = XEN_BUS(bus);
 459    unsigned int domid;
 460    const char **type;
 461    unsigned int i;
 462    Error *local_err = NULL;
 463
 464    trace_xen_bus_realize();
 465
 466    xenbus->xsh = xs_open(0);
 467    if (!xenbus->xsh) {
 468        error_setg_errno(errp, errno, "failed xs_open");
 469        goto fail;
 470    }
 471
 472    if (xs_node_scanf(xenbus->xsh, XBT_NULL, "", /* domain root node */
 473                      "domid", NULL, "%u", &domid) == 1) {
 474        xenbus->backend_id = domid;
 475    } else {
 476        xenbus->backend_id = 0; /* Assume lack of node means dom0 */
 477    }
 478
 479    xenbus->watch_list = watch_list_create(xenbus->xsh);
 480
 481    module_call_init(MODULE_INIT_XEN_BACKEND);
 482
 483    type = xen_backend_get_types(&xenbus->backend_types);
 484    xenbus->backend_watch = g_new(XenWatch *, xenbus->backend_types);
 485
 486    for (i = 0; i < xenbus->backend_types; i++) {
 487        char *node = g_strdup_printf("backend/%s", type[i]);
 488
 489        xenbus->backend_watch[i] =
 490            xen_bus_add_watch(xenbus, node, key, xen_bus_backend_changed,
 491                              &local_err);
 492        if (local_err) {
 493            /* This need not be treated as a hard error so don't propagate */
 494            error_reportf_err(local_err,
 495                              "failed to set up '%s' enumeration watch: ",
 496                              type[i]);
 497        }
 498
 499        g_free(node);
 500    }
 501
 502    g_free(type);
 503    g_free(key);
 504    return;
 505
 506fail:
 507    xen_bus_unrealize(bus);
 508    g_free(key);
 509}
 510
 511static void xen_bus_unplug_request(HotplugHandler *hotplug,
 512                                   DeviceState *dev,
 513                                   Error **errp)
 514{
 515    XenDevice *xendev = XEN_DEVICE(dev);
 516
 517    xen_device_unplug(xendev, errp);
 518}
 519
 520static void xen_bus_class_init(ObjectClass *class, void *data)
 521{
 522    BusClass *bus_class = BUS_CLASS(class);
 523    HotplugHandlerClass *hotplug_class = HOTPLUG_HANDLER_CLASS(class);
 524
 525    bus_class->print_dev = xen_bus_print_dev;
 526    bus_class->get_dev_path = xen_bus_get_dev_path;
 527    bus_class->realize = xen_bus_realize;
 528    bus_class->unrealize = xen_bus_unrealize;
 529
 530    hotplug_class->unplug_request = xen_bus_unplug_request;
 531}
 532
 533static const TypeInfo xen_bus_type_info = {
 534    .name = TYPE_XEN_BUS,
 535    .parent = TYPE_BUS,
 536    .instance_size = sizeof(XenBus),
 537    .class_size = sizeof(XenBusClass),
 538    .class_init = xen_bus_class_init,
 539    .interfaces = (InterfaceInfo[]) {
 540        { TYPE_HOTPLUG_HANDLER },
 541        { }
 542    },
 543};
 544
 545void xen_device_backend_printf(XenDevice *xendev, const char *key,
 546                               const char *fmt, ...)
 547{
 548    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 549    Error *local_err = NULL;
 550    va_list ap;
 551
 552    g_assert(xenbus->xsh);
 553
 554    va_start(ap, fmt);
 555    xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
 556                    &local_err, fmt, ap);
 557    va_end(ap);
 558
 559    if (local_err) {
 560        error_report_err(local_err);
 561    }
 562}
 563
 564static int xen_device_backend_scanf(XenDevice *xendev, const char *key,
 565                                    const char *fmt, ...)
 566{
 567    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 568    va_list ap;
 569    int rc;
 570
 571    g_assert(xenbus->xsh);
 572
 573    va_start(ap, fmt);
 574    rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->backend_path, key,
 575                        NULL, fmt, ap);
 576    va_end(ap);
 577
 578    return rc;
 579}
 580
 581void xen_device_backend_set_state(XenDevice *xendev,
 582                                  enum xenbus_state state)
 583{
 584    const char *type = object_get_typename(OBJECT(xendev));
 585
 586    if (xendev->backend_state == state) {
 587        return;
 588    }
 589
 590    trace_xen_device_backend_state(type, xendev->name,
 591                                   xs_strstate(state));
 592
 593    xendev->backend_state = state;
 594    xen_device_backend_printf(xendev, "state", "%u", state);
 595}
 596
 597enum xenbus_state xen_device_backend_get_state(XenDevice *xendev)
 598{
 599    return xendev->backend_state;
 600}
 601
 602static void xen_device_backend_set_online(XenDevice *xendev, bool online)
 603{
 604    const char *type = object_get_typename(OBJECT(xendev));
 605
 606    if (xendev->backend_online == online) {
 607        return;
 608    }
 609
 610    trace_xen_device_backend_online(type, xendev->name, online);
 611
 612    xendev->backend_online = online;
 613    xen_device_backend_printf(xendev, "online", "%u", online);
 614}
 615
 616/*
 617 * Tell from the state whether the frontend is likely alive,
 618 * i.e. it will react to a change of state of the backend.
 619 */
 620static bool xen_device_frontend_is_active(XenDevice *xendev)
 621{
 622    switch (xendev->frontend_state) {
 623    case XenbusStateInitWait:
 624    case XenbusStateInitialised:
 625    case XenbusStateConnected:
 626    case XenbusStateClosing:
 627        return true;
 628    default:
 629        return false;
 630    }
 631}
 632
 633static void xen_device_backend_changed(void *opaque)
 634{
 635    XenDevice *xendev = opaque;
 636    const char *type = object_get_typename(OBJECT(xendev));
 637    enum xenbus_state state;
 638    unsigned int online;
 639
 640    trace_xen_device_backend_changed(type, xendev->name);
 641
 642    if (xen_device_backend_scanf(xendev, "state", "%u", &state) != 1) {
 643        state = XenbusStateUnknown;
 644    }
 645
 646    xen_device_backend_set_state(xendev, state);
 647
 648    if (xen_device_backend_scanf(xendev, "online", "%u", &online) != 1) {
 649        online = 0;
 650    }
 651
 652    xen_device_backend_set_online(xendev, !!online);
 653
 654    /*
 655     * If the toolstack (or unplug request callback) has set the backend
 656     * state to Closing, but there is no active frontend then set the
 657     * backend state to Closed.
 658     */
 659    if (state == XenbusStateClosing &&
 660        !xen_device_frontend_is_active(xendev)) {
 661        xen_device_backend_set_state(xendev, XenbusStateClosed);
 662    }
 663
 664    /*
 665     * If a backend is still 'online' then we should leave it alone but,
 666     * if a backend is not 'online', then the device is a candidate
 667     * for destruction. Hence add it to the 'inactive' list to be cleaned
 668     * by xen_bus_cleanup().
 669     */
 670    if (!online &&
 671        (state == XenbusStateClosed ||  state == XenbusStateInitialising ||
 672         state == XenbusStateInitWait || state == XenbusStateUnknown) &&
 673        !xendev->inactive) {
 674        XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 675
 676        xendev->inactive = true;
 677        QLIST_INSERT_HEAD(&xenbus->inactive_devices, xendev, list);
 678
 679        /*
 680         * Re-write the state to cause a XenBus backend_watch notification,
 681         * resulting in a call to xen_bus_cleanup().
 682         */
 683        xen_device_backend_printf(xendev, "state", "%u", state);
 684    }
 685}
 686
 687static XenWatch *xen_device_add_watch(XenDevice *xendev, const char *node,
 688                                      const char *key,
 689                                      XenWatchHandler handler,
 690                                      Error **errp)
 691{
 692    const char *type = object_get_typename(OBJECT(xendev));
 693
 694    trace_xen_device_add_watch(type, xendev->name, node, key);
 695
 696    return watch_list_add(xendev->watch_list, node, key, handler, xendev,
 697                          errp);
 698}
 699
 700static void xen_device_remove_watch(XenDevice *xendev, XenWatch *watch,
 701                                    Error **errp)
 702{
 703    const char *type = object_get_typename(OBJECT(xendev));
 704
 705    trace_xen_device_remove_watch(type, xendev->name, watch->node,
 706                                  watch->key);
 707
 708    watch_list_remove(xendev->watch_list, watch, errp);
 709}
 710
 711
 712static void xen_device_backend_create(XenDevice *xendev, Error **errp)
 713{
 714    ERRP_GUARD();
 715    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 716    struct xs_permissions perms[2];
 717
 718    xendev->backend_path = xen_device_get_backend_path(xendev);
 719
 720    perms[0].id = xenbus->backend_id;
 721    perms[0].perms = XS_PERM_NONE;
 722    perms[1].id = xendev->frontend_id;
 723    perms[1].perms = XS_PERM_READ;
 724
 725    g_assert(xenbus->xsh);
 726
 727    xs_node_create(xenbus->xsh, XBT_NULL, xendev->backend_path, perms,
 728                   ARRAY_SIZE(perms), errp);
 729    if (*errp) {
 730        error_prepend(errp, "failed to create backend: ");
 731        return;
 732    }
 733
 734    xendev->backend_state_watch =
 735        xen_device_add_watch(xendev, xendev->backend_path,
 736                             "state", xen_device_backend_changed,
 737                             errp);
 738    if (*errp) {
 739        error_prepend(errp, "failed to watch backend state: ");
 740        return;
 741    }
 742
 743    xendev->backend_online_watch =
 744        xen_device_add_watch(xendev, xendev->backend_path,
 745                             "online", xen_device_backend_changed,
 746                             errp);
 747    if (*errp) {
 748        error_prepend(errp, "failed to watch backend online: ");
 749        return;
 750    }
 751}
 752
 753static void xen_device_backend_destroy(XenDevice *xendev)
 754{
 755    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 756    Error *local_err = NULL;
 757
 758    if (xendev->backend_online_watch) {
 759        xen_device_remove_watch(xendev, xendev->backend_online_watch, NULL);
 760        xendev->backend_online_watch = NULL;
 761    }
 762
 763    if (xendev->backend_state_watch) {
 764        xen_device_remove_watch(xendev, xendev->backend_state_watch, NULL);
 765        xendev->backend_state_watch = NULL;
 766    }
 767
 768    if (!xendev->backend_path) {
 769        return;
 770    }
 771
 772    g_assert(xenbus->xsh);
 773
 774    xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->backend_path,
 775                    &local_err);
 776    g_free(xendev->backend_path);
 777    xendev->backend_path = NULL;
 778
 779    if (local_err) {
 780        error_report_err(local_err);
 781    }
 782}
 783
 784void xen_device_frontend_printf(XenDevice *xendev, const char *key,
 785                                const char *fmt, ...)
 786{
 787    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 788    Error *local_err = NULL;
 789    va_list ap;
 790
 791    g_assert(xenbus->xsh);
 792
 793    va_start(ap, fmt);
 794    xs_node_vprintf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
 795                    &local_err, fmt, ap);
 796    va_end(ap);
 797
 798    if (local_err) {
 799        error_report_err(local_err);
 800    }
 801}
 802
 803int xen_device_frontend_scanf(XenDevice *xendev, const char *key,
 804                              const char *fmt, ...)
 805{
 806    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 807    va_list ap;
 808    int rc;
 809
 810    g_assert(xenbus->xsh);
 811
 812    va_start(ap, fmt);
 813    rc = xs_node_vscanf(xenbus->xsh, XBT_NULL, xendev->frontend_path, key,
 814                        NULL, fmt, ap);
 815    va_end(ap);
 816
 817    return rc;
 818}
 819
 820static void xen_device_frontend_set_state(XenDevice *xendev,
 821                                          enum xenbus_state state,
 822                                          bool publish)
 823{
 824    const char *type = object_get_typename(OBJECT(xendev));
 825
 826    if (xendev->frontend_state == state) {
 827        return;
 828    }
 829
 830    trace_xen_device_frontend_state(type, xendev->name,
 831                                    xs_strstate(state));
 832
 833    xendev->frontend_state = state;
 834    if (publish) {
 835        xen_device_frontend_printf(xendev, "state", "%u", state);
 836    }
 837}
 838
 839static void xen_device_frontend_changed(void *opaque)
 840{
 841    XenDevice *xendev = opaque;
 842    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
 843    const char *type = object_get_typename(OBJECT(xendev));
 844    enum xenbus_state state;
 845
 846    trace_xen_device_frontend_changed(type, xendev->name);
 847
 848    if (xen_device_frontend_scanf(xendev, "state", "%u", &state) != 1) {
 849        state = XenbusStateUnknown;
 850    }
 851
 852    xen_device_frontend_set_state(xendev, state, false);
 853
 854    if (state == XenbusStateInitialising &&
 855        xendev->backend_state == XenbusStateClosed &&
 856        xendev->backend_online) {
 857        /*
 858         * The frontend is re-initializing so switch back to
 859         * InitWait.
 860         */
 861        xen_device_backend_set_state(xendev, XenbusStateInitWait);
 862        return;
 863    }
 864
 865    if (xendev_class->frontend_changed) {
 866        Error *local_err = NULL;
 867
 868        xendev_class->frontend_changed(xendev, state, &local_err);
 869
 870        if (local_err) {
 871            error_reportf_err(local_err, "frontend change error: ");
 872        }
 873    }
 874}
 875
 876static bool xen_device_frontend_exists(XenDevice *xendev)
 877{
 878    enum xenbus_state state;
 879
 880    return (xen_device_frontend_scanf(xendev, "state", "%u", &state) == 1);
 881}
 882
 883static void xen_device_frontend_create(XenDevice *xendev, Error **errp)
 884{
 885    ERRP_GUARD();
 886    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 887    struct xs_permissions perms[2];
 888
 889    xendev->frontend_path = xen_device_get_frontend_path(xendev);
 890
 891    /*
 892     * The frontend area may have already been created by a legacy
 893     * toolstack.
 894     */
 895    if (!xen_device_frontend_exists(xendev)) {
 896        perms[0].id = xendev->frontend_id;
 897        perms[0].perms = XS_PERM_NONE;
 898        perms[1].id = xenbus->backend_id;
 899        perms[1].perms = XS_PERM_READ | XS_PERM_WRITE;
 900
 901        g_assert(xenbus->xsh);
 902
 903        xs_node_create(xenbus->xsh, XBT_NULL, xendev->frontend_path, perms,
 904                       ARRAY_SIZE(perms), errp);
 905        if (*errp) {
 906            error_prepend(errp, "failed to create frontend: ");
 907            return;
 908        }
 909    }
 910
 911    xendev->frontend_state_watch =
 912        xen_device_add_watch(xendev, xendev->frontend_path, "state",
 913                             xen_device_frontend_changed, errp);
 914    if (*errp) {
 915        error_prepend(errp, "failed to watch frontend state: ");
 916    }
 917}
 918
 919static void xen_device_frontend_destroy(XenDevice *xendev)
 920{
 921    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
 922    Error *local_err = NULL;
 923
 924    if (xendev->frontend_state_watch) {
 925        xen_device_remove_watch(xendev, xendev->frontend_state_watch,
 926                                NULL);
 927        xendev->frontend_state_watch = NULL;
 928    }
 929
 930    if (!xendev->frontend_path) {
 931        return;
 932    }
 933
 934    g_assert(xenbus->xsh);
 935
 936    xs_node_destroy(xenbus->xsh, XBT_NULL, xendev->frontend_path,
 937                    &local_err);
 938    g_free(xendev->frontend_path);
 939    xendev->frontend_path = NULL;
 940
 941    if (local_err) {
 942        error_report_err(local_err);
 943    }
 944}
 945
 946void xen_device_set_max_grant_refs(XenDevice *xendev, unsigned int nr_refs,
 947                                   Error **errp)
 948{
 949    if (xengnttab_set_max_grants(xendev->xgth, nr_refs)) {
 950        error_setg_errno(errp, errno, "xengnttab_set_max_grants failed");
 951    }
 952}
 953
 954void *xen_device_map_grant_refs(XenDevice *xendev, uint32_t *refs,
 955                                unsigned int nr_refs, int prot,
 956                                Error **errp)
 957{
 958    void *map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_refs,
 959                                                xendev->frontend_id, refs,
 960                                                prot);
 961
 962    if (!map) {
 963        error_setg_errno(errp, errno,
 964                         "xengnttab_map_domain_grant_refs failed");
 965    }
 966
 967    return map;
 968}
 969
 970void xen_device_unmap_grant_refs(XenDevice *xendev, void *map,
 971                                 unsigned int nr_refs, Error **errp)
 972{
 973    if (xengnttab_unmap(xendev->xgth, map, nr_refs)) {
 974        error_setg_errno(errp, errno, "xengnttab_unmap failed");
 975    }
 976}
 977
 978static void compat_copy_grant_refs(XenDevice *xendev, bool to_domain,
 979                                   XenDeviceGrantCopySegment segs[],
 980                                   unsigned int nr_segs, Error **errp)
 981{
 982    uint32_t *refs = g_new(uint32_t, nr_segs);
 983    int prot = to_domain ? PROT_WRITE : PROT_READ;
 984    void *map;
 985    unsigned int i;
 986
 987    for (i = 0; i < nr_segs; i++) {
 988        XenDeviceGrantCopySegment *seg = &segs[i];
 989
 990        refs[i] = to_domain ? seg->dest.foreign.ref :
 991            seg->source.foreign.ref;
 992    }
 993
 994    map = xengnttab_map_domain_grant_refs(xendev->xgth, nr_segs,
 995                                          xendev->frontend_id, refs,
 996                                          prot);
 997    if (!map) {
 998        error_setg_errno(errp, errno,
 999                         "xengnttab_map_domain_grant_refs failed");
1000        goto done;
1001    }
1002
1003    for (i = 0; i < nr_segs; i++) {
1004        XenDeviceGrantCopySegment *seg = &segs[i];
1005        void *page = map + (i * XC_PAGE_SIZE);
1006
1007        if (to_domain) {
1008            memcpy(page + seg->dest.foreign.offset, seg->source.virt,
1009                   seg->len);
1010        } else {
1011            memcpy(seg->dest.virt, page + seg->source.foreign.offset,
1012                   seg->len);
1013        }
1014    }
1015
1016    if (xengnttab_unmap(xendev->xgth, map, nr_segs)) {
1017        error_setg_errno(errp, errno, "xengnttab_unmap failed");
1018    }
1019
1020done:
1021    g_free(refs);
1022}
1023
1024void xen_device_copy_grant_refs(XenDevice *xendev, bool to_domain,
1025                                XenDeviceGrantCopySegment segs[],
1026                                unsigned int nr_segs, Error **errp)
1027{
1028    xengnttab_grant_copy_segment_t *xengnttab_segs;
1029    unsigned int i;
1030
1031    if (!xendev->feature_grant_copy) {
1032        compat_copy_grant_refs(xendev, to_domain, segs, nr_segs, errp);
1033        return;
1034    }
1035
1036    xengnttab_segs = g_new0(xengnttab_grant_copy_segment_t, nr_segs);
1037
1038    for (i = 0; i < nr_segs; i++) {
1039        XenDeviceGrantCopySegment *seg = &segs[i];
1040        xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
1041
1042        if (to_domain) {
1043            xengnttab_seg->flags = GNTCOPY_dest_gref;
1044            xengnttab_seg->dest.foreign.domid = xendev->frontend_id;
1045            xengnttab_seg->dest.foreign.ref = seg->dest.foreign.ref;
1046            xengnttab_seg->dest.foreign.offset = seg->dest.foreign.offset;
1047            xengnttab_seg->source.virt = seg->source.virt;
1048        } else {
1049            xengnttab_seg->flags = GNTCOPY_source_gref;
1050            xengnttab_seg->source.foreign.domid = xendev->frontend_id;
1051            xengnttab_seg->source.foreign.ref = seg->source.foreign.ref;
1052            xengnttab_seg->source.foreign.offset =
1053                seg->source.foreign.offset;
1054            xengnttab_seg->dest.virt = seg->dest.virt;
1055        }
1056
1057        xengnttab_seg->len = seg->len;
1058    }
1059
1060    if (xengnttab_grant_copy(xendev->xgth, nr_segs, xengnttab_segs)) {
1061        error_setg_errno(errp, errno, "xengnttab_grant_copy failed");
1062        goto done;
1063    }
1064
1065    for (i = 0; i < nr_segs; i++) {
1066        xengnttab_grant_copy_segment_t *xengnttab_seg = &xengnttab_segs[i];
1067
1068        if (xengnttab_seg->status != GNTST_okay) {
1069            error_setg(errp, "xengnttab_grant_copy seg[%u] failed", i);
1070            break;
1071        }
1072    }
1073
1074done:
1075    g_free(xengnttab_segs);
1076}
1077
1078struct XenEventChannel {
1079    QLIST_ENTRY(XenEventChannel) list;
1080    AioContext *ctx;
1081    xenevtchn_handle *xeh;
1082    evtchn_port_t local_port;
1083    XenEventHandler handler;
1084    void *opaque;
1085};
1086
1087static bool xen_device_poll(void *opaque)
1088{
1089    XenEventChannel *channel = opaque;
1090
1091    return channel->handler(channel->opaque);
1092}
1093
1094static void xen_device_event(void *opaque)
1095{
1096    XenEventChannel *channel = opaque;
1097    unsigned long port = xenevtchn_pending(channel->xeh);
1098
1099    if (port == channel->local_port) {
1100        xen_device_poll(channel);
1101
1102        xenevtchn_unmask(channel->xeh, port);
1103    }
1104}
1105
1106void xen_device_set_event_channel_context(XenDevice *xendev,
1107                                          XenEventChannel *channel,
1108                                          AioContext *ctx,
1109                                          Error **errp)
1110{
1111    if (!channel) {
1112        error_setg(errp, "bad channel");
1113        return;
1114    }
1115
1116    if (channel->ctx)
1117        aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1118                           NULL, NULL, NULL, NULL);
1119
1120    channel->ctx = ctx;
1121    aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1122                       xen_device_event, NULL, xen_device_poll, channel);
1123}
1124
1125XenEventChannel *xen_device_bind_event_channel(XenDevice *xendev,
1126                                               unsigned int port,
1127                                               XenEventHandler handler,
1128                                               void *opaque, Error **errp)
1129{
1130    XenEventChannel *channel = g_new0(XenEventChannel, 1);
1131    xenevtchn_port_or_error_t local_port;
1132
1133    channel->xeh = xenevtchn_open(NULL, 0);
1134    if (!channel->xeh) {
1135        error_setg_errno(errp, errno, "failed xenevtchn_open");
1136        goto fail;
1137    }
1138
1139    local_port = xenevtchn_bind_interdomain(channel->xeh,
1140                                            xendev->frontend_id,
1141                                            port);
1142    if (local_port < 0) {
1143        error_setg_errno(errp, errno, "xenevtchn_bind_interdomain failed");
1144        goto fail;
1145    }
1146
1147    channel->local_port = local_port;
1148    channel->handler = handler;
1149    channel->opaque = opaque;
1150
1151    /* Only reason for failure is a NULL channel */
1152    xen_device_set_event_channel_context(xendev, channel,
1153                                         qemu_get_aio_context(),
1154                                         &error_abort);
1155
1156    QLIST_INSERT_HEAD(&xendev->event_channels, channel, list);
1157
1158    return channel;
1159
1160fail:
1161    if (channel->xeh) {
1162        xenevtchn_close(channel->xeh);
1163    }
1164
1165    g_free(channel);
1166
1167    return NULL;
1168}
1169
1170void xen_device_notify_event_channel(XenDevice *xendev,
1171                                     XenEventChannel *channel,
1172                                     Error **errp)
1173{
1174    if (!channel) {
1175        error_setg(errp, "bad channel");
1176        return;
1177    }
1178
1179    if (xenevtchn_notify(channel->xeh, channel->local_port) < 0) {
1180        error_setg_errno(errp, errno, "xenevtchn_notify failed");
1181    }
1182}
1183
1184void xen_device_unbind_event_channel(XenDevice *xendev,
1185                                     XenEventChannel *channel,
1186                                     Error **errp)
1187{
1188    if (!channel) {
1189        error_setg(errp, "bad channel");
1190        return;
1191    }
1192
1193    QLIST_REMOVE(channel, list);
1194
1195    aio_set_fd_handler(channel->ctx, xenevtchn_fd(channel->xeh), true,
1196                       NULL, NULL, NULL, NULL);
1197
1198    if (xenevtchn_unbind(channel->xeh, channel->local_port) < 0) {
1199        error_setg_errno(errp, errno, "xenevtchn_unbind failed");
1200    }
1201
1202    xenevtchn_close(channel->xeh);
1203    g_free(channel);
1204}
1205
1206static void xen_device_unrealize(DeviceState *dev)
1207{
1208    XenDevice *xendev = XEN_DEVICE(dev);
1209    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1210    const char *type = object_get_typename(OBJECT(xendev));
1211    XenEventChannel *channel, *next;
1212
1213    if (!xendev->name) {
1214        return;
1215    }
1216
1217    trace_xen_device_unrealize(type, xendev->name);
1218
1219    if (xendev->exit.notify) {
1220        qemu_remove_exit_notifier(&xendev->exit);
1221        xendev->exit.notify = NULL;
1222    }
1223
1224    if (xendev_class->unrealize) {
1225        xendev_class->unrealize(xendev);
1226    }
1227
1228    /* Make sure all event channels are cleaned up */
1229    QLIST_FOREACH_SAFE(channel, &xendev->event_channels, list, next) {
1230        xen_device_unbind_event_channel(xendev, channel, NULL);
1231    }
1232
1233    xen_device_frontend_destroy(xendev);
1234    xen_device_backend_destroy(xendev);
1235
1236    if (xendev->xgth) {
1237        xengnttab_close(xendev->xgth);
1238        xendev->xgth = NULL;
1239    }
1240
1241    if (xendev->watch_list) {
1242        watch_list_destroy(xendev->watch_list);
1243        xendev->watch_list = NULL;
1244    }
1245
1246    if (xendev->xsh) {
1247        xs_close(xendev->xsh);
1248        xendev->xsh = NULL;
1249    }
1250
1251    g_free(xendev->name);
1252    xendev->name = NULL;
1253}
1254
1255static void xen_device_exit(Notifier *n, void *data)
1256{
1257    XenDevice *xendev = container_of(n, XenDevice, exit);
1258
1259    xen_device_unrealize(DEVICE(xendev));
1260}
1261
1262static void xen_device_realize(DeviceState *dev, Error **errp)
1263{
1264    ERRP_GUARD();
1265    XenDevice *xendev = XEN_DEVICE(dev);
1266    XenDeviceClass *xendev_class = XEN_DEVICE_GET_CLASS(xendev);
1267    XenBus *xenbus = XEN_BUS(qdev_get_parent_bus(DEVICE(xendev)));
1268    const char *type = object_get_typename(OBJECT(xendev));
1269
1270    if (xendev->frontend_id == DOMID_INVALID) {
1271        xendev->frontend_id = xen_domid;
1272    }
1273
1274    if (xendev->frontend_id >= DOMID_FIRST_RESERVED) {
1275        error_setg(errp, "invalid frontend-id");
1276        goto unrealize;
1277    }
1278
1279    if (!xendev_class->get_name) {
1280        error_setg(errp, "get_name method not implemented");
1281        goto unrealize;
1282    }
1283
1284    xendev->name = xendev_class->get_name(xendev, errp);
1285    if (*errp) {
1286        error_prepend(errp, "failed to get device name: ");
1287        goto unrealize;
1288    }
1289
1290    trace_xen_device_realize(type, xendev->name);
1291
1292    xendev->xsh = xs_open(0);
1293    if (!xendev->xsh) {
1294        error_setg_errno(errp, errno, "failed xs_open");
1295        goto unrealize;
1296    }
1297
1298    xendev->watch_list = watch_list_create(xendev->xsh);
1299
1300    xendev->xgth = xengnttab_open(NULL, 0);
1301    if (!xendev->xgth) {
1302        error_setg_errno(errp, errno, "failed xengnttab_open");
1303        goto unrealize;
1304    }
1305
1306    xendev->feature_grant_copy =
1307        (xengnttab_grant_copy(xendev->xgth, 0, NULL) == 0);
1308
1309    xen_device_backend_create(xendev, errp);
1310    if (*errp) {
1311        goto unrealize;
1312    }
1313
1314    xen_device_frontend_create(xendev, errp);
1315    if (*errp) {
1316        goto unrealize;
1317    }
1318
1319    if (xendev_class->realize) {
1320        xendev_class->realize(xendev, errp);
1321        if (*errp) {
1322            goto unrealize;
1323        }
1324    }
1325
1326    xen_device_backend_printf(xendev, "frontend", "%s",
1327                              xendev->frontend_path);
1328    xen_device_backend_printf(xendev, "frontend-id", "%u",
1329                              xendev->frontend_id);
1330    xen_device_backend_printf(xendev, "hotplug-status", "connected");
1331
1332    xen_device_backend_set_online(xendev, true);
1333    xen_device_backend_set_state(xendev, XenbusStateInitWait);
1334
1335    if (!xen_device_frontend_exists(xendev)) {
1336        xen_device_frontend_printf(xendev, "backend", "%s",
1337                                   xendev->backend_path);
1338        xen_device_frontend_printf(xendev, "backend-id", "%u",
1339                                   xenbus->backend_id);
1340
1341        xen_device_frontend_set_state(xendev, XenbusStateInitialising, true);
1342    }
1343
1344    xendev->exit.notify = xen_device_exit;
1345    qemu_add_exit_notifier(&xendev->exit);
1346    return;
1347
1348unrealize:
1349    xen_device_unrealize(dev);
1350}
1351
1352static Property xen_device_props[] = {
1353    DEFINE_PROP_UINT16("frontend-id", XenDevice, frontend_id,
1354                       DOMID_INVALID),
1355    DEFINE_PROP_END_OF_LIST()
1356};
1357
1358static void xen_device_class_init(ObjectClass *class, void *data)
1359{
1360    DeviceClass *dev_class = DEVICE_CLASS(class);
1361
1362    dev_class->realize = xen_device_realize;
1363    dev_class->unrealize = xen_device_unrealize;
1364    device_class_set_props(dev_class, xen_device_props);
1365    dev_class->bus_type = TYPE_XEN_BUS;
1366}
1367
1368static const TypeInfo xen_device_type_info = {
1369    .name = TYPE_XEN_DEVICE,
1370    .parent = TYPE_DEVICE,
1371    .instance_size = sizeof(XenDevice),
1372    .abstract = true,
1373    .class_size = sizeof(XenDeviceClass),
1374    .class_init = xen_device_class_init,
1375};
1376
1377typedef struct XenBridge {
1378    SysBusDevice busdev;
1379} XenBridge;
1380
1381#define TYPE_XEN_BRIDGE "xen-bridge"
1382
1383static const TypeInfo xen_bridge_type_info = {
1384    .name = TYPE_XEN_BRIDGE,
1385    .parent = TYPE_SYS_BUS_DEVICE,
1386    .instance_size = sizeof(XenBridge),
1387};
1388
1389static void xen_register_types(void)
1390{
1391    type_register_static(&xen_bridge_type_info);
1392    type_register_static(&xen_bus_type_info);
1393    type_register_static(&xen_device_type_info);
1394}
1395
1396type_init(xen_register_types)
1397
1398void xen_bus_init(void)
1399{
1400    DeviceState *dev = qdev_new(TYPE_XEN_BRIDGE);
1401    BusState *bus = qbus_new(TYPE_XEN_BUS, dev, NULL);
1402
1403    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
1404    qbus_set_bus_hotplug_handler(bus);
1405}
1406