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-legacy-backend.c (24142B)


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