4 * Copyright 2015 Red Hat, Inc.
7 * Stefan Hajnoczi <stefanha@redhat.com>
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.
14 #include "qemu/osdep.h"
15 #include <sys/ioctl.h>
16 #include "standard-headers/linux/virtio_vsock.h"
17 #include "qapi/error.h"
18 #include "hw/virtio/virtio-bus.h"
19 #include "hw/virtio/virtio-access.h"
20 #include "qemu/error-report.h"
21 #include "hw/qdev-properties.h"
22 #include "hw/virtio/vhost-vsock.h"
24 #include "qemu/module.h"
25 #include "monitor/monitor.h"
28 VHOST_VSOCK_SAVEVM_VERSION
= 0,
30 VHOST_VSOCK_QUEUE_SIZE
= 128,
33 static void vhost_vsock_get_config(VirtIODevice
*vdev
, uint8_t *config
)
35 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
36 struct virtio_vsock_config vsockcfg
= {};
38 virtio_stq_p(vdev
, &vsockcfg
.guest_cid
, vsock
->conf
.guest_cid
);
39 memcpy(config
, &vsockcfg
, sizeof(vsockcfg
));
42 static int vhost_vsock_set_guest_cid(VHostVSock
*vsock
)
44 const VhostOps
*vhost_ops
= vsock
->vhost_dev
.vhost_ops
;
47 if (!vhost_ops
->vhost_vsock_set_guest_cid
) {
51 ret
= vhost_ops
->vhost_vsock_set_guest_cid(&vsock
->vhost_dev
,
52 vsock
->conf
.guest_cid
);
59 static int vhost_vsock_set_running(VHostVSock
*vsock
, int start
)
61 const VhostOps
*vhost_ops
= vsock
->vhost_dev
.vhost_ops
;
64 if (!vhost_ops
->vhost_vsock_set_running
) {
68 ret
= vhost_ops
->vhost_vsock_set_running(&vsock
->vhost_dev
, start
);
75 static void vhost_vsock_start(VirtIODevice
*vdev
)
77 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
78 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(vdev
)));
79 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(qbus
);
83 if (!k
->set_guest_notifiers
) {
84 error_report("binding does not support guest notifiers");
88 ret
= vhost_dev_enable_notifiers(&vsock
->vhost_dev
, vdev
);
90 error_report("Error enabling host notifiers: %d", -ret
);
94 ret
= k
->set_guest_notifiers(qbus
->parent
, vsock
->vhost_dev
.nvqs
, true);
96 error_report("Error binding guest notifier: %d", -ret
);
97 goto err_host_notifiers
;
100 vsock
->vhost_dev
.acked_features
= vdev
->guest_features
;
101 ret
= vhost_dev_start(&vsock
->vhost_dev
, vdev
);
103 error_report("Error starting vhost: %d", -ret
);
104 goto err_guest_notifiers
;
107 ret
= vhost_vsock_set_running(vsock
, 1);
109 error_report("Error starting vhost vsock: %d", -ret
);
113 /* guest_notifier_mask/pending not used yet, so just unmask
114 * everything here. virtio-pci will do the right thing by
115 * enabling/disabling irqfd.
117 for (i
= 0; i
< vsock
->vhost_dev
.nvqs
; i
++) {
118 vhost_virtqueue_mask(&vsock
->vhost_dev
, vdev
, i
, false);
124 vhost_dev_stop(&vsock
->vhost_dev
, vdev
);
126 k
->set_guest_notifiers(qbus
->parent
, vsock
->vhost_dev
.nvqs
, false);
128 vhost_dev_disable_notifiers(&vsock
->vhost_dev
, vdev
);
131 static void vhost_vsock_stop(VirtIODevice
*vdev
)
133 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
134 BusState
*qbus
= BUS(qdev_get_parent_bus(DEVICE(vdev
)));
135 VirtioBusClass
*k
= VIRTIO_BUS_GET_CLASS(qbus
);
138 if (!k
->set_guest_notifiers
) {
142 ret
= vhost_vsock_set_running(vsock
, 0);
144 error_report("vhost vsock set running failed: %d", ret
);
148 vhost_dev_stop(&vsock
->vhost_dev
, vdev
);
150 ret
= k
->set_guest_notifiers(qbus
->parent
, vsock
->vhost_dev
.nvqs
, false);
152 error_report("vhost guest notifier cleanup failed: %d", ret
);
156 vhost_dev_disable_notifiers(&vsock
->vhost_dev
, vdev
);
159 static void vhost_vsock_set_status(VirtIODevice
*vdev
, uint8_t status
)
161 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
162 bool should_start
= status
& VIRTIO_CONFIG_S_DRIVER_OK
;
164 if (!vdev
->vm_running
) {
165 should_start
= false;
168 if (vsock
->vhost_dev
.started
== should_start
) {
173 vhost_vsock_start(vdev
);
175 vhost_vsock_stop(vdev
);
179 static uint64_t vhost_vsock_get_features(VirtIODevice
*vdev
,
180 uint64_t requested_features
,
183 /* No feature bits used yet */
184 return requested_features
;
187 static void vhost_vsock_handle_output(VirtIODevice
*vdev
, VirtQueue
*vq
)
192 static void vhost_vsock_guest_notifier_mask(VirtIODevice
*vdev
, int idx
,
195 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
197 vhost_virtqueue_mask(&vsock
->vhost_dev
, vdev
, idx
, mask
);
200 static bool vhost_vsock_guest_notifier_pending(VirtIODevice
*vdev
, int idx
)
202 VHostVSock
*vsock
= VHOST_VSOCK(vdev
);
204 return vhost_virtqueue_pending(&vsock
->vhost_dev
, idx
);
207 static void vhost_vsock_send_transport_reset(VHostVSock
*vsock
)
209 VirtQueueElement
*elem
;
210 VirtQueue
*vq
= vsock
->event_vq
;
211 struct virtio_vsock_event event
= {
212 .id
= cpu_to_le32(VIRTIO_VSOCK_EVENT_TRANSPORT_RESET
),
215 elem
= virtqueue_pop(vq
, sizeof(VirtQueueElement
));
217 error_report("vhost-vsock missed transport reset event");
222 error_report("invalid vhost-vsock event virtqueue element with "
227 if (iov_from_buf(elem
->in_sg
, elem
->in_num
, 0,
228 &event
, sizeof(event
)) != sizeof(event
)) {
229 error_report("vhost-vsock event virtqueue element is too short");
233 virtqueue_push(vq
, elem
, sizeof(event
));
234 virtio_notify(VIRTIO_DEVICE(vsock
), vq
);
240 static void vhost_vsock_post_load_timer_cleanup(VHostVSock
*vsock
)
242 if (!vsock
->post_load_timer
) {
246 timer_del(vsock
->post_load_timer
);
247 timer_free(vsock
->post_load_timer
);
248 vsock
->post_load_timer
= NULL
;
251 static void vhost_vsock_post_load_timer_cb(void *opaque
)
253 VHostVSock
*vsock
= opaque
;
255 vhost_vsock_post_load_timer_cleanup(vsock
);
256 vhost_vsock_send_transport_reset(vsock
);
259 static int vhost_vsock_pre_save(void *opaque
)
261 VHostVSock
*vsock
= opaque
;
263 /* At this point, backend must be stopped, otherwise
264 * it might keep writing to memory. */
265 assert(!vsock
->vhost_dev
.started
);
270 static int vhost_vsock_post_load(void *opaque
, int version_id
)
272 VHostVSock
*vsock
= opaque
;
273 VirtIODevice
*vdev
= VIRTIO_DEVICE(vsock
);
275 if (virtio_queue_get_addr(vdev
, 2)) {
276 /* Defer transport reset event to a vm clock timer so that virtqueue
277 * changes happen after migration has completed.
279 assert(!vsock
->post_load_timer
);
280 vsock
->post_load_timer
=
281 timer_new_ns(QEMU_CLOCK_VIRTUAL
,
282 vhost_vsock_post_load_timer_cb
,
284 timer_mod(vsock
->post_load_timer
, 1);
289 static const VMStateDescription vmstate_virtio_vhost_vsock
= {
290 .name
= "virtio-vhost_vsock",
291 .minimum_version_id
= VHOST_VSOCK_SAVEVM_VERSION
,
292 .version_id
= VHOST_VSOCK_SAVEVM_VERSION
,
293 .fields
= (VMStateField
[]) {
294 VMSTATE_VIRTIO_DEVICE
,
295 VMSTATE_END_OF_LIST()
297 .pre_save
= vhost_vsock_pre_save
,
298 .post_load
= vhost_vsock_post_load
,
301 static void vhost_vsock_device_realize(DeviceState
*dev
, Error
**errp
)
303 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
304 VHostVSock
*vsock
= VHOST_VSOCK(dev
);
308 /* Refuse to use reserved CID numbers */
309 if (vsock
->conf
.guest_cid
<= 2) {
310 error_setg(errp
, "guest-cid property must be greater than 2");
314 if (vsock
->conf
.guest_cid
> UINT32_MAX
) {
315 error_setg(errp
, "guest-cid property must be a 32-bit number");
319 if (vsock
->conf
.vhostfd
) {
320 vhostfd
= monitor_fd_param(cur_mon
, vsock
->conf
.vhostfd
, errp
);
322 error_prepend(errp
, "vhost-vsock: unable to parse vhostfd: ");
326 vhostfd
= open("/dev/vhost-vsock", O_RDWR
);
328 error_setg_errno(errp
, -errno
,
329 "vhost-vsock: failed to open vhost device");
334 virtio_init(vdev
, "vhost-vsock", VIRTIO_ID_VSOCK
,
335 sizeof(struct virtio_vsock_config
));
337 /* Receive and transmit queues belong to vhost */
338 virtio_add_queue(vdev
, VHOST_VSOCK_QUEUE_SIZE
, vhost_vsock_handle_output
);
339 virtio_add_queue(vdev
, VHOST_VSOCK_QUEUE_SIZE
, vhost_vsock_handle_output
);
341 /* The event queue belongs to QEMU */
342 vsock
->event_vq
= virtio_add_queue(vdev
, VHOST_VSOCK_QUEUE_SIZE
,
343 vhost_vsock_handle_output
);
345 vsock
->vhost_dev
.nvqs
= ARRAY_SIZE(vsock
->vhost_vqs
);
346 vsock
->vhost_dev
.vqs
= vsock
->vhost_vqs
;
347 ret
= vhost_dev_init(&vsock
->vhost_dev
, (void *)(uintptr_t)vhostfd
,
348 VHOST_BACKEND_TYPE_KERNEL
, 0);
350 error_setg_errno(errp
, -ret
, "vhost-vsock: vhost_dev_init failed");
354 ret
= vhost_vsock_set_guest_cid(vsock
);
356 error_setg_errno(errp
, -ret
, "vhost-vsock: unable to set guest cid");
360 vsock
->post_load_timer
= NULL
;
364 vhost_dev_cleanup(&vsock
->vhost_dev
);
366 virtio_cleanup(vdev
);
371 static void vhost_vsock_device_unrealize(DeviceState
*dev
, Error
**errp
)
373 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
374 VHostVSock
*vsock
= VHOST_VSOCK(dev
);
376 vhost_vsock_post_load_timer_cleanup(vsock
);
378 /* This will stop vhost backend if appropriate. */
379 vhost_vsock_set_status(vdev
, 0);
381 vhost_dev_cleanup(&vsock
->vhost_dev
);
382 virtio_cleanup(vdev
);
385 static Property vhost_vsock_properties
[] = {
386 DEFINE_PROP_UINT64("guest-cid", VHostVSock
, conf
.guest_cid
, 0),
387 DEFINE_PROP_STRING("vhostfd", VHostVSock
, conf
.vhostfd
),
388 DEFINE_PROP_END_OF_LIST(),
391 static void vhost_vsock_class_init(ObjectClass
*klass
, void *data
)
393 DeviceClass
*dc
= DEVICE_CLASS(klass
);
394 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
396 dc
->props
= vhost_vsock_properties
;
397 dc
->vmsd
= &vmstate_virtio_vhost_vsock
;
398 set_bit(DEVICE_CATEGORY_MISC
, dc
->categories
);
399 vdc
->realize
= vhost_vsock_device_realize
;
400 vdc
->unrealize
= vhost_vsock_device_unrealize
;
401 vdc
->get_features
= vhost_vsock_get_features
;
402 vdc
->get_config
= vhost_vsock_get_config
;
403 vdc
->set_status
= vhost_vsock_set_status
;
404 vdc
->guest_notifier_mask
= vhost_vsock_guest_notifier_mask
;
405 vdc
->guest_notifier_pending
= vhost_vsock_guest_notifier_pending
;
408 static const TypeInfo vhost_vsock_info
= {
409 .name
= TYPE_VHOST_VSOCK
,
410 .parent
= TYPE_VIRTIO_DEVICE
,
411 .instance_size
= sizeof(VHostVSock
),
412 .class_init
= vhost_vsock_class_init
,
415 static void vhost_vsock_register_types(void)
417 type_register_static(&vhost_vsock_info
);
420 type_init(vhost_vsock_register_types
)