1 /* 2 * Parent class for vhost-vsock devices 3 * 4 * Copyright 2015-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 #include "standard-headers/linux/virtio_vsock.h" 13 #include "qapi/error.h" 14 #include "hw/virtio/virtio-access.h" 15 #include "qemu/error-report.h" 16 #include "hw/qdev-properties.h" 17 #include "hw/virtio/vhost-vsock.h" 18 #include "qemu/iov.h" 19 #include "monitor/monitor.h" 20 21 int vhost_vsock_common_start(VirtIODevice *vdev) 22 { 23 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 24 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); 25 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); 26 int ret; 27 int i; 28 29 if (!k->set_guest_notifiers) { 30 error_report("binding does not support guest notifiers"); 31 return -ENOSYS; 32 } 33 34 ret = vhost_dev_enable_notifiers(&vvc->vhost_dev, vdev); 35 if (ret < 0) { 36 error_report("Error enabling host notifiers: %d", -ret); 37 return ret; 38 } 39 40 ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, true); 41 if (ret < 0) { 42 error_report("Error binding guest notifier: %d", -ret); 43 goto err_host_notifiers; 44 } 45 46 vvc->vhost_dev.acked_features = vdev->guest_features; 47 ret = vhost_dev_start(&vvc->vhost_dev, vdev); 48 if (ret < 0) { 49 error_report("Error starting vhost: %d", -ret); 50 goto err_guest_notifiers; 51 } 52 53 /* 54 * guest_notifier_mask/pending not used yet, so just unmask 55 * everything here. virtio-pci will do the right thing by 56 * enabling/disabling irqfd. 57 */ 58 for (i = 0; i < vvc->vhost_dev.nvqs; i++) { 59 vhost_virtqueue_mask(&vvc->vhost_dev, vdev, i, false); 60 } 61 62 return 0; 63 64 err_guest_notifiers: 65 k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false); 66 err_host_notifiers: 67 vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev); 68 return ret; 69 } 70 71 void vhost_vsock_common_stop(VirtIODevice *vdev) 72 { 73 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 74 BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev))); 75 VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus); 76 int ret; 77 78 if (!k->set_guest_notifiers) { 79 return; 80 } 81 82 vhost_dev_stop(&vvc->vhost_dev, vdev); 83 84 ret = k->set_guest_notifiers(qbus->parent, vvc->vhost_dev.nvqs, false); 85 if (ret < 0) { 86 error_report("vhost guest notifier cleanup failed: %d", ret); 87 return; 88 } 89 90 vhost_dev_disable_notifiers(&vvc->vhost_dev, vdev); 91 } 92 93 94 static void vhost_vsock_common_handle_output(VirtIODevice *vdev, VirtQueue *vq) 95 { 96 /* Do nothing */ 97 } 98 99 static void vhost_vsock_common_guest_notifier_mask(VirtIODevice *vdev, int idx, 100 bool mask) 101 { 102 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 103 104 vhost_virtqueue_mask(&vvc->vhost_dev, vdev, idx, mask); 105 } 106 107 static bool vhost_vsock_common_guest_notifier_pending(VirtIODevice *vdev, 108 int idx) 109 { 110 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 111 112 return vhost_virtqueue_pending(&vvc->vhost_dev, idx); 113 } 114 115 static void vhost_vsock_common_send_transport_reset(VHostVSockCommon *vvc) 116 { 117 VirtQueueElement *elem; 118 VirtQueue *vq = vvc->event_vq; 119 struct virtio_vsock_event event = { 120 .id = cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET), 121 }; 122 123 elem = virtqueue_pop(vq, sizeof(VirtQueueElement)); 124 if (!elem) { 125 error_report("vhost-vsock missed transport reset event"); 126 return; 127 } 128 129 if (elem->out_num) { 130 error_report("invalid vhost-vsock event virtqueue element with " 131 "out buffers"); 132 goto out; 133 } 134 135 if (iov_from_buf(elem->in_sg, elem->in_num, 0, 136 &event, sizeof(event)) != sizeof(event)) { 137 error_report("vhost-vsock event virtqueue element is too short"); 138 goto out; 139 } 140 141 virtqueue_push(vq, elem, sizeof(event)); 142 virtio_notify(VIRTIO_DEVICE(vvc), vq); 143 144 out: 145 g_free(elem); 146 } 147 148 static void vhost_vsock_common_post_load_timer_cleanup(VHostVSockCommon *vvc) 149 { 150 if (!vvc->post_load_timer) { 151 return; 152 } 153 154 timer_del(vvc->post_load_timer); 155 timer_free(vvc->post_load_timer); 156 vvc->post_load_timer = NULL; 157 } 158 159 static void vhost_vsock_common_post_load_timer_cb(void *opaque) 160 { 161 VHostVSockCommon *vvc = opaque; 162 163 vhost_vsock_common_post_load_timer_cleanup(vvc); 164 vhost_vsock_common_send_transport_reset(vvc); 165 } 166 167 int vhost_vsock_common_pre_save(void *opaque) 168 { 169 VHostVSockCommon *vvc = opaque; 170 171 /* 172 * At this point, backend must be stopped, otherwise 173 * it might keep writing to memory. 174 */ 175 assert(!vvc->vhost_dev.started); 176 177 return 0; 178 } 179 180 int vhost_vsock_common_post_load(void *opaque, int version_id) 181 { 182 VHostVSockCommon *vvc = opaque; 183 VirtIODevice *vdev = VIRTIO_DEVICE(vvc); 184 185 if (virtio_queue_get_addr(vdev, 2)) { 186 /* 187 * Defer transport reset event to a vm clock timer so that virtqueue 188 * changes happen after migration has completed. 189 */ 190 assert(!vvc->post_load_timer); 191 vvc->post_load_timer = 192 timer_new_ns(QEMU_CLOCK_VIRTUAL, 193 vhost_vsock_common_post_load_timer_cb, 194 vvc); 195 timer_mod(vvc->post_load_timer, 1); 196 } 197 return 0; 198 } 199 200 void vhost_vsock_common_realize(VirtIODevice *vdev, const char *name) 201 { 202 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 203 204 virtio_init(vdev, name, VIRTIO_ID_VSOCK, 205 sizeof(struct virtio_vsock_config)); 206 207 /* Receive and transmit queues belong to vhost */ 208 vvc->recv_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, 209 vhost_vsock_common_handle_output); 210 vvc->trans_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, 211 vhost_vsock_common_handle_output); 212 213 /* The event queue belongs to QEMU */ 214 vvc->event_vq = virtio_add_queue(vdev, VHOST_VSOCK_QUEUE_SIZE, 215 vhost_vsock_common_handle_output); 216 217 vvc->vhost_dev.nvqs = ARRAY_SIZE(vvc->vhost_vqs); 218 vvc->vhost_dev.vqs = vvc->vhost_vqs; 219 220 vvc->post_load_timer = NULL; 221 } 222 223 void vhost_vsock_common_unrealize(VirtIODevice *vdev) 224 { 225 VHostVSockCommon *vvc = VHOST_VSOCK_COMMON(vdev); 226 227 vhost_vsock_common_post_load_timer_cleanup(vvc); 228 229 virtio_delete_queue(vvc->recv_vq); 230 virtio_delete_queue(vvc->trans_vq); 231 virtio_delete_queue(vvc->event_vq); 232 virtio_cleanup(vdev); 233 } 234 235 static void vhost_vsock_common_class_init(ObjectClass *klass, void *data) 236 { 237 DeviceClass *dc = DEVICE_CLASS(klass); 238 VirtioDeviceClass *vdc = VIRTIO_DEVICE_CLASS(klass); 239 240 set_bit(DEVICE_CATEGORY_MISC, dc->categories); 241 vdc->guest_notifier_mask = vhost_vsock_common_guest_notifier_mask; 242 vdc->guest_notifier_pending = vhost_vsock_common_guest_notifier_pending; 243 } 244 245 static const TypeInfo vhost_vsock_common_info = { 246 .name = TYPE_VHOST_VSOCK_COMMON, 247 .parent = TYPE_VIRTIO_DEVICE, 248 .instance_size = sizeof(VHostVSockCommon), 249 .class_init = vhost_vsock_common_class_init, 250 .abstract = true, 251 }; 252 253 static void vhost_vsock_common_register_types(void) 254 { 255 type_register_static(&vhost_vsock_common_info); 256 } 257 258 type_init(vhost_vsock_common_register_types) 259