Add a new vhost-user message to give a unix socket for gpu updates to a vhost-user backend.
Back when I started that work, I added a new GPU channel because the vhost-user protocol wasn't bidirectional. Since then, there is a vhost-user-slave channel for the slave to send requests to the master. We could extend it with GPU messages. However, the GPU protocol is quite orthogonal to vhost-user and may not need the same kind of stability guarantees, thus I chose to have a new dedicated channel. Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- contrib/libvhost-user/libvhost-user.h | 1 + include/hw/virtio/vhost-backend.h | 1 + hw/virtio/vhost-user.c | 11 ++ MAINTAINERS | 6 + docs/interop/vhost-user-gpu.txt | 236 ++++++++++++++++++++++++++ docs/interop/vhost-user.txt | 8 + 6 files changed, 263 insertions(+) create mode 100644 docs/interop/vhost-user-gpu.txt diff --git a/contrib/libvhost-user/libvhost-user.h b/contrib/libvhost-user/libvhost-user.h index 40d7cbfc2a..9899bfda9e 100644 --- a/contrib/libvhost-user/libvhost-user.h +++ b/contrib/libvhost-user/libvhost-user.h @@ -92,6 +92,7 @@ typedef enum VhostUserRequest { VHOST_USER_POSTCOPY_LISTEN = 29, VHOST_USER_POSTCOPY_END = 30, VHOST_USER_INPUT_GET_CONFIG, + VHOST_USER_GPU_SET_SOCKET, VHOST_USER_MAX } VhostUserRequest; diff --git a/include/hw/virtio/vhost-backend.h b/include/hw/virtio/vhost-backend.h index 1fca321d8a..daf9180c33 100644 --- a/include/hw/virtio/vhost-backend.h +++ b/include/hw/virtio/vhost-backend.h @@ -163,5 +163,6 @@ int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, int vhost_user_input_get_config(struct vhost_dev *dev, struct virtio_input_config **config); +int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd); #endif /* VHOST_BACKEND_H */ diff --git a/hw/virtio/vhost-user.c b/hw/virtio/vhost-user.c index cbd2900f39..37864bc06a 100644 --- a/hw/virtio/vhost-user.c +++ b/hw/virtio/vhost-user.c @@ -90,6 +90,7 @@ typedef enum VhostUserRequest { VHOST_USER_POSTCOPY_LISTEN = 29, VHOST_USER_POSTCOPY_END = 30, VHOST_USER_INPUT_GET_CONFIG, + VHOST_USER_GPU_SET_SOCKET, VHOST_USER_MAX } VhostUserRequest; @@ -397,6 +398,16 @@ err: return -1; } +int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd) +{ + VhostUserMsg msg = { + .hdr.request = VHOST_USER_GPU_SET_SOCKET, + .hdr.flags = VHOST_USER_VERSION, + }; + + return vhost_user_write(dev, &msg, &fd, 1); +} + static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base, struct vhost_log *log) { diff --git a/MAINTAINERS b/MAINTAINERS index 773624f095..e5dee15967 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1339,6 +1339,12 @@ F: hw/display/virtio-gpu* F: hw/display/virtio-vga.c F: include/hw/virtio/virtio-gpu.h +vhost-user-gpu +M: Marc-André Lureau <marcandre.lur...@redhat.com> +M: Gerd Hoffmann <kra...@redhat.com> +S: Maintained +F: docs/interop/vhost-user-gpu.txt + Cirrus VGA M: Gerd Hoffmann <kra...@redhat.com> S: Odd Fixes diff --git a/docs/interop/vhost-user-gpu.txt b/docs/interop/vhost-user-gpu.txt new file mode 100644 index 0000000000..309d07fd6d --- /dev/null +++ b/docs/interop/vhost-user-gpu.txt @@ -0,0 +1,236 @@ +======================= +Vhost-user-gpu Protocol +======================= + +This work is licensed under the terms of the GNU GPL, version 2 or later. +See the COPYING file in the top-level directory. + +Overview +======== + +The vhost-user-gpu protocol is aiming at sharing the rendering result +of a virtio-gpu, done from a vhost-user slave process to a vhost-user +master process (such as QEMU). It bears a resemblance to a display +server protocol, if you consider QEMU as the display server and the +slave as the client, but in a very limited way. Typically, it will +work by setting a scanout/display configuration, before sending flush +events for the display updates. It will also update the cursor shape +and position. + +The protocol is sent over a UNIX domain stream socket, since it uses +socket ancillary data to share opened file descriptors (DMABUF fds or +shared memory). + +Requests are sent by the slave, and the optional replies by the master. + +Wire format +=========== + +Unless specified differently, numbers are in the machine native byte +order. + +A vhost-user-gpu request consists of 2 header fields and a payload: + +:: + + ------------------------------------ + | u32:request | u32:size | payload | + ------------------------------------ + +- request: 32-bit type of the request +- size: 32-bit size of the payload + +A reply consists only of a payload, whose content depends on on the request. + + +Payload types +------------- + +VhostUserGpuCursorPos +^^^^^^^^^^^^^^^^^^^^^ + +:: + + ---------------------------------- + | u32:scanout-id | u32:x | u32:y | + ---------------------------------- + +- scanout-id: the scanout where the cursor is located +- x/y: the cursor postion + +VhostUserGpuCursorUpdate +^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + ----------------------------------------------------------------------------- + | VhostUserGpuCursorPos:pos | u32:hot_x | u32:hot_y | [u32; 64 * 64] cursor | + ----------------------------------------------------------------------------- + +- pos: the cursor location +- hot_x/hot_y: the cursor hot location +- cursor: RGBA cursor data + +VhostUserGpuScanout +^^^^^^^^^^^^^^^^^^^ + +:: + + ---------------------------------- + | u32:scanout-id | u32:w | u32:h | + ---------------------------------- + +- scanout-id: the scanout configuration to set +- w/h: the scanout width/height size + + +VhostUserGpuUpdate +^^^^^^^^^^^^^^^^^^ + +:: + + --------------------------------------------------------- + | u32:scanout-id | u32:x | u32:y | u32:w | u32:h | data | + --------------------------------------------------------- + +- scanout-id: the scanout content to update +- x/y/w/h: region of the update +- data: RGBA data (size is computed based on the region size, and request type) + +VhostUserGpuDMABUFScanout +^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + --------------------------------------------------- + | u32:scanout-id | u32:x | u32:y | u32:w | u32:h | ... + ---------------------------------------------------------- + u32:fdw | u32:fwh | u32:stride | u32:flags | i32:fourcc | + ---------------------------------------------------------- + +- scanout-id: the scanout configuration to set +- x/y: the location of the scanout within the DMABUF +- w/h: the scanout width/height size +- fdw/fdh/stride/flags/fourcc: the DMABUF width/height/stride/flags/drm-fourcc + + +In QEMU the vhost-user-gpu message is implemented with the following struct: + +:: + + typedef struct VhostUserGpuMsg { + uint32_t request; /* VhostUserGpuRequest */ + uint32_t size; /* the following payload size */ + union { + VhostUserGpuCursorPos cursor_pos; + VhostUserGpuCursorUpdate cursor_update; + VhostUserGpuScanout scanout; + VhostUserGpuUpdate update; + VhostUserGpuDMABUFScanout dmabuf_scanout; + uint64_t u64; + } payload; + } QEMU_PACKED VhostUserGpuMsg; + +Protocol features +================= + +None yet. + +As the protocol may need to evolve, new messages and communication +changes are negotiated thanks to preliminary +VHOST_USER_GPU_GET_PROTOCOL_FEATURES and +VHOST_USER_GPU_SET_PROTOCOL_FEATURES requests. + +Message types +============= + +- VHOST_USER_GPU_GET_PROTOCOL_FEATURES + + Id:1 + Request payload: N/A + Reply payload: uint64_t + + Get the supported protocol features bitmask. + +- VHOST_USER_GPU_SET_PROTOCOL_FEATURES + + Id:2 + Request payload: uint64_t + Reply payload: N/A + + Enable protocol features using a bitmask. + +- VHOST_USER_GPU_GET_DISPLAY_INFO + + Id:3 + Request payload: N/A + Reply payload: struct virtio_gpu_resp_display_info (numbers in LE, + according to the virtio protocol) + + Get the preferred display configuration. + +- VHOST_USER_GPU_CURSOR_POS + + Id: 4 + Request payload: struct VhostUserGpuCursorPos + Reply payload: N/A + + Set/show the cursor position. + +- VHOST_USER_GPU_CURSOR_POS_HIDE + + Id:5 + Request payload: struct VhostUserGpuCursorPos + Reply payload: N/A + + Set/hide the cursor. + +- VHOST_USER_GPU_CURSOR_UPDATE + + Id:6 + Request payload: struct VhostUserGpuCursorUpdate + Reply payload: N/A + + Update the cursor shape and location. + +- VHOST_USER_GPU_SCANOUT + + Id:7 + Request payload: struct VhostUserGpuScanout + Reply payload: N/A + + Set the scanout resolution. To disable a scanout, the dimensions + width/height are set to 0. + +- VHOST_USER_GPU_UPDATE + + Id:8 + Request payload: struct VhostUserGpuUpdate + Reply payload: N/A + + Update the scanout content. The data payload contains the graphical bits. + The display should be flushed and presented. + +- VHOST_USER_GPU_DMABUF_SCANOUT + + Id:9 + Request payload: struct VhostUserGpuDMABUFScanout + Reply payload: N/A + + Set the scanout resolution/configuration, and share a DMABUF file + descriptor for the scanout content, which is passed as ancillary + data. To disable a scanout, the dimensions width/height are set + to 0, there is no file descriptor passed. + +- VHOST_USER_GPU_DMABUF_UPDATE + + Id:10 + Request payload: struct VhostUserGpuUpdate + Reply payload: u32 + + The display should be flushed and presented according to updated + region from VhostUserGpuUpdate. + + Note: there is no data payload, since the scanout is shared thanks + to DMABUF, that must have been set previously with + VHOST_USER_GPU_DMABUF_SCANOUT. diff --git a/docs/interop/vhost-user.txt b/docs/interop/vhost-user.txt index 2efa44d124..40ba89675c 100644 --- a/docs/interop/vhost-user.txt +++ b/docs/interop/vhost-user.txt @@ -768,6 +768,14 @@ Master message types Ask vhost user input backend the list of virtio_input_config. + * VHOST_USER_GPU_SET_SOCKET + Id: TBD + Master payload: N/A + + Sets the GPU protocol socket file descriptor, which is passed as + ancillary data. The GPU protocol is used to inform the master of + rendering state and updates. See vhost-user-gpu.txt for details. + Slave message types ------------------- -- 2.18.0.rc1