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-buffer.c (7138B)


      1/*
      2 * QEMU I/O channels memory buffer driver
      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-buffer.h"
     23#include "io/channel-watch.h"
     24#include "qemu/module.h"
     25#include "qemu/sockets.h"
     26#include "trace.h"
     27
     28QIOChannelBuffer *
     29qio_channel_buffer_new(size_t capacity)
     30{
     31    QIOChannelBuffer *ioc;
     32
     33    ioc = QIO_CHANNEL_BUFFER(object_new(TYPE_QIO_CHANNEL_BUFFER));
     34
     35    if (capacity) {
     36        ioc->data = g_new0(uint8_t, capacity);
     37        ioc->capacity = capacity;
     38    }
     39
     40    return ioc;
     41}
     42
     43
     44static void qio_channel_buffer_finalize(Object *obj)
     45{
     46    QIOChannelBuffer *ioc = QIO_CHANNEL_BUFFER(obj);
     47    g_free(ioc->data);
     48    ioc->capacity = ioc->usage = ioc->offset = 0;
     49}
     50
     51
     52static ssize_t qio_channel_buffer_readv(QIOChannel *ioc,
     53                                        const struct iovec *iov,
     54                                        size_t niov,
     55                                        int **fds,
     56                                        size_t *nfds,
     57                                        Error **errp)
     58{
     59    QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
     60    ssize_t ret = 0;
     61    size_t i;
     62
     63    for (i = 0; i < niov; i++) {
     64        size_t want = iov[i].iov_len;
     65        if (bioc->offset >= bioc->usage) {
     66            break;
     67        }
     68        if ((bioc->offset + want) > bioc->usage)  {
     69            want = bioc->usage - bioc->offset;
     70        }
     71        memcpy(iov[i].iov_base, bioc->data + bioc->offset, want);
     72        ret += want;
     73        bioc->offset += want;
     74    }
     75
     76    return ret;
     77}
     78
     79static ssize_t qio_channel_buffer_writev(QIOChannel *ioc,
     80                                         const struct iovec *iov,
     81                                         size_t niov,
     82                                         int *fds,
     83                                         size_t nfds,
     84                                         Error **errp)
     85{
     86    QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
     87    ssize_t ret = 0;
     88    size_t i;
     89    size_t towrite = 0;
     90
     91    for (i = 0; i < niov; i++) {
     92        towrite += iov[i].iov_len;
     93    }
     94
     95    if ((bioc->offset + towrite) > bioc->capacity) {
     96        bioc->capacity = bioc->offset + towrite;
     97        bioc->data = g_realloc(bioc->data, bioc->capacity);
     98    }
     99
    100    if (bioc->offset > bioc->usage) {
    101        memset(bioc->data, 0, bioc->offset - bioc->usage);
    102        bioc->usage = bioc->offset;
    103    }
    104
    105    for (i = 0; i < niov; i++) {
    106        memcpy(bioc->data + bioc->usage,
    107               iov[i].iov_base,
    108               iov[i].iov_len);
    109        bioc->usage += iov[i].iov_len;
    110        bioc->offset += iov[i].iov_len;
    111        ret += iov[i].iov_len;
    112    }
    113
    114    return ret;
    115}
    116
    117static int qio_channel_buffer_set_blocking(QIOChannel *ioc G_GNUC_UNUSED,
    118                                           bool enabled G_GNUC_UNUSED,
    119                                           Error **errp G_GNUC_UNUSED)
    120{
    121    return 0;
    122}
    123
    124
    125static off_t qio_channel_buffer_seek(QIOChannel *ioc,
    126                                     off_t offset,
    127                                     int whence,
    128                                     Error **errp)
    129{
    130    QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
    131
    132    bioc->offset = offset;
    133
    134    return offset;
    135}
    136
    137
    138static int qio_channel_buffer_close(QIOChannel *ioc,
    139                                    Error **errp)
    140{
    141    QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
    142
    143    g_free(bioc->data);
    144    bioc->data = NULL;
    145    bioc->capacity = bioc->usage = bioc->offset = 0;
    146
    147    return 0;
    148}
    149
    150
    151typedef struct QIOChannelBufferSource QIOChannelBufferSource;
    152struct QIOChannelBufferSource {
    153    GSource parent;
    154    QIOChannelBuffer *bioc;
    155    GIOCondition condition;
    156};
    157
    158static gboolean
    159qio_channel_buffer_source_prepare(GSource *source,
    160                                  gint *timeout)
    161{
    162    QIOChannelBufferSource *bsource = (QIOChannelBufferSource *)source;
    163
    164    *timeout = -1;
    165
    166    return (G_IO_IN | G_IO_OUT) & bsource->condition;
    167}
    168
    169static gboolean
    170qio_channel_buffer_source_check(GSource *source)
    171{
    172    QIOChannelBufferSource *bsource = (QIOChannelBufferSource *)source;
    173
    174    return (G_IO_IN | G_IO_OUT) & bsource->condition;
    175}
    176
    177static gboolean
    178qio_channel_buffer_source_dispatch(GSource *source,
    179                                   GSourceFunc callback,
    180                                   gpointer user_data)
    181{
    182    QIOChannelFunc func = (QIOChannelFunc)callback;
    183    QIOChannelBufferSource *bsource = (QIOChannelBufferSource *)source;
    184
    185    return (*func)(QIO_CHANNEL(bsource->bioc),
    186                   ((G_IO_IN | G_IO_OUT) & bsource->condition),
    187                   user_data);
    188}
    189
    190static void
    191qio_channel_buffer_source_finalize(GSource *source)
    192{
    193    QIOChannelBufferSource *ssource = (QIOChannelBufferSource *)source;
    194
    195    object_unref(OBJECT(ssource->bioc));
    196}
    197
    198GSourceFuncs qio_channel_buffer_source_funcs = {
    199    qio_channel_buffer_source_prepare,
    200    qio_channel_buffer_source_check,
    201    qio_channel_buffer_source_dispatch,
    202    qio_channel_buffer_source_finalize
    203};
    204
    205static GSource *qio_channel_buffer_create_watch(QIOChannel *ioc,
    206                                                GIOCondition condition)
    207{
    208    QIOChannelBuffer *bioc = QIO_CHANNEL_BUFFER(ioc);
    209    QIOChannelBufferSource *ssource;
    210    GSource *source;
    211
    212    source = g_source_new(&qio_channel_buffer_source_funcs,
    213                          sizeof(QIOChannelBufferSource));
    214    ssource = (QIOChannelBufferSource *)source;
    215
    216    ssource->bioc = bioc;
    217    object_ref(OBJECT(bioc));
    218
    219    ssource->condition = condition;
    220
    221    return source;
    222}
    223
    224
    225static void qio_channel_buffer_class_init(ObjectClass *klass,
    226                                          void *class_data G_GNUC_UNUSED)
    227{
    228    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
    229
    230    ioc_klass->io_writev = qio_channel_buffer_writev;
    231    ioc_klass->io_readv = qio_channel_buffer_readv;
    232    ioc_klass->io_set_blocking = qio_channel_buffer_set_blocking;
    233    ioc_klass->io_seek = qio_channel_buffer_seek;
    234    ioc_klass->io_close = qio_channel_buffer_close;
    235    ioc_klass->io_create_watch = qio_channel_buffer_create_watch;
    236}
    237
    238static const TypeInfo qio_channel_buffer_info = {
    239    .parent = TYPE_QIO_CHANNEL,
    240    .name = TYPE_QIO_CHANNEL_BUFFER,
    241    .instance_size = sizeof(QIOChannelBuffer),
    242    .instance_finalize = qio_channel_buffer_finalize,
    243    .class_init = qio_channel_buffer_class_init,
    244};
    245
    246static void qio_channel_buffer_register_types(void)
    247{
    248    type_register_static(&qio_channel_buffer_info);
    249}
    250
    251type_init(qio_channel_buffer_register_types);