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

vhost-vsock.c (6734B)


      1/*
      2 * Virtio vsock device
      3 *
      4 * Copyright 2015 Red Hat, Inc.
      5 *
      6 * Authors:
      7 *  Stefan Hajnoczi <stefanha@redhat.com>
      8 *
      9 * This work is licensed under the terms of the GNU GPL, version 2 or
     10 * (at your option) any later version.  See the COPYING file in the
     11 * top-level directory.
     12 */
     13
     14#include "qemu/osdep.h"
     15#include "standard-headers/linux/virtio_vsock.h"
     16#include "qapi/error.h"
     17#include "hw/virtio/virtio-access.h"
     18#include "qemu/error-report.h"
     19#include "qemu/sockets.h"
     20#include "hw/qdev-properties.h"
     21#include "hw/virtio/vhost-vsock.h"
     22#include "monitor/monitor.h"
     23
     24static void vhost_vsock_get_config(VirtIODevice *vdev, uint8_t *config)
     25{
     26    VHostVSock *vsock = VHOST_VSOCK(vdev);
     27    struct virtio_vsock_config vsockcfg = {};
     28
     29    virtio_stq_p(vdev, &vsockcfg.guest_cid, vsock->conf.guest_cid);
     30    memcpy(config, &vsockcfg, sizeof(vsockcfg));
     31}
     32
     33static int vhost_vsock_set_guest_cid(VirtIODevice *vdev)
     34{
     35    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     36    VHostVSock *vsock = VHOST_VSOCK(vdev);
     37    const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops;
     38    int ret;
     39
     40    if (!vhost_ops->vhost_vsock_set_guest_cid) {
     41        return -ENOSYS;
     42    }
     43
     44    ret = vhost_ops->vhost_vsock_set_guest_cid(&vvc->vhost_dev,
     45                                               vsock->conf.guest_cid);
     46    if (ret < 0) {
     47        return -errno;
     48    }
     49    return 0;
     50}
     51
     52static int vhost_vsock_set_running(VirtIODevice *vdev, int start)
     53{
     54    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     55    const VhostOps *vhost_ops = vvc->vhost_dev.vhost_ops;
     56    int ret;
     57
     58    if (!vhost_ops->vhost_vsock_set_running) {
     59        return -ENOSYS;
     60    }
     61
     62    ret = vhost_ops->vhost_vsock_set_running(&vvc->vhost_dev, start);
     63    if (ret < 0) {
     64        return -errno;
     65    }
     66    return 0;
     67}
     68
     69
     70static void vhost_vsock_set_status(VirtIODevice *vdev, uint8_t status)
     71{
     72    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     73    bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
     74    int ret;
     75
     76    if (!vdev->vm_running) {
     77        should_start = false;
     78    }
     79
     80    if (vvc->vhost_dev.started == should_start) {
     81        return;
     82    }
     83
     84    if (should_start) {
     85        ret = vhost_vsock_common_start(vdev);
     86        if (ret < 0) {
     87            return;
     88        }
     89
     90        ret = vhost_vsock_set_running(vdev, 1);
     91        if (ret < 0) {
     92            vhost_vsock_common_stop(vdev);
     93            error_report("Error starting vhost vsock: %d", -ret);
     94            return;
     95        }
     96    } else {
     97        ret = vhost_vsock_set_running(vdev, 0);
     98        if (ret < 0) {
     99            error_report("vhost vsock set running failed: %d", ret);
    100            return;
    101        }
    102
    103        vhost_vsock_common_stop(vdev);
    104    }
    105}
    106
    107static uint64_t vhost_vsock_get_features(VirtIODevice *vdev,
    108                                         uint64_t requested_features,
    109                                         Error **errp)
    110{
    111    return vhost_vsock_common_get_features(vdev, requested_features, errp);
    112}
    113
    114static const VMStateDescription vmstate_virtio_vhost_vsock = {
    115    .name = "virtio-vhost_vsock",
    116    .minimum_version_id = VHOST_VSOCK_SAVEVM_VERSION,
    117    .version_id = VHOST_VSOCK_SAVEVM_VERSION,
    118    .fields = (VMStateField[]) {
    119        VMSTATE_VIRTIO_DEVICE,
    120        VMSTATE_END_OF_LIST()
    121    },
    122    .pre_save = vhost_vsock_common_pre_save,
    123    .post_load = vhost_vsock_common_post_load,
    124};
    125
    126static void vhost_vsock_device_realize(DeviceState *dev, Error **errp)
    127{
    128    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    129    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    130    VHostVSock *vsock = VHOST_VSOCK(dev);
    131    int vhostfd;
    132    int ret;
    133
    134    /* Refuse to use reserved CID numbers */
    135    if (vsock->conf.guest_cid <= 2) {
    136        error_setg(errp, "guest-cid property must be greater than 2");
    137        return;
    138    }
    139
    140    if (vsock->conf.guest_cid > UINT32_MAX) {
    141        error_setg(errp, "guest-cid property must be a 32-bit number");
    142        return;
    143    }
    144
    145    if (vsock->conf.vhostfd) {
    146        vhostfd = monitor_fd_param(monitor_cur(), vsock->conf.vhostfd, errp);
    147        if (vhostfd == -1) {
    148            error_prepend(errp, "vhost-vsock: unable to parse vhostfd: ");
    149            return;
    150        }
    151
    152        ret = qemu_try_set_nonblock(vhostfd);
    153        if (ret < 0) {
    154            error_setg_errno(errp, -ret,
    155                             "vhost-vsock: unable to set non-blocking mode");
    156            return;
    157        }
    158    } else {
    159        vhostfd = open("/dev/vhost-vsock", O_RDWR);
    160        if (vhostfd < 0) {
    161            error_setg_errno(errp, errno,
    162                             "vhost-vsock: failed to open vhost device");
    163            return;
    164        }
    165
    166        qemu_set_nonblock(vhostfd);
    167    }
    168
    169    vhost_vsock_common_realize(vdev, "vhost-vsock");
    170
    171    ret = vhost_dev_init(&vvc->vhost_dev, (void *)(uintptr_t)vhostfd,
    172                         VHOST_BACKEND_TYPE_KERNEL, 0, errp);
    173    if (ret < 0) {
    174        goto err_virtio;
    175    }
    176
    177    ret = vhost_vsock_set_guest_cid(vdev);
    178    if (ret < 0) {
    179        error_setg_errno(errp, -ret, "vhost-vsock: unable to set guest cid");
    180        goto err_vhost_dev;
    181    }
    182
    183    return;
    184
    185err_vhost_dev:
    186    vhost_dev_cleanup(&vvc->vhost_dev);
    187    /* vhost_dev_cleanup() closes the vhostfd passed to vhost_dev_init() */
    188    vhostfd = -1;
    189err_virtio:
    190    vhost_vsock_common_unrealize(vdev);
    191    if (vhostfd >= 0) {
    192        close(vhostfd);
    193    }
    194    return;
    195}
    196
    197static void vhost_vsock_device_unrealize(DeviceState *dev)
    198{
    199    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    200    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    201
    202    /* This will stop vhost backend if appropriate. */
    203    vhost_vsock_set_status(vdev, 0);
    204
    205    vhost_dev_cleanup(&vvc->vhost_dev);
    206    vhost_vsock_common_unrealize(vdev);
    207}
    208
    209static Property vhost_vsock_properties[] = {
    210    DEFINE_PROP_UINT64("guest-cid", VHostVSock, conf.guest_cid, 0),
    211    DEFINE_PROP_STRING("vhostfd", VHostVSock, conf.vhostfd),
    212    DEFINE_PROP_END_OF_LIST(),
    213};
    214
    215static void vhost_vsock_class_init(ObjectClass *klass, void *data)
    216{
    217    DeviceClass *dc = DEVICE_CLASS(klass);
    218    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    219
    220    device_class_set_props(dc, vhost_vsock_properties);
    221    dc->vmsd = &vmstate_virtio_vhost_vsock;
    222    vdc->realize = vhost_vsock_device_realize;
    223    vdc->unrealize = vhost_vsock_device_unrealize;
    224    vdc->get_features = vhost_vsock_get_features;
    225    vdc->get_config = vhost_vsock_get_config;
    226    vdc->set_status = vhost_vsock_set_status;
    227}
    228
    229static const TypeInfo vhost_vsock_info = {
    230    .name = TYPE_VHOST_VSOCK,
    231    .parent = TYPE_VHOST_VSOCK_COMMON,
    232    .instance_size = sizeof(VHostVSock),
    233    .class_init = vhost_vsock_class_init,
    234};
    235
    236static void vhost_vsock_register_types(void)
    237{
    238    type_register_static(&vhost_vsock_info);
    239}
    240
    241type_init(vhost_vsock_register_types)