qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

vhost-user: add vhost_user_gpu_set_socket()

Add a new vhost-user message to give a unix socket to a vhost-user
backend for GPU display updates.

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, thus I chose to have a new dedicated
channel.

See vhost-user-gpu.rst for the protocol details.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-id: 20190524130946.31736-2-marcandre.lureau@redhat.com
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>

authored by

Marc-André Lureau and committed by
Gerd Hoffmann
bd2e44fe da35f7f1

+273
+6
MAINTAINERS
··· 1676 1676 F: hw/display/virtio-vga.c 1677 1677 F: include/hw/virtio/virtio-gpu.h 1678 1678 1679 + vhost-user-gpu 1680 + M: Marc-André Lureau <marcandre.lureau@redhat.com> 1681 + M: Gerd Hoffmann <kraxel@redhat.com> 1682 + S: Maintained 1683 + F: docs/interop/vhost-user-gpu.rst 1684 + 1679 1685 Cirrus VGA 1680 1686 M: Gerd Hoffmann <kraxel@redhat.com> 1681 1687 S: Odd Fixes
+1
contrib/libvhost-user/libvhost-user.c
··· 130 130 REQ(VHOST_USER_POSTCOPY_END), 131 131 REQ(VHOST_USER_GET_INFLIGHT_FD), 132 132 REQ(VHOST_USER_SET_INFLIGHT_FD), 133 + REQ(VHOST_USER_GPU_SET_SOCKET), 133 134 REQ(VHOST_USER_MAX), 134 135 }; 135 136 #undef REQ
+1
contrib/libvhost-user/libvhost-user.h
··· 94 94 VHOST_USER_POSTCOPY_END = 30, 95 95 VHOST_USER_GET_INFLIGHT_FD = 31, 96 96 VHOST_USER_SET_INFLIGHT_FD = 32, 97 + VHOST_USER_GPU_SET_SOCKET = 33, 97 98 VHOST_USER_MAX 98 99 } VhostUserRequest; 99 100
+1
docs/interop/index.rst
··· 16 16 live-block-operations 17 17 pr-helper 18 18 vhost-user 19 + vhost-user-gpu
+242
docs/interop/vhost-user-gpu.rst
··· 1 + ======================= 2 + Vhost-user-gpu Protocol 3 + ======================= 4 + 5 + :Licence: This work is licensed under the terms of the GNU GPL, 6 + version 2 or later. See the COPYING file in the top-level 7 + directory. 8 + 9 + .. contents:: Table of Contents 10 + 11 + Introduction 12 + ============ 13 + 14 + The vhost-user-gpu protocol is aiming at sharing the rendering result 15 + of a virtio-gpu, done from a vhost-user slave process to a vhost-user 16 + master process (such as QEMU). It bears a resemblance to a display 17 + server protocol, if you consider QEMU as the display server and the 18 + slave as the client, but in a very limited way. Typically, it will 19 + work by setting a scanout/display configuration, before sending flush 20 + events for the display updates. It will also update the cursor shape 21 + and position. 22 + 23 + The protocol is sent over a UNIX domain stream socket, since it uses 24 + socket ancillary data to share opened file descriptors (DMABUF fds or 25 + shared memory). The socket is usually obtained via 26 + ``VHOST_USER_GPU_SET_SOCKET``. 27 + 28 + Requests are sent by the *slave*, and the optional replies by the 29 + *master*. 30 + 31 + Wire format 32 + =========== 33 + 34 + Unless specified differently, numbers are in the machine native byte 35 + order. 36 + 37 + A vhost-user-gpu message (request and reply) consists of 3 header 38 + fields and a payload. 39 + 40 + +---------+-------+------+---------+ 41 + | request | flags | size | payload | 42 + +---------+-------+------+---------+ 43 + 44 + Header 45 + ------ 46 + 47 + :request: ``u32``, type of the request 48 + 49 + :flags: ``u32``, 32-bit bit field: 50 + 51 + - Bit 2 is the reply flag - needs to be set on each reply 52 + 53 + :size: ``u32``, size of the payload 54 + 55 + Payload types 56 + ------------- 57 + 58 + Depending on the request type, **payload** can be: 59 + 60 + VhostUserGpuCursorPos 61 + ^^^^^^^^^^^^^^^^^^^^^ 62 + 63 + +------------+---+---+ 64 + | scanout-id | x | y | 65 + +------------+---+---+ 66 + 67 + :scanout-id: ``u32``, the scanout where the cursor is located 68 + 69 + :x/y: ``u32``, the cursor postion 70 + 71 + VhostUserGpuCursorUpdate 72 + ^^^^^^^^^^^^^^^^^^^^^^^^ 73 + 74 + +-----+-------+-------+--------+ 75 + | pos | hot_x | hot_y | cursor | 76 + +-----+-------+-------+--------+ 77 + 78 + :pos: a ``VhostUserGpuCursorPos``, the cursor location 79 + 80 + :hot_x/hot_y: ``u32``, the cursor hot location 81 + 82 + :cursor: ``[u32; 64 * 64]``, 64x64 RGBA cursor data (PIXMAN_a8r8g8b8 format) 83 + 84 + VhostUserGpuScanout 85 + ^^^^^^^^^^^^^^^^^^^ 86 + 87 + +------------+---+---+ 88 + | scanout-id | w | h | 89 + +------------+---+---+ 90 + 91 + :scanout-id: ``u32``, the scanout configuration to set 92 + 93 + :w/h: ``u32``, the scanout width/height size 94 + 95 + VhostUserGpuUpdate 96 + ^^^^^^^^^^^^^^^^^^ 97 + 98 + +------------+---+---+---+---+------+ 99 + | scanout-id | x | y | w | h | data | 100 + +------------+---+---+---+---+------+ 101 + 102 + :scanout-id: ``u32``, the scanout content to update 103 + 104 + :x/y/w/h: ``u32``, region of the update 105 + 106 + :data: RGB data (PIXMAN_x8r8g8b8 format) 107 + 108 + VhostUserGpuDMABUFScanout 109 + ^^^^^^^^^^^^^^^^^^^^^^^^^ 110 + 111 + +------------+---+---+---+---+-----+-----+--------+-------+--------+ 112 + | scanout-id | x | y | w | h | fdw | fwh | stride | flags | fourcc | 113 + +------------+---+---+---+---+-----+-----+--------+-------+--------+ 114 + 115 + :scanout-id: ``u32``, the scanout configuration to set 116 + 117 + :x/y: ``u32``, the location of the scanout within the DMABUF 118 + 119 + :w/h: ``u32``, the scanout width/height size 120 + 121 + :fdw/fdh/stride/flags: ``u32``, the DMABUF width/height/stride/flags 122 + 123 + :fourcc: ``i32``, the DMABUF fourcc 124 + 125 + 126 + C structure 127 + ----------- 128 + 129 + In QEMU the vhost-user-gpu message is implemented with the following struct: 130 + 131 + .. code:: c 132 + 133 + typedef struct VhostUserGpuMsg { 134 + uint32_t request; /* VhostUserGpuRequest */ 135 + uint32_t flags; 136 + uint32_t size; /* the following payload size */ 137 + union { 138 + VhostUserGpuCursorPos cursor_pos; 139 + VhostUserGpuCursorUpdate cursor_update; 140 + VhostUserGpuScanout scanout; 141 + VhostUserGpuUpdate update; 142 + VhostUserGpuDMABUFScanout dmabuf_scanout; 143 + struct virtio_gpu_resp_display_info display_info; 144 + uint64_t u64; 145 + } payload; 146 + } QEMU_PACKED VhostUserGpuMsg; 147 + 148 + Protocol features 149 + ----------------- 150 + 151 + None yet. 152 + 153 + As the protocol may need to evolve, new messages and communication 154 + changes are negotiated thanks to preliminary 155 + ``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` and 156 + ``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` requests. 157 + 158 + Communication 159 + ============= 160 + 161 + Message types 162 + ------------- 163 + 164 + ``VHOST_USER_GPU_GET_PROTOCOL_FEATURES`` 165 + :id: 1 166 + :request payload: N/A 167 + :reply payload: ``u64`` 168 + 169 + Get the supported protocol features bitmask. 170 + 171 + ``VHOST_USER_GPU_SET_PROTOCOL_FEATURES`` 172 + :id: 2 173 + :request payload: ``u64`` 174 + :reply payload: N/A 175 + 176 + Enable protocol features using a bitmask. 177 + 178 + ``VHOST_USER_GPU_GET_DISPLAY_INFO`` 179 + :id: 3 180 + :request payload: N/A 181 + :reply payload: ``struct virtio_gpu_resp_display_info`` (from virtio specification) 182 + 183 + Get the preferred display configuration. 184 + 185 + ``VHOST_USER_GPU_CURSOR_POS`` 186 + :id: 4 187 + :request payload: ``VhostUserGpuCursorPos`` 188 + :reply payload: N/A 189 + 190 + Set/show the cursor position. 191 + 192 + ``VHOST_USER_GPU_CURSOR_POS_HIDE`` 193 + :id: 5 194 + :request payload: ``VhostUserGpuCursorPos`` 195 + :reply payload: N/A 196 + 197 + Set/hide the cursor. 198 + 199 + ``VHOST_USER_GPU_CURSOR_UPDATE`` 200 + :id: 6 201 + :request payload: ``VhostUserGpuCursorUpdate`` 202 + :reply payload: N/A 203 + 204 + Update the cursor shape and location. 205 + 206 + ``VHOST_USER_GPU_SCANOUT`` 207 + :id: 7 208 + :request payload: ``VhostUserGpuScanout`` 209 + :reply payload: N/A 210 + 211 + Set the scanout resolution. To disable a scanout, the dimensions 212 + width/height are set to 0. 213 + 214 + ``VHOST_USER_GPU_UPDATE`` 215 + :id: 8 216 + :request payload: ``VhostUserGpuUpdate`` 217 + :reply payload: N/A 218 + 219 + Update the scanout content. The data payload contains the graphical bits. 220 + The display should be flushed and presented. 221 + 222 + ``VHOST_USER_GPU_DMABUF_SCANOUT`` 223 + :id: 9 224 + :request payload: ``VhostUserGpuDMABUFScanout`` 225 + :reply payload: N/A 226 + 227 + Set the scanout resolution/configuration, and share a DMABUF file 228 + descriptor for the scanout content, which is passed as ancillary 229 + data. To disable a scanout, the dimensions width/height are set 230 + to 0, there is no file descriptor passed. 231 + 232 + ``VHOST_USER_GPU_DMABUF_UPDATE`` 233 + :id: 10 234 + :request payload: ``VhostUserGpuUpdate`` 235 + :reply payload: empty payload 236 + 237 + The display should be flushed and presented according to updated 238 + region from ``VhostUserGpuUpdate``. 239 + 240 + Note: there is no data payload, since the scanout is shared thanks 241 + to DMABUF, that must have been set previously with 242 + ``VHOST_USER_GPU_DMABUF_SCANOUT``.
+9
docs/interop/vhost-user.rst
··· 1163 1163 send the shared inflight buffer back to slave so that slave could 1164 1164 get inflight I/O after a crash or restart. 1165 1165 1166 + ``VHOST_USER_GPU_SET_SOCKET`` 1167 + :id: 33 1168 + :equivalent ioctl: N/A 1169 + :master payload: N/A 1170 + 1171 + Sets the GPU protocol socket file descriptor, which is passed as 1172 + ancillary data. The GPU protocol is used to inform the master of 1173 + rendering state and updates. See vhost-user-gpu.rst for details. 1174 + 1166 1175 Slave message types 1167 1176 ------------------- 1168 1177
+11
hw/virtio/vhost-user.c
··· 96 96 VHOST_USER_POSTCOPY_END = 30, 97 97 VHOST_USER_GET_INFLIGHT_FD = 31, 98 98 VHOST_USER_SET_INFLIGHT_FD = 32, 99 + VHOST_USER_GPU_SET_SOCKET = 33, 99 100 VHOST_USER_MAX 100 101 } VhostUserRequest; 101 102 ··· 351 352 } 352 353 353 354 return 0; 355 + } 356 + 357 + int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd) 358 + { 359 + VhostUserMsg msg = { 360 + .hdr.request = VHOST_USER_GPU_SET_SOCKET, 361 + .hdr.flags = VHOST_USER_VERSION, 362 + }; 363 + 364 + return vhost_user_write(dev, &msg, &fd, 1); 354 365 } 355 366 356 367 static int vhost_user_set_log_base(struct vhost_dev *dev, uint64_t base,
+2
include/hw/virtio/vhost-backend.h
··· 170 170 int vhost_backend_handle_iotlb_msg(struct vhost_dev *dev, 171 171 struct vhost_iotlb_msg *imsg); 172 172 173 + int vhost_user_gpu_set_socket(struct vhost_dev *dev, int fd); 174 + 173 175 #endif /* VHOST_BACKEND_H */