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

channel-watch.c (8922B)


      1/*
      2 * QEMU I/O channels watch helper APIs
      3 *
      4 * Copyright (c) 2015 Red Hat, Inc.
      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
     21#include "qemu/osdep.h"
     22#include "io/channel-watch.h"
     23
     24typedef struct QIOChannelFDSource QIOChannelFDSource;
     25struct QIOChannelFDSource {
     26    GSource parent;
     27    GPollFD fd;
     28    QIOChannel *ioc;
     29    GIOCondition condition;
     30};
     31
     32
     33#ifdef CONFIG_WIN32
     34typedef struct QIOChannelSocketSource QIOChannelSocketSource;
     35struct QIOChannelSocketSource {
     36    GSource parent;
     37    GPollFD fd;
     38    QIOChannel *ioc;
     39    SOCKET socket;
     40    int revents;
     41    GIOCondition condition;
     42};
     43
     44#endif
     45
     46
     47typedef struct QIOChannelFDPairSource QIOChannelFDPairSource;
     48struct QIOChannelFDPairSource {
     49    GSource parent;
     50    GPollFD fdread;
     51    GPollFD fdwrite;
     52    QIOChannel *ioc;
     53    GIOCondition condition;
     54};
     55
     56
     57static gboolean
     58qio_channel_fd_source_prepare(GSource *source G_GNUC_UNUSED,
     59                              gint *timeout)
     60{
     61    *timeout = -1;
     62
     63    return FALSE;
     64}
     65
     66
     67static gboolean
     68qio_channel_fd_source_check(GSource *source)
     69{
     70    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
     71
     72    return ssource->fd.revents & ssource->condition;
     73}
     74
     75
     76static gboolean
     77qio_channel_fd_source_dispatch(GSource *source,
     78                               GSourceFunc callback,
     79                               gpointer user_data)
     80{
     81    QIOChannelFunc func = (QIOChannelFunc)callback;
     82    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
     83
     84    return (*func)(ssource->ioc,
     85                   ssource->fd.revents & ssource->condition,
     86                   user_data);
     87}
     88
     89
     90static void
     91qio_channel_fd_source_finalize(GSource *source)
     92{
     93    QIOChannelFDSource *ssource = (QIOChannelFDSource *)source;
     94
     95    object_unref(OBJECT(ssource->ioc));
     96}
     97
     98
     99#ifdef CONFIG_WIN32
    100static gboolean
    101qio_channel_socket_source_prepare(GSource *source G_GNUC_UNUSED,
    102                                  gint *timeout)
    103{
    104    *timeout = -1;
    105
    106    return FALSE;
    107}
    108
    109
    110/*
    111 * NB, this impl only works when the socket is in non-blocking
    112 * mode on Win32
    113 */
    114static gboolean
    115qio_channel_socket_source_check(GSource *source)
    116{
    117    static struct timeval tv0;
    118
    119    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
    120    WSANETWORKEVENTS ev;
    121    fd_set rfds, wfds, xfds;
    122
    123    if (!ssource->condition) {
    124        return 0;
    125    }
    126
    127    WSAEnumNetworkEvents(ssource->socket, ssource->ioc->event, &ev);
    128
    129    FD_ZERO(&rfds);
    130    FD_ZERO(&wfds);
    131    FD_ZERO(&xfds);
    132    if (ssource->condition & G_IO_IN) {
    133        FD_SET((SOCKET)ssource->socket, &rfds);
    134    }
    135    if (ssource->condition & G_IO_OUT) {
    136        FD_SET((SOCKET)ssource->socket, &wfds);
    137    }
    138    if (ssource->condition & G_IO_PRI) {
    139        FD_SET((SOCKET)ssource->socket, &xfds);
    140    }
    141    ssource->revents = 0;
    142    if (select(0, &rfds, &wfds, &xfds, &tv0) == 0) {
    143        return 0;
    144    }
    145
    146    if (FD_ISSET(ssource->socket, &rfds)) {
    147        ssource->revents |= G_IO_IN;
    148    }
    149    if (FD_ISSET(ssource->socket, &wfds)) {
    150        ssource->revents |= G_IO_OUT;
    151    }
    152    if (FD_ISSET(ssource->socket, &xfds)) {
    153        ssource->revents |= G_IO_PRI;
    154    }
    155
    156    return ssource->revents;
    157}
    158
    159
    160static gboolean
    161qio_channel_socket_source_dispatch(GSource *source,
    162                                   GSourceFunc callback,
    163                                   gpointer user_data)
    164{
    165    QIOChannelFunc func = (QIOChannelFunc)callback;
    166    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
    167
    168    return (*func)(ssource->ioc, ssource->revents, user_data);
    169}
    170
    171
    172static void
    173qio_channel_socket_source_finalize(GSource *source)
    174{
    175    QIOChannelSocketSource *ssource = (QIOChannelSocketSource *)source;
    176
    177    object_unref(OBJECT(ssource->ioc));
    178}
    179
    180
    181GSourceFuncs qio_channel_socket_source_funcs = {
    182    qio_channel_socket_source_prepare,
    183    qio_channel_socket_source_check,
    184    qio_channel_socket_source_dispatch,
    185    qio_channel_socket_source_finalize
    186};
    187#endif
    188
    189
    190static gboolean
    191qio_channel_fd_pair_source_prepare(GSource *source G_GNUC_UNUSED,
    192                                   gint *timeout)
    193{
    194    *timeout = -1;
    195
    196    return FALSE;
    197}
    198
    199
    200static gboolean
    201qio_channel_fd_pair_source_check(GSource *source)
    202{
    203    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
    204    GIOCondition poll_condition = ssource->fdread.revents |
    205        ssource->fdwrite.revents;
    206
    207    return poll_condition & ssource->condition;
    208}
    209
    210
    211static gboolean
    212qio_channel_fd_pair_source_dispatch(GSource *source,
    213                                    GSourceFunc callback,
    214                                    gpointer user_data)
    215{
    216    QIOChannelFunc func = (QIOChannelFunc)callback;
    217    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
    218    GIOCondition poll_condition = ssource->fdread.revents |
    219        ssource->fdwrite.revents;
    220
    221    return (*func)(ssource->ioc,
    222                   poll_condition & ssource->condition,
    223                   user_data);
    224}
    225
    226
    227static void
    228qio_channel_fd_pair_source_finalize(GSource *source)
    229{
    230    QIOChannelFDPairSource *ssource = (QIOChannelFDPairSource *)source;
    231
    232    object_unref(OBJECT(ssource->ioc));
    233}
    234
    235
    236GSourceFuncs qio_channel_fd_source_funcs = {
    237    qio_channel_fd_source_prepare,
    238    qio_channel_fd_source_check,
    239    qio_channel_fd_source_dispatch,
    240    qio_channel_fd_source_finalize
    241};
    242
    243
    244GSourceFuncs qio_channel_fd_pair_source_funcs = {
    245    qio_channel_fd_pair_source_prepare,
    246    qio_channel_fd_pair_source_check,
    247    qio_channel_fd_pair_source_dispatch,
    248    qio_channel_fd_pair_source_finalize
    249};
    250
    251
    252GSource *qio_channel_create_fd_watch(QIOChannel *ioc,
    253                                     int fd,
    254                                     GIOCondition condition)
    255{
    256    GSource *source;
    257    QIOChannelFDSource *ssource;
    258
    259    source = g_source_new(&qio_channel_fd_source_funcs,
    260                          sizeof(QIOChannelFDSource));
    261    ssource = (QIOChannelFDSource *)source;
    262
    263    ssource->ioc = ioc;
    264    object_ref(OBJECT(ioc));
    265
    266    ssource->condition = condition;
    267
    268#ifdef CONFIG_WIN32
    269    ssource->fd.fd = (gint64)_get_osfhandle(fd);
    270#else
    271    ssource->fd.fd = fd;
    272#endif
    273    ssource->fd.events = condition;
    274
    275    g_source_add_poll(source, &ssource->fd);
    276
    277    return source;
    278}
    279
    280#ifdef CONFIG_WIN32
    281GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
    282                                         int socket,
    283                                         GIOCondition condition)
    284{
    285    GSource *source;
    286    QIOChannelSocketSource *ssource;
    287
    288#ifdef WIN32
    289    WSAEventSelect(socket, ioc->event,
    290                   FD_READ | FD_ACCEPT | FD_CLOSE |
    291                   FD_CONNECT | FD_WRITE | FD_OOB);
    292#endif
    293
    294    source = g_source_new(&qio_channel_socket_source_funcs,
    295                          sizeof(QIOChannelSocketSource));
    296    ssource = (QIOChannelSocketSource *)source;
    297
    298    ssource->ioc = ioc;
    299    object_ref(OBJECT(ioc));
    300
    301    ssource->condition = condition;
    302    ssource->socket = socket;
    303    ssource->revents = 0;
    304
    305    ssource->fd.fd = (gintptr)ioc->event;
    306    ssource->fd.events = G_IO_IN;
    307
    308    g_source_add_poll(source, &ssource->fd);
    309
    310    return source;
    311}
    312#else
    313GSource *qio_channel_create_socket_watch(QIOChannel *ioc,
    314                                         int socket,
    315                                         GIOCondition condition)
    316{
    317    return qio_channel_create_fd_watch(ioc, socket, condition);
    318}
    319#endif
    320
    321GSource *qio_channel_create_fd_pair_watch(QIOChannel *ioc,
    322                                          int fdread,
    323                                          int fdwrite,
    324                                          GIOCondition condition)
    325{
    326    GSource *source;
    327    QIOChannelFDPairSource *ssource;
    328
    329    source = g_source_new(&qio_channel_fd_pair_source_funcs,
    330                          sizeof(QIOChannelFDPairSource));
    331    ssource = (QIOChannelFDPairSource *)source;
    332
    333    ssource->ioc = ioc;
    334    object_ref(OBJECT(ioc));
    335
    336    ssource->condition = condition;
    337
    338#ifdef CONFIG_WIN32
    339    ssource->fdread.fd = (gint64)_get_osfhandle(fdread);
    340    ssource->fdwrite.fd = (gint64)_get_osfhandle(fdwrite);
    341#else
    342    ssource->fdread.fd = fdread;
    343    ssource->fdwrite.fd = fdwrite;
    344#endif
    345
    346    ssource->fdread.events = condition & G_IO_IN;
    347    ssource->fdwrite.events = condition & G_IO_OUT;
    348
    349    g_source_add_poll(source, &ssource->fdread);
    350    g_source_add_poll(source, &ssource->fdwrite);
    351
    352    return source;
    353}