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

qemu-file-channel.c (5619B)


      1/*
      2 * QEMUFile backend for QIOChannel objects
      3 *
      4 * Copyright (c) 2015-2016 Red Hat, Inc
      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
     25#include "qemu/osdep.h"
     26#include "qemu-file-channel.h"
     27#include "qemu-file.h"
     28#include "io/channel-socket.h"
     29#include "io/channel-tls.h"
     30#include "qemu/iov.h"
     31#include "qemu/yank.h"
     32#include "yank_functions.h"
     33
     34
     35static ssize_t channel_writev_buffer(void *opaque,
     36                                     struct iovec *iov,
     37                                     int iovcnt,
     38                                     int64_t pos,
     39                                     Error **errp)
     40{
     41    QIOChannel *ioc = QIO_CHANNEL(opaque);
     42    ssize_t done = 0;
     43    struct iovec *local_iov = g_new(struct iovec, iovcnt);
     44    struct iovec *local_iov_head = local_iov;
     45    unsigned int nlocal_iov = iovcnt;
     46
     47    nlocal_iov = iov_copy(local_iov, nlocal_iov,
     48                          iov, iovcnt,
     49                          0, iov_size(iov, iovcnt));
     50
     51    while (nlocal_iov > 0) {
     52        ssize_t len;
     53        len = qio_channel_writev(ioc, local_iov, nlocal_iov, errp);
     54        if (len == QIO_CHANNEL_ERR_BLOCK) {
     55            if (qemu_in_coroutine()) {
     56                qio_channel_yield(ioc, G_IO_OUT);
     57            } else {
     58                qio_channel_wait(ioc, G_IO_OUT);
     59            }
     60            continue;
     61        }
     62        if (len < 0) {
     63            done = -EIO;
     64            goto cleanup;
     65        }
     66
     67        iov_discard_front(&local_iov, &nlocal_iov, len);
     68        done += len;
     69    }
     70
     71 cleanup:
     72    g_free(local_iov_head);
     73    return done;
     74}
     75
     76
     77static ssize_t channel_get_buffer(void *opaque,
     78                                  uint8_t *buf,
     79                                  int64_t pos,
     80                                  size_t size,
     81                                  Error **errp)
     82{
     83    QIOChannel *ioc = QIO_CHANNEL(opaque);
     84    ssize_t ret;
     85
     86    do {
     87        ret = qio_channel_read(ioc, (char *)buf, size, errp);
     88        if (ret < 0) {
     89            if (ret == QIO_CHANNEL_ERR_BLOCK) {
     90                if (qemu_in_coroutine()) {
     91                    qio_channel_yield(ioc, G_IO_IN);
     92                } else {
     93                    qio_channel_wait(ioc, G_IO_IN);
     94                }
     95            } else {
     96                return -EIO;
     97            }
     98        }
     99    } while (ret == QIO_CHANNEL_ERR_BLOCK);
    100
    101    return ret;
    102}
    103
    104
    105static int channel_close(void *opaque, Error **errp)
    106{
    107    int ret;
    108    QIOChannel *ioc = QIO_CHANNEL(opaque);
    109    ret = qio_channel_close(ioc, errp);
    110    object_unref(OBJECT(ioc));
    111    return ret;
    112}
    113
    114
    115static int channel_shutdown(void *opaque,
    116                            bool rd,
    117                            bool wr,
    118                            Error **errp)
    119{
    120    QIOChannel *ioc = QIO_CHANNEL(opaque);
    121
    122    if (qio_channel_has_feature(ioc,
    123                                QIO_CHANNEL_FEATURE_SHUTDOWN)) {
    124        QIOChannelShutdown mode;
    125        if (rd && wr) {
    126            mode = QIO_CHANNEL_SHUTDOWN_BOTH;
    127        } else if (rd) {
    128            mode = QIO_CHANNEL_SHUTDOWN_READ;
    129        } else {
    130            mode = QIO_CHANNEL_SHUTDOWN_WRITE;
    131        }
    132        if (qio_channel_shutdown(ioc, mode, errp) < 0) {
    133            return -EIO;
    134        }
    135    }
    136    return 0;
    137}
    138
    139
    140static int channel_set_blocking(void *opaque,
    141                                bool enabled,
    142                                Error **errp)
    143{
    144    QIOChannel *ioc = QIO_CHANNEL(opaque);
    145
    146    if (qio_channel_set_blocking(ioc, enabled, errp) < 0) {
    147        return -1;
    148    }
    149    return 0;
    150}
    151
    152static QEMUFile *channel_get_input_return_path(void *opaque)
    153{
    154    QIOChannel *ioc = QIO_CHANNEL(opaque);
    155
    156    return qemu_fopen_channel_output(ioc);
    157}
    158
    159static QEMUFile *channel_get_output_return_path(void *opaque)
    160{
    161    QIOChannel *ioc = QIO_CHANNEL(opaque);
    162
    163    return qemu_fopen_channel_input(ioc);
    164}
    165
    166static const QEMUFileOps channel_input_ops = {
    167    .get_buffer = channel_get_buffer,
    168    .close = channel_close,
    169    .shut_down = channel_shutdown,
    170    .set_blocking = channel_set_blocking,
    171    .get_return_path = channel_get_input_return_path,
    172};
    173
    174
    175static const QEMUFileOps channel_output_ops = {
    176    .writev_buffer = channel_writev_buffer,
    177    .close = channel_close,
    178    .shut_down = channel_shutdown,
    179    .set_blocking = channel_set_blocking,
    180    .get_return_path = channel_get_output_return_path,
    181};
    182
    183
    184QEMUFile *qemu_fopen_channel_input(QIOChannel *ioc)
    185{
    186    object_ref(OBJECT(ioc));
    187    return qemu_fopen_ops(ioc, &channel_input_ops, true);
    188}
    189
    190QEMUFile *qemu_fopen_channel_output(QIOChannel *ioc)
    191{
    192    object_ref(OBJECT(ioc));
    193    return qemu_fopen_ops(ioc, &channel_output_ops, true);
    194}