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_pvdev.c (8066B)


      1/*
      2 * Xen para-virtualization device
      3 *
      4 *  (c) 2008 Gerd Hoffmann <kraxel@redhat.com>
      5 *
      6 * This library is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU Lesser General Public
      8 * License as published by the Free Software Foundation; either
      9 * version 2.1 of the License, or (at your option) any later version.
     10 *
     11 * This library is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 * Lesser General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU Lesser General Public
     17 * License along with this library; if not, see <http://www.gnu.org/licenses/>
     18 */
     19
     20#include "qemu/osdep.h"
     21#include "qemu/log.h"
     22#include "qemu/main-loop.h"
     23#include "hw/qdev-core.h"
     24#include "hw/xen/xen-legacy-backend.h"
     25#include "hw/xen/xen_pvdev.h"
     26
     27/* private */
     28static int debug;
     29
     30struct xs_dirs {
     31    char *xs_dir;
     32    QTAILQ_ENTRY(xs_dirs) list;
     33};
     34
     35static QTAILQ_HEAD(, xs_dirs) xs_cleanup =
     36    QTAILQ_HEAD_INITIALIZER(xs_cleanup);
     37
     38static QTAILQ_HEAD(, XenLegacyDevice) xendevs =
     39    QTAILQ_HEAD_INITIALIZER(xendevs);
     40
     41/* ------------------------------------------------------------- */
     42
     43static void xenstore_cleanup_dir(char *dir)
     44{
     45    struct xs_dirs *d;
     46
     47    d = g_malloc(sizeof(*d));
     48    d->xs_dir = dir;
     49    QTAILQ_INSERT_TAIL(&xs_cleanup, d, list);
     50}
     51
     52void xen_config_cleanup(void)
     53{
     54    struct xs_dirs *d;
     55
     56    QTAILQ_FOREACH(d, &xs_cleanup, list) {
     57        xs_rm(xenstore, 0, d->xs_dir);
     58    }
     59}
     60
     61int xenstore_mkdir(char *path, int p)
     62{
     63    struct xs_permissions perms[2] = {
     64        {
     65            .id    = 0, /* set owner: dom0 */
     66        }, {
     67            .id    = xen_domid,
     68            .perms = p,
     69        }
     70    };
     71
     72    if (!xs_mkdir(xenstore, 0, path)) {
     73        xen_pv_printf(NULL, 0, "xs_mkdir %s: failed\n", path);
     74        return -1;
     75    }
     76    xenstore_cleanup_dir(g_strdup(path));
     77
     78    if (!xs_set_permissions(xenstore, 0, path, perms, 2)) {
     79        xen_pv_printf(NULL, 0, "xs_set_permissions %s: failed\n", path);
     80        return -1;
     81    }
     82    return 0;
     83}
     84
     85int xenstore_write_str(const char *base, const char *node, const char *val)
     86{
     87    char abspath[XEN_BUFSIZE];
     88
     89    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
     90    if (!xs_write(xenstore, 0, abspath, val, strlen(val))) {
     91        return -1;
     92    }
     93    return 0;
     94}
     95
     96char *xenstore_read_str(const char *base, const char *node)
     97{
     98    char abspath[XEN_BUFSIZE];
     99    unsigned int len;
    100    char *str, *ret = NULL;
    101
    102    snprintf(abspath, sizeof(abspath), "%s/%s", base, node);
    103    str = xs_read(xenstore, 0, abspath, &len);
    104    if (str != NULL) {
    105        /* move to qemu-allocated memory to make sure
    106         * callers can savely g_free() stuff. */
    107        ret = g_strdup(str);
    108        free(str);
    109    }
    110    return ret;
    111}
    112
    113int xenstore_write_int(const char *base, const char *node, int ival)
    114{
    115    char val[12];
    116
    117    snprintf(val, sizeof(val), "%d", ival);
    118    return xenstore_write_str(base, node, val);
    119}
    120
    121int xenstore_write_int64(const char *base, const char *node, int64_t ival)
    122{
    123    char val[21];
    124
    125    snprintf(val, sizeof(val), "%"PRId64, ival);
    126    return xenstore_write_str(base, node, val);
    127}
    128
    129int xenstore_read_int(const char *base, const char *node, int *ival)
    130{
    131    char *val;
    132    int rc = -1;
    133
    134    val = xenstore_read_str(base, node);
    135    if (val && 1 == sscanf(val, "%d", ival)) {
    136        rc = 0;
    137    }
    138    g_free(val);
    139    return rc;
    140}
    141
    142int xenstore_read_uint64(const char *base, const char *node, uint64_t *uval)
    143{
    144    char *val;
    145    int rc = -1;
    146
    147    val = xenstore_read_str(base, node);
    148    if (val && 1 == sscanf(val, "%"SCNu64, uval)) {
    149        rc = 0;
    150    }
    151    g_free(val);
    152    return rc;
    153}
    154
    155void xenstore_update(void *unused)
    156{
    157    char **vec = NULL;
    158    intptr_t type, ops, ptr;
    159    unsigned int dom, count;
    160
    161    vec = xs_read_watch(xenstore, &count);
    162    if (vec == NULL) {
    163        goto cleanup;
    164    }
    165
    166    if (sscanf(vec[XS_WATCH_TOKEN], "be:%" PRIxPTR ":%d:%" PRIxPTR,
    167               &type, &dom, &ops) == 3) {
    168        xenstore_update_be(vec[XS_WATCH_PATH], (void *)type, dom, (void*)ops);
    169    }
    170    if (sscanf(vec[XS_WATCH_TOKEN], "fe:%" PRIxPTR, &ptr) == 1) {
    171        xenstore_update_fe(vec[XS_WATCH_PATH], (void *)ptr);
    172    }
    173
    174cleanup:
    175    free(vec);
    176}
    177
    178const char *xenbus_strstate(enum xenbus_state state)
    179{
    180    static const char *const name[] = {
    181        [XenbusStateUnknown]       = "Unknown",
    182        [XenbusStateInitialising]  = "Initialising",
    183        [XenbusStateInitWait]      = "InitWait",
    184        [XenbusStateInitialised]   = "Initialised",
    185        [XenbusStateConnected]     = "Connected",
    186        [XenbusStateClosing]       = "Closing",
    187        [XenbusStateClosed]        = "Closed",
    188    };
    189    return (state < ARRAY_SIZE(name)) ? name[state] : "INVALID";
    190}
    191
    192/*
    193 * msg_level:
    194 *  0 == errors (stderr + logfile).
    195 *  1 == informative debug messages (logfile only).
    196 *  2 == noisy debug messages (logfile only).
    197 *  3 == will flood your log (logfile only).
    198 */
    199void xen_pv_printf(struct XenLegacyDevice *xendev, int msg_level,
    200                   const char *fmt, ...)
    201{
    202    va_list args;
    203
    204    if (xendev) {
    205        if (msg_level > xendev->debug) {
    206            return;
    207        }
    208        qemu_log("xen be: %s: ", xendev->name);
    209        if (msg_level == 0) {
    210            fprintf(stderr, "xen be: %s: ", xendev->name);
    211        }
    212    } else {
    213        if (msg_level > debug) {
    214            return;
    215        }
    216        qemu_log("xen be core: ");
    217        if (msg_level == 0) {
    218            fprintf(stderr, "xen be core: ");
    219        }
    220    }
    221    va_start(args, fmt);
    222    qemu_log_vprintf(fmt, args);
    223    va_end(args);
    224    if (msg_level == 0) {
    225        va_start(args, fmt);
    226        vfprintf(stderr, fmt, args);
    227        va_end(args);
    228    }
    229    qemu_log_flush();
    230}
    231
    232void xen_pv_evtchn_event(void *opaque)
    233{
    234    struct XenLegacyDevice *xendev = opaque;
    235    evtchn_port_t port;
    236
    237    port = xenevtchn_pending(xendev->evtchndev);
    238    if (port != xendev->local_port) {
    239        xen_pv_printf(xendev, 0,
    240                      "xenevtchn_pending returned %d (expected %d)\n",
    241                      port, xendev->local_port);
    242        return;
    243    }
    244    xenevtchn_unmask(xendev->evtchndev, port);
    245
    246    if (xendev->ops->event) {
    247        xendev->ops->event(xendev);
    248    }
    249}
    250
    251void xen_pv_unbind_evtchn(struct XenLegacyDevice *xendev)
    252{
    253    if (xendev->local_port == -1) {
    254        return;
    255    }
    256    qemu_set_fd_handler(xenevtchn_fd(xendev->evtchndev), NULL, NULL, NULL);
    257    xenevtchn_unbind(xendev->evtchndev, xendev->local_port);
    258    xen_pv_printf(xendev, 2, "unbind evtchn port %d\n", xendev->local_port);
    259    xendev->local_port = -1;
    260}
    261
    262int xen_pv_send_notify(struct XenLegacyDevice *xendev)
    263{
    264    return xenevtchn_notify(xendev->evtchndev, xendev->local_port);
    265}
    266
    267/* ------------------------------------------------------------- */
    268
    269struct XenLegacyDevice *xen_pv_find_xendev(const char *type, int dom, int dev)
    270{
    271    struct XenLegacyDevice *xendev;
    272
    273    QTAILQ_FOREACH(xendev, &xendevs, next) {
    274        if (xendev->dom != dom) {
    275            continue;
    276        }
    277        if (xendev->dev != dev) {
    278            continue;
    279        }
    280        if (strcmp(xendev->type, type) != 0) {
    281            continue;
    282        }
    283        return xendev;
    284    }
    285    return NULL;
    286}
    287
    288/*
    289 * release xen backend device.
    290 */
    291void xen_pv_del_xendev(struct XenLegacyDevice *xendev)
    292{
    293    if (xendev->ops->free) {
    294        xendev->ops->free(xendev);
    295    }
    296
    297    if (xendev->fe) {
    298        char token[XEN_BUFSIZE];
    299        snprintf(token, sizeof(token), "fe:%p", xendev);
    300        xs_unwatch(xenstore, xendev->fe, token);
    301        g_free(xendev->fe);
    302    }
    303
    304    if (xendev->evtchndev != NULL) {
    305        xenevtchn_close(xendev->evtchndev);
    306    }
    307    if (xendev->gnttabdev != NULL) {
    308        xengnttab_close(xendev->gnttabdev);
    309    }
    310
    311    QTAILQ_REMOVE(&xendevs, xendev, next);
    312
    313    qdev_unplug(&xendev->qdev, NULL);
    314}
    315
    316void xen_pv_insert_xendev(struct XenLegacyDevice *xendev)
    317{
    318    QTAILQ_INSERT_TAIL(&xendevs, xendev, next);
    319}