Enable VHOST_USER_GET_CONFIG/VHOST_USER_SET_CONFIG/VHOST_USER_SET_CONFIG_FD
messages in libvhost-user library, users can implement their own I/O target
based on the library. This enable the virtio config space delivered between
Qemu host device and the I/O target, also event notifier is added in case
of virtio config space changed.
Signed-off-by: Changpeng Liu
---
contrib/libvhost-user/libvhost-user.c | 80 +++
contrib/libvhost-user/libvhost-user.h | 36 +++-
2 files changed, 115 insertions(+), 1 deletion(-)
diff --git a/contrib/libvhost-user/libvhost-user.c
b/contrib/libvhost-user/libvhost-user.c
index f409bd3..5dd00c9 100644
--- a/contrib/libvhost-user/libvhost-user.c
+++ b/contrib/libvhost-user/libvhost-user.c
@@ -84,6 +84,9 @@ vu_request_to_string(unsigned int req)
REQ(VHOST_USER_SET_SLAVE_REQ_FD),
REQ(VHOST_USER_IOTLB_MSG),
REQ(VHOST_USER_SET_VRING_ENDIAN),
+REQ(VHOST_USER_GET_CONFIG),
+REQ(VHOST_USER_SET_CONFIG),
+REQ(VHOST_USER_SET_CONFIG_FD),
REQ(VHOST_USER_MAX),
};
#undef REQ
@@ -798,6 +801,70 @@ vu_set_slave_req_fd(VuDev *dev, VhostUserMsg *vmsg)
}
static bool
+vu_get_config(VuDev *dev, VhostUserMsg *vmsg)
+{
+int ret = -1;
+
+if (dev->iface->get_config) {
+ret = dev->iface->get_config(dev, vmsg->payload.config.region,
+ vmsg->payload.config.size);
+}
+
+if (ret) {
+/* resize to zero to indicate an error to master */
+vmsg->size = 0;
+}
+
+return true;
+}
+
+static bool
+vu_set_config(VuDev *dev, VhostUserMsg *vmsg)
+{
+int ret = -1;
+bool reply_supported = !!(dev->protocol_features &
+ (1ULL << VHOST_USER_PROTOCOL_F_REPLY_ACK));
+
+if (dev->iface->set_config) {
+ret = dev->iface->set_config(dev, vmsg->payload.config.region,
+ vmsg->payload.config.offset,
+ vmsg->payload.config.size,
+ vmsg->payload.config.flags);
+}
+
+vmsg->size = sizeof(vmsg->payload.u64);
+if (!ret) {
+vmsg->payload.u64 = 0;
+} else {
+/* indicate an error in case reply supported */
+vmsg->payload.u64 = 1;
+}
+
+if (reply_supported) {
+return true;
+}
+
+return false;
+}
+
+static bool
+vu_set_config_fd(VuDev *dev, VhostUserMsg *vmsg)
+{
+ if (vmsg->fd_num != 1) {
+vu_panic(dev, "Invalid config_fd message");
+return false;
+}
+
+if (dev->config_fd != -1) {
+close(dev->config_fd);
+}
+dev->config_fd = vmsg->fds[0];
+DPRINT("Got config_fd: %d\n", vmsg->fds[0]);
+
+return false;
+}
+
+static bool
vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
{
int do_reply = 0;
@@ -862,6 +929,12 @@ vu_process_message(VuDev *dev, VhostUserMsg *vmsg)
return vu_set_vring_enable_exec(dev, vmsg);
case VHOST_USER_SET_SLAVE_REQ_FD:
return vu_set_slave_req_fd(dev, vmsg);
+case VHOST_USER_GET_CONFIG:
+return vu_get_config(dev, vmsg);
+case VHOST_USER_SET_CONFIG:
+return vu_set_config(dev, vmsg);
+case VHOST_USER_SET_CONFIG_FD:
+return vu_set_config_fd(dev, vmsg);
case VHOST_USER_NONE:
break;
default:
@@ -940,6 +1013,11 @@ vu_deinit(VuDev *dev)
dev->slave_fd = -1;
}
+if (dev->config_fd != -1) {
+close(dev->config_fd);
+dev->config_fd = -1;
+}
+
if (dev->sock != -1) {
close(dev->sock);
}
@@ -970,6 +1048,8 @@ vu_init(VuDev *dev,
dev->iface = iface;
dev->log_call_fd = -1;
dev->slave_fd = -1;
+dev->config_fd = -1;
+
for (i = 0; i < VHOST_MAX_NR_VIRTQUEUE; i++) {
dev->vq[i] = (VuVirtq) {
.call_fd = -1, .kick_fd = -1, .err_fd = -1,
diff --git a/contrib/libvhost-user/libvhost-user.h
b/contrib/libvhost-user/libvhost-user.h
index 2f5864b..46f3315 100644
--- a/contrib/libvhost-user/libvhost-user.h
+++ b/contrib/libvhost-user/libvhost-user.h
@@ -30,6 +30,16 @@
#define VHOST_MEMORY_MAX_NREGIONS 8
+typedef enum VhostSetConfigType {
+VHOST_SET_CONFIG_TYPE_MASTER = 0,
+VHOST_SET_CONFIG_TYPE_MIGRATION = 1,
+} VhostSetConfigType;
+
+/*
+ * Maximum size of virtio device config space
+ */
+#define VHOST_USER_MAX_CONFIG_SIZE 256
+
enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_MQ = 0,
VHOST_USER_PROTOCOL_F_LOG_SHMFD = 1,
@@ -38,7 +48,6 @@ enum VhostUserProtocolFeature {
VHOST_USER_PROTOCOL_F_NET_MTU = 4,
VHOST_USER_PROTOCOL_F_SLAVE_REQ = 5,
VHOST_USER_PROTOCOL_F_CROSS_ENDIAN = 6,
-
VHOST_USER_PROTOCOL_F_MAX
};
@@ -69,6 +78,9 @@ typedef enum VhostUserRequest {
VHOST_USER_SET_SLAVE_REQ_FD = 21,
VHOST_USER_IOTLB_MSG = 22,
VHOST_USER_SET_VRING_ENDIAN = 23,
+VHOST_USER_GET_CONFIG = 24,
+VHOST_USER_SET_CONFIG = 25,
+