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