From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58996) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZkIZA-0005zs-0i for qemu-devel@nongnu.org; Thu, 08 Oct 2015 17:17:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ZkIZ6-0007Fr-04 for qemu-devel@nongnu.org; Thu, 08 Oct 2015 17:17:31 -0400 Received: from mx1.redhat.com ([209.132.183.28]:7639) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ZkIZ5-0007Fn-KA for qemu-devel@nongnu.org; Thu, 08 Oct 2015 17:17:27 -0400 Date: Fri, 9 Oct 2015 00:17:21 +0300 From: "Michael S. Tsirkin" Message-ID: <1444338957-15293-13-git-send-email-mst@redhat.com> References: <1444338957-15293-1-git-send-email-mst@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline In-Reply-To: <1444338957-15293-1-git-send-email-mst@redhat.com> Content-Transfer-Encoding: quoted-printable Subject: [Qemu-devel] [PULL 12/25] vhost: use a function for each call List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Peter Maydell , Jason Wang , Paolo Bonzini , =?us-ascii?B?PT9VVEYtOD9xP01hcmMtQW5kcj1DMz1BOT0yMEx1cmVhdT89?= From: Marc-Andr=E9 Lureau Replace the generic vhost_call() by specific functions for each function call to help with type safety and changing arguments. While doing this, I found that "unsigned long long" and "uint64_t" were used interchangeably and causing compilation warnings, using uint64_t instead, as the vhost & protocol specifies. Signed-off-by: Marc-Andr=E9 Lureau Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin --- include/hw/virtio/vhost-backend.h | 63 ++++- include/hw/virtio/vhost.h | 12 +- hw/net/vhost_net.c | 16 +- hw/scsi/vhost-scsi.c | 7 +- hw/virtio/vhost-backend.c | 124 ++++++++- hw/virtio/vhost-user.c | 518 ++++++++++++++++++++++----------= ------ hw/virtio/vhost.c | 36 +-- 7 files changed, 501 insertions(+), 275 deletions(-) diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-= backend.h index 7064a12..e07118c 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -22,28 +22,77 @@ typedef enum VhostBackendType { =20 struct vhost_dev; struct vhost_log; +struct vhost_memory; +struct vhost_vring_file; +struct vhost_vring_state; +struct vhost_vring_addr; +struct vhost_scsi_target; =20 -typedef int (*vhost_call)(struct vhost_dev *dev, unsigned long int reque= st, - void *arg); typedef int (*vhost_backend_init)(struct vhost_dev *dev, void *opaque); typedef int (*vhost_backend_cleanup)(struct vhost_dev *dev); -typedef int (*vhost_backend_get_vq_index)(struct vhost_dev *dev, int idx= ); -typedef int (*vhost_backend_set_vring_enable)(struct vhost_dev *dev, int= enable); =20 +typedef int (*vhost_net_set_backend_op)(struct vhost_dev *dev, + struct vhost_vring_file *file); +typedef int (*vhost_scsi_set_endpoint_op)(struct vhost_dev *dev, + struct vhost_scsi_target *target); +typedef int (*vhost_scsi_clear_endpoint_op)(struct vhost_dev *dev, + struct vhost_scsi_target *target); +typedef int (*vhost_scsi_get_abi_version_op)(struct vhost_dev *dev, + int *version); typedef int (*vhost_set_log_base_op)(struct vhost_dev *dev, uint64_t bas= e, struct vhost_log *log); +typedef int (*vhost_set_mem_table_op)(struct vhost_dev *dev, + struct vhost_memory *mem); +typedef int (*vhost_set_vring_addr_op)(struct vhost_dev *dev, + struct vhost_vring_addr *addr); +typedef int (*vhost_set_vring_endian_op)(struct vhost_dev *dev, + struct vhost_vring_state *ring)= ; +typedef int (*vhost_set_vring_num_op)(struct vhost_dev *dev, + struct vhost_vring_state *ring); +typedef int (*vhost_set_vring_base_op)(struct vhost_dev *dev, + struct vhost_vring_state *ring); +typedef int (*vhost_get_vring_base_op)(struct vhost_dev *dev, + struct vhost_vring_state *ring); +typedef int (*vhost_set_vring_kick_op)(struct vhost_dev *dev, + struct vhost_vring_file *file); +typedef int (*vhost_set_vring_call_op)(struct vhost_dev *dev, + struct vhost_vring_file *file); +typedef int (*vhost_set_features_op)(struct vhost_dev *dev, + uint64_t features); +typedef int (*vhost_get_features_op)(struct vhost_dev *dev, + uint64_t *features); +typedef int (*vhost_set_owner_op)(struct vhost_dev *dev); +typedef int (*vhost_reset_device_op)(struct vhost_dev *dev); +typedef int (*vhost_get_vq_index_op)(struct vhost_dev *dev, int idx); +typedef int (*vhost_set_vring_enable_op)(struct vhost_dev *dev, + int enable); typedef bool (*vhost_requires_shm_log_op)(struct vhost_dev *dev); =20 typedef struct VhostOps { VhostBackendType backend_type; - vhost_call vhost_call; =20 vhost_backend_init vhost_backend_init; vhost_backend_cleanup vhost_backend_cleanup; - vhost_backend_get_vq_index vhost_backend_get_vq_index; - vhost_backend_set_vring_enable vhost_backend_set_vring_enable; =20 + vhost_net_set_backend_op vhost_net_set_backend; + vhost_scsi_set_endpoint_op vhost_scsi_set_endpoint; + vhost_scsi_clear_endpoint_op vhost_scsi_clear_endpoint; + vhost_scsi_get_abi_version_op vhost_scsi_get_abi_version; vhost_set_log_base_op vhost_set_log_base; + vhost_set_mem_table_op vhost_set_mem_table; + vhost_set_vring_addr_op vhost_set_vring_addr; + vhost_set_vring_endian_op vhost_set_vring_endian; + vhost_set_vring_num_op vhost_set_vring_num; + vhost_set_vring_base_op vhost_set_vring_base; + vhost_get_vring_base_op vhost_get_vring_base; + vhost_set_vring_kick_op vhost_set_vring_kick; + vhost_set_vring_call_op vhost_set_vring_call; + vhost_set_features_op vhost_set_features; + vhost_get_features_op vhost_get_features; + vhost_set_owner_op vhost_set_owner; + vhost_reset_device_op vhost_reset_device; + vhost_get_vq_index_op vhost_get_vq_index; + vhost_set_vring_enable_op vhost_set_vring_enable; vhost_requires_shm_log_op vhost_requires_shm_log; } VhostOps; =20 diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 7e7dc45..c8c42cc 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -45,14 +45,14 @@ struct vhost_dev { int nvqs; /* the first virtqueue which would be used by this vhost dev */ int vq_index; - unsigned long long features; - unsigned long long acked_features; - unsigned long long backend_features; - unsigned long long protocol_features; - unsigned long long max_queues; + uint64_t features; + uint64_t acked_features; + uint64_t backend_features; + uint64_t protocol_features; + uint64_t max_queues; bool started; bool log_enabled; - unsigned long long log_size; + uint64_t log_size; Error *migration_blocker; bool memory_changed; hwaddr mem_changed_start_addr; diff --git a/hw/net/vhost_net.c b/hw/net/vhost_net.c index 2bce891..1ab4133 100644 --- a/hw/net/vhost_net.c +++ b/hw/net/vhost_net.c @@ -252,8 +252,7 @@ static int vhost_net_start_one(struct vhost_net *net, file.fd =3D net->backend; for (file.index =3D 0; file.index < net->dev.nvqs; ++file.index)= { const VhostOps *vhost_ops =3D net->dev.vhost_ops; - r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BACKEND= , - &file); + r =3D vhost_ops->vhost_net_set_backend(&net->dev, &file); if (r < 0) { r =3D -errno; goto fail; @@ -266,8 +265,7 @@ fail: if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_TAP) { while (file.index-- > 0) { const VhostOps *vhost_ops =3D net->dev.vhost_ops; - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BAC= KEND, - &file); + int r =3D vhost_ops->vhost_net_set_backend(&net->dev, &file)= ; assert(r >=3D 0); } } @@ -289,15 +287,13 @@ static void vhost_net_stop_one(struct vhost_net *ne= t, if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_TAP) { for (file.index =3D 0; file.index < net->dev.nvqs; ++file.index)= { const VhostOps *vhost_ops =3D net->dev.vhost_ops; - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_NET_SET_BAC= KEND, - &file); + int r =3D vhost_ops->vhost_net_set_backend(&net->dev, &file)= ; assert(r >=3D 0); } } else if (net->nc->info->type =3D=3D NET_CLIENT_OPTIONS_KIND_VHOST_= USER) { for (file.index =3D 0; file.index < net->dev.nvqs; ++file.index)= { const VhostOps *vhost_ops =3D net->dev.vhost_ops; - int r =3D vhost_ops->vhost_call(&net->dev, VHOST_RESET_DEVIC= E, - NULL); + int r =3D vhost_ops->vhost_reset_device(&net->dev); assert(r >=3D 0); } } @@ -428,8 +424,8 @@ int vhost_set_vring_enable(NetClientState *nc, int en= able) VHostNetState *net =3D get_vhost_net(nc); const VhostOps *vhost_ops =3D net->dev.vhost_ops; =20 - if (vhost_ops->vhost_backend_set_vring_enable) { - return vhost_ops->vhost_backend_set_vring_enable(&net->dev, enab= le); + if (vhost_ops->vhost_set_vring_enable) { + return vhost_ops->vhost_set_vring_enable(&net->dev, enable); } =20 return 0; diff --git a/hw/scsi/vhost-scsi.c b/hw/scsi/vhost-scsi.c index fb7983d..00cdac6 100644 --- a/hw/scsi/vhost-scsi.c +++ b/hw/scsi/vhost-scsi.c @@ -46,7 +46,7 @@ static int vhost_scsi_set_endpoint(VHostSCSI *s) =20 memset(&backend, 0, sizeof(backend)); pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwp= n); - ret =3D vhost_ops->vhost_call(&s->dev, VHOST_SCSI_SET_ENDPOINT, &bac= kend); + ret =3D vhost_ops->vhost_scsi_set_endpoint(&s->dev, &backend); if (ret < 0) { return -errno; } @@ -61,7 +61,7 @@ static void vhost_scsi_clear_endpoint(VHostSCSI *s) =20 memset(&backend, 0, sizeof(backend)); pstrcpy(backend.vhost_wwpn, sizeof(backend.vhost_wwpn), vs->conf.wwp= n); - vhost_ops->vhost_call(&s->dev, VHOST_SCSI_CLEAR_ENDPOINT, &backend); + vhost_ops->vhost_scsi_clear_endpoint(&s->dev, &backend); } =20 static int vhost_scsi_start(VHostSCSI *s) @@ -77,8 +77,7 @@ static int vhost_scsi_start(VHostSCSI *s) return -ENOSYS; } =20 - ret =3D vhost_ops->vhost_call(&s->dev, - VHOST_SCSI_GET_ABI_VERSION, &abi_version= ); + ret =3D vhost_ops->vhost_scsi_get_abi_version(&s->dev, &abi_version)= ; if (ret < 0) { return -errno; } diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c index 87ab028..3820af4 100644 --- a/hw/virtio/vhost-backend.c +++ b/hw/virtio/vhost-backend.c @@ -43,27 +43,135 @@ static int vhost_kernel_cleanup(struct vhost_dev *de= v) return close(fd); } =20 -static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx) +static int vhost_kernel_net_set_backend(struct vhost_dev *dev, + struct vhost_vring_file *file) { - assert(idx >=3D dev->vq_index && idx < dev->vq_index + dev->nvqs); + return vhost_kernel_call(dev, VHOST_NET_SET_BACKEND, file); +} =20 - return idx - dev->vq_index; +static int vhost_kernel_scsi_set_endpoint(struct vhost_dev *dev, + struct vhost_scsi_target *targ= et) +{ + return vhost_kernel_call(dev, VHOST_SCSI_SET_ENDPOINT, target); +} + +static int vhost_kernel_scsi_clear_endpoint(struct vhost_dev *dev, + struct vhost_scsi_target *ta= rget) +{ + return vhost_kernel_call(dev, VHOST_SCSI_CLEAR_ENDPOINT, target); +} + +static int vhost_kernel_scsi_get_abi_version(struct vhost_dev *dev, int = *version) +{ + return vhost_kernel_call(dev, VHOST_SCSI_GET_ABI_VERSION, version); } =20 -static int vhost_set_log_base(struct vhost_dev *dev, uint64_t base, - struct vhost_log *log) +static int vhost_kernel_set_log_base(struct vhost_dev *dev, uint64_t bas= e, + struct vhost_log *log) { return vhost_kernel_call(dev, VHOST_SET_LOG_BASE, &base); } =20 +static int vhost_kernel_set_mem_table(struct vhost_dev *dev, + struct vhost_memory *mem) +{ + return vhost_kernel_call(dev, VHOST_SET_MEM_TABLE, mem); +} + +static int vhost_kernel_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_ADDR, addr); +} + +static int vhost_kernel_set_vring_endian(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_ENDIAN, ring); +} + +static int vhost_kernel_set_vring_num(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_NUM, ring); +} + +static int vhost_kernel_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_BASE, ring); +} + +static int vhost_kernel_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_kernel_call(dev, VHOST_GET_VRING_BASE, ring); +} + +static int vhost_kernel_set_vring_kick(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_KICK, file); +} + +static int vhost_kernel_set_vring_call(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + return vhost_kernel_call(dev, VHOST_SET_VRING_CALL, file); +} + +static int vhost_kernel_set_features(struct vhost_dev *dev, + uint64_t features) +{ + return vhost_kernel_call(dev, VHOST_SET_FEATURES, &features); +} + +static int vhost_kernel_get_features(struct vhost_dev *dev, + uint64_t *features) +{ + return vhost_kernel_call(dev, VHOST_GET_FEATURES, features); +} + +static int vhost_kernel_set_owner(struct vhost_dev *dev) +{ + return vhost_kernel_call(dev, VHOST_SET_OWNER, NULL); +} + +static int vhost_kernel_reset_device(struct vhost_dev *dev) +{ + return vhost_kernel_call(dev, VHOST_RESET_DEVICE, NULL); +} + +static int vhost_kernel_get_vq_index(struct vhost_dev *dev, int idx) +{ + assert(idx >=3D dev->vq_index && idx < dev->vq_index + dev->nvqs); + + return idx - dev->vq_index; +} + static const VhostOps kernel_ops =3D { .backend_type =3D VHOST_BACKEND_TYPE_KERNEL, - .vhost_call =3D vhost_kernel_call, .vhost_backend_init =3D vhost_kernel_init, .vhost_backend_cleanup =3D vhost_kernel_cleanup, - .vhost_backend_get_vq_index =3D vhost_kernel_get_vq_index, =20 - .vhost_set_log_base =3D vhost_set_log_base, + .vhost_net_set_backend =3D vhost_kernel_net_set_backend, + .vhost_scsi_set_endpoint =3D vhost_kernel_scsi_set_endpoint, + .vhost_scsi_clear_endpoint =3D vhost_kernel_scsi_clear_endpoint, + .vhost_scsi_get_abi_version =3D vhost_kernel_scsi_get_abi_versio= n, + .vhost_set_log_base =3D vhost_kernel_set_log_base, + .vhost_set_mem_table =3D vhost_kernel_set_mem_table, + .vhost_set_vring_addr =3D vhost_kernel_set_vring_addr, + .vhost_set_vring_endian =3D vhost_kernel_set_vring_endian, + .vhost_set_vring_num =3D vhost_kernel_set_vring_num, + .vhost_set_vring_base =3D vhost_kernel_set_vring_base, + .vhost_get_vring_base =3D vhost_kernel_get_vring_base, + .vhost_set_vring_kick =3D vhost_kernel_set_vring_kick, + .vhost_set_vring_call =3D vhost_kernel_set_vring_call, + .vhost_set_features =3D vhost_kernel_set_features, + .vhost_get_features =3D vhost_kernel_get_features, + .vhost_set_owner =3D vhost_kernel_set_owner, + .vhost_reset_device =3D vhost_kernel_reset_device, + .vhost_get_vq_index =3D vhost_kernel_get_vq_index, }; =20 int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType backe= nd_type) diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index f1edd04..cd84f0c 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -99,37 +99,6 @@ static bool ioeventfd_enabled(void) return kvm_enabled() && kvm_eventfds_enabled(); } =20 -static unsigned long int ioctl_to_vhost_user_request[VHOST_USER_MAX] =3D= { - -1, /* VHOST_USER_NONE */ - VHOST_GET_FEATURES, /* VHOST_USER_GET_FEATURES */ - VHOST_SET_FEATURES, /* VHOST_USER_SET_FEATURES */ - VHOST_SET_OWNER, /* VHOST_USER_SET_OWNER */ - VHOST_RESET_DEVICE, /* VHOST_USER_RESET_DEVICE */ - VHOST_SET_MEM_TABLE, /* VHOST_USER_SET_MEM_TABLE */ - VHOST_SET_LOG_BASE, /* VHOST_USER_SET_LOG_BASE */ - VHOST_SET_LOG_FD, /* VHOST_USER_SET_LOG_FD */ - VHOST_SET_VRING_NUM, /* VHOST_USER_SET_VRING_NUM */ - VHOST_SET_VRING_ADDR, /* VHOST_USER_SET_VRING_ADDR */ - VHOST_SET_VRING_BASE, /* VHOST_USER_SET_VRING_BASE */ - VHOST_GET_VRING_BASE, /* VHOST_USER_GET_VRING_BASE */ - VHOST_SET_VRING_KICK, /* VHOST_USER_SET_VRING_KICK */ - VHOST_SET_VRING_CALL, /* VHOST_USER_SET_VRING_CALL */ - VHOST_SET_VRING_ERR /* VHOST_USER_SET_VRING_ERR */ -}; - -static VhostUserRequest vhost_user_request_translate(unsigned long int r= equest) -{ - VhostUserRequest idx; - - for (idx =3D 0; idx < VHOST_USER_MAX; idx++) { - if (ioctl_to_vhost_user_request[idx] =3D=3D request) { - break; - } - } - - return (idx =3D=3D VHOST_USER_MAX) ? VHOST_USER_NONE : idx; -} - static int vhost_user_read(struct vhost_dev *dev, VhostUserMsg *msg) { CharDriverState *chr =3D dev->opaque; @@ -176,12 +145,35 @@ fail: return -1; } =20 +static bool vhost_user_one_time_request(VhostUserRequest request) +{ + switch (request) { + case VHOST_USER_SET_OWNER: + case VHOST_USER_RESET_DEVICE: + case VHOST_USER_SET_MEM_TABLE: + case VHOST_USER_GET_QUEUE_NUM: + return true; + default: + return false; + } +} + +/* most non-init callers ignore the error */ static int vhost_user_write(struct vhost_dev *dev, VhostUserMsg *msg, int *fds, int fd_num) { CharDriverState *chr =3D dev->opaque; int size =3D VHOST_USER_HDR_SIZE + msg->size; =20 + /* + * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE, + * we just need send it once in the first time. For later such + * request, we just ignore it. + */ + if (vhost_user_one_time_request(msg->request) && dev->vq_index !=3D = 0) { + return 0; + } + if (fd_num) { qemu_chr_fe_set_msgfds(chr, fds, fd_num); } @@ -190,231 +182,317 @@ static int vhost_user_write(struct vhost_dev *dev= , VhostUserMsg *msg, 0 : -1; } =20 -static bool vhost_user_one_time_request(VhostUserRequest request) +static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, + struct vhost_log *log) { - switch (request) { - case VHOST_USER_SET_OWNER: - case VHOST_USER_RESET_DEVICE: - case VHOST_USER_SET_MEM_TABLE: - case VHOST_USER_GET_QUEUE_NUM: - return true; - default: - return false; + int fds[VHOST_MEMORY_MAX_NREGIONS]; + size_t fd_num =3D 0; + bool shmfd =3D virtio_has_feature(dev->protocol_features, + VHOST_USER_PROTOCOL_F_LOG_SHMFD); + VhostUserMsg msg =3D { + .request =3D VHOST_USER_SET_LOG_BASE, + .flags =3D VHOST_USER_VERSION, + .u64 =3D base, + .size =3D sizeof(m.u64), + }; + + if (shmfd && log->fd !=3D -1) { + fds[fd_num++] =3D log->fd; } + + vhost_user_write(dev, &msg, fds, fd_num); + + if (shmfd) { + msg.size =3D 0; + if (vhost_user_read(dev, &msg) < 0) { + return 0; + } + + if (msg.request !=3D VHOST_USER_SET_LOG_BASE) { + error_report("Received unexpected msg type. " + "Expected %d received %d", + VHOST_USER_SET_LOG_BASE, msg.request); + return -1; + } + } + + return 0; } =20 -static int vhost_user_call(struct vhost_dev *dev, unsigned long int requ= est, - void *arg) +static int vhost_user_set_mem_table(struct vhost_dev *dev, + struct vhost_memory *mem) { - VhostUserMsg msg; - VhostUserRequest msg_request; - struct vhost_vring_file *file =3D 0; - int need_reply =3D 0; int fds[VHOST_MEMORY_MAX_NREGIONS]; int i, fd; size_t fd_num =3D 0; + VhostUserMsg msg =3D { + .request =3D VHOST_USER_SET_MEM_TABLE, + .flags =3D VHOST_USER_VERSION, + }; =20 - assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_USER); - - /* only translate vhost ioctl requests */ - if (request > VHOST_USER_MAX) { - msg_request =3D vhost_user_request_translate(request); - } else { - msg_request =3D request; + for (i =3D 0; i < dev->mem->nregions; ++i) { + struct vhost_memory_region *reg =3D dev->mem->regions + i; + ram_addr_t ram_addr; + + assert((uintptr_t)reg->userspace_addr =3D=3D reg->userspace_addr= ); + qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_addr, + &ram_addr); + fd =3D qemu_get_ram_fd(ram_addr); + if (fd > 0) { + msg.memory.regions[fd_num].userspace_addr =3D reg->userspace= _addr; + msg.memory.regions[fd_num].memory_size =3D reg->memory_size= ; + msg.memory.regions[fd_num].guest_phys_addr =3D reg->guest_ph= ys_addr; + msg.memory.regions[fd_num].mmap_offset =3D reg->userspace_ad= dr - + (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr); + assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); + fds[fd_num++] =3D fd; + } } =20 - /* - * For non-vring specific requests, like VHOST_USER_SET_MEM_TABLE, - * we just need send it once in the first time. For later such - * request, we just ignore it. - */ - if (vhost_user_one_time_request(msg_request) && dev->vq_index !=3D 0= ) { - return 0; + msg.memory.nregions =3D fd_num; + + if (!fd_num) { + error_report("Failed initializing vhost-user memory map, " + "consider using -object memory-backend-file share=3D= on"); + return -1; } =20 - msg.request =3D msg_request; - msg.flags =3D VHOST_USER_VERSION; - msg.size =3D 0; + msg.size =3D sizeof(m.memory.nregions); + msg.size +=3D sizeof(m.memory.padding); + msg.size +=3D fd_num * sizeof(VhostUserMemoryRegion); =20 - switch (msg_request) { - case VHOST_USER_GET_FEATURES: - case VHOST_USER_GET_PROTOCOL_FEATURES: - case VHOST_USER_GET_QUEUE_NUM: - need_reply =3D 1; - break; + vhost_user_write(dev, &msg, fds, fd_num); =20 - case VHOST_USER_SET_FEATURES: - case VHOST_USER_SET_PROTOCOL_FEATURES: - msg.u64 =3D *((__u64 *) arg); - msg.size =3D sizeof(m.u64); - break; + return 0; +} =20 - case VHOST_USER_SET_OWNER: - case VHOST_USER_RESET_DEVICE: - break; +static int vhost_user_set_vring_addr(struct vhost_dev *dev, + struct vhost_vring_addr *addr) +{ + VhostUserMsg msg =3D { + .request =3D VHOST_USER_SET_VRING_ADDR, + .flags =3D VHOST_USER_VERSION, + .addr =3D *addr, + .size =3D sizeof(*addr), + }; =20 - case VHOST_USER_SET_MEM_TABLE: - for (i =3D 0; i < dev->mem->nregions; ++i) { - struct vhost_memory_region *reg =3D dev->mem->regions + i; - ram_addr_t ram_addr; - - assert((uintptr_t)reg->userspace_addr =3D=3D reg->userspace_= addr); - qemu_ram_addr_from_host((void *)(uintptr_t)reg->userspace_ad= dr, &ram_addr); - fd =3D qemu_get_ram_fd(ram_addr); - if (fd > 0) { - msg.memory.regions[fd_num].userspace_addr =3D reg->users= pace_addr; - msg.memory.regions[fd_num].memory_size =3D reg->memory_= size; - msg.memory.regions[fd_num].guest_phys_addr =3D reg->gues= t_phys_addr; - msg.memory.regions[fd_num].mmap_offset =3D reg->userspac= e_addr - - (uintptr_t) qemu_get_ram_block_host_ptr(ram_addr); - assert(fd_num < VHOST_MEMORY_MAX_NREGIONS); - fds[fd_num++] =3D fd; - } - } + vhost_user_write(dev, &msg, NULL, 0); =20 - msg.memory.nregions =3D fd_num; + return 0; +} =20 - if (!fd_num) { - error_report("Failed initializing vhost-user memory map, " - "consider using -object memory-backend-file share=3D= on"); - return -1; - } +static int vhost_user_set_vring_endian(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + error_report("vhost-user trying to send unhandled ioctl"); + return -1; +} =20 - msg.size =3D sizeof(m.memory.nregions); - msg.size +=3D sizeof(m.memory.padding); - msg.size +=3D fd_num * sizeof(VhostUserMemoryRegion); - - break; - - case VHOST_USER_SET_LOG_FD: - fds[fd_num++] =3D *((int *) arg); - break; - - case VHOST_USER_SET_VRING_NUM: - case VHOST_USER_SET_VRING_BASE: - case VHOST_USER_SET_VRING_ENABLE: - memcpy(&msg.state, arg, sizeof(struct vhost_vring_state)); - msg.size =3D sizeof(m.state); - break; - - case VHOST_USER_GET_VRING_BASE: - memcpy(&msg.state, arg, sizeof(struct vhost_vring_state)); - msg.size =3D sizeof(m.state); - need_reply =3D 1; - break; - - case VHOST_USER_SET_VRING_ADDR: - memcpy(&msg.addr, arg, sizeof(struct vhost_vring_addr)); - msg.size =3D sizeof(m.addr); - break; - - case VHOST_USER_SET_VRING_KICK: - case VHOST_USER_SET_VRING_CALL: - case VHOST_USER_SET_VRING_ERR: - file =3D arg; - msg.u64 =3D file->index & VHOST_USER_VRING_IDX_MASK; - msg.size =3D sizeof(m.u64); - if (ioeventfd_enabled() && file->fd > 0) { - fds[fd_num++] =3D file->fd; - } else { - msg.u64 |=3D VHOST_USER_VRING_NOFD_MASK; - } - break; - default: - error_report("vhost-user trying to send unhandled ioctl"); +static int vhost_set_vring(struct vhost_dev *dev, + unsigned long int request, + struct vhost_vring_state *ring) +{ + VhostUserMsg msg =3D { + .request =3D request, + .flags =3D VHOST_USER_VERSION, + .state =3D *ring, + .size =3D sizeof(*ring), + }; + + vhost_user_write(dev, &msg, NULL, 0); + + return 0; +} + +static int vhost_user_set_vring_num(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_set_vring(dev, VHOST_SET_VRING_NUM, ring); +} + +static int vhost_user_set_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + return vhost_set_vring(dev, VHOST_SET_VRING_BASE, ring); +} + +static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable= ) +{ + struct vhost_vring_state state =3D { + .index =3D dev->vq_index, + .num =3D enable, + }; + + if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ))) = { return -1; - break; } =20 - if (vhost_user_write(dev, &msg, fds, fd_num) < 0) { + return vhost_set_vring(dev, VHOST_USER_SET_VRING_ENABLE, &state); +} + + +static int vhost_user_get_vring_base(struct vhost_dev *dev, + struct vhost_vring_state *ring) +{ + VhostUserMsg msg =3D { + .request =3D VHOST_USER_GET_VRING_BASE, + .flags =3D VHOST_USER_VERSION, + .state =3D *ring, + .size =3D sizeof(*ring), + }; + + vhost_user_write(dev, &msg, NULL, 0); + + if (vhost_user_read(dev, &msg) < 0) { return 0; } =20 - if (need_reply) { - if (vhost_user_read(dev, &msg) < 0) { - return 0; - } - - if (msg_request !=3D msg.request) { - error_report("Received unexpected msg type." - " Expected %d received %d", msg_request, msg.request= ); - return -1; - } + if (msg.request !=3D VHOST_USER_GET_VRING_BASE) { + error_report("Received unexpected msg type. Expected %d received= %d", + VHOST_USER_GET_VRING_BASE, msg.request); + return -1; + } =20 - switch (msg_request) { - case VHOST_USER_GET_FEATURES: - case VHOST_USER_GET_PROTOCOL_FEATURES: - case VHOST_USER_GET_QUEUE_NUM: - if (msg.size !=3D sizeof(m.u64)) { - error_report("Received bad msg size."); - return -1; - } - *((__u64 *) arg) =3D msg.u64; - break; - case VHOST_USER_GET_VRING_BASE: - if (msg.size !=3D sizeof(m.state)) { - error_report("Received bad msg size."); - return -1; - } - memcpy(arg, &msg.state, sizeof(struct vhost_vring_state)); - break; - default: - error_report("Received unexpected msg type."); - return -1; - break; - } + if (msg.size !=3D sizeof(m.state)) { + error_report("Received bad msg size."); + return -1; } =20 + *ring =3D msg.state; + return 0; } =20 -static int vhost_set_log_base(struct vhost_dev *dev, uint64_t base, - struct vhost_log *log) +static int vhost_set_vring_file(struct vhost_dev *dev, + VhostUserRequest request, + struct vhost_vring_file *file) { int fds[VHOST_MEMORY_MAX_NREGIONS]; size_t fd_num =3D 0; - bool shmfd =3D virtio_has_feature(dev->protocol_features, - VHOST_USER_PROTOCOL_F_LOG_SHMFD); VhostUserMsg msg =3D { - .request =3D VHOST_USER_SET_LOG_BASE, + .request =3D request, .flags =3D VHOST_USER_VERSION, - .u64 =3D base, + .u64 =3D file->index & VHOST_USER_VRING_IDX_MASK, .size =3D sizeof(m.u64), }; =20 - if (shmfd && log->fd !=3D -1) { - fds[fd_num++] =3D log->fd; + if (ioeventfd_enabled() && file->fd > 0) { + fds[fd_num++] =3D file->fd; + } else { + msg.u64 |=3D VHOST_USER_VRING_NOFD_MASK; } =20 vhost_user_write(dev, &msg, fds, fd_num); =20 - if (shmfd) { - msg.size =3D 0; - if (vhost_user_read(dev, &msg) < 0) { - return 0; - } + return 0; +} =20 - if (msg.request !=3D VHOST_USER_SET_LOG_BASE) { - error_report("Received unexpected msg type. " - "Expected %d received %d", - VHOST_USER_SET_LOG_BASE, msg.request); - return -1; - } +static int vhost_user_set_vring_kick(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_KICK, file); +} + +static int vhost_user_set_vring_call(struct vhost_dev *dev, + struct vhost_vring_file *file) +{ + return vhost_set_vring_file(dev, VHOST_USER_SET_VRING_CALL, file); +} + +static int vhost_user_set_u64(struct vhost_dev *dev, int request, uint64= _t u64) +{ + VhostUserMsg msg =3D { + .request =3D request, + .flags =3D VHOST_USER_VERSION, + .u64 =3D u64, + .size =3D sizeof(m.u64), + }; + + vhost_user_write(dev, &msg, NULL, 0); + + return 0; +} + +static int vhost_user_set_features(struct vhost_dev *dev, + uint64_t features) +{ + return vhost_user_set_u64(dev, VHOST_USER_SET_FEATURES, features); +} + +static int vhost_user_set_protocol_features(struct vhost_dev *dev, + uint64_t features) +{ + return vhost_user_set_u64(dev, VHOST_USER_SET_PROTOCOL_FEATURES, fea= tures); +} + +static int vhost_user_get_u64(struct vhost_dev *dev, int request, uint64= _t *u64) +{ + VhostUserMsg msg =3D { + .request =3D request, + .flags =3D VHOST_USER_VERSION, + }; + + vhost_user_write(dev, &msg, NULL, 0); + + if (vhost_user_read(dev, &msg) < 0) { + return 0; + } + + if (msg.request !=3D request) { + error_report("Received unexpected msg type. Expected %d received= %d", + request, msg.request); + return -1; + } + + if (msg.size !=3D sizeof(m.u64)) { + error_report("Received bad msg size."); + return -1; } =20 + *u64 =3D msg.u64; + + return 0; +} + +static int vhost_user_get_features(struct vhost_dev *dev, uint64_t *feat= ures) +{ + return vhost_user_get_u64(dev, VHOST_USER_GET_FEATURES, features); +} + +static int vhost_user_set_owner(struct vhost_dev *dev) +{ + VhostUserMsg msg =3D { + .request =3D VHOST_USER_SET_OWNER, + .flags =3D VHOST_USER_VERSION, + }; + + vhost_user_write(dev, &msg, NULL, 0); + + return 0; +} + +static int vhost_user_reset_device(struct vhost_dev *dev) +{ + VhostUserMsg msg =3D { + .request =3D VHOST_USER_RESET_DEVICE, + .flags =3D VHOST_USER_VERSION, + }; + + vhost_user_write(dev, &msg, NULL, 0); + return 0; } =20 static int vhost_user_init(struct vhost_dev *dev, void *opaque) { - unsigned long long features; + uint64_t features; int err; =20 assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_USER); =20 dev->opaque =3D opaque; =20 - err =3D vhost_user_call(dev, VHOST_USER_GET_FEATURES, &features); + err =3D vhost_user_get_features(dev, &features); if (err < 0) { return err; } @@ -422,21 +500,22 @@ static int vhost_user_init(struct vhost_dev *dev, v= oid *opaque) if (virtio_has_feature(features, VHOST_USER_F_PROTOCOL_FEATURES)) { dev->backend_features |=3D 1ULL << VHOST_USER_F_PROTOCOL_FEATURE= S; =20 - err =3D vhost_user_call(dev, VHOST_USER_GET_PROTOCOL_FEATURES, &= features); + err =3D vhost_user_get_u64(dev, VHOST_USER_GET_PROTOCOL_FEATURES= , + &features); if (err < 0) { return err; } =20 dev->protocol_features =3D features & VHOST_USER_PROTOCOL_FEATUR= E_MASK; - err =3D vhost_user_call(dev, VHOST_USER_SET_PROTOCOL_FEATURES, - &dev->protocol_features); + err =3D vhost_user_set_protocol_features(dev, dev->protocol_feat= ures); if (err < 0) { return err; } =20 /* query the max queues we support if backend supports Multiple = Queue */ if (dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ))= { - err =3D vhost_user_call(dev, VHOST_USER_GET_QUEUE_NUM, &dev-= >max_queues); + err =3D vhost_user_get_u64(dev, VHOST_USER_GET_QUEUE_NUM, + &dev->max_queues); if (err < 0) { return err; } @@ -454,22 +533,6 @@ static int vhost_user_init(struct vhost_dev *dev, vo= id *opaque) return 0; } =20 -static int vhost_user_set_vring_enable(struct vhost_dev *dev, int enable= ) -{ - struct vhost_vring_state state =3D { - .index =3D dev->vq_index, - .num =3D enable, - }; - - assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_USER); - - if (!(dev->protocol_features & (1ULL << VHOST_USER_PROTOCOL_F_MQ))) = { - return -1; - } - - return vhost_user_call(dev, VHOST_USER_SET_VRING_ENABLE, &state); -} - static int vhost_user_cleanup(struct vhost_dev *dev) { assert(dev->vhost_ops->backend_type =3D=3D VHOST_BACKEND_TYPE_USER); @@ -496,12 +559,23 @@ static bool vhost_user_requires_shm_log(struct vhos= t_dev *dev) =20 const VhostOps user_ops =3D { .backend_type =3D VHOST_BACKEND_TYPE_USER, - .vhost_call =3D vhost_user_call, .vhost_backend_init =3D vhost_user_init, .vhost_backend_cleanup =3D vhost_user_cleanup, - .vhost_backend_get_vq_index =3D vhost_user_get_vq_index, - .vhost_backend_set_vring_enable =3D vhost_user_set_vring_enable, =20 - .vhost_set_log_base =3D vhost_set_log_base, + .vhost_set_log_base =3D vhost_user_set_log_base, + .vhost_set_mem_table =3D vhost_user_set_mem_table, + .vhost_set_vring_addr =3D vhost_user_set_vring_addr, + .vhost_set_vring_endian =3D vhost_user_set_vring_endian, + .vhost_set_vring_num =3D vhost_user_set_vring_num, + .vhost_set_vring_base =3D vhost_user_set_vring_base, + .vhost_get_vring_base =3D vhost_user_get_vring_base, + .vhost_set_vring_kick =3D vhost_user_set_vring_kick, + .vhost_set_vring_call =3D vhost_user_set_vring_call, + .vhost_set_features =3D vhost_user_set_features, + .vhost_get_features =3D vhost_user_get_features, + .vhost_set_owner =3D vhost_user_set_owner, + .vhost_reset_device =3D vhost_user_reset_device, + .vhost_get_vq_index =3D vhost_user_get_vq_index, + .vhost_set_vring_enable =3D vhost_user_set_vring_enable, .vhost_requires_shm_log =3D vhost_user_requires_shm_log, }; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index 554e49d..1e8ee76 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -538,7 +538,7 @@ static void vhost_commit(MemoryListener *listener) } =20 if (!dev->log_enabled) { - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->= mem); + r =3D dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); assert(r >=3D 0); dev->memory_changed =3D false; return; @@ -551,7 +551,7 @@ static void vhost_commit(MemoryListener *listener) if (dev->log_size < log_size) { vhost_dev_log_resize(dev, log_size + VHOST_LOG_BUFFER); } - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_MEM_TABLE, dev->mem)= ; + r =3D dev->vhost_ops->vhost_set_mem_table(dev, dev->mem); assert(r >=3D 0); /* To log less, can only decrease log size after table update. */ if (dev->log_size > log_size + VHOST_LOG_BUFFER) { @@ -619,7 +619,7 @@ static int vhost_virtqueue_set_addr(struct vhost_dev = *dev, .log_guest_addr =3D vq->used_phys, .flags =3D enable_log ? (1 << VHOST_VRING_F_LOG) : 0, }; - int r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ADDR, &add= r); + int r =3D dev->vhost_ops->vhost_set_vring_addr(dev, &addr); if (r < 0) { return -errno; } @@ -633,7 +633,7 @@ static int vhost_dev_set_features(struct vhost_dev *d= ev, bool enable_log) if (enable_log) { features |=3D 0x1ULL << VHOST_F_LOG_ALL; } - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_FEATURES, &features)= ; + r =3D dev->vhost_ops->vhost_set_features(dev, features); return r < 0 ? -errno : 0; } =20 @@ -738,7 +738,7 @@ static int vhost_virtqueue_set_vring_endian_legacy(st= ruct vhost_dev *dev, .num =3D is_big_endian }; =20 - if (!dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_ENDIAN, &s)) { + if (!dev->vhost_ops->vhost_set_vring_endian(dev, &s)) { return 0; } =20 @@ -757,7 +757,7 @@ static int vhost_virtqueue_start(struct vhost_dev *de= v, { hwaddr s, l, a; int r; - int vhost_vq_index =3D dev->vhost_ops->vhost_backend_get_vq_index(de= v, idx); + int vhost_vq_index =3D dev->vhost_ops->vhost_get_vq_index(dev, idx); struct vhost_vring_file file =3D { .index =3D vhost_vq_index }; @@ -768,13 +768,13 @@ static int vhost_virtqueue_start(struct vhost_dev *= dev, =20 =20 vq->num =3D state.num =3D virtio_queue_get_num(vdev, idx); - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_NUM, &state); + r =3D dev->vhost_ops->vhost_set_vring_num(dev, &state); if (r) { return -errno; } =20 state.num =3D virtio_queue_get_last_avail_idx(vdev, idx); - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_BASE, &state); + r =3D dev->vhost_ops->vhost_set_vring_base(dev, &state); if (r) { return -errno; } @@ -826,7 +826,7 @@ static int vhost_virtqueue_start(struct vhost_dev *de= v, } =20 file.fd =3D event_notifier_get_fd(virtio_queue_get_host_notifier(vvq= )); - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_KICK, &file); + r =3D dev->vhost_ops->vhost_set_vring_kick(dev, &file); if (r) { r =3D -errno; goto fail_kick; @@ -859,13 +859,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *= dev, struct vhost_virtqueue *vq, unsigned idx) { - int vhost_vq_index =3D dev->vhost_ops->vhost_backend_get_vq_index(de= v, idx); + int vhost_vq_index =3D dev->vhost_ops->vhost_get_vq_index(dev, idx); struct vhost_vring_state state =3D { .index =3D vhost_vq_index, }; int r; =20 - r =3D dev->vhost_ops->vhost_call(dev, VHOST_GET_VRING_BASE, &state); + r =3D dev->vhost_ops->vhost_get_vring_base(dev, &state); if (r < 0) { fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r)= ; fflush(stderr); @@ -912,7 +912,7 @@ static void vhost_eventfd_del(MemoryListener *listene= r, static int vhost_virtqueue_init(struct vhost_dev *dev, struct vhost_virtqueue *vq, int n) { - int vhost_vq_index =3D dev->vhost_ops->vhost_backend_get_vq_index(de= v, n); + int vhost_vq_index =3D dev->vhost_ops->vhost_get_vq_index(dev, n); struct vhost_vring_file file =3D { .index =3D vhost_vq_index, }; @@ -922,7 +922,7 @@ static int vhost_virtqueue_init(struct vhost_dev *dev= , } =20 file.fd =3D event_notifier_get_fd(&vq->masked_notifier); - r =3D dev->vhost_ops->vhost_call(dev, VHOST_SET_VRING_CALL, &file); + r =3D dev->vhost_ops->vhost_set_vring_call(dev, &file); if (r) { r =3D -errno; goto fail_call; @@ -956,12 +956,12 @@ int vhost_dev_init(struct vhost_dev *hdev, void *op= aque, return -errno; } =20 - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_OWNER, NULL); + r =3D hdev->vhost_ops->vhost_set_owner(hdev); if (r < 0) { goto fail; } =20 - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_GET_FEATURES, &feature= s); + r =3D hdev->vhost_ops->vhost_get_features(hdev, &features); if (r < 0) { goto fail; } @@ -1120,8 +1120,8 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, V= irtIODevice *vdev, int n, file.fd =3D event_notifier_get_fd(virtio_queue_get_guest_notifie= r(vvq)); } =20 - file.index =3D hdev->vhost_ops->vhost_backend_get_vq_index(hdev, n); - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_VRING_CALL, &file)= ; + file.index =3D hdev->vhost_ops->vhost_get_vq_index(hdev, n); + r =3D hdev->vhost_ops->vhost_set_vring_call(hdev, &file); assert(r >=3D 0); } =20 @@ -1163,7 +1163,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIOD= evice *vdev) if (r < 0) { goto fail_features; } - r =3D hdev->vhost_ops->vhost_call(hdev, VHOST_SET_MEM_TABLE, hdev->m= em); + r =3D hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); if (r < 0) { r =3D -errno; goto fail_mem; --=20 MST