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
= virtio_device_should_start(vdev
, status
);
60 if (vhost_dev_is_started(&vvc
->vhost_dev
) == should_start
) {
65 int ret
= vhost_vsock_common_start(vdev
);
70 vhost_vsock_common_stop(vdev
);
74 static uint64_t vuv_get_features(VirtIODevice
*vdev
,
78 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(vdev
);
80 features
= vhost_get_features(&vvc
->vhost_dev
, user_feature_bits
, features
);
82 return vhost_vsock_common_get_features(vdev
, features
, errp
);
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
);
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, errp
);
116 ret
= vhost_dev_get_config(&vvc
->vhost_dev
, (uint8_t *)&vsock
->vsockcfg
,
117 sizeof(struct virtio_vsock_config
), errp
);
125 vhost_dev_cleanup(&vvc
->vhost_dev
);
127 vhost_vsock_common_unrealize(vdev
);
128 vhost_user_cleanup(&vsock
->vhost_user
);
132 static void vuv_device_unrealize(DeviceState
*dev
)
134 VHostVSockCommon
*vvc
= VHOST_VSOCK_COMMON(dev
);
135 VirtIODevice
*vdev
= VIRTIO_DEVICE(dev
);
136 VHostUserVSock
*vsock
= VHOST_USER_VSOCK(dev
);
138 /* This will stop vhost backend if appropriate. */
139 vuv_set_status(vdev
, 0);
141 vhost_dev_cleanup(&vvc
->vhost_dev
);
143 vhost_vsock_common_unrealize(vdev
);
145 vhost_user_cleanup(&vsock
->vhost_user
);
149 static Property vuv_properties
[] = {
150 DEFINE_PROP_CHR("chardev", VHostUserVSock
, conf
.chardev
),
151 DEFINE_PROP_END_OF_LIST(),
154 static void vuv_class_init(ObjectClass
*klass
, void *data
)
156 DeviceClass
*dc
= DEVICE_CLASS(klass
);
157 VirtioDeviceClass
*vdc
= VIRTIO_DEVICE_CLASS(klass
);
159 device_class_set_props(dc
, vuv_properties
);
160 dc
->vmsd
= &vuv_vmstate
;
161 vdc
->realize
= vuv_device_realize
;
162 vdc
->unrealize
= vuv_device_unrealize
;
163 vdc
->get_features
= vuv_get_features
;
164 vdc
->get_config
= vuv_get_config
;
165 vdc
->set_status
= vuv_set_status
;
168 static const TypeInfo vuv_info
= {
169 .name
= TYPE_VHOST_USER_VSOCK
,
170 .parent
= TYPE_VHOST_VSOCK_COMMON
,
171 .instance_size
= sizeof(VHostUserVSock
),
172 .class_init
= vuv_class_init
,
175 static void vuv_register_types(void)
177 type_register_static(&vuv_info
);
180 type_init(vuv_register_types
)