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

libvhost-user-glib.c (3850B)


      1/*
      2 * Vhost User library
      3 *
      4 * Copyright (c) 2016 Nutanix Inc. All rights reserved.
      5 * Copyright (c) 2017 Red Hat, Inc.
      6 *
      7 * Authors:
      8 *  Marc-André Lureau <mlureau@redhat.com>
      9 *  Felipe Franciosi <felipe@nutanix.com>
     10 *
     11 * This work is licensed under the terms of the GNU GPL, version 2 or
     12 * later.  See the COPYING file in the top-level directory.
     13 */
     14
     15#include "libvhost-user-glib.h"
     16
     17#ifndef container_of
     18#define container_of(ptr, type, member)              \
     19    __extension__({                                  \
     20        void *__mptr = (void *)(ptr);                \
     21        ((type *)(__mptr - offsetof(type, member))); \
     22    })
     23#endif
     24
     25/* glib event loop integration for libvhost-user and misc callbacks */
     26
     27G_STATIC_ASSERT((int)G_IO_IN == (int)VU_WATCH_IN);
     28G_STATIC_ASSERT((int)G_IO_OUT == (int)VU_WATCH_OUT);
     29G_STATIC_ASSERT((int)G_IO_PRI == (int)VU_WATCH_PRI);
     30G_STATIC_ASSERT((int)G_IO_ERR == (int)VU_WATCH_ERR);
     31G_STATIC_ASSERT((int)G_IO_HUP == (int)VU_WATCH_HUP);
     32
     33typedef struct VugSrc {
     34    GSource parent;
     35    VuDev *dev;
     36    GPollFD gfd;
     37} VugSrc;
     38
     39static gboolean
     40vug_src_prepare(GSource *gsrc, gint *timeout)
     41{
     42    g_assert(timeout);
     43
     44    *timeout = -1;
     45    return FALSE;
     46}
     47
     48static gboolean
     49vug_src_check(GSource *gsrc)
     50{
     51    VugSrc *src = (VugSrc *)gsrc;
     52
     53    g_assert(src);
     54
     55    return src->gfd.revents & src->gfd.events;
     56}
     57
     58static gboolean
     59vug_src_dispatch(GSource *gsrc, GSourceFunc cb, gpointer data)
     60{
     61    VugSrc *src = (VugSrc *)gsrc;
     62
     63    g_assert(src);
     64
     65    ((vu_watch_cb)cb)(src->dev, src->gfd.revents, data);
     66
     67    return G_SOURCE_CONTINUE;
     68}
     69
     70static GSourceFuncs vug_src_funcs = {
     71    vug_src_prepare,
     72    vug_src_check,
     73    vug_src_dispatch,
     74    NULL
     75};
     76
     77GSource *
     78vug_source_new(VugDev *gdev, int fd, GIOCondition cond,
     79               vu_watch_cb vu_cb, gpointer data)
     80{
     81    VuDev *dev = &gdev->parent;
     82    GSource *gsrc;
     83    VugSrc *src;
     84    guint id;
     85
     86    g_assert(gdev);
     87    g_assert(fd >= 0);
     88    g_assert(vu_cb);
     89
     90    gsrc = g_source_new(&vug_src_funcs, sizeof(VugSrc));
     91    g_source_set_callback(gsrc, (GSourceFunc)vu_cb, data, NULL);
     92    src = (VugSrc *)gsrc;
     93    src->dev = dev;
     94    src->gfd.fd = fd;
     95    src->gfd.events = cond;
     96
     97    g_source_add_poll(gsrc, &src->gfd);
     98    id = g_source_attach(gsrc, g_main_context_get_thread_default());
     99    g_assert(id);
    100
    101    return gsrc;
    102}
    103
    104static void
    105set_watch(VuDev *vu_dev, int fd, int vu_evt, vu_watch_cb cb, void *pvt)
    106{
    107    GSource *src;
    108    VugDev *dev;
    109
    110    g_assert(vu_dev);
    111    g_assert(fd >= 0);
    112    g_assert(cb);
    113
    114    dev = container_of(vu_dev, VugDev, parent);
    115    src = vug_source_new(dev, fd, vu_evt, cb, pvt);
    116    g_hash_table_replace(dev->fdmap, GINT_TO_POINTER(fd), src);
    117}
    118
    119static void
    120remove_watch(VuDev *vu_dev, int fd)
    121{
    122    VugDev *dev;
    123
    124    g_assert(vu_dev);
    125    g_assert(fd >= 0);
    126
    127    dev = container_of(vu_dev, VugDev, parent);
    128    g_hash_table_remove(dev->fdmap, GINT_TO_POINTER(fd));
    129}
    130
    131
    132static void vug_watch(VuDev *dev, int condition, void *data)
    133{
    134    if (!vu_dispatch(dev) != 0) {
    135        dev->panic(dev, "Error processing vhost message");
    136    }
    137}
    138
    139void vug_source_destroy(GSource *src)
    140{
    141    if (!src) {
    142        return;
    143    }
    144
    145    g_source_destroy(src);
    146    g_source_unref(src);
    147}
    148
    149bool
    150vug_init(VugDev *dev, uint16_t max_queues, int socket,
    151         vu_panic_cb panic, const VuDevIface *iface)
    152{
    153    g_assert(dev);
    154    g_assert(iface);
    155
    156    if (!vu_init(&dev->parent, max_queues, socket, panic, NULL, set_watch,
    157                 remove_watch, iface)) {
    158        return false;
    159    }
    160
    161    dev->fdmap = g_hash_table_new_full(NULL, NULL, NULL,
    162                                       (GDestroyNotify) vug_source_destroy);
    163
    164    dev->src = vug_source_new(dev, socket, G_IO_IN, vug_watch, NULL);
    165
    166    return true;
    167}
    168
    169void
    170vug_deinit(VugDev *dev)
    171{
    172    g_assert(dev);
    173
    174    g_hash_table_unref(dev->fdmap);
    175    vug_source_destroy(dev->src);
    176}