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 Error
*local_err
= NULL
;
38 int ret
= vhost_dev_get_config(dev
, (uint8_t *)&vsock
->vsockcfg
,
39 sizeof(struct virtio_vsock_config
),
42 error_report_err(local_err
);
46 virtio_notify_config(dev
->vdev
);
51 const VhostDevConfigOps vsock_ops
= {
52 .vhost_dev_config_notifier
= vuv_handle_config_change
,
55 static void vuv_set_status(VirtIODevice
*vdev
, uint8_t status
)
57 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(vdev
);
58 bool should_start
= status
& VIRTIO_CONFIG_S_DRIVER_OK
;
60 if (!vdev
->vm_running
) {
64 if (vvc
->vhost_dev
.started
== should_start
) {
69 int ret
= vhost_vsock_common_start(vdev
);
74 vhost_vsock_common_stop(vdev
);
78 static uint64_t vuv_get_features(VirtIODevice
*vdev
,
82 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(vdev
);
84 features
= vhost_get_features(&vvc
->vhost_dev
, user_feature_bits
, features
);
86 return vhost_vsock_common_get_features(vdev
, features
, errp
);
89 static const VMStateDescription vuv_vmstate
= {
90 .name
= "vhost-user-vsock",
94 static void vuv_device_realize(DeviceState
*dev
, Error
**errp
)
96 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(dev
);
97 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
98 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
);
101 if (!vsock
->conf
.chardev
.chr
) {
102 error_setg(errp
, "missing chardev");
106 if (!vhost_user_init(&vsock
->vhost_user
, &vsock
->conf
.chardev
, errp
)) {
110 vhost_vsock_common_realize(vdev
);
112 vhost_dev_set_config_notifier(&vvc
->vhost_dev
, &vsock_ops
);
114 ret
= vhost_dev_init(&vvc
->vhost_dev
, &vsock
->vhost_user
,
115 VHOST_BACKEND_TYPE_USER
, 0, errp
);
120 ret
= vhost_dev_get_config(&vvc
->vhost_dev
, (uint8_t *)&vsock
->vsockcfg
,
121 sizeof(struct virtio_vsock_config
), errp
);
129 vhost_dev_cleanup(&vvc
->vhost_dev
);
131 vhost_vsock_common_unrealize(vdev
);
132 vhost_user_cleanup(&vsock
->vhost_user
);
136 static void vuv_device_unrealize(DeviceState
*dev
)
138 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(dev
);
139 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
140 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
);
142 /* This will stop vhost backend if appropriate. */
143 vuv_set_status(vdev
, 0);
145 vhost_dev_cleanup(&vvc
->vhost_dev
);
147 vhost_vsock_common_unrealize(vdev
);
149 vhost_user_cleanup(&vsock
->vhost_user
);
153 static Property vuv_properties
[] = {
154 DEFINE_PROP_CHR("chardev", VHostUserVSock
, conf
.chardev
),
155 DEFINE_PROP_END_OF_LIST(),
158 static void vuv_class_init(ObjectClass
*klass
, void *data
)
160 DeviceClass
*dc
= DEVICE_CLASS(klass
);
161 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
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
;
172 static 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
,
179 static void vuv_register_types(void)
181 type_register_static(&vuv_info
);
184 type_init(vuv_register_types
)