1d52c454aSMarc-André Lureau /* 2d52c454aSMarc-André Lureau * Virtio vhost-user GPU Device 3d52c454aSMarc-André Lureau * 4d52c454aSMarc-André Lureau * Copyright Red Hat, Inc. 2013-2018 5d52c454aSMarc-André Lureau * 6d52c454aSMarc-André Lureau * Authors: 7d52c454aSMarc-André Lureau * Dave Airlie <airlied@redhat.com> 8d52c454aSMarc-André Lureau * Gerd Hoffmann <kraxel@redhat.com> 9d52c454aSMarc-André Lureau * Marc-André Lureau <marcandre.lureau@redhat.com> 10d52c454aSMarc-André Lureau * 11d52c454aSMarc-André Lureau * This work is licensed under the terms of the GNU GPL, version 2 or later. 12d52c454aSMarc-André Lureau * See the COPYING file in the top-level directory. 13d52c454aSMarc-André Lureau */ 14fe2611b0SMarkus Armbruster 15fe2611b0SMarkus Armbruster #ifndef VUGPU_H 16fe2611b0SMarkus Armbruster #define VUGPU_H 17d52c454aSMarc-André Lureau 18d52c454aSMarc-André Lureau 190df750e9SMarc-André Lureau #include "libvhost-user-glib.h" 20d52c454aSMarc-André Lureau #include "standard-headers/linux/virtio_gpu.h" 21d52c454aSMarc-André Lureau 22d52c454aSMarc-André Lureau #include "qemu/queue.h" 23d52c454aSMarc-André Lureau #include "qemu/iov.h" 24d52c454aSMarc-André Lureau #include "qemu/bswap.h" 25d52c454aSMarc-André Lureau #include "vugbm.h" 26d52c454aSMarc-André Lureau 27d52c454aSMarc-André Lureau typedef enum VhostUserGpuRequest { 28d52c454aSMarc-André Lureau VHOST_USER_GPU_NONE = 0, 29d52c454aSMarc-André Lureau VHOST_USER_GPU_GET_PROTOCOL_FEATURES, 30d52c454aSMarc-André Lureau VHOST_USER_GPU_SET_PROTOCOL_FEATURES, 31d52c454aSMarc-André Lureau VHOST_USER_GPU_GET_DISPLAY_INFO, 32d52c454aSMarc-André Lureau VHOST_USER_GPU_CURSOR_POS, 33d52c454aSMarc-André Lureau VHOST_USER_GPU_CURSOR_POS_HIDE, 34d52c454aSMarc-André Lureau VHOST_USER_GPU_CURSOR_UPDATE, 35d52c454aSMarc-André Lureau VHOST_USER_GPU_SCANOUT, 36d52c454aSMarc-André Lureau VHOST_USER_GPU_UPDATE, 37d52c454aSMarc-André Lureau VHOST_USER_GPU_DMABUF_SCANOUT, 38d52c454aSMarc-André Lureau VHOST_USER_GPU_DMABUF_UPDATE, 39c0644426SErico Nunes VHOST_USER_GPU_GET_EDID, 40e3c82fe0SErico Nunes VHOST_USER_GPU_DMABUF_SCANOUT2, 41d52c454aSMarc-André Lureau } VhostUserGpuRequest; 42d52c454aSMarc-André Lureau 43d52c454aSMarc-André Lureau typedef struct VhostUserGpuDisplayInfoReply { 44d52c454aSMarc-André Lureau struct virtio_gpu_resp_display_info info; 45d52c454aSMarc-André Lureau } VhostUserGpuDisplayInfoReply; 46d52c454aSMarc-André Lureau 47d52c454aSMarc-André Lureau typedef struct VhostUserGpuCursorPos { 48d52c454aSMarc-André Lureau uint32_t scanout_id; 49d52c454aSMarc-André Lureau uint32_t x; 50d52c454aSMarc-André Lureau uint32_t y; 51d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuCursorPos; 52d52c454aSMarc-André Lureau 53d52c454aSMarc-André Lureau typedef struct VhostUserGpuCursorUpdate { 54d52c454aSMarc-André Lureau VhostUserGpuCursorPos pos; 55d52c454aSMarc-André Lureau uint32_t hot_x; 56d52c454aSMarc-André Lureau uint32_t hot_y; 57d52c454aSMarc-André Lureau uint32_t data[64 * 64]; 58d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuCursorUpdate; 59d52c454aSMarc-André Lureau 60d52c454aSMarc-André Lureau typedef struct VhostUserGpuScanout { 61d52c454aSMarc-André Lureau uint32_t scanout_id; 62d52c454aSMarc-André Lureau uint32_t width; 63d52c454aSMarc-André Lureau uint32_t height; 64d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuScanout; 65d52c454aSMarc-André Lureau 66d52c454aSMarc-André Lureau typedef struct VhostUserGpuUpdate { 67d52c454aSMarc-André Lureau uint32_t scanout_id; 68d52c454aSMarc-André Lureau uint32_t x; 69d52c454aSMarc-André Lureau uint32_t y; 70d52c454aSMarc-André Lureau uint32_t width; 71d52c454aSMarc-André Lureau uint32_t height; 72d52c454aSMarc-André Lureau uint8_t data[]; 73d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuUpdate; 74d52c454aSMarc-André Lureau 75d52c454aSMarc-André Lureau typedef struct VhostUserGpuDMABUFScanout { 76d52c454aSMarc-André Lureau uint32_t scanout_id; 77d52c454aSMarc-André Lureau uint32_t x; 78d52c454aSMarc-André Lureau uint32_t y; 79d52c454aSMarc-André Lureau uint32_t width; 80d52c454aSMarc-André Lureau uint32_t height; 81d52c454aSMarc-André Lureau uint32_t fd_width; 82d52c454aSMarc-André Lureau uint32_t fd_height; 83d52c454aSMarc-André Lureau uint32_t fd_stride; 84d52c454aSMarc-André Lureau uint32_t fd_flags; 85d52c454aSMarc-André Lureau int fd_drm_fourcc; 86d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuDMABUFScanout; 87d52c454aSMarc-André Lureau 88e3c82fe0SErico Nunes typedef struct VhostUserGpuDMABUFScanout2 { 89e3c82fe0SErico Nunes struct VhostUserGpuDMABUFScanout dmabuf_scanout; 90e3c82fe0SErico Nunes uint64_t modifier; 91e3c82fe0SErico Nunes } QEMU_PACKED VhostUserGpuDMABUFScanout2; 92e3c82fe0SErico Nunes 93c0644426SErico Nunes typedef struct VhostUserGpuEdidRequest { 94c0644426SErico Nunes uint32_t scanout_id; 95c0644426SErico Nunes } QEMU_PACKED VhostUserGpuEdidRequest; 96c0644426SErico Nunes 97d52c454aSMarc-André Lureau typedef struct VhostUserGpuMsg { 98d52c454aSMarc-André Lureau uint32_t request; /* VhostUserGpuRequest */ 99d52c454aSMarc-André Lureau uint32_t flags; 100d52c454aSMarc-André Lureau uint32_t size; /* the following payload size */ 101d52c454aSMarc-André Lureau union { 102d52c454aSMarc-André Lureau VhostUserGpuCursorPos cursor_pos; 103d52c454aSMarc-André Lureau VhostUserGpuCursorUpdate cursor_update; 104d52c454aSMarc-André Lureau VhostUserGpuScanout scanout; 105d52c454aSMarc-André Lureau VhostUserGpuUpdate update; 106d52c454aSMarc-André Lureau VhostUserGpuDMABUFScanout dmabuf_scanout; 107e3c82fe0SErico Nunes VhostUserGpuDMABUFScanout2 dmabuf_scanout2; 108c0644426SErico Nunes VhostUserGpuEdidRequest edid_req; 109c0644426SErico Nunes struct virtio_gpu_resp_edid resp_edid; 110d52c454aSMarc-André Lureau struct virtio_gpu_resp_display_info display_info; 111d52c454aSMarc-André Lureau uint64_t u64; 112d52c454aSMarc-André Lureau } payload; 113d52c454aSMarc-André Lureau } QEMU_PACKED VhostUserGpuMsg; 114d52c454aSMarc-André Lureau 115d52c454aSMarc-André Lureau static VhostUserGpuMsg m __attribute__ ((unused)); 116d52c454aSMarc-André Lureau #define VHOST_USER_GPU_HDR_SIZE \ 117d52c454aSMarc-André Lureau (sizeof(m.request) + sizeof(m.flags) + sizeof(m.size)) 118d52c454aSMarc-André Lureau 119d52c454aSMarc-André Lureau #define VHOST_USER_GPU_MSG_FLAG_REPLY 0x4 120d52c454aSMarc-André Lureau 121c0644426SErico Nunes #define VHOST_USER_GPU_PROTOCOL_F_EDID 0 122e3c82fe0SErico Nunes #define VHOST_USER_GPU_PROTOCOL_F_DMABUF2 1 123c0644426SErico Nunes 124d52c454aSMarc-André Lureau struct virtio_gpu_scanout { 125d52c454aSMarc-André Lureau uint32_t width, height; 126d52c454aSMarc-André Lureau int x, y; 127d52c454aSMarc-André Lureau int invalidate; 128d52c454aSMarc-André Lureau uint32_t resource_id; 129d52c454aSMarc-André Lureau }; 130d52c454aSMarc-André Lureau 131d52c454aSMarc-André Lureau typedef struct VuGpu { 132d52c454aSMarc-André Lureau VugDev dev; 133d52c454aSMarc-André Lureau struct virtio_gpu_config virtio_config; 134d52c454aSMarc-André Lureau struct vugbm_device gdev; 135d52c454aSMarc-André Lureau int sock_fd; 136d52c454aSMarc-André Lureau int drm_rnode_fd; 137d52c454aSMarc-André Lureau GSource *renderer_source; 1381f83ea8dSMarc-André Lureau guint wait_in; 139d52c454aSMarc-André Lureau 140d52c454aSMarc-André Lureau bool virgl; 141d52c454aSMarc-André Lureau bool virgl_inited; 142c0644426SErico Nunes bool edid_inited; 143e3c82fe0SErico Nunes bool use_modifiers; 144d52c454aSMarc-André Lureau uint32_t inflight; 145d52c454aSMarc-André Lureau 146d52c454aSMarc-André Lureau struct virtio_gpu_scanout scanout[VIRTIO_GPU_MAX_SCANOUTS]; 147d52c454aSMarc-André Lureau QTAILQ_HEAD(, virtio_gpu_simple_resource) reslist; 148d52c454aSMarc-André Lureau QTAILQ_HEAD(, virtio_gpu_ctrl_command) fenceq; 149d52c454aSMarc-André Lureau } VuGpu; 150d52c454aSMarc-André Lureau 15172e631c6SMarc-André Lureau enum { 15272e631c6SMarc-André Lureau VG_CMD_STATE_NEW, 15372e631c6SMarc-André Lureau VG_CMD_STATE_PENDING, 15472e631c6SMarc-André Lureau VG_CMD_STATE_FINISHED, 15572e631c6SMarc-André Lureau }; 15672e631c6SMarc-André Lureau 157d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_command { 158d52c454aSMarc-André Lureau VuVirtqElement elem; 159d52c454aSMarc-André Lureau VuVirtq *vq; 160d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_hdr cmd_hdr; 161d52c454aSMarc-André Lureau uint32_t error; 16272e631c6SMarc-André Lureau int state; 163d52c454aSMarc-André Lureau QTAILQ_ENTRY(virtio_gpu_ctrl_command) next; 164d52c454aSMarc-André Lureau }; 165d52c454aSMarc-André Lureau 166d52c454aSMarc-André Lureau #define VUGPU_FILL_CMD(out) do { \ 167*cc46a7efSThomas Huth size_t vugpufillcmd_s_ = \ 168*cc46a7efSThomas Huth iov_to_buf(cmd->elem.out_sg, cmd->elem.out_num, 0, \ 169d52c454aSMarc-André Lureau &out, sizeof(out)); \ 170*cc46a7efSThomas Huth if (vugpufillcmd_s_ != sizeof(out)) { \ 171d52c454aSMarc-André Lureau g_critical("%s: command size incorrect %zu vs %zu", \ 172*cc46a7efSThomas Huth __func__, vugpufillcmd_s_, sizeof(out)); \ 173d52c454aSMarc-André Lureau return; \ 174d52c454aSMarc-André Lureau } \ 175d52c454aSMarc-André Lureau } while (0) 176d52c454aSMarc-André Lureau 177d52c454aSMarc-André Lureau 178d52c454aSMarc-André Lureau void vg_ctrl_response(VuGpu *g, 179d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_command *cmd, 180d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_hdr *resp, 181d52c454aSMarc-André Lureau size_t resp_len); 182d52c454aSMarc-André Lureau 183d52c454aSMarc-André Lureau void vg_ctrl_response_nodata(VuGpu *g, 184d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_command *cmd, 185d52c454aSMarc-André Lureau enum virtio_gpu_ctrl_type type); 186d52c454aSMarc-André Lureau 187d52c454aSMarc-André Lureau int vg_create_mapping_iov(VuGpu *g, 188d52c454aSMarc-André Lureau struct virtio_gpu_resource_attach_backing *ab, 189d52c454aSMarc-André Lureau struct virtio_gpu_ctrl_command *cmd, 190d52c454aSMarc-André Lureau struct iovec **iov); 1913ea32d13SLi Qiang void vg_cleanup_mapping_iov(VuGpu *g, struct iovec *iov, uint32_t count); 192d52c454aSMarc-André Lureau void vg_get_display_info(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); 193c0644426SErico Nunes void vg_get_edid(VuGpu *vg, struct virtio_gpu_ctrl_command *cmd); 194d52c454aSMarc-André Lureau 195d52c454aSMarc-André Lureau void vg_wait_ok(VuGpu *g); 196d52c454aSMarc-André Lureau 197d52c454aSMarc-André Lureau void vg_send_msg(VuGpu *g, const VhostUserGpuMsg *msg, int fd); 198d52c454aSMarc-André Lureau 199d52c454aSMarc-André Lureau bool vg_recv_msg(VuGpu *g, uint32_t expect_req, uint32_t expect_size, 200d52c454aSMarc-André Lureau gpointer payload); 201d52c454aSMarc-André Lureau 202d52c454aSMarc-André Lureau 203d52c454aSMarc-André Lureau #endif 204