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-user-vsock.c (4775B)


      1/*
      2 * Vhost-user vsock virtio device
      3 *
      4 * Copyright 2020 Red Hat, Inc.
      5 *
      6 * This work is licensed under the terms of the GNU GPL, version 2 or
      7 * (at your option) any later version.  See the COPYING file in the
      8 * top-level directory.
      9 */
     10
     11#include "qemu/osdep.h"
     12
     13#include "qapi/error.h"
     14#include "qemu/error-report.h"
     15#include "hw/qdev-properties.h"
     16#include "hw/qdev-properties-system.h"
     17#include "hw/virtio/vhost-user-vsock.h"
     18
     19static const int user_feature_bits[] = {
     20    VIRTIO_F_VERSION_1,
     21    VIRTIO_RING_F_INDIRECT_DESC,
     22    VIRTIO_RING_F_EVENT_IDX,
     23    VIRTIO_F_NOTIFY_ON_EMPTY,
     24    VHOST_INVALID_FEATURE_BIT
     25};
     26
     27static void vuv_get_config(VirtIODevice *vdev, uint8_t *config)
     28{
     29    VHostUserVSock *vsock = VHOST_USER_VSOCK(vdev);
     30
     31    memcpy(config, &vsock->vsockcfg, sizeof(struct virtio_vsock_config));
     32}
     33
     34static int vuv_handle_config_change(struct vhost_dev *dev)
     35{
     36    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev->vdev);
     37    Error *local_err = NULL;
     38    int ret = vhost_dev_get_config(dev, (uint8_t *)&vsock->vsockcfg,
     39                                   sizeof(struct virtio_vsock_config),
     40                                   &local_err);
     41    if (ret < 0) {
     42        error_report_err(local_err);
     43        return -1;
     44    }
     45
     46    virtio_notify_config(dev->vdev);
     47
     48    return 0;
     49}
     50
     51const VhostDevConfigOps vsock_ops = {
     52    .vhost_dev_config_notifier = vuv_handle_config_change,
     53};
     54
     55static void vuv_set_status(VirtIODevice *vdev, uint8_t status)
     56{
     57    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     58    bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK;
     59
     60    if (!vdev->vm_running) {
     61        should_start = false;
     62    }
     63
     64    if (vvc->vhost_dev.started == should_start) {
     65        return;
     66    }
     67
     68    if (should_start) {
     69        int ret = vhost_vsock_common_start(vdev);
     70        if (ret < 0) {
     71            return;
     72        }
     73    } else {
     74        vhost_vsock_common_stop(vdev);
     75    }
     76}
     77
     78static uint64_t vuv_get_features(VirtIODevice *vdev,
     79                                 uint64_t features,
     80                                 Error **errp)
     81{
     82    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev);
     83
     84    features = vhost_get_features(&vvc->vhost_dev, user_feature_bits, features);
     85
     86    return vhost_vsock_common_get_features(vdev, features, errp);
     87}
     88
     89static const VMStateDescription vuv_vmstate = {
     90    .name = "vhost-user-vsock",
     91    .unmigratable = 1,
     92};
     93
     94static void vuv_device_realize(DeviceState *dev, Error **errp)
     95{
     96    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
     97    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
     98    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev);
     99    int ret;
    100
    101    if (!vsock->conf.chardev.chr) {
    102        error_setg(errp, "missing chardev");
    103        return;
    104    }
    105
    106    if (!vhost_user_init(&vsock->vhost_user, &vsock->conf.chardev, errp)) {
    107        return;
    108    }
    109
    110    vhost_vsock_common_realize(vdev, "vhost-user-vsock");
    111
    112    vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops);
    113
    114    ret = vhost_dev_init(&vvc->vhost_dev, &vsock->vhost_user,
    115                         VHOST_BACKEND_TYPE_USER, 0, errp);
    116    if (ret < 0) {
    117        goto err_virtio;
    118    }
    119
    120    ret = vhost_dev_get_config(&vvc->vhost_dev, (uint8_t *)&vsock->vsockcfg,
    121                               sizeof(struct virtio_vsock_config), errp);
    122    if (ret < 0) {
    123        goto err_vhost_dev;
    124    }
    125
    126    return;
    127
    128err_vhost_dev:
    129    vhost_dev_cleanup(&vvc->vhost_dev);
    130err_virtio:
    131    vhost_vsock_common_unrealize(vdev);
    132    vhost_user_cleanup(&vsock->vhost_user);
    133    return;
    134}
    135
    136static void vuv_device_unrealize(DeviceState *dev)
    137{
    138    VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev);
    139    VirtIODevice *vdev = VIRTIO_DEVICE(dev);
    140    VHostUserVSock *vsock = VHOST_USER_VSOCK(dev);
    141
    142    /* This will stop vhost backend if appropriate. */
    143    vuv_set_status(vdev, 0);
    144
    145    vhost_dev_cleanup(&vvc->vhost_dev);
    146
    147    vhost_vsock_common_unrealize(vdev);
    148
    149    vhost_user_cleanup(&vsock->vhost_user);
    150
    151}
    152
    153static Property vuv_properties[] = {
    154    DEFINE_PROP_CHR("chardev", VHostUserVSock, conf.chardev),
    155    DEFINE_PROP_END_OF_LIST(),
    156};
    157
    158static void vuv_class_init(ObjectClass *klass, void *data)
    159{
    160    DeviceClass *dc = DEVICE_CLASS(klass);
    161    VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass);
    162
    163    device_class_set_props(dc, vuv_properties);
    164    dc->vmsd = &vuv_vmstate;
    165    vdc->realize = vuv_device_realize;
    166    vdc->unrealize = vuv_device_unrealize;
    167    vdc->get_features = vuv_get_features;
    168    vdc->get_config = vuv_get_config;
    169    vdc->set_status = vuv_set_status;
    170}
    171
    172static const TypeInfo vuv_info = {
    173    .name = TYPE_VHOST_USER_VSOCK,
    174    .parent = TYPE_VHOST_VSOCK_COMMON,
    175    .instance_size = sizeof(VHostUserVSock),
    176    .class_init = vuv_class_init,
    177};
    178
    179static void vuv_register_types(void)
    180{
    181    type_register_static(&vuv_info);
    182}
    183
    184type_init(vuv_register_types)