]>
Commit | Line | Data |
---|---|---|
62fb7a5e GH |
1 | /* |
2 | * Copyright (C) 2015 Red Hat, Inc. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * Authors: | |
6 | * Dave Airlie | |
7 | * Alon Levy | |
8 | * | |
9 | * Permission is hereby granted, free of charge, to any person obtaining a | |
10 | * copy of this software and associated documentation files (the "Software"), | |
11 | * to deal in the Software without restriction, including without limitation | |
12 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | |
13 | * and/or sell copies of the Software, and to permit persons to whom the | |
14 | * Software is furnished to do so, subject to the following conditions: | |
15 | * | |
16 | * The above copyright notice and this permission notice shall be included in | |
17 | * all copies or substantial portions of the Software. | |
18 | * | |
19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
22 | * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR | |
23 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, | |
24 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
25 | * OTHER DEALINGS IN THE SOFTWARE. | |
26 | */ | |
27 | ||
a3d63977 | 28 | #include <linux/file.h> |
2cd7b6f0 | 29 | #include <linux/sync_file.h> |
6bbc2b63 | 30 | #include <linux/uaccess.h> |
ff67a25d | 31 | |
a3d63977 | 32 | #include <drm/drm_file.h> |
a3d63977 SR |
33 | #include <drm/virtgpu_drm.h> |
34 | ||
ff67a25d | 35 | #include "virtgpu_drv.h" |
62fb7a5e | 36 | |
c3e2850a | 37 | void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file) |
40cadedd GS |
38 | { |
39 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
40 | struct virtio_gpu_fpriv *vfpriv = file->driver_priv; | |
41 | char dbgname[TASK_COMM_LEN]; | |
42 | ||
d2a983b2 GS |
43 | mutex_lock(&vfpriv->context_lock); |
44 | if (vfpriv->context_created) | |
45 | goto out_unlock; | |
46 | ||
40cadedd GS |
47 | get_task_comm(dbgname, current); |
48 | virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, | |
49 | strlen(dbgname), dbgname); | |
50 | virtio_gpu_notify(vgdev); | |
d2a983b2 GS |
51 | vfpriv->context_created = true; |
52 | ||
53 | out_unlock: | |
54 | mutex_unlock(&vfpriv->context_lock); | |
40cadedd GS |
55 | } |
56 | ||
62fb7a5e | 57 | static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data, |
30349f8f | 58 | struct drm_file *file) |
62fb7a5e GH |
59 | { |
60 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
61 | struct drm_virtgpu_map *virtio_gpu_map = data; | |
62 | ||
30349f8f | 63 | return virtio_gpu_mode_dumb_mmap(file, vgdev->ddev, |
62fb7a5e GH |
64 | virtio_gpu_map->handle, |
65 | &virtio_gpu_map->offset); | |
66 | } | |
67 | ||
5c32c3dd GP |
68 | /* |
69 | * Usage of execbuffer: | |
70 | * Relocations need to take into account the full VIRTIO_GPUDrawable size. | |
71 | * However, the command as passed from user space must *not* contain the initial | |
72 | * VIRTIO_GPUReleaseInfo struct (first XXX bytes) | |
73 | */ | |
74 | static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data, | |
30349f8f | 75 | struct drm_file *file) |
62fb7a5e | 76 | { |
5c32c3dd | 77 | struct drm_virtgpu_execbuffer *exbuf = data; |
62fb7a5e | 78 | struct virtio_gpu_device *vgdev = dev->dev_private; |
30349f8f | 79 | struct virtio_gpu_fpriv *vfpriv = file->driver_priv; |
2cd7b6f0 | 80 | struct virtio_gpu_fence *out_fence; |
62fb7a5e GH |
81 | int ret; |
82 | uint32_t *bo_handles = NULL; | |
83 | void __user *user_bo_handles = NULL; | |
da758d51 | 84 | struct virtio_gpu_object_array *buflist = NULL; |
2cd7b6f0 RF |
85 | struct sync_file *sync_file; |
86 | int in_fence_fd = exbuf->fence_fd; | |
87 | int out_fence_fd = -1; | |
62fb7a5e GH |
88 | void *buf; |
89 | ||
90 | if (vgdev->has_virgl_3d == false) | |
91 | return -ENOSYS; | |
92 | ||
a56f9c86 RF |
93 | if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS)) |
94 | return -EINVAL; | |
95 | ||
96 | exbuf->fence_fd = -1; | |
97 | ||
72b48ae8 | 98 | virtio_gpu_create_context(dev, file); |
2cd7b6f0 RF |
99 | if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) { |
100 | struct dma_fence *in_fence; | |
101 | ||
102 | in_fence = sync_file_get_fence(in_fence_fd); | |
103 | ||
104 | if (!in_fence) | |
105 | return -EINVAL; | |
106 | ||
107 | /* | |
108 | * Wait if the fence is from a foreign context, or if the fence | |
109 | * array contains any fence from a foreign context. | |
110 | */ | |
111 | ret = 0; | |
112 | if (!dma_fence_match_context(in_fence, vgdev->fence_drv.context)) | |
113 | ret = dma_fence_wait(in_fence, true); | |
114 | ||
115 | dma_fence_put(in_fence); | |
116 | if (ret) | |
117 | return ret; | |
118 | } | |
119 | ||
120 | if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) { | |
121 | out_fence_fd = get_unused_fd_flags(O_CLOEXEC); | |
122 | if (out_fence_fd < 0) | |
123 | return out_fence_fd; | |
124 | } | |
125 | ||
62fb7a5e | 126 | if (exbuf->num_bo_handles) { |
2098105e | 127 | bo_handles = kvmalloc_array(exbuf->num_bo_handles, |
da758d51 GH |
128 | sizeof(uint32_t), GFP_KERNEL); |
129 | if (!bo_handles) { | |
2cd7b6f0 RF |
130 | ret = -ENOMEM; |
131 | goto out_unused_fd; | |
62fb7a5e GH |
132 | } |
133 | ||
4b013bb2 | 134 | user_bo_handles = u64_to_user_ptr(exbuf->bo_handles); |
62fb7a5e GH |
135 | if (copy_from_user(bo_handles, user_bo_handles, |
136 | exbuf->num_bo_handles * sizeof(uint32_t))) { | |
137 | ret = -EFAULT; | |
2cd7b6f0 | 138 | goto out_unused_fd; |
62fb7a5e GH |
139 | } |
140 | ||
30349f8f | 141 | buflist = virtio_gpu_array_from_handles(file, bo_handles, |
da758d51 GH |
142 | exbuf->num_bo_handles); |
143 | if (!buflist) { | |
144 | ret = -ENOENT; | |
145 | goto out_unused_fd; | |
62fb7a5e | 146 | } |
2098105e | 147 | kvfree(bo_handles); |
2cd7b6f0 | 148 | bo_handles = NULL; |
62fb7a5e GH |
149 | } |
150 | ||
e1218b8c | 151 | buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size); |
7ad61e6b ME |
152 | if (IS_ERR(buf)) { |
153 | ret = PTR_ERR(buf); | |
d822ccae GH |
154 | goto out_unused_fd; |
155 | } | |
156 | ||
157 | if (buflist) { | |
158 | ret = virtio_gpu_array_lock_resv(buflist); | |
159 | if (ret) | |
160 | goto out_memdup; | |
62fb7a5e | 161 | } |
9fdd90c0 | 162 | |
2cd7b6f0 RF |
163 | out_fence = virtio_gpu_fence_alloc(vgdev); |
164 | if(!out_fence) { | |
9fdd90c0 | 165 | ret = -ENOMEM; |
d822ccae | 166 | goto out_unresv; |
9fdd90c0 | 167 | } |
2cd7b6f0 RF |
168 | |
169 | if (out_fence_fd >= 0) { | |
170 | sync_file = sync_file_create(&out_fence->f); | |
171 | if (!sync_file) { | |
172 | dma_fence_put(&out_fence->f); | |
173 | ret = -ENOMEM; | |
174 | goto out_memdup; | |
175 | } | |
176 | ||
177 | exbuf->fence_fd = out_fence_fd; | |
178 | fd_install(out_fence_fd, sync_file->file); | |
179 | } | |
180 | ||
62fb7a5e | 181 | virtio_gpu_cmd_submit(vgdev, buf, exbuf->size, |
da758d51 | 182 | vfpriv->ctx_id, buflist, out_fence); |
97452907 | 183 | virtio_gpu_notify(vgdev); |
62fb7a5e GH |
184 | return 0; |
185 | ||
186 | out_unresv: | |
da758d51 GH |
187 | if (buflist) |
188 | virtio_gpu_array_unlock_resv(buflist); | |
d822ccae GH |
189 | out_memdup: |
190 | kvfree(buf); | |
2cd7b6f0 RF |
191 | out_unused_fd: |
192 | kvfree(bo_handles); | |
da758d51 GH |
193 | if (buflist) |
194 | virtio_gpu_array_put_free(buflist); | |
2cd7b6f0 RF |
195 | |
196 | if (out_fence_fd >= 0) | |
197 | put_unused_fd(out_fence_fd); | |
198 | ||
62fb7a5e GH |
199 | return ret; |
200 | } | |
201 | ||
62fb7a5e | 202 | static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, |
30349f8f | 203 | struct drm_file *file) |
62fb7a5e GH |
204 | { |
205 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
206 | struct drm_virtgpu_getparam *param = data; | |
207 | int value; | |
208 | ||
209 | switch (param->param) { | |
210 | case VIRTGPU_PARAM_3D_FEATURES: | |
211 | value = vgdev->has_virgl_3d == true ? 1 : 0; | |
212 | break; | |
9a191b11 DA |
213 | case VIRTGPU_PARAM_CAPSET_QUERY_FIX: |
214 | value = 1; | |
215 | break; | |
62fb7a5e GH |
216 | default: |
217 | return -EINVAL; | |
218 | } | |
4b013bb2 | 219 | if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int))) |
62fb7a5e | 220 | return -EFAULT; |
4b013bb2 | 221 | |
62fb7a5e GH |
222 | return 0; |
223 | } | |
224 | ||
225 | static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data, | |
30349f8f | 226 | struct drm_file *file) |
62fb7a5e GH |
227 | { |
228 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
229 | struct drm_virtgpu_resource_create *rc = data; | |
530b2842 | 230 | struct virtio_gpu_fence *fence; |
62fb7a5e | 231 | int ret; |
62fb7a5e GH |
232 | struct virtio_gpu_object *qobj; |
233 | struct drm_gem_object *obj; | |
234 | uint32_t handle = 0; | |
4441235f | 235 | struct virtio_gpu_object_params params = { 0 }; |
62fb7a5e | 236 | |
72b48ae8 GS |
237 | if (vgdev->has_virgl_3d) { |
238 | virtio_gpu_create_context(dev, file); | |
239 | params.virgl = true; | |
240 | params.target = rc->target; | |
241 | params.bind = rc->bind; | |
242 | params.depth = rc->depth; | |
243 | params.array_size = rc->array_size; | |
244 | params.last_level = rc->last_level; | |
245 | params.nr_samples = rc->nr_samples; | |
246 | params.flags = rc->flags; | |
247 | } else { | |
62fb7a5e GH |
248 | if (rc->depth > 1) |
249 | return -EINVAL; | |
250 | if (rc->nr_samples > 1) | |
251 | return -EINVAL; | |
252 | if (rc->last_level > 1) | |
253 | return -EINVAL; | |
254 | if (rc->target != 2) | |
255 | return -EINVAL; | |
256 | if (rc->array_size > 1) | |
257 | return -EINVAL; | |
258 | } | |
259 | ||
f9659329 GH |
260 | params.format = rc->format; |
261 | params.width = rc->width; | |
262 | params.height = rc->height; | |
4441235f | 263 | params.size = rc->size; |
62fb7a5e | 264 | /* allocate a single page size object */ |
4441235f GH |
265 | if (params.size == 0) |
266 | params.size = PAGE_SIZE; | |
62fb7a5e | 267 | |
530b2842 GH |
268 | fence = virtio_gpu_fence_alloc(vgdev); |
269 | if (!fence) | |
270 | return -ENOMEM; | |
2e0d9ee4 | 271 | ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence); |
530b2842 | 272 | dma_fence_put(&fence->f); |
2e0d9ee4 GH |
273 | if (ret < 0) |
274 | return ret; | |
c66df701 | 275 | obj = &qobj->base.base; |
62fb7a5e | 276 | |
30349f8f | 277 | ret = drm_gem_handle_create(file, obj, &handle); |
62fb7a5e | 278 | if (ret) { |
62fb7a5e | 279 | drm_gem_object_release(obj); |
62fb7a5e GH |
280 | return ret; |
281 | } | |
1af0838d | 282 | drm_gem_object_put_unlocked(obj); |
62fb7a5e | 283 | |
70a0d6a3 | 284 | rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */ |
62fb7a5e | 285 | rc->bo_handle = handle; |
62fb7a5e | 286 | return 0; |
62fb7a5e GH |
287 | } |
288 | ||
289 | static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data, | |
30349f8f | 290 | struct drm_file *file) |
62fb7a5e GH |
291 | { |
292 | struct drm_virtgpu_resource_info *ri = data; | |
293 | struct drm_gem_object *gobj = NULL; | |
294 | struct virtio_gpu_object *qobj = NULL; | |
295 | ||
30349f8f | 296 | gobj = drm_gem_object_lookup(file, ri->bo_handle); |
62fb7a5e GH |
297 | if (gobj == NULL) |
298 | return -ENOENT; | |
299 | ||
300 | qobj = gem_to_virtio_gpu_obj(gobj); | |
301 | ||
c66df701 | 302 | ri->size = qobj->base.base.size; |
62fb7a5e | 303 | ri->res_handle = qobj->hw_res_handle; |
1af0838d | 304 | drm_gem_object_put_unlocked(gobj); |
62fb7a5e GH |
305 | return 0; |
306 | } | |
307 | ||
308 | static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev, | |
309 | void *data, | |
310 | struct drm_file *file) | |
311 | { | |
312 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
313 | struct virtio_gpu_fpriv *vfpriv = file->driver_priv; | |
314 | struct drm_virtgpu_3d_transfer_from_host *args = data; | |
375f156a | 315 | struct virtio_gpu_object_array *objs; |
62fb7a5e GH |
316 | struct virtio_gpu_fence *fence; |
317 | int ret; | |
318 | u32 offset = args->offset; | |
62fb7a5e GH |
319 | |
320 | if (vgdev->has_virgl_3d == false) | |
321 | return -ENOSYS; | |
322 | ||
72b48ae8 | 323 | virtio_gpu_create_context(dev, file); |
375f156a GH |
324 | objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); |
325 | if (objs == NULL) | |
62fb7a5e GH |
326 | return -ENOENT; |
327 | ||
375f156a GH |
328 | ret = virtio_gpu_array_lock_resv(objs); |
329 | if (ret != 0) | |
330 | goto err_put_free; | |
62fb7a5e | 331 | |
9fdd90c0 RF |
332 | fence = virtio_gpu_fence_alloc(vgdev); |
333 | if (!fence) { | |
334 | ret = -ENOMEM; | |
375f156a | 335 | goto err_unlock; |
9fdd90c0 | 336 | } |
62fb7a5e | 337 | virtio_gpu_cmd_transfer_from_host_3d |
375f156a | 338 | (vgdev, vfpriv->ctx_id, offset, args->level, |
1dc34852 | 339 | &args->box, objs, fence); |
f54d1867 | 340 | dma_fence_put(&fence->f); |
97452907 | 341 | virtio_gpu_notify(vgdev); |
375f156a GH |
342 | return 0; |
343 | ||
344 | err_unlock: | |
345 | virtio_gpu_array_unlock_resv(objs); | |
346 | err_put_free: | |
347 | virtio_gpu_array_put_free(objs); | |
62fb7a5e GH |
348 | return ret; |
349 | } | |
350 | ||
351 | static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data, | |
352 | struct drm_file *file) | |
353 | { | |
354 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
355 | struct virtio_gpu_fpriv *vfpriv = file->driver_priv; | |
356 | struct drm_virtgpu_3d_transfer_to_host *args = data; | |
3d3bdbc0 | 357 | struct virtio_gpu_object_array *objs; |
62fb7a5e | 358 | struct virtio_gpu_fence *fence; |
62fb7a5e GH |
359 | int ret; |
360 | u32 offset = args->offset; | |
361 | ||
3d3bdbc0 GH |
362 | objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1); |
363 | if (objs == NULL) | |
62fb7a5e GH |
364 | return -ENOENT; |
365 | ||
62fb7a5e GH |
366 | if (!vgdev->has_virgl_3d) { |
367 | virtio_gpu_cmd_transfer_to_host_2d | |
3d3bdbc0 | 368 | (vgdev, offset, |
1dc34852 | 369 | args->box.w, args->box.h, args->box.x, args->box.y, |
3d3bdbc0 | 370 | objs, NULL); |
62fb7a5e | 371 | } else { |
72b48ae8 | 372 | virtio_gpu_create_context(dev, file); |
3d3bdbc0 GH |
373 | ret = virtio_gpu_array_lock_resv(objs); |
374 | if (ret != 0) | |
375 | goto err_put_free; | |
376 | ||
377 | ret = -ENOMEM; | |
9fdd90c0 | 378 | fence = virtio_gpu_fence_alloc(vgdev); |
3d3bdbc0 GH |
379 | if (!fence) |
380 | goto err_unlock; | |
381 | ||
62fb7a5e | 382 | virtio_gpu_cmd_transfer_to_host_3d |
3d3bdbc0 | 383 | (vgdev, |
62fb7a5e | 384 | vfpriv ? vfpriv->ctx_id : 0, offset, |
1dc34852 | 385 | args->level, &args->box, objs, fence); |
f54d1867 | 386 | dma_fence_put(&fence->f); |
62fb7a5e | 387 | } |
790bcd79 | 388 | virtio_gpu_notify(vgdev); |
3d3bdbc0 | 389 | return 0; |
62fb7a5e | 390 | |
3d3bdbc0 GH |
391 | err_unlock: |
392 | virtio_gpu_array_unlock_resv(objs); | |
393 | err_put_free: | |
394 | virtio_gpu_array_put_free(objs); | |
62fb7a5e GH |
395 | return ret; |
396 | } | |
397 | ||
398 | static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data, | |
29cf1239 | 399 | struct drm_file *file) |
62fb7a5e GH |
400 | { |
401 | struct drm_virtgpu_3d_wait *args = data; | |
29cf1239 GH |
402 | struct drm_gem_object *obj; |
403 | long timeout = 15 * HZ; | |
62fb7a5e | 404 | int ret; |
62fb7a5e | 405 | |
29cf1239 GH |
406 | obj = drm_gem_object_lookup(file, args->handle); |
407 | if (obj == NULL) | |
62fb7a5e GH |
408 | return -ENOENT; |
409 | ||
29cf1239 GH |
410 | if (args->flags & VIRTGPU_WAIT_NOWAIT) { |
411 | ret = dma_resv_test_signaled_rcu(obj->resv, true); | |
412 | } else { | |
413 | ret = dma_resv_wait_timeout_rcu(obj->resv, true, true, | |
414 | timeout); | |
415 | } | |
416 | if (ret == 0) | |
417 | ret = -EBUSY; | |
418 | else if (ret > 0) | |
419 | ret = 0; | |
62fb7a5e | 420 | |
29cf1239 | 421 | drm_gem_object_put_unlocked(obj); |
62fb7a5e GH |
422 | return ret; |
423 | } | |
424 | ||
425 | static int virtio_gpu_get_caps_ioctl(struct drm_device *dev, | |
426 | void *data, struct drm_file *file) | |
427 | { | |
428 | struct virtio_gpu_device *vgdev = dev->dev_private; | |
429 | struct drm_virtgpu_get_caps *args = data; | |
9a191b11 | 430 | unsigned size, host_caps_size; |
62fb7a5e GH |
431 | int i; |
432 | int found_valid = -1; | |
433 | int ret; | |
434 | struct virtio_gpu_drv_cap_cache *cache_ent; | |
435 | void *ptr; | |
9d492b6b | 436 | |
62fb7a5e GH |
437 | if (vgdev->num_capsets == 0) |
438 | return -ENOSYS; | |
439 | ||
9a191b11 DA |
440 | /* don't allow userspace to pass 0 */ |
441 | if (args->size == 0) | |
442 | return -EINVAL; | |
443 | ||
62fb7a5e GH |
444 | spin_lock(&vgdev->display_info_lock); |
445 | for (i = 0; i < vgdev->num_capsets; i++) { | |
446 | if (vgdev->capsets[i].id == args->cap_set_id) { | |
447 | if (vgdev->capsets[i].max_version >= args->cap_set_ver) { | |
448 | found_valid = i; | |
449 | break; | |
450 | } | |
451 | } | |
452 | } | |
453 | ||
454 | if (found_valid == -1) { | |
455 | spin_unlock(&vgdev->display_info_lock); | |
456 | return -EINVAL; | |
457 | } | |
458 | ||
9a191b11 DA |
459 | host_caps_size = vgdev->capsets[found_valid].max_size; |
460 | /* only copy to user the minimum of the host caps size or the guest caps size */ | |
461 | size = min(args->size, host_caps_size); | |
62fb7a5e GH |
462 | |
463 | list_for_each_entry(cache_ent, &vgdev->cap_cache, head) { | |
464 | if (cache_ent->id == args->cap_set_id && | |
465 | cache_ent->version == args->cap_set_ver) { | |
62fb7a5e GH |
466 | spin_unlock(&vgdev->display_info_lock); |
467 | goto copy_exit; | |
468 | } | |
469 | } | |
470 | spin_unlock(&vgdev->display_info_lock); | |
471 | ||
472 | /* not in cache - need to talk to hw */ | |
473 | virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver, | |
474 | &cache_ent); | |
97452907 | 475 | virtio_gpu_notify(vgdev); |
62fb7a5e | 476 | |
7fdf478a | 477 | copy_exit: |
62fb7a5e GH |
478 | ret = wait_event_timeout(vgdev->resp_wq, |
479 | atomic_read(&cache_ent->is_valid), 5 * HZ); | |
424c3f05 TV |
480 | if (!ret) |
481 | return -EBUSY; | |
62fb7a5e | 482 | |
9ff3a5c8 DR |
483 | /* is_valid check must proceed before copy of the cache entry. */ |
484 | smp_rmb(); | |
485 | ||
62fb7a5e GH |
486 | ptr = cache_ent->caps_cache; |
487 | ||
4b013bb2 | 488 | if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size)) |
62fb7a5e GH |
489 | return -EFAULT; |
490 | ||
491 | return 0; | |
492 | } | |
493 | ||
494 | struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { | |
495 | DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, | |
848ed7d5 | 496 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
497 | |
498 | DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl, | |
848ed7d5 | 499 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
500 | |
501 | DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl, | |
848ed7d5 | 502 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
503 | |
504 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE, | |
505 | virtio_gpu_resource_create_ioctl, | |
848ed7d5 | 506 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
507 | |
508 | DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl, | |
848ed7d5 | 509 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
510 | |
511 | /* make transfer async to the main ring? - no sure, can we | |
5d883850 RS |
512 | * thread these in the underlying GL |
513 | */ | |
62fb7a5e GH |
514 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST, |
515 | virtio_gpu_transfer_from_host_ioctl, | |
848ed7d5 | 516 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
517 | DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST, |
518 | virtio_gpu_transfer_to_host_ioctl, | |
848ed7d5 | 519 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
520 | |
521 | DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl, | |
848ed7d5 | 522 | DRM_RENDER_ALLOW), |
62fb7a5e GH |
523 | |
524 | DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl, | |
848ed7d5 | 525 | DRM_RENDER_ALLOW), |
62fb7a5e | 526 | }; |