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
28 #include <linux/file.h>
29 #include <linux/sync_file.h>
30 #include <linux/uaccess.h>
31
32 #include <drm/drm_file.h>
33 #include <drm/virtgpu_drm.h>
34
35 #include "virtgpu_drv.h"
36
37 #define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \
38 VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
39 VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
40
virtio_gpu_create_context(struct drm_device * dev,struct drm_file * file)41 void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)
42 {
43 struct virtio_gpu_device *vgdev = dev->dev_private;
44 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
45 char dbgname[TASK_COMM_LEN];
46
47 mutex_lock(&vfpriv->context_lock);
48 if (vfpriv->context_created)
49 goto out_unlock;
50
51 get_task_comm(dbgname, current);
52 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,
53 strlen(dbgname), dbgname);
54 vfpriv->context_created = true;
55
56 out_unlock:
57 mutex_unlock(&vfpriv->context_lock);
58 }
59
virtio_gpu_map_ioctl(struct drm_device * dev,void * data,struct drm_file * file)60 static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
61 struct drm_file *file)
62 {
63 struct virtio_gpu_device *vgdev = dev->dev_private;
64 struct drm_virtgpu_map *virtio_gpu_map = data;
65
66 return virtio_gpu_mode_dumb_mmap(file, vgdev->ddev,
67 virtio_gpu_map->handle,
68 &virtio_gpu_map->offset);
69 }
70
71 /*
72 * Usage of execbuffer:
73 * Relocations need to take into account the full VIRTIO_GPUDrawable size.
74 * However, the command as passed from user space must *not* contain the initial
75 * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
76 */
virtio_gpu_execbuffer_ioctl(struct drm_device * dev,void * data,struct drm_file * file)77 static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
78 struct drm_file *file)
79 {
80 struct drm_virtgpu_execbuffer *exbuf = data;
81 struct virtio_gpu_device *vgdev = dev->dev_private;
82 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
83 struct virtio_gpu_fence *out_fence;
84 int ret;
85 uint32_t *bo_handles = NULL;
86 void __user *user_bo_handles = NULL;
87 struct virtio_gpu_object_array *buflist = NULL;
88 struct sync_file *sync_file;
89 int in_fence_fd = exbuf->fence_fd;
90 int out_fence_fd = -1;
91 void *buf;
92
93 if (vgdev->has_virgl_3d == false)
94 return -ENOSYS;
95
96 if ((exbuf->flags & ~VIRTGPU_EXECBUF_FLAGS))
97 return -EINVAL;
98
99 exbuf->fence_fd = -1;
100
101 virtio_gpu_create_context(dev, file);
102 if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_IN) {
103 struct dma_fence *in_fence;
104
105 in_fence = sync_file_get_fence(in_fence_fd);
106
107 if (!in_fence)
108 return -EINVAL;
109
110 /*
111 * Wait if the fence is from a foreign context, or if the fence
112 * array contains any fence from a foreign context.
113 */
114 ret = 0;
115 if (!dma_fence_match_context(in_fence, vgdev->fence_drv.context))
116 ret = dma_fence_wait(in_fence, true);
117
118 dma_fence_put(in_fence);
119 if (ret)
120 return ret;
121 }
122
123 if (exbuf->flags & VIRTGPU_EXECBUF_FENCE_FD_OUT) {
124 out_fence_fd = get_unused_fd_flags(O_CLOEXEC);
125 if (out_fence_fd < 0)
126 return out_fence_fd;
127 }
128
129 if (exbuf->num_bo_handles) {
130 bo_handles = kvmalloc_array(exbuf->num_bo_handles,
131 sizeof(uint32_t), GFP_KERNEL);
132 if (!bo_handles) {
133 ret = -ENOMEM;
134 goto out_unused_fd;
135 }
136
137 user_bo_handles = u64_to_user_ptr(exbuf->bo_handles);
138 if (copy_from_user(bo_handles, user_bo_handles,
139 exbuf->num_bo_handles * sizeof(uint32_t))) {
140 ret = -EFAULT;
141 goto out_unused_fd;
142 }
143
144 buflist = virtio_gpu_array_from_handles(file, bo_handles,
145 exbuf->num_bo_handles);
146 if (!buflist) {
147 ret = -ENOENT;
148 goto out_unused_fd;
149 }
150 kvfree(bo_handles);
151 bo_handles = NULL;
152 }
153
154 buf = vmemdup_user(u64_to_user_ptr(exbuf->command), exbuf->size);
155 if (IS_ERR(buf)) {
156 ret = PTR_ERR(buf);
157 goto out_unused_fd;
158 }
159
160 if (buflist) {
161 ret = virtio_gpu_array_lock_resv(buflist);
162 if (ret)
163 goto out_memdup;
164 }
165
166 out_fence = virtio_gpu_fence_alloc(vgdev);
167 if(!out_fence) {
168 ret = -ENOMEM;
169 goto out_unresv;
170 }
171
172 if (out_fence_fd >= 0) {
173 sync_file = sync_file_create(&out_fence->f);
174 if (!sync_file) {
175 dma_fence_put(&out_fence->f);
176 ret = -ENOMEM;
177 goto out_unresv;
178 }
179
180 exbuf->fence_fd = out_fence_fd;
181 fd_install(out_fence_fd, sync_file->file);
182 }
183
184 virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
185 vfpriv->ctx_id, buflist, out_fence);
186 dma_fence_put(&out_fence->f);
187 virtio_gpu_notify(vgdev);
188 return 0;
189
190 out_unresv:
191 if (buflist)
192 virtio_gpu_array_unlock_resv(buflist);
193 out_memdup:
194 kvfree(buf);
195 out_unused_fd:
196 kvfree(bo_handles);
197 if (buflist)
198 virtio_gpu_array_put_free(buflist);
199
200 if (out_fence_fd >= 0)
201 put_unused_fd(out_fence_fd);
202
203 return ret;
204 }
205
virtio_gpu_getparam_ioctl(struct drm_device * dev,void * data,struct drm_file * file)206 static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
207 struct drm_file *file)
208 {
209 struct virtio_gpu_device *vgdev = dev->dev_private;
210 struct drm_virtgpu_getparam *param = data;
211 int value;
212
213 switch (param->param) {
214 case VIRTGPU_PARAM_3D_FEATURES:
215 value = vgdev->has_virgl_3d ? 1 : 0;
216 break;
217 case VIRTGPU_PARAM_CAPSET_QUERY_FIX:
218 value = 1;
219 break;
220 case VIRTGPU_PARAM_RESOURCE_BLOB:
221 value = vgdev->has_resource_blob ? 1 : 0;
222 break;
223 case VIRTGPU_PARAM_HOST_VISIBLE:
224 value = vgdev->has_host_visible ? 1 : 0;
225 break;
226 case VIRTGPU_PARAM_CROSS_DEVICE:
227 value = vgdev->has_resource_assign_uuid ? 1 : 0;
228 break;
229 default:
230 return -EINVAL;
231 }
232 if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int)))
233 return -EFAULT;
234
235 return 0;
236 }
237
virtio_gpu_resource_create_ioctl(struct drm_device * dev,void * data,struct drm_file * file)238 static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
239 struct drm_file *file)
240 {
241 struct virtio_gpu_device *vgdev = dev->dev_private;
242 struct drm_virtgpu_resource_create *rc = data;
243 struct virtio_gpu_fence *fence;
244 int ret;
245 struct virtio_gpu_object *qobj;
246 struct drm_gem_object *obj;
247 uint32_t handle = 0;
248 struct virtio_gpu_object_params params = { 0 };
249
250 if (vgdev->has_virgl_3d) {
251 virtio_gpu_create_context(dev, file);
252 params.virgl = true;
253 params.target = rc->target;
254 params.bind = rc->bind;
255 params.depth = rc->depth;
256 params.array_size = rc->array_size;
257 params.last_level = rc->last_level;
258 params.nr_samples = rc->nr_samples;
259 params.flags = rc->flags;
260 } else {
261 if (rc->depth > 1)
262 return -EINVAL;
263 if (rc->nr_samples > 1)
264 return -EINVAL;
265 if (rc->last_level > 1)
266 return -EINVAL;
267 if (rc->target != 2)
268 return -EINVAL;
269 if (rc->array_size > 1)
270 return -EINVAL;
271 }
272
273 params.format = rc->format;
274 params.width = rc->width;
275 params.height = rc->height;
276 params.size = rc->size;
277 /* allocate a single page size object */
278 if (params.size == 0)
279 params.size = PAGE_SIZE;
280
281 fence = virtio_gpu_fence_alloc(vgdev);
282 if (!fence)
283 return -ENOMEM;
284 ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence);
285 dma_fence_put(&fence->f);
286 if (ret < 0)
287 return ret;
288 obj = &qobj->base.base;
289
290 ret = drm_gem_handle_create(file, obj, &handle);
291 if (ret) {
292 drm_gem_object_release(obj);
293 return ret;
294 }
295
296 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
297 rc->bo_handle = handle;
298
299 /*
300 * The handle owns the reference now. But we must drop our
301 * remaining reference *after* we no longer need to dereference
302 * the obj. Otherwise userspace could guess the handle and
303 * race closing it from another thread.
304 */
305 drm_gem_object_put(obj);
306
307 return 0;
308 }
309
virtio_gpu_resource_info_ioctl(struct drm_device * dev,void * data,struct drm_file * file)310 static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
311 struct drm_file *file)
312 {
313 struct drm_virtgpu_resource_info *ri = data;
314 struct drm_gem_object *gobj = NULL;
315 struct virtio_gpu_object *qobj = NULL;
316
317 gobj = drm_gem_object_lookup(file, ri->bo_handle);
318 if (gobj == NULL)
319 return -ENOENT;
320
321 qobj = gem_to_virtio_gpu_obj(gobj);
322
323 ri->size = qobj->base.base.size;
324 ri->res_handle = qobj->hw_res_handle;
325 if (qobj->host3d_blob || qobj->guest_blob)
326 ri->blob_mem = qobj->blob_mem;
327
328 drm_gem_object_put(gobj);
329 return 0;
330 }
331
virtio_gpu_transfer_from_host_ioctl(struct drm_device * dev,void * data,struct drm_file * file)332 static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
333 void *data,
334 struct drm_file *file)
335 {
336 struct virtio_gpu_device *vgdev = dev->dev_private;
337 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
338 struct drm_virtgpu_3d_transfer_from_host *args = data;
339 struct virtio_gpu_object *bo;
340 struct virtio_gpu_object_array *objs;
341 struct virtio_gpu_fence *fence;
342 int ret;
343 u32 offset = args->offset;
344
345 if (vgdev->has_virgl_3d == false)
346 return -ENOSYS;
347
348 virtio_gpu_create_context(dev, file);
349 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
350 if (objs == NULL)
351 return -ENOENT;
352
353 bo = gem_to_virtio_gpu_obj(objs->objs[0]);
354 if (bo->guest_blob && !bo->host3d_blob) {
355 ret = -EINVAL;
356 goto err_put_free;
357 }
358
359 if (!bo->host3d_blob && (args->stride || args->layer_stride)) {
360 ret = -EINVAL;
361 goto err_put_free;
362 }
363
364 ret = virtio_gpu_array_lock_resv(objs);
365 if (ret != 0)
366 goto err_put_free;
367
368 fence = virtio_gpu_fence_alloc(vgdev);
369 if (!fence) {
370 ret = -ENOMEM;
371 goto err_unlock;
372 }
373
374 virtio_gpu_cmd_transfer_from_host_3d
375 (vgdev, vfpriv->ctx_id, offset, args->level, args->stride,
376 args->layer_stride, &args->box, objs, fence);
377 dma_fence_put(&fence->f);
378 virtio_gpu_notify(vgdev);
379 return 0;
380
381 err_unlock:
382 virtio_gpu_array_unlock_resv(objs);
383 err_put_free:
384 virtio_gpu_array_put_free(objs);
385 return ret;
386 }
387
virtio_gpu_transfer_to_host_ioctl(struct drm_device * dev,void * data,struct drm_file * file)388 static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
389 struct drm_file *file)
390 {
391 struct virtio_gpu_device *vgdev = dev->dev_private;
392 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
393 struct drm_virtgpu_3d_transfer_to_host *args = data;
394 struct virtio_gpu_object *bo;
395 struct virtio_gpu_object_array *objs;
396 struct virtio_gpu_fence *fence;
397 int ret;
398 u32 offset = args->offset;
399
400 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
401 if (objs == NULL)
402 return -ENOENT;
403
404 bo = gem_to_virtio_gpu_obj(objs->objs[0]);
405 if (bo->guest_blob && !bo->host3d_blob) {
406 ret = -EINVAL;
407 goto err_put_free;
408 }
409
410 if (!vgdev->has_virgl_3d) {
411 virtio_gpu_cmd_transfer_to_host_2d
412 (vgdev, offset,
413 args->box.w, args->box.h, args->box.x, args->box.y,
414 objs, NULL);
415 } else {
416 virtio_gpu_create_context(dev, file);
417
418 if (!bo->host3d_blob && (args->stride || args->layer_stride)) {
419 ret = -EINVAL;
420 goto err_put_free;
421 }
422
423 ret = virtio_gpu_array_lock_resv(objs);
424 if (ret != 0)
425 goto err_put_free;
426
427 ret = -ENOMEM;
428 fence = virtio_gpu_fence_alloc(vgdev);
429 if (!fence)
430 goto err_unlock;
431
432 virtio_gpu_cmd_transfer_to_host_3d
433 (vgdev,
434 vfpriv ? vfpriv->ctx_id : 0, offset, args->level,
435 args->stride, args->layer_stride, &args->box, objs,
436 fence);
437 dma_fence_put(&fence->f);
438 }
439 virtio_gpu_notify(vgdev);
440 return 0;
441
442 err_unlock:
443 virtio_gpu_array_unlock_resv(objs);
444 err_put_free:
445 virtio_gpu_array_put_free(objs);
446 return ret;
447 }
448
virtio_gpu_wait_ioctl(struct drm_device * dev,void * data,struct drm_file * file)449 static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,
450 struct drm_file *file)
451 {
452 struct drm_virtgpu_3d_wait *args = data;
453 struct drm_gem_object *obj;
454 long timeout = 15 * HZ;
455 int ret;
456
457 obj = drm_gem_object_lookup(file, args->handle);
458 if (obj == NULL)
459 return -ENOENT;
460
461 if (args->flags & VIRTGPU_WAIT_NOWAIT) {
462 ret = dma_resv_test_signaled(obj->resv, true);
463 } else {
464 ret = dma_resv_wait_timeout(obj->resv, true, true, timeout);
465 }
466 if (ret == 0)
467 ret = -EBUSY;
468 else if (ret > 0)
469 ret = 0;
470
471 drm_gem_object_put(obj);
472 return ret;
473 }
474
virtio_gpu_get_caps_ioctl(struct drm_device * dev,void * data,struct drm_file * file)475 static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
476 void *data, struct drm_file *file)
477 {
478 struct virtio_gpu_device *vgdev = dev->dev_private;
479 struct drm_virtgpu_get_caps *args = data;
480 unsigned size, host_caps_size;
481 int i;
482 int found_valid = -1;
483 int ret;
484 struct virtio_gpu_drv_cap_cache *cache_ent;
485 void *ptr;
486
487 if (vgdev->num_capsets == 0)
488 return -ENOSYS;
489
490 /* don't allow userspace to pass 0 */
491 if (args->size == 0)
492 return -EINVAL;
493
494 spin_lock(&vgdev->display_info_lock);
495 for (i = 0; i < vgdev->num_capsets; i++) {
496 if (vgdev->capsets[i].id == args->cap_set_id) {
497 if (vgdev->capsets[i].max_version >= args->cap_set_ver) {
498 found_valid = i;
499 break;
500 }
501 }
502 }
503
504 if (found_valid == -1) {
505 spin_unlock(&vgdev->display_info_lock);
506 return -EINVAL;
507 }
508
509 host_caps_size = vgdev->capsets[found_valid].max_size;
510 /* only copy to user the minimum of the host caps size or the guest caps size */
511 size = min(args->size, host_caps_size);
512
513 list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
514 if (cache_ent->id == args->cap_set_id &&
515 cache_ent->version == args->cap_set_ver) {
516 spin_unlock(&vgdev->display_info_lock);
517 goto copy_exit;
518 }
519 }
520 spin_unlock(&vgdev->display_info_lock);
521
522 /* not in cache - need to talk to hw */
523 ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,
524 &cache_ent);
525 if (ret)
526 return ret;
527 virtio_gpu_notify(vgdev);
528
529 copy_exit:
530 ret = wait_event_timeout(vgdev->resp_wq,
531 atomic_read(&cache_ent->is_valid), 5 * HZ);
532 if (!ret)
533 return -EBUSY;
534
535 /* is_valid check must proceed before copy of the cache entry. */
536 smp_rmb();
537
538 ptr = cache_ent->caps_cache;
539
540 if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size))
541 return -EFAULT;
542
543 return 0;
544 }
545
verify_blob(struct virtio_gpu_device * vgdev,struct virtio_gpu_fpriv * vfpriv,struct virtio_gpu_object_params * params,struct drm_virtgpu_resource_create_blob * rc_blob,bool * guest_blob,bool * host3d_blob)546 static int verify_blob(struct virtio_gpu_device *vgdev,
547 struct virtio_gpu_fpriv *vfpriv,
548 struct virtio_gpu_object_params *params,
549 struct drm_virtgpu_resource_create_blob *rc_blob,
550 bool *guest_blob, bool *host3d_blob)
551 {
552 if (!vgdev->has_resource_blob)
553 return -EINVAL;
554
555 if ((rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK) ||
556 !rc_blob->blob_flags)
557 return -EINVAL;
558
559 if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
560 if (!vgdev->has_resource_assign_uuid)
561 return -EINVAL;
562 }
563
564 switch (rc_blob->blob_mem) {
565 case VIRTGPU_BLOB_MEM_GUEST:
566 *guest_blob = true;
567 break;
568 case VIRTGPU_BLOB_MEM_HOST3D_GUEST:
569 *guest_blob = true;
570 fallthrough;
571 case VIRTGPU_BLOB_MEM_HOST3D:
572 *host3d_blob = true;
573 break;
574 default:
575 return -EINVAL;
576 }
577
578 if (*host3d_blob) {
579 if (!vgdev->has_virgl_3d)
580 return -EINVAL;
581
582 /* Must be dword aligned. */
583 if (rc_blob->cmd_size % 4 != 0)
584 return -EINVAL;
585
586 params->ctx_id = vfpriv->ctx_id;
587 params->blob_id = rc_blob->blob_id;
588 } else {
589 if (rc_blob->blob_id != 0)
590 return -EINVAL;
591
592 if (rc_blob->cmd_size != 0)
593 return -EINVAL;
594 }
595
596 params->blob_mem = rc_blob->blob_mem;
597 params->size = rc_blob->size;
598 params->blob = true;
599 params->blob_flags = rc_blob->blob_flags;
600 return 0;
601 }
602
virtio_gpu_resource_create_blob_ioctl(struct drm_device * dev,void * data,struct drm_file * file)603 static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
604 void *data,
605 struct drm_file *file)
606 {
607 int ret = 0;
608 uint32_t handle = 0;
609 bool guest_blob = false;
610 bool host3d_blob = false;
611 struct drm_gem_object *obj;
612 struct virtio_gpu_object *bo;
613 struct virtio_gpu_object_params params = { 0 };
614 struct virtio_gpu_device *vgdev = dev->dev_private;
615 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
616 struct drm_virtgpu_resource_create_blob *rc_blob = data;
617
618 if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob,
619 &guest_blob, &host3d_blob))
620 return -EINVAL;
621
622 if (vgdev->has_virgl_3d)
623 virtio_gpu_create_context(dev, file);
624
625 if (rc_blob->cmd_size) {
626 void *buf;
627
628 buf = memdup_user(u64_to_user_ptr(rc_blob->cmd),
629 rc_blob->cmd_size);
630
631 if (IS_ERR(buf))
632 return PTR_ERR(buf);
633
634 virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size,
635 vfpriv->ctx_id, NULL, NULL);
636 }
637
638 if (guest_blob)
639 ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL);
640 else if (!guest_blob && host3d_blob)
641 ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo);
642 else
643 return -EINVAL;
644
645 if (ret < 0)
646 return ret;
647
648 bo->guest_blob = guest_blob;
649 bo->host3d_blob = host3d_blob;
650 bo->blob_mem = rc_blob->blob_mem;
651 bo->blob_flags = rc_blob->blob_flags;
652
653 obj = &bo->base.base;
654 if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
655 ret = virtio_gpu_resource_assign_uuid(vgdev, bo);
656 if (ret) {
657 drm_gem_object_release(obj);
658 return ret;
659 }
660 }
661
662 ret = drm_gem_handle_create(file, obj, &handle);
663 if (ret) {
664 drm_gem_object_release(obj);
665 return ret;
666 }
667
668 rc_blob->res_handle = bo->hw_res_handle;
669 rc_blob->bo_handle = handle;
670
671 /*
672 * The handle owns the reference now. But we must drop our
673 * remaining reference *after* we no longer need to dereference
674 * the obj. Otherwise userspace could guess the handle and
675 * race closing it from another thread.
676 */
677 drm_gem_object_put(obj);
678
679 return 0;
680 }
681
682 struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
683 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
684 DRM_RENDER_ALLOW),
685
686 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
687 DRM_RENDER_ALLOW),
688
689 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
690 DRM_RENDER_ALLOW),
691
692 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
693 virtio_gpu_resource_create_ioctl,
694 DRM_RENDER_ALLOW),
695
696 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
697 DRM_RENDER_ALLOW),
698
699 /* make transfer async to the main ring? - no sure, can we
700 * thread these in the underlying GL
701 */
702 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
703 virtio_gpu_transfer_from_host_ioctl,
704 DRM_RENDER_ALLOW),
705 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
706 virtio_gpu_transfer_to_host_ioctl,
707 DRM_RENDER_ALLOW),
708
709 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
710 DRM_RENDER_ALLOW),
711
712 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
713 DRM_RENDER_ALLOW),
714
715 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB,
716 virtio_gpu_resource_create_blob_ioctl,
717 DRM_RENDER_ALLOW),
718 };
719