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

char-io.c (4394B)


      1/*
      2 * QEMU System Emulator
      3 *
      4 * Copyright (c) 2003-2008 Fabrice Bellard
      5 *
      6 * Permission is hereby granted, free of charge, to any person obtaining a copy
      7 * of this software and associated documentation files (the "Software"), to deal
      8 * in the Software without restriction, including without limitation the rights
      9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10 * copies of the Software, and to permit persons to whom the Software is
     11 * furnished to do so, subject to the following conditions:
     12 *
     13 * The above copyright notice and this permission notice shall be included in
     14 * all copies or substantial portions of the Software.
     15 *
     16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22 * THE SOFTWARE.
     23 */
     24#include "qemu/osdep.h"
     25#include "chardev/char-io.h"
     26
     27typedef struct IOWatchPoll {
     28    GSource parent;
     29
     30    QIOChannel *ioc;
     31    GSource *src;
     32
     33    IOCanReadHandler *fd_can_read;
     34    GSourceFunc fd_read;
     35    void *opaque;
     36} IOWatchPoll;
     37
     38static IOWatchPoll *io_watch_poll_from_source(GSource *source)
     39{
     40    return container_of(source, IOWatchPoll, parent);
     41}
     42
     43static gboolean io_watch_poll_prepare(GSource *source,
     44                                      gint *timeout)
     45{
     46    IOWatchPoll *iwp = io_watch_poll_from_source(source);
     47    bool now_active = iwp->fd_can_read(iwp->opaque) > 0;
     48    bool was_active = iwp->src != NULL;
     49    if (was_active == now_active) {
     50        return FALSE;
     51    }
     52
     53    if (now_active) {
     54        iwp->src = qio_channel_create_watch(
     55            iwp->ioc, G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL);
     56        g_source_set_callback(iwp->src, iwp->fd_read, iwp->opaque, NULL);
     57        g_source_add_child_source(source, iwp->src);
     58        g_source_unref(iwp->src);
     59    } else {
     60        g_source_remove_child_source(source, iwp->src);
     61        iwp->src = NULL;
     62    }
     63    return FALSE;
     64}
     65
     66static gboolean io_watch_poll_dispatch(GSource *source, GSourceFunc callback,
     67                                       gpointer user_data)
     68{
     69    return G_SOURCE_CONTINUE;
     70}
     71
     72static GSourceFuncs io_watch_poll_funcs = {
     73    .prepare = io_watch_poll_prepare,
     74    .dispatch = io_watch_poll_dispatch,
     75};
     76
     77GSource *io_add_watch_poll(Chardev *chr,
     78                        QIOChannel *ioc,
     79                        IOCanReadHandler *fd_can_read,
     80                        QIOChannelFunc fd_read,
     81                        gpointer user_data,
     82                        GMainContext *context)
     83{
     84    IOWatchPoll *iwp;
     85    char *name;
     86
     87    iwp = (IOWatchPoll *) g_source_new(&io_watch_poll_funcs,
     88                                       sizeof(IOWatchPoll));
     89    iwp->fd_can_read = fd_can_read;
     90    iwp->opaque = user_data;
     91    iwp->ioc = ioc;
     92    iwp->fd_read = (GSourceFunc) fd_read;
     93    iwp->src = NULL;
     94
     95    name = g_strdup_printf("chardev-iowatch-%s", chr->label);
     96    g_source_set_name((GSource *)iwp, name);
     97    g_free(name);
     98
     99    g_source_attach(&iwp->parent, context);
    100    g_source_unref(&iwp->parent);
    101    return (GSource *)iwp;
    102}
    103
    104void remove_fd_in_watch(Chardev *chr)
    105{
    106    if (chr->gsource) {
    107        g_source_destroy(chr->gsource);
    108        chr->gsource = NULL;
    109    }
    110}
    111
    112int io_channel_send_full(QIOChannel *ioc,
    113                         const void *buf, size_t len,
    114                         int *fds, size_t nfds)
    115{
    116    size_t offset = 0;
    117
    118    while (offset < len) {
    119        ssize_t ret = 0;
    120        struct iovec iov = { .iov_base = (char *)buf + offset,
    121                             .iov_len = len - offset };
    122
    123        ret = qio_channel_writev_full(
    124            ioc, &iov, 1,
    125            fds, nfds, NULL);
    126        if (ret == QIO_CHANNEL_ERR_BLOCK) {
    127            if (offset) {
    128                return offset;
    129            }
    130
    131            errno = EAGAIN;
    132            return -1;
    133        } else if (ret < 0) {
    134            errno = EINVAL;
    135            return -1;
    136        }
    137
    138        offset += ret;
    139    }
    140
    141    return offset;
    142}
    143
    144int io_channel_send(QIOChannel *ioc, const void *buf, size_t len)
    145{
    146    return io_channel_send_full(ioc, buf, len, NULL, 0);
    147}