From 53c24913f2f7545d8c7ec692fd6669b5305834cb Mon Sep 17 00:00:00 2001 From: Changpeng Liu Date: Wed, 8 Nov 2017 14:53:12 -0500 Subject: [PATCH] vhost_lib: enable virtio configuration space feature New added vhost user messages: GET_CONFIG/SET_CONFIG are used for get/set virtio device's configuration space, this commit enable the new added vhost messages. Change-Id: I5c3e3f8fb6ed55e99299323c39658765b1724bb8 Signed-off-by: Changpeng Liu Reviewed-on: https://review.gerrithub.io/386545 Tested-by: SPDK Automated Test System Reviewed-by: Dariusz Stojaczyk Reviewed-by: Daniel Verkamp Reviewed-by: Jim Harris --- lib/vhost/rte_vhost/rte_vhost.h | 4 +++ lib/vhost/rte_vhost/vhost_user.c | 21 ++++++++++++++ lib/vhost/rte_vhost/vhost_user.h | 22 ++++++++++++++ lib/vhost/vhost.c | 49 ++++++++++++++++++++++++++++++++ lib/vhost/vhost_internal.h | 4 +++ 5 files changed, 100 insertions(+) diff --git a/lib/vhost/rte_vhost/rte_vhost.h b/lib/vhost/rte_vhost/rte_vhost.h index baabc8ee1..08380cca6 100644 --- a/lib/vhost/rte_vhost/rte_vhost.h +++ b/lib/vhost/rte_vhost/rte_vhost.h @@ -108,6 +108,10 @@ struct vhost_device_ops { int (*new_connection)(int vid); void (*destroy_connection)(int vid); + int (*get_config)(int vid, uint8_t *config, uint32_t config_len); + int (*set_config)(int vid, uint8_t *config, uint32_t offset, + uint32_t len, uint32_t flags); + void *reserved[2]; /**< Reserved for future extension */ }; diff --git a/lib/vhost/rte_vhost/vhost_user.c b/lib/vhost/rte_vhost/vhost_user.c index 6827b5549..ef920f66d 100644 --- a/lib/vhost/rte_vhost/vhost_user.c +++ b/lib/vhost/rte_vhost/vhost_user.c @@ -76,6 +76,8 @@ static const char *vhost_message_str[VHOST_USER_MAX] = { [VHOST_USER_SET_VRING_ENABLE] = "VHOST_USER_SET_VRING_ENABLE", [VHOST_USER_SEND_RARP] = "VHOST_USER_SEND_RARP", [VHOST_USER_NET_SET_MTU] = "VHOST_USER_NET_SET_MTU", + [VHOST_USER_GET_CONFIG] = "VHOST_USER_GET_CONFIG", + [VHOST_USER_SET_CONFIG] = "VHOST_USER_SET_CONFIG", }; static uint64_t @@ -1063,6 +1065,25 @@ vhost_user_msg_handler(int vid, int fd) } switch (msg.request) { + case VHOST_USER_GET_CONFIG: + if (dev->notify_ops->get_config(dev->vid, + msg.payload.config.region, + msg.payload.config.size) != 0) { + msg.size = sizeof(uint64_t); + } + send_vhost_message(fd, &msg); + break; + case VHOST_USER_SET_CONFIG: + if ((dev->notify_ops->set_config(dev->vid, + msg.payload.config.region, + msg.payload.config.offset, + msg.payload.config.size, + msg.payload.config.flags)) != 0) { + ret = 1; + } else { + ret = 0; + } + break; case VHOST_USER_GET_FEATURES: msg.payload.u64 = vhost_user_get_features(dev); msg.size = sizeof(msg.payload.u64); diff --git a/lib/vhost/rte_vhost/vhost_user.h b/lib/vhost/rte_vhost/vhost_user.h index 2ba22dbb0..1f3941c8c 100644 --- a/lib/vhost/rte_vhost/vhost_user.h +++ b/lib/vhost/rte_vhost/vhost_user.h @@ -43,6 +43,11 @@ #define VHOST_MEMORY_MAX_NREGIONS 8 +/* + * Maximum size of virtio device config space + */ +#define VHOST_USER_MAX_CONFIG_SIZE 256 + #define VHOST_USER_PROTOCOL_F_MQ 0 #define VHOST_USER_PROTOCOL_F_LOG_SHMFD 1 #define VHOST_USER_PROTOCOL_F_RARP 2 @@ -77,9 +82,18 @@ typedef enum VhostUserRequest { VHOST_USER_SET_VRING_ENABLE = 18, VHOST_USER_SEND_RARP = 19, VHOST_USER_NET_SET_MTU = 20, + VHOST_USER_GET_CONFIG = 24, + VHOST_USER_SET_CONFIG = 25, VHOST_USER_MAX } VhostUserRequest; +typedef enum VhostUserSlaveRequest { + VHOST_USER_SLAVE_NONE = 0, + VHOST_USER_SLAVE_IOTLB_MSG = 1, + VHOST_USER_SLAVE_CONFIG_CHANGE_MSG = 2, + VHOST_USER_SLAVE_MAX +} VhostUserSlaveRequest; + typedef struct VhostUserMemoryRegion { uint64_t guest_phys_addr; uint64_t memory_size; @@ -98,6 +112,13 @@ typedef struct VhostUserLog { uint64_t mmap_offset; } VhostUserLog; +typedef struct VhostUserConfig { + uint32_t offset; + uint32_t size; + uint32_t flags; + uint8_t region[VHOST_USER_MAX_CONFIG_SIZE]; +} VhostUserConfig; + typedef struct VhostUserMsg { VhostUserRequest request; @@ -114,6 +135,7 @@ typedef struct VhostUserMsg { struct vhost_vring_addr addr; VhostUserMemory memory; VhostUserLog log; + VhostUserConfig config; } payload; int fds[VHOST_MEMORY_MAX_NREGIONS]; } __attribute((packed)) VhostUserMsg; diff --git a/lib/vhost/vhost.c b/lib/vhost/vhost.c index ef9c46746..d5107f816 100644 --- a/lib/vhost/vhost.c +++ b/lib/vhost/vhost.c @@ -70,10 +70,15 @@ static int new_connection(int vid); static int start_device(int vid); static void stop_device(int vid); static void destroy_connection(int vid); +static int get_config(int vid, uint8_t *config, uint32_t len); +static int set_config(int vid, uint8_t *config, uint32_t offset, + uint32_t size, uint32_t flags); const struct vhost_device_ops g_spdk_vhost_ops = { .new_device = start_device, .destroy_device = stop_device, + .get_config = get_config, + .set_config = set_config, .new_connection = new_connection, .destroy_connection = destroy_connection, }; @@ -957,6 +962,50 @@ out: return rc; } +static int +get_config(int vid, uint8_t *config, uint32_t len) +{ + struct spdk_vhost_dev *vdev; + int rc = -1; + + pthread_mutex_lock(&g_spdk_vhost_mutex); + vdev = spdk_vhost_dev_find_by_vid(vid); + if (vdev == NULL) { + SPDK_ERRLOG("Controller with vid %d doesn't exist.\n", vid); + goto out; + } + + if (vdev->backend->vhost_get_config) { + rc = vdev->backend->vhost_get_config(vdev, config, len); + } + +out: + pthread_mutex_unlock(&g_spdk_vhost_mutex); + return rc; +} + +static int +set_config(int vid, uint8_t *config, uint32_t offset, uint32_t size, uint32_t flags) +{ + struct spdk_vhost_dev *vdev; + int rc = -1; + + pthread_mutex_lock(&g_spdk_vhost_mutex); + vdev = spdk_vhost_dev_find_by_vid(vid); + if (vdev == NULL) { + SPDK_ERRLOG("Controller with vid %d doesn't exist.\n", vid); + goto out; + } + + if (vdev->backend->vhost_set_config) { + rc = vdev->backend->vhost_set_config(vdev, config, offset, size, flags); + } + +out: + pthread_mutex_unlock(&g_spdk_vhost_mutex); + return rc; +} + void spdk_vhost_startup(void *arg1, void *arg2) { diff --git a/lib/vhost/vhost_internal.h b/lib/vhost/vhost_internal.h index f1fbbfe80..9ecfacd6e 100644 --- a/lib/vhost/vhost_internal.h +++ b/lib/vhost/vhost_internal.h @@ -130,6 +130,10 @@ struct spdk_vhost_dev_backend { spdk_vhost_event_fn start_device; spdk_vhost_event_fn stop_device; + int (*vhost_get_config)(struct spdk_vhost_dev *vdev, uint8_t *config, uint32_t len); + int (*vhost_set_config)(struct spdk_vhost_dev *vdev, uint8_t *config, + uint32_t offset, uint32_t size, uint32_t flags); + void (*dump_config_json)(struct spdk_vhost_dev *vdev, struct spdk_json_write_ctx *w); int (*vhost_remove_controller)(struct spdk_vhost_dev *vdev); };