2 * Vhost-user vsock virtio device
4 * Copyright 2020 Red Hat, Inc.
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
11 #include "qemu/osdep.h"
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"
19 static const int user_feature_bits
[] = {
21 VIRTIO_RING_F_INDIRECT_DESC
,
22 VIRTIO_RING_F_EVENT_IDX
,
23 VIRTIO_F_NOTIFY_ON_EMPTY
,
24 VHOST_INVALID_FEATURE_BIT
27 static void vuv_get_config(VirtIODevice
*vdev
, uint8_t *config
)
29 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(vdev
);
31 memcpy(config
, &vsock
->vsockcfg
, sizeof(struct virtio_vsock_config
));
34 static int vuv_handle_config_change(struct vhost_dev
*dev
)
36 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
->vdev
);
37 int ret
= vhost_dev_get_config(dev
, (uint8_t *)&vsock
->vsockcfg
,
38 sizeof(struct virtio_vsock_config
));
40 error_report("get config space failed");
44 virtio_notify_config(dev
->vdev
);
49 const VhostDevConfigOps vsock_ops
= {
50 .vhost_dev_config_notifier
= vuv_handle_config_change
,
53 static void vuv_set_status(VirtIODevice
*vdev
, uint8_t status
)
55 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(vdev
);
56 bool should_start
= status
& VIRTIO_CONFIG_S_DRIVER_OK
;
58 if (!vdev
->vm_running
) {
62 if (vvc
->vhost_dev
.started
== should_start
) {
67 int ret
= vhost_vsock_common_start(vdev
);
72 vhost_vsock_common_stop(vdev
);
76 static uint64_t vuv_get_features(VirtIODevice
*vdev
,
80 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(vdev
);
82 return vhost_get_features(&vvc
->vhost_dev
, user_feature_bits
, features
);
85 static const VMStateDescription vuv_vmstate
= {
86 .name
= "vhost-user-vsock",
90 static void vuv_device_realize(DeviceState
*dev
, Error
**errp
)
92 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(dev
);
93 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
94 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
);
97 if (!vsock
->conf
.chardev
.chr
) {
98 error_setg(errp
, "missing chardev");
102 if (!vhost_user_init(&vsock
->vhost_user
, &vsock
->conf
.chardev
, errp
)) {
106 vhost_vsock_common_realize(vdev
, "vhost-user-vsock");
108 vhost_dev_set_config_notifier(&vvc
->vhost_dev
, &vsock_ops
);
110 ret
= vhost_dev_init(&vvc
->vhost_dev
, &vsock
->vhost_user
,
111 VHOST_BACKEND_TYPE_USER
, 0);
113 error_setg_errno(errp
, -ret
, "vhost_dev_init failed");
117 ret
= vhost_dev_get_config(&vvc
->vhost_dev
, (uint8_t *)&vsock
->vsockcfg
,
118 sizeof(struct virtio_vsock_config
));
120 error_setg_errno(errp
, -ret
, "get config space failed");
127 vhost_dev_cleanup(&vvc
->vhost_dev
);
129 vhost_vsock_common_unrealize(vdev
);
130 vhost_user_cleanup(&vsock
->vhost_user
);
134 static void vuv_device_unrealize(DeviceState
*dev
)
136 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(dev
);
137 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
138 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
);
140 /* This will stop vhost backend if appropriate. */
141 vuv_set_status(vdev
, 0);
143 vhost_dev_cleanup(&vvc
->vhost_dev
);
145 vhost_vsock_common_unrealize(vdev
);
147 vhost_user_cleanup(&vsock
->vhost_user
);
151 static Property vuv_properties
[] = {
152 DEFINE_PROP_CHR("chardev", VHostUserVSock
, conf
.chardev
),
153 DEFINE_PROP_END_OF_LIST(),
156 static void vuv_class_init(ObjectClass
*klass
, void *data
)
158 DeviceClass
*dc
= DEVICE_CLASS(klass
);
159 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
161 device_class_set_props(dc
, vuv_properties
);
162 dc
->vmsd
= &vuv_vmstate
;
163 vdc
->realize
= vuv_device_realize
;
164 vdc
->unrealize
= vuv_device_unrealize
;
165 vdc
->get_features
= vuv_get_features
;
166 vdc
->get_config
= vuv_get_config
;
167 vdc
->set_status
= vuv_set_status
;
170 static const TypeInfo vuv_info
= {
171 .name
= TYPE_VHOST_USER_VSOCK
,
172 .parent
= TYPE_VHOST_VSOCK_COMMON
,
173 .instance_size
= sizeof(VHostUserVSock
),
174 .class_init
= vuv_class_init
,
177 static void vuv_register_types(void)
179 type_register_static(&vuv_info
);
182 type_init(vuv_register_types
)