cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

xen-bus.c (38923B)


      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}