qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

virtio: add vhost-user-vsock base device

This patch introduces a vhost-user device for vsock, using the
vhost-vsock-common parent class.

The vhost-user-vsock device can be used to implement the virtio-vsock
device emulation in user-space.

Signed-off-by: Stefano Garzarella <sgarzare@redhat.com>
Message-Id: <20200522122512.87413-3-sgarzare@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

authored by

Stefano Garzarella and committed by
Michael S. Tsirkin
5fe97d88 c6136ec0

+221
+3
configure
··· 7196 7196 fi 7197 7197 if test "$vhost_vsock" = "yes" ; then 7198 7198 echo "CONFIG_VHOST_VSOCK=y" >> $config_host_mak 7199 + if test "$vhost_user" = "yes" ; then 7200 + echo "CONFIG_VHOST_USER_VSOCK=y" >> $config_host_mak 7201 + fi 7199 7202 fi 7200 7203 if test "$vhost_kernel" = "yes" ; then 7201 7204 echo "CONFIG_VHOST_KERNEL=y" >> $config_host_mak
+1
hw/virtio/Makefile.objs
··· 18 18 obj-$(call land,$(CONFIG_VHOST_USER_FS),$(CONFIG_VIRTIO_PCI)) += vhost-user-fs-pci.o 19 19 obj-$(CONFIG_VIRTIO_IOMMU) += virtio-iommu.o 20 20 obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-common.o vhost-vsock.o 21 + obj-$(CONFIG_VHOST_USER_VSOCK) += vhost-vsock-common.o vhost-user-vsock.o 21 22 22 23 ifeq ($(CONFIG_VIRTIO_PCI),y) 23 24 obj-$(CONFIG_VHOST_VSOCK) += vhost-vsock-pci.o
+181
hw/virtio/vhost-user-vsock.c
··· 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/virtio/vhost-user-vsock.h" 17 + 18 + static const int user_feature_bits[] = { 19 + VIRTIO_F_VERSION_1, 20 + VIRTIO_RING_F_INDIRECT_DESC, 21 + VIRTIO_RING_F_EVENT_IDX, 22 + VIRTIO_F_NOTIFY_ON_EMPTY, 23 + VHOST_INVALID_FEATURE_BIT 24 + }; 25 + 26 + static void vuv_get_config(VirtIODevice *vdev, uint8_t *config) 27 + { 28 + VHostUserVSock *vsock = VHOST_USER_VSOCK(vdev); 29 + 30 + memcpy(config, &vsock->vsockcfg, sizeof(struct virtio_vsock_config)); 31 + } 32 + 33 + static int vuv_handle_config_change(struct vhost_dev *dev) 34 + { 35 + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev->vdev); 36 + int ret = vhost_dev_get_config(dev, (uint8_t *)&vsock->vsockcfg, 37 + sizeof(struct virtio_vsock_config)); 38 + if (ret < 0) { 39 + error_report("get config space failed"); 40 + return -1; 41 + } 42 + 43 + virtio_notify_config(dev->vdev); 44 + 45 + return 0; 46 + } 47 + 48 + const VhostDevConfigOps vsock_ops = { 49 + .vhost_dev_config_notifier = vuv_handle_config_change, 50 + }; 51 + 52 + static void vuv_set_status(VirtIODevice *vdev, uint8_t status) 53 + { 54 + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 55 + bool should_start = status & VIRTIO_CONFIG_S_DRIVER_OK; 56 + 57 + if (!vdev->vm_running) { 58 + should_start = false; 59 + } 60 + 61 + if (vvc->vhost_dev.started == should_start) { 62 + return; 63 + } 64 + 65 + if (should_start) { 66 + int ret = vhost_vsock_common_start(vdev); 67 + if (ret < 0) { 68 + return; 69 + } 70 + } else { 71 + vhost_vsock_common_stop(vdev); 72 + } 73 + } 74 + 75 + static uint64_t vuv_get_features(VirtIODevice *vdev, 76 + uint64_t features, 77 + Error **errp) 78 + { 79 + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 80 + 81 + return vhost_get_features(&vvc->vhost_dev, user_feature_bits, features); 82 + } 83 + 84 + static const VMStateDescription vuv_vmstate = { 85 + .name = "vhost-user-vsock", 86 + .unmigratable = 1, 87 + }; 88 + 89 + static void vuv_device_realize(DeviceState *dev, Error **errp) 90 + { 91 + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); 92 + VirtIODevice *vdev = VIRTIO_DEVICE(dev); 93 + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev); 94 + int ret; 95 + 96 + if (!vsock->conf.chardev.chr) { 97 + error_setg(errp, "missing chardev"); 98 + return; 99 + } 100 + 101 + if (!vhost_user_init(&vsock->vhost_user, &vsock->conf.chardev, errp)) { 102 + return; 103 + } 104 + 105 + vhost_vsock_common_realize(vdev, "vhost-user-vsock"); 106 + 107 + vhost_dev_set_config_notifier(&vvc->vhost_dev, &vsock_ops); 108 + 109 + ret = vhost_dev_init(&vvc->vhost_dev, &vsock->vhost_user, 110 + VHOST_BACKEND_TYPE_USER, 0); 111 + if (ret < 0) { 112 + error_setg_errno(errp, -ret, "vhost_dev_init failed"); 113 + goto err_virtio; 114 + } 115 + 116 + ret = vhost_dev_get_config(&vvc->vhost_dev, (uint8_t *)&vsock->vsockcfg, 117 + sizeof(struct virtio_vsock_config)); 118 + if (ret < 0) { 119 + error_setg_errno(errp, -ret, "get config space failed"); 120 + goto err_vhost_dev; 121 + } 122 + 123 + return; 124 + 125 + err_vhost_dev: 126 + vhost_dev_cleanup(&vvc->vhost_dev); 127 + err_virtio: 128 + vhost_vsock_common_unrealize(vdev); 129 + vhost_user_cleanup(&vsock->vhost_user); 130 + return; 131 + } 132 + 133 + static void vuv_device_unrealize(DeviceState *dev) 134 + { 135 + VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(dev); 136 + VirtIODevice *vdev = VIRTIO_DEVICE(dev); 137 + VHostUserVSock *vsock = VHOST_USER_VSOCK(dev); 138 + 139 + /* This will stop vhost backend if appropriate. */ 140 + vuv_set_status(vdev, 0); 141 + 142 + vhost_dev_cleanup(&vvc->vhost_dev); 143 + 144 + vhost_vsock_common_unrealize(vdev); 145 + 146 + vhost_user_cleanup(&vsock->vhost_user); 147 + 148 + } 149 + 150 + static Property vuv_properties[] = { 151 + DEFINE_PROP_CHR("chardev", VHostUserVSock, conf.chardev), 152 + DEFINE_PROP_END_OF_LIST(), 153 + }; 154 + 155 + static void vuv_class_init(ObjectClass *klass, void *data) 156 + { 157 + DeviceClass *dc = DEVICE_CLASS(klass); 158 + VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); 159 + 160 + device_class_set_props(dc, vuv_properties); 161 + dc->vmsd = &vuv_vmstate; 162 + vdc->realize = vuv_device_realize; 163 + vdc->unrealize = vuv_device_unrealize; 164 + vdc->get_features = vuv_get_features; 165 + vdc->get_config = vuv_get_config; 166 + vdc->set_status = vuv_set_status; 167 + } 168 + 169 + static const TypeInfo vuv_info = { 170 + .name = TYPE_VHOST_USER_VSOCK, 171 + .parent = TYPE_VHOST_VSOCK_COMMON, 172 + .instance_size = sizeof(VHostUserVSock), 173 + .class_init = vuv_class_init, 174 + }; 175 + 176 + static void vuv_register_types(void) 177 + { 178 + type_register_static(&vuv_info); 179 + } 180 + 181 + type_init(vuv_register_types)
+36
include/hw/virtio/vhost-user-vsock.h
··· 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 + #ifndef _QEMU_VHOST_USER_VSOCK_H 12 + #define _QEMU_VHOST_USER_VSOCK_H 13 + 14 + #include "hw/virtio/vhost-vsock-common.h" 15 + #include "hw/virtio/vhost-user.h" 16 + #include "standard-headers/linux/virtio_vsock.h" 17 + 18 + #define TYPE_VHOST_USER_VSOCK "vhost-user-vsock-device" 19 + #define VHOST_USER_VSOCK(obj) \ 20 + OBJECT_CHECK(VHostUserVSock, (obj), TYPE_VHOST_USER_VSOCK) 21 + 22 + typedef struct { 23 + CharBackend chardev; 24 + } VHostUserVSockConf; 25 + 26 + typedef struct { 27 + /*< private >*/ 28 + VHostVSockCommon parent; 29 + VhostUserState vhost_user; 30 + VHostUserVSockConf conf; 31 + struct virtio_vsock_config vsockcfg; 32 + 33 + /*< public >*/ 34 + } VHostUserVSock; 35 + 36 + #endif /* _QEMU_VHOST_USER_VSOCK_H */