736 lines · c
1/*2 * Copyright (C) 2015 Red Hat, Inc.3 * All Rights Reserved.4 *5 * Authors:6 * Dave Airlie7 * Alon Levy8 *9 * Permission is hereby granted, free of charge, to any person obtaining a10 * copy of this software and associated documentation files (the "Software"),11 * to deal in the Software without restriction, including without limitation12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,13 * and/or sell copies of the Software, and to permit persons to whom the14 * Software is furnished to do so, subject to the following conditions:15 *16 * The above copyright notice and this permission notice shall be included in17 * all copies or substantial portions of the Software.18 *19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL22 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR23 * 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 OR25 * 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 41/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */42static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,43 struct virtio_gpu_fpriv *vfpriv)44{45 if (vfpriv->explicit_debug_name) {46 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,47 vfpriv->context_init,48 strlen(vfpriv->debug_name),49 vfpriv->debug_name);50 } else {51 char dbgname[TASK_COMM_LEN];52 53 get_task_comm(dbgname, current);54 virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,55 vfpriv->context_init, strlen(dbgname),56 dbgname);57 }58 59 vfpriv->context_created = true;60}61 62void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)63{64 struct virtio_gpu_device *vgdev = dev->dev_private;65 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;66 67 mutex_lock(&vfpriv->context_lock);68 if (vfpriv->context_created)69 goto out_unlock;70 71 virtio_gpu_create_context_locked(vgdev, vfpriv);72 73out_unlock:74 mutex_unlock(&vfpriv->context_lock);75}76 77static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,78 struct drm_file *file)79{80 struct virtio_gpu_device *vgdev = dev->dev_private;81 struct drm_virtgpu_map *virtio_gpu_map = data;82 83 return virtio_gpu_mode_dumb_mmap(file, vgdev->ddev,84 virtio_gpu_map->handle,85 &virtio_gpu_map->offset);86}87 88static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,89 struct drm_file *file)90{91 struct virtio_gpu_device *vgdev = dev->dev_private;92 struct drm_virtgpu_getparam *param = data;93 int value;94 95 switch (param->param) {96 case VIRTGPU_PARAM_3D_FEATURES:97 value = vgdev->has_virgl_3d ? 1 : 0;98 break;99 case VIRTGPU_PARAM_CAPSET_QUERY_FIX:100 value = 1;101 break;102 case VIRTGPU_PARAM_RESOURCE_BLOB:103 value = vgdev->has_resource_blob ? 1 : 0;104 break;105 case VIRTGPU_PARAM_HOST_VISIBLE:106 value = vgdev->has_host_visible ? 1 : 0;107 break;108 case VIRTGPU_PARAM_CROSS_DEVICE:109 value = vgdev->has_resource_assign_uuid ? 1 : 0;110 break;111 case VIRTGPU_PARAM_CONTEXT_INIT:112 value = vgdev->has_context_init ? 1 : 0;113 break;114 case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs:115 value = vgdev->capset_id_mask;116 break;117 case VIRTGPU_PARAM_EXPLICIT_DEBUG_NAME:118 value = vgdev->has_context_init ? 1 : 0;119 break;120 default:121 return -EINVAL;122 }123 if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int)))124 return -EFAULT;125 126 return 0;127}128 129static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,130 struct drm_file *file)131{132 struct virtio_gpu_device *vgdev = dev->dev_private;133 struct drm_virtgpu_resource_create *rc = data;134 struct virtio_gpu_fence *fence;135 int ret;136 struct virtio_gpu_object *qobj;137 struct drm_gem_object *obj;138 uint32_t handle = 0;139 struct virtio_gpu_object_params params = { 0 };140 141 if (vgdev->has_virgl_3d) {142 virtio_gpu_create_context(dev, file);143 params.virgl = true;144 params.target = rc->target;145 params.bind = rc->bind;146 params.depth = rc->depth;147 params.array_size = rc->array_size;148 params.last_level = rc->last_level;149 params.nr_samples = rc->nr_samples;150 params.flags = rc->flags;151 } else {152 if (rc->depth > 1)153 return -EINVAL;154 if (rc->nr_samples > 1)155 return -EINVAL;156 if (rc->last_level > 1)157 return -EINVAL;158 if (rc->target != 2)159 return -EINVAL;160 if (rc->array_size > 1)161 return -EINVAL;162 }163 164 params.format = rc->format;165 params.width = rc->width;166 params.height = rc->height;167 params.size = rc->size;168 /* allocate a single page size object */169 if (params.size == 0)170 params.size = PAGE_SIZE;171 172 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0);173 if (!fence)174 return -ENOMEM;175 ret = virtio_gpu_object_create(vgdev, ¶ms, &qobj, fence);176 dma_fence_put(&fence->f);177 if (ret < 0)178 return ret;179 obj = &qobj->base.base;180 181 ret = drm_gem_handle_create(file, obj, &handle);182 if (ret) {183 drm_gem_object_release(obj);184 return ret;185 }186 187 rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */188 rc->bo_handle = handle;189 190 /*191 * The handle owns the reference now. But we must drop our192 * remaining reference *after* we no longer need to dereference193 * the obj. Otherwise userspace could guess the handle and194 * race closing it from another thread.195 */196 drm_gem_object_put(obj);197 198 return 0;199}200 201static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,202 struct drm_file *file)203{204 struct drm_virtgpu_resource_info *ri = data;205 struct drm_gem_object *gobj = NULL;206 struct virtio_gpu_object *qobj = NULL;207 208 gobj = drm_gem_object_lookup(file, ri->bo_handle);209 if (gobj == NULL)210 return -ENOENT;211 212 qobj = gem_to_virtio_gpu_obj(gobj);213 214 ri->size = qobj->base.base.size;215 ri->res_handle = qobj->hw_res_handle;216 if (qobj->host3d_blob || qobj->guest_blob)217 ri->blob_mem = qobj->blob_mem;218 219 drm_gem_object_put(gobj);220 return 0;221}222 223static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,224 void *data,225 struct drm_file *file)226{227 struct virtio_gpu_device *vgdev = dev->dev_private;228 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;229 struct drm_virtgpu_3d_transfer_from_host *args = data;230 struct virtio_gpu_object *bo;231 struct virtio_gpu_object_array *objs;232 struct virtio_gpu_fence *fence;233 int ret;234 u32 offset = args->offset;235 236 if (vgdev->has_virgl_3d == false)237 return -ENOSYS;238 239 virtio_gpu_create_context(dev, file);240 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);241 if (objs == NULL)242 return -ENOENT;243 244 bo = gem_to_virtio_gpu_obj(objs->objs[0]);245 if (bo->guest_blob && !bo->host3d_blob) {246 ret = -EINVAL;247 goto err_put_free;248 }249 250 if (!bo->host3d_blob && (args->stride || args->layer_stride)) {251 ret = -EINVAL;252 goto err_put_free;253 }254 255 ret = virtio_gpu_array_lock_resv(objs);256 if (ret != 0)257 goto err_put_free;258 259 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0);260 if (!fence) {261 ret = -ENOMEM;262 goto err_unlock;263 }264 265 virtio_gpu_cmd_transfer_from_host_3d266 (vgdev, vfpriv->ctx_id, offset, args->level, args->stride,267 args->layer_stride, &args->box, objs, fence);268 dma_fence_put(&fence->f);269 virtio_gpu_notify(vgdev);270 return 0;271 272err_unlock:273 virtio_gpu_array_unlock_resv(objs);274err_put_free:275 virtio_gpu_array_put_free(objs);276 return ret;277}278 279static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,280 struct drm_file *file)281{282 struct virtio_gpu_device *vgdev = dev->dev_private;283 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;284 struct drm_virtgpu_3d_transfer_to_host *args = data;285 struct virtio_gpu_object *bo;286 struct virtio_gpu_object_array *objs;287 struct virtio_gpu_fence *fence;288 int ret;289 u32 offset = args->offset;290 291 objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);292 if (objs == NULL)293 return -ENOENT;294 295 bo = gem_to_virtio_gpu_obj(objs->objs[0]);296 if (bo->guest_blob && !bo->host3d_blob) {297 ret = -EINVAL;298 goto err_put_free;299 }300 301 if (!vgdev->has_virgl_3d) {302 virtio_gpu_cmd_transfer_to_host_2d303 (vgdev, offset,304 args->box.w, args->box.h, args->box.x, args->box.y,305 objs, NULL);306 } else {307 virtio_gpu_create_context(dev, file);308 309 if (!bo->host3d_blob && (args->stride || args->layer_stride)) {310 ret = -EINVAL;311 goto err_put_free;312 }313 314 ret = virtio_gpu_array_lock_resv(objs);315 if (ret != 0)316 goto err_put_free;317 318 ret = -ENOMEM;319 fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context,320 0);321 if (!fence)322 goto err_unlock;323 324 virtio_gpu_cmd_transfer_to_host_3d325 (vgdev,326 vfpriv ? vfpriv->ctx_id : 0, offset, args->level,327 args->stride, args->layer_stride, &args->box, objs,328 fence);329 dma_fence_put(&fence->f);330 }331 virtio_gpu_notify(vgdev);332 return 0;333 334err_unlock:335 virtio_gpu_array_unlock_resv(objs);336err_put_free:337 virtio_gpu_array_put_free(objs);338 return ret;339}340 341static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,342 struct drm_file *file)343{344 struct drm_virtgpu_3d_wait *args = data;345 struct drm_gem_object *obj;346 long timeout = 15 * HZ;347 int ret;348 349 obj = drm_gem_object_lookup(file, args->handle);350 if (obj == NULL)351 return -ENOENT;352 353 if (args->flags & VIRTGPU_WAIT_NOWAIT) {354 ret = dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ);355 } else {356 ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ,357 true, timeout);358 }359 if (ret == 0)360 ret = -EBUSY;361 else if (ret > 0)362 ret = 0;363 364 drm_gem_object_put(obj);365 return ret;366}367 368static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,369 void *data, struct drm_file *file)370{371 struct virtio_gpu_device *vgdev = dev->dev_private;372 struct drm_virtgpu_get_caps *args = data;373 unsigned size, host_caps_size;374 int i;375 int found_valid = -1;376 int ret;377 struct virtio_gpu_drv_cap_cache *cache_ent;378 void *ptr;379 380 if (vgdev->num_capsets == 0)381 return -ENOSYS;382 383 /* don't allow userspace to pass 0 */384 if (args->size == 0)385 return -EINVAL;386 387 spin_lock(&vgdev->display_info_lock);388 for (i = 0; i < vgdev->num_capsets; i++) {389 if (vgdev->capsets[i].id == args->cap_set_id) {390 if (vgdev->capsets[i].max_version >= args->cap_set_ver) {391 found_valid = i;392 break;393 }394 }395 }396 397 if (found_valid == -1) {398 spin_unlock(&vgdev->display_info_lock);399 return -EINVAL;400 }401 402 host_caps_size = vgdev->capsets[found_valid].max_size;403 /* only copy to user the minimum of the host caps size or the guest caps size */404 size = min(args->size, host_caps_size);405 406 list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {407 if (cache_ent->id == args->cap_set_id &&408 cache_ent->version == args->cap_set_ver) {409 spin_unlock(&vgdev->display_info_lock);410 goto copy_exit;411 }412 }413 spin_unlock(&vgdev->display_info_lock);414 415 /* not in cache - need to talk to hw */416 ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,417 &cache_ent);418 if (ret)419 return ret;420 virtio_gpu_notify(vgdev);421 422copy_exit:423 ret = wait_event_timeout(vgdev->resp_wq,424 atomic_read(&cache_ent->is_valid), 5 * HZ);425 if (!ret)426 return -EBUSY;427 428 /* is_valid check must proceed before copy of the cache entry. */429 smp_rmb();430 431 ptr = cache_ent->caps_cache;432 433 if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size))434 return -EFAULT;435 436 return 0;437}438 439static int verify_blob(struct virtio_gpu_device *vgdev,440 struct virtio_gpu_fpriv *vfpriv,441 struct virtio_gpu_object_params *params,442 struct drm_virtgpu_resource_create_blob *rc_blob,443 bool *guest_blob, bool *host3d_blob)444{445 if (!vgdev->has_resource_blob)446 return -EINVAL;447 448 if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK)449 return -EINVAL;450 451 if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {452 if (!vgdev->has_resource_assign_uuid)453 return -EINVAL;454 }455 456 switch (rc_blob->blob_mem) {457 case VIRTGPU_BLOB_MEM_GUEST:458 *guest_blob = true;459 break;460 case VIRTGPU_BLOB_MEM_HOST3D_GUEST:461 *guest_blob = true;462 fallthrough;463 case VIRTGPU_BLOB_MEM_HOST3D:464 *host3d_blob = true;465 break;466 default:467 return -EINVAL;468 }469 470 if (*host3d_blob) {471 if (!vgdev->has_virgl_3d)472 return -EINVAL;473 474 /* Must be dword aligned. */475 if (rc_blob->cmd_size % 4 != 0)476 return -EINVAL;477 478 params->ctx_id = vfpriv->ctx_id;479 params->blob_id = rc_blob->blob_id;480 } else {481 if (rc_blob->blob_id != 0)482 return -EINVAL;483 484 if (rc_blob->cmd_size != 0)485 return -EINVAL;486 }487 488 params->blob_mem = rc_blob->blob_mem;489 params->size = rc_blob->size;490 params->blob = true;491 params->blob_flags = rc_blob->blob_flags;492 return 0;493}494 495static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,496 void *data,497 struct drm_file *file)498{499 int ret = 0;500 uint32_t handle = 0;501 bool guest_blob = false;502 bool host3d_blob = false;503 struct drm_gem_object *obj;504 struct virtio_gpu_object *bo;505 struct virtio_gpu_object_params params = { 0 };506 struct virtio_gpu_device *vgdev = dev->dev_private;507 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;508 struct drm_virtgpu_resource_create_blob *rc_blob = data;509 510 if (verify_blob(vgdev, vfpriv, ¶ms, rc_blob,511 &guest_blob, &host3d_blob))512 return -EINVAL;513 514 if (vgdev->has_virgl_3d)515 virtio_gpu_create_context(dev, file);516 517 if (rc_blob->cmd_size) {518 void *buf;519 520 buf = memdup_user(u64_to_user_ptr(rc_blob->cmd),521 rc_blob->cmd_size);522 523 if (IS_ERR(buf))524 return PTR_ERR(buf);525 526 virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size,527 vfpriv->ctx_id, NULL, NULL);528 }529 530 if (guest_blob)531 ret = virtio_gpu_object_create(vgdev, ¶ms, &bo, NULL);532 else if (!guest_blob && host3d_blob)533 ret = virtio_gpu_vram_create(vgdev, ¶ms, &bo);534 else535 return -EINVAL;536 537 if (ret < 0)538 return ret;539 540 bo->guest_blob = guest_blob;541 bo->host3d_blob = host3d_blob;542 bo->blob_mem = rc_blob->blob_mem;543 bo->blob_flags = rc_blob->blob_flags;544 545 obj = &bo->base.base;546 if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {547 ret = virtio_gpu_resource_assign_uuid(vgdev, bo);548 if (ret) {549 drm_gem_object_release(obj);550 return ret;551 }552 }553 554 ret = drm_gem_handle_create(file, obj, &handle);555 if (ret) {556 drm_gem_object_release(obj);557 return ret;558 }559 560 rc_blob->res_handle = bo->hw_res_handle;561 rc_blob->bo_handle = handle;562 563 /*564 * The handle owns the reference now. But we must drop our565 * remaining reference *after* we no longer need to dereference566 * the obj. Otherwise userspace could guess the handle and567 * race closing it from another thread.568 */569 drm_gem_object_put(obj);570 571 return 0;572}573 574static int virtio_gpu_context_init_ioctl(struct drm_device *dev,575 void *data, struct drm_file *file)576{577 int ret = 0;578 uint32_t num_params, i;579 uint64_t valid_ring_mask, param, value;580 size_t len;581 struct drm_virtgpu_context_set_param *ctx_set_params = NULL;582 struct virtio_gpu_device *vgdev = dev->dev_private;583 struct virtio_gpu_fpriv *vfpriv = file->driver_priv;584 struct drm_virtgpu_context_init *args = data;585 586 num_params = args->num_params;587 len = num_params * sizeof(struct drm_virtgpu_context_set_param);588 589 if (!vgdev->has_context_init || !vgdev->has_virgl_3d)590 return -EINVAL;591 592 /* Number of unique parameters supported at this time. */593 if (num_params > 4)594 return -EINVAL;595 596 ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params),597 len);598 599 if (IS_ERR(ctx_set_params))600 return PTR_ERR(ctx_set_params);601 602 mutex_lock(&vfpriv->context_lock);603 if (vfpriv->context_created) {604 ret = -EEXIST;605 goto out_unlock;606 }607 608 for (i = 0; i < num_params; i++) {609 param = ctx_set_params[i].param;610 value = ctx_set_params[i].value;611 612 switch (param) {613 case VIRTGPU_CONTEXT_PARAM_CAPSET_ID:614 if (value > MAX_CAPSET_ID) {615 ret = -EINVAL;616 goto out_unlock;617 }618 619 if ((vgdev->capset_id_mask & (1ULL << value)) == 0) {620 ret = -EINVAL;621 goto out_unlock;622 }623 624 /* Context capset ID already set */625 if (vfpriv->context_init &626 VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) {627 ret = -EINVAL;628 goto out_unlock;629 }630 631 vfpriv->context_init |= value;632 break;633 case VIRTGPU_CONTEXT_PARAM_NUM_RINGS:634 if (vfpriv->base_fence_ctx) {635 ret = -EINVAL;636 goto out_unlock;637 }638 639 if (value > MAX_RINGS) {640 ret = -EINVAL;641 goto out_unlock;642 }643 644 vfpriv->base_fence_ctx = dma_fence_context_alloc(value);645 vfpriv->num_rings = value;646 break;647 case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK:648 if (vfpriv->ring_idx_mask) {649 ret = -EINVAL;650 goto out_unlock;651 }652 653 vfpriv->ring_idx_mask = value;654 break;655 case VIRTGPU_CONTEXT_PARAM_DEBUG_NAME:656 if (vfpriv->explicit_debug_name) {657 ret = -EINVAL;658 goto out_unlock;659 }660 661 ret = strncpy_from_user(vfpriv->debug_name,662 u64_to_user_ptr(value),663 DEBUG_NAME_MAX_LEN - 1);664 if (ret < 0)665 goto out_unlock;666 667 vfpriv->explicit_debug_name = true;668 ret = 0;669 break;670 default:671 ret = -EINVAL;672 goto out_unlock;673 }674 }675 676 if (vfpriv->ring_idx_mask) {677 valid_ring_mask = 0;678 for (i = 0; i < vfpriv->num_rings; i++)679 valid_ring_mask |= 1ULL << i;680 681 if (~valid_ring_mask & vfpriv->ring_idx_mask) {682 ret = -EINVAL;683 goto out_unlock;684 }685 }686 687 virtio_gpu_create_context_locked(vgdev, vfpriv);688 virtio_gpu_notify(vgdev);689 690out_unlock:691 mutex_unlock(&vfpriv->context_lock);692 kfree(ctx_set_params);693 return ret;694}695 696struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {697 DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,698 DRM_RENDER_ALLOW),699 700 DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,701 DRM_RENDER_ALLOW),702 703 DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,704 DRM_RENDER_ALLOW),705 706 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,707 virtio_gpu_resource_create_ioctl,708 DRM_RENDER_ALLOW),709 710 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,711 DRM_RENDER_ALLOW),712 713 /* make transfer async to the main ring? - no sure, can we714 * thread these in the underlying GL715 */716 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,717 virtio_gpu_transfer_from_host_ioctl,718 DRM_RENDER_ALLOW),719 DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,720 virtio_gpu_transfer_to_host_ioctl,721 DRM_RENDER_ALLOW),722 723 DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,724 DRM_RENDER_ALLOW),725 726 DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,727 DRM_RENDER_ALLOW),728 729 DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB,730 virtio_gpu_resource_create_blob_ioctl,731 DRM_RENDER_ALLOW),732 733 DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl,734 DRM_RENDER_ALLOW),735};736