162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright (C) 2015 Red Hat, Inc.
362306a36Sopenharmony_ci * All Rights Reserved.
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Authors:
662306a36Sopenharmony_ci *    Dave Airlie
762306a36Sopenharmony_ci *    Alon Levy
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
1062306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
1162306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
1262306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1362306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1462306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1762306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1862306a36Sopenharmony_ci *
1962306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2062306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2162306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
2262306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2362306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2462306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2562306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2662306a36Sopenharmony_ci */
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#include <linux/file.h>
2962306a36Sopenharmony_ci#include <linux/sync_file.h>
3062306a36Sopenharmony_ci#include <linux/uaccess.h>
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci#include <drm/drm_file.h>
3362306a36Sopenharmony_ci#include <drm/virtgpu_drm.h>
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "virtgpu_drv.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#define VIRTGPU_BLOB_FLAG_USE_MASK (VIRTGPU_BLOB_FLAG_USE_MAPPABLE | \
3862306a36Sopenharmony_ci				    VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
3962306a36Sopenharmony_ci				    VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_ci/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
4262306a36Sopenharmony_cistatic void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
4362306a36Sopenharmony_ci					     struct virtio_gpu_fpriv *vfpriv)
4462306a36Sopenharmony_ci{
4562306a36Sopenharmony_ci	char dbgname[TASK_COMM_LEN];
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	get_task_comm(dbgname, current);
4862306a36Sopenharmony_ci	virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,
4962306a36Sopenharmony_ci				      vfpriv->context_init, strlen(dbgname),
5062306a36Sopenharmony_ci				      dbgname);
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci	vfpriv->context_created = true;
5362306a36Sopenharmony_ci}
5462306a36Sopenharmony_ci
5562306a36Sopenharmony_civoid virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)
5662306a36Sopenharmony_ci{
5762306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
5862306a36Sopenharmony_ci	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_ci	mutex_lock(&vfpriv->context_lock);
6162306a36Sopenharmony_ci	if (vfpriv->context_created)
6262306a36Sopenharmony_ci		goto out_unlock;
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	virtio_gpu_create_context_locked(vgdev, vfpriv);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciout_unlock:
6762306a36Sopenharmony_ci	mutex_unlock(&vfpriv->context_lock);
6862306a36Sopenharmony_ci}
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_cistatic int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
7162306a36Sopenharmony_ci				struct drm_file *file)
7262306a36Sopenharmony_ci{
7362306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
7462306a36Sopenharmony_ci	struct drm_virtgpu_map *virtio_gpu_map = data;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return virtio_gpu_mode_dumb_mmap(file, vgdev->ddev,
7762306a36Sopenharmony_ci					 virtio_gpu_map->handle,
7862306a36Sopenharmony_ci					 &virtio_gpu_map->offset);
7962306a36Sopenharmony_ci}
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
8262306a36Sopenharmony_ci				     struct drm_file *file)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
8562306a36Sopenharmony_ci	struct drm_virtgpu_getparam *param = data;
8662306a36Sopenharmony_ci	int value;
8762306a36Sopenharmony_ci
8862306a36Sopenharmony_ci	switch (param->param) {
8962306a36Sopenharmony_ci	case VIRTGPU_PARAM_3D_FEATURES:
9062306a36Sopenharmony_ci		value = vgdev->has_virgl_3d ? 1 : 0;
9162306a36Sopenharmony_ci		break;
9262306a36Sopenharmony_ci	case VIRTGPU_PARAM_CAPSET_QUERY_FIX:
9362306a36Sopenharmony_ci		value = 1;
9462306a36Sopenharmony_ci		break;
9562306a36Sopenharmony_ci	case VIRTGPU_PARAM_RESOURCE_BLOB:
9662306a36Sopenharmony_ci		value = vgdev->has_resource_blob ? 1 : 0;
9762306a36Sopenharmony_ci		break;
9862306a36Sopenharmony_ci	case VIRTGPU_PARAM_HOST_VISIBLE:
9962306a36Sopenharmony_ci		value = vgdev->has_host_visible ? 1 : 0;
10062306a36Sopenharmony_ci		break;
10162306a36Sopenharmony_ci	case VIRTGPU_PARAM_CROSS_DEVICE:
10262306a36Sopenharmony_ci		value = vgdev->has_resource_assign_uuid ? 1 : 0;
10362306a36Sopenharmony_ci		break;
10462306a36Sopenharmony_ci	case VIRTGPU_PARAM_CONTEXT_INIT:
10562306a36Sopenharmony_ci		value = vgdev->has_context_init ? 1 : 0;
10662306a36Sopenharmony_ci		break;
10762306a36Sopenharmony_ci	case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs:
10862306a36Sopenharmony_ci		value = vgdev->capset_id_mask;
10962306a36Sopenharmony_ci		break;
11062306a36Sopenharmony_ci	default:
11162306a36Sopenharmony_ci		return -EINVAL;
11262306a36Sopenharmony_ci	}
11362306a36Sopenharmony_ci	if (copy_to_user(u64_to_user_ptr(param->value), &value, sizeof(int)))
11462306a36Sopenharmony_ci		return -EFAULT;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	return 0;
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
12062306a36Sopenharmony_ci					    struct drm_file *file)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
12362306a36Sopenharmony_ci	struct drm_virtgpu_resource_create *rc = data;
12462306a36Sopenharmony_ci	struct virtio_gpu_fence *fence;
12562306a36Sopenharmony_ci	int ret;
12662306a36Sopenharmony_ci	struct virtio_gpu_object *qobj;
12762306a36Sopenharmony_ci	struct drm_gem_object *obj;
12862306a36Sopenharmony_ci	uint32_t handle = 0;
12962306a36Sopenharmony_ci	struct virtio_gpu_object_params params = { 0 };
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci	if (vgdev->has_virgl_3d) {
13262306a36Sopenharmony_ci		virtio_gpu_create_context(dev, file);
13362306a36Sopenharmony_ci		params.virgl = true;
13462306a36Sopenharmony_ci		params.target = rc->target;
13562306a36Sopenharmony_ci		params.bind = rc->bind;
13662306a36Sopenharmony_ci		params.depth = rc->depth;
13762306a36Sopenharmony_ci		params.array_size = rc->array_size;
13862306a36Sopenharmony_ci		params.last_level = rc->last_level;
13962306a36Sopenharmony_ci		params.nr_samples = rc->nr_samples;
14062306a36Sopenharmony_ci		params.flags = rc->flags;
14162306a36Sopenharmony_ci	} else {
14262306a36Sopenharmony_ci		if (rc->depth > 1)
14362306a36Sopenharmony_ci			return -EINVAL;
14462306a36Sopenharmony_ci		if (rc->nr_samples > 1)
14562306a36Sopenharmony_ci			return -EINVAL;
14662306a36Sopenharmony_ci		if (rc->last_level > 1)
14762306a36Sopenharmony_ci			return -EINVAL;
14862306a36Sopenharmony_ci		if (rc->target != 2)
14962306a36Sopenharmony_ci			return -EINVAL;
15062306a36Sopenharmony_ci		if (rc->array_size > 1)
15162306a36Sopenharmony_ci			return -EINVAL;
15262306a36Sopenharmony_ci	}
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	params.format = rc->format;
15562306a36Sopenharmony_ci	params.width = rc->width;
15662306a36Sopenharmony_ci	params.height = rc->height;
15762306a36Sopenharmony_ci	params.size = rc->size;
15862306a36Sopenharmony_ci	/* allocate a single page size object */
15962306a36Sopenharmony_ci	if (params.size == 0)
16062306a36Sopenharmony_ci		params.size = PAGE_SIZE;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci	fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0);
16362306a36Sopenharmony_ci	if (!fence)
16462306a36Sopenharmony_ci		return -ENOMEM;
16562306a36Sopenharmony_ci	ret = virtio_gpu_object_create(vgdev, &params, &qobj, fence);
16662306a36Sopenharmony_ci	dma_fence_put(&fence->f);
16762306a36Sopenharmony_ci	if (ret < 0)
16862306a36Sopenharmony_ci		return ret;
16962306a36Sopenharmony_ci	obj = &qobj->base.base;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	ret = drm_gem_handle_create(file, obj, &handle);
17262306a36Sopenharmony_ci	if (ret) {
17362306a36Sopenharmony_ci		drm_gem_object_release(obj);
17462306a36Sopenharmony_ci		return ret;
17562306a36Sopenharmony_ci	}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_ci	rc->res_handle = qobj->hw_res_handle; /* similiar to a VM address */
17862306a36Sopenharmony_ci	rc->bo_handle = handle;
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	/*
18162306a36Sopenharmony_ci	 * The handle owns the reference now.  But we must drop our
18262306a36Sopenharmony_ci	 * remaining reference *after* we no longer need to dereference
18362306a36Sopenharmony_ci	 * the obj.  Otherwise userspace could guess the handle and
18462306a36Sopenharmony_ci	 * race closing it from another thread.
18562306a36Sopenharmony_ci	 */
18662306a36Sopenharmony_ci	drm_gem_object_put(obj);
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ci	return 0;
18962306a36Sopenharmony_ci}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_cistatic int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
19262306a36Sopenharmony_ci					  struct drm_file *file)
19362306a36Sopenharmony_ci{
19462306a36Sopenharmony_ci	struct drm_virtgpu_resource_info *ri = data;
19562306a36Sopenharmony_ci	struct drm_gem_object *gobj = NULL;
19662306a36Sopenharmony_ci	struct virtio_gpu_object *qobj = NULL;
19762306a36Sopenharmony_ci
19862306a36Sopenharmony_ci	gobj = drm_gem_object_lookup(file, ri->bo_handle);
19962306a36Sopenharmony_ci	if (gobj == NULL)
20062306a36Sopenharmony_ci		return -ENOENT;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	qobj = gem_to_virtio_gpu_obj(gobj);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	ri->size = qobj->base.base.size;
20562306a36Sopenharmony_ci	ri->res_handle = qobj->hw_res_handle;
20662306a36Sopenharmony_ci	if (qobj->host3d_blob || qobj->guest_blob)
20762306a36Sopenharmony_ci		ri->blob_mem = qobj->blob_mem;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	drm_gem_object_put(gobj);
21062306a36Sopenharmony_ci	return 0;
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
21462306a36Sopenharmony_ci					       void *data,
21562306a36Sopenharmony_ci					       struct drm_file *file)
21662306a36Sopenharmony_ci{
21762306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
21862306a36Sopenharmony_ci	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
21962306a36Sopenharmony_ci	struct drm_virtgpu_3d_transfer_from_host *args = data;
22062306a36Sopenharmony_ci	struct virtio_gpu_object *bo;
22162306a36Sopenharmony_ci	struct virtio_gpu_object_array *objs;
22262306a36Sopenharmony_ci	struct virtio_gpu_fence *fence;
22362306a36Sopenharmony_ci	int ret;
22462306a36Sopenharmony_ci	u32 offset = args->offset;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci	if (vgdev->has_virgl_3d == false)
22762306a36Sopenharmony_ci		return -ENOSYS;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	virtio_gpu_create_context(dev, file);
23062306a36Sopenharmony_ci	objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
23162306a36Sopenharmony_ci	if (objs == NULL)
23262306a36Sopenharmony_ci		return -ENOENT;
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci	bo = gem_to_virtio_gpu_obj(objs->objs[0]);
23562306a36Sopenharmony_ci	if (bo->guest_blob && !bo->host3d_blob) {
23662306a36Sopenharmony_ci		ret = -EINVAL;
23762306a36Sopenharmony_ci		goto err_put_free;
23862306a36Sopenharmony_ci	}
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci	if (!bo->host3d_blob && (args->stride || args->layer_stride)) {
24162306a36Sopenharmony_ci		ret = -EINVAL;
24262306a36Sopenharmony_ci		goto err_put_free;
24362306a36Sopenharmony_ci	}
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci	ret = virtio_gpu_array_lock_resv(objs);
24662306a36Sopenharmony_ci	if (ret != 0)
24762306a36Sopenharmony_ci		goto err_put_free;
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context, 0);
25062306a36Sopenharmony_ci	if (!fence) {
25162306a36Sopenharmony_ci		ret = -ENOMEM;
25262306a36Sopenharmony_ci		goto err_unlock;
25362306a36Sopenharmony_ci	}
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	virtio_gpu_cmd_transfer_from_host_3d
25662306a36Sopenharmony_ci		(vgdev, vfpriv->ctx_id, offset, args->level, args->stride,
25762306a36Sopenharmony_ci		 args->layer_stride, &args->box, objs, fence);
25862306a36Sopenharmony_ci	dma_fence_put(&fence->f);
25962306a36Sopenharmony_ci	virtio_gpu_notify(vgdev);
26062306a36Sopenharmony_ci	return 0;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_cierr_unlock:
26362306a36Sopenharmony_ci	virtio_gpu_array_unlock_resv(objs);
26462306a36Sopenharmony_cierr_put_free:
26562306a36Sopenharmony_ci	virtio_gpu_array_put_free(objs);
26662306a36Sopenharmony_ci	return ret;
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
27062306a36Sopenharmony_ci					     struct drm_file *file)
27162306a36Sopenharmony_ci{
27262306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
27362306a36Sopenharmony_ci	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
27462306a36Sopenharmony_ci	struct drm_virtgpu_3d_transfer_to_host *args = data;
27562306a36Sopenharmony_ci	struct virtio_gpu_object *bo;
27662306a36Sopenharmony_ci	struct virtio_gpu_object_array *objs;
27762306a36Sopenharmony_ci	struct virtio_gpu_fence *fence;
27862306a36Sopenharmony_ci	int ret;
27962306a36Sopenharmony_ci	u32 offset = args->offset;
28062306a36Sopenharmony_ci
28162306a36Sopenharmony_ci	objs = virtio_gpu_array_from_handles(file, &args->bo_handle, 1);
28262306a36Sopenharmony_ci	if (objs == NULL)
28362306a36Sopenharmony_ci		return -ENOENT;
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	bo = gem_to_virtio_gpu_obj(objs->objs[0]);
28662306a36Sopenharmony_ci	if (bo->guest_blob && !bo->host3d_blob) {
28762306a36Sopenharmony_ci		ret = -EINVAL;
28862306a36Sopenharmony_ci		goto err_put_free;
28962306a36Sopenharmony_ci	}
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	if (!vgdev->has_virgl_3d) {
29262306a36Sopenharmony_ci		virtio_gpu_cmd_transfer_to_host_2d
29362306a36Sopenharmony_ci			(vgdev, offset,
29462306a36Sopenharmony_ci			 args->box.w, args->box.h, args->box.x, args->box.y,
29562306a36Sopenharmony_ci			 objs, NULL);
29662306a36Sopenharmony_ci	} else {
29762306a36Sopenharmony_ci		virtio_gpu_create_context(dev, file);
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_ci		if (!bo->host3d_blob && (args->stride || args->layer_stride)) {
30062306a36Sopenharmony_ci			ret = -EINVAL;
30162306a36Sopenharmony_ci			goto err_put_free;
30262306a36Sopenharmony_ci		}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci		ret = virtio_gpu_array_lock_resv(objs);
30562306a36Sopenharmony_ci		if (ret != 0)
30662306a36Sopenharmony_ci			goto err_put_free;
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		ret = -ENOMEM;
30962306a36Sopenharmony_ci		fence = virtio_gpu_fence_alloc(vgdev, vgdev->fence_drv.context,
31062306a36Sopenharmony_ci					       0);
31162306a36Sopenharmony_ci		if (!fence)
31262306a36Sopenharmony_ci			goto err_unlock;
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		virtio_gpu_cmd_transfer_to_host_3d
31562306a36Sopenharmony_ci			(vgdev,
31662306a36Sopenharmony_ci			 vfpriv ? vfpriv->ctx_id : 0, offset, args->level,
31762306a36Sopenharmony_ci			 args->stride, args->layer_stride, &args->box, objs,
31862306a36Sopenharmony_ci			 fence);
31962306a36Sopenharmony_ci		dma_fence_put(&fence->f);
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci	virtio_gpu_notify(vgdev);
32262306a36Sopenharmony_ci	return 0;
32362306a36Sopenharmony_ci
32462306a36Sopenharmony_cierr_unlock:
32562306a36Sopenharmony_ci	virtio_gpu_array_unlock_resv(objs);
32662306a36Sopenharmony_cierr_put_free:
32762306a36Sopenharmony_ci	virtio_gpu_array_put_free(objs);
32862306a36Sopenharmony_ci	return ret;
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistatic int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,
33262306a36Sopenharmony_ci				 struct drm_file *file)
33362306a36Sopenharmony_ci{
33462306a36Sopenharmony_ci	struct drm_virtgpu_3d_wait *args = data;
33562306a36Sopenharmony_ci	struct drm_gem_object *obj;
33662306a36Sopenharmony_ci	long timeout = 15 * HZ;
33762306a36Sopenharmony_ci	int ret;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	obj = drm_gem_object_lookup(file, args->handle);
34062306a36Sopenharmony_ci	if (obj == NULL)
34162306a36Sopenharmony_ci		return -ENOENT;
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_ci	if (args->flags & VIRTGPU_WAIT_NOWAIT) {
34462306a36Sopenharmony_ci		ret = dma_resv_test_signaled(obj->resv, DMA_RESV_USAGE_READ);
34562306a36Sopenharmony_ci	} else {
34662306a36Sopenharmony_ci		ret = dma_resv_wait_timeout(obj->resv, DMA_RESV_USAGE_READ,
34762306a36Sopenharmony_ci					    true, timeout);
34862306a36Sopenharmony_ci	}
34962306a36Sopenharmony_ci	if (ret == 0)
35062306a36Sopenharmony_ci		ret = -EBUSY;
35162306a36Sopenharmony_ci	else if (ret > 0)
35262306a36Sopenharmony_ci		ret = 0;
35362306a36Sopenharmony_ci
35462306a36Sopenharmony_ci	drm_gem_object_put(obj);
35562306a36Sopenharmony_ci	return ret;
35662306a36Sopenharmony_ci}
35762306a36Sopenharmony_ci
35862306a36Sopenharmony_cistatic int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
35962306a36Sopenharmony_ci				void *data, struct drm_file *file)
36062306a36Sopenharmony_ci{
36162306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
36262306a36Sopenharmony_ci	struct drm_virtgpu_get_caps *args = data;
36362306a36Sopenharmony_ci	unsigned size, host_caps_size;
36462306a36Sopenharmony_ci	int i;
36562306a36Sopenharmony_ci	int found_valid = -1;
36662306a36Sopenharmony_ci	int ret;
36762306a36Sopenharmony_ci	struct virtio_gpu_drv_cap_cache *cache_ent;
36862306a36Sopenharmony_ci	void *ptr;
36962306a36Sopenharmony_ci
37062306a36Sopenharmony_ci	if (vgdev->num_capsets == 0)
37162306a36Sopenharmony_ci		return -ENOSYS;
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci	/* don't allow userspace to pass 0 */
37462306a36Sopenharmony_ci	if (args->size == 0)
37562306a36Sopenharmony_ci		return -EINVAL;
37662306a36Sopenharmony_ci
37762306a36Sopenharmony_ci	spin_lock(&vgdev->display_info_lock);
37862306a36Sopenharmony_ci	for (i = 0; i < vgdev->num_capsets; i++) {
37962306a36Sopenharmony_ci		if (vgdev->capsets[i].id == args->cap_set_id) {
38062306a36Sopenharmony_ci			if (vgdev->capsets[i].max_version >= args->cap_set_ver) {
38162306a36Sopenharmony_ci				found_valid = i;
38262306a36Sopenharmony_ci				break;
38362306a36Sopenharmony_ci			}
38462306a36Sopenharmony_ci		}
38562306a36Sopenharmony_ci	}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	if (found_valid == -1) {
38862306a36Sopenharmony_ci		spin_unlock(&vgdev->display_info_lock);
38962306a36Sopenharmony_ci		return -EINVAL;
39062306a36Sopenharmony_ci	}
39162306a36Sopenharmony_ci
39262306a36Sopenharmony_ci	host_caps_size = vgdev->capsets[found_valid].max_size;
39362306a36Sopenharmony_ci	/* only copy to user the minimum of the host caps size or the guest caps size */
39462306a36Sopenharmony_ci	size = min(args->size, host_caps_size);
39562306a36Sopenharmony_ci
39662306a36Sopenharmony_ci	list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
39762306a36Sopenharmony_ci		if (cache_ent->id == args->cap_set_id &&
39862306a36Sopenharmony_ci		    cache_ent->version == args->cap_set_ver) {
39962306a36Sopenharmony_ci			spin_unlock(&vgdev->display_info_lock);
40062306a36Sopenharmony_ci			goto copy_exit;
40162306a36Sopenharmony_ci		}
40262306a36Sopenharmony_ci	}
40362306a36Sopenharmony_ci	spin_unlock(&vgdev->display_info_lock);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	/* not in cache - need to talk to hw */
40662306a36Sopenharmony_ci	ret = virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,
40762306a36Sopenharmony_ci					&cache_ent);
40862306a36Sopenharmony_ci	if (ret)
40962306a36Sopenharmony_ci		return ret;
41062306a36Sopenharmony_ci	virtio_gpu_notify(vgdev);
41162306a36Sopenharmony_ci
41262306a36Sopenharmony_cicopy_exit:
41362306a36Sopenharmony_ci	ret = wait_event_timeout(vgdev->resp_wq,
41462306a36Sopenharmony_ci				 atomic_read(&cache_ent->is_valid), 5 * HZ);
41562306a36Sopenharmony_ci	if (!ret)
41662306a36Sopenharmony_ci		return -EBUSY;
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	/* is_valid check must proceed before copy of the cache entry. */
41962306a36Sopenharmony_ci	smp_rmb();
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci	ptr = cache_ent->caps_cache;
42262306a36Sopenharmony_ci
42362306a36Sopenharmony_ci	if (copy_to_user(u64_to_user_ptr(args->addr), ptr, size))
42462306a36Sopenharmony_ci		return -EFAULT;
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	return 0;
42762306a36Sopenharmony_ci}
42862306a36Sopenharmony_ci
42962306a36Sopenharmony_cistatic int verify_blob(struct virtio_gpu_device *vgdev,
43062306a36Sopenharmony_ci		       struct virtio_gpu_fpriv *vfpriv,
43162306a36Sopenharmony_ci		       struct virtio_gpu_object_params *params,
43262306a36Sopenharmony_ci		       struct drm_virtgpu_resource_create_blob *rc_blob,
43362306a36Sopenharmony_ci		       bool *guest_blob, bool *host3d_blob)
43462306a36Sopenharmony_ci{
43562306a36Sopenharmony_ci	if (!vgdev->has_resource_blob)
43662306a36Sopenharmony_ci		return -EINVAL;
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_ci	if (rc_blob->blob_flags & ~VIRTGPU_BLOB_FLAG_USE_MASK)
43962306a36Sopenharmony_ci		return -EINVAL;
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_ci	if (rc_blob->blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
44262306a36Sopenharmony_ci		if (!vgdev->has_resource_assign_uuid)
44362306a36Sopenharmony_ci			return -EINVAL;
44462306a36Sopenharmony_ci	}
44562306a36Sopenharmony_ci
44662306a36Sopenharmony_ci	switch (rc_blob->blob_mem) {
44762306a36Sopenharmony_ci	case VIRTGPU_BLOB_MEM_GUEST:
44862306a36Sopenharmony_ci		*guest_blob = true;
44962306a36Sopenharmony_ci		break;
45062306a36Sopenharmony_ci	case VIRTGPU_BLOB_MEM_HOST3D_GUEST:
45162306a36Sopenharmony_ci		*guest_blob = true;
45262306a36Sopenharmony_ci		fallthrough;
45362306a36Sopenharmony_ci	case VIRTGPU_BLOB_MEM_HOST3D:
45462306a36Sopenharmony_ci		*host3d_blob = true;
45562306a36Sopenharmony_ci		break;
45662306a36Sopenharmony_ci	default:
45762306a36Sopenharmony_ci		return -EINVAL;
45862306a36Sopenharmony_ci	}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	if (*host3d_blob) {
46162306a36Sopenharmony_ci		if (!vgdev->has_virgl_3d)
46262306a36Sopenharmony_ci			return -EINVAL;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci		/* Must be dword aligned. */
46562306a36Sopenharmony_ci		if (rc_blob->cmd_size % 4 != 0)
46662306a36Sopenharmony_ci			return -EINVAL;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci		params->ctx_id = vfpriv->ctx_id;
46962306a36Sopenharmony_ci		params->blob_id = rc_blob->blob_id;
47062306a36Sopenharmony_ci	} else {
47162306a36Sopenharmony_ci		if (rc_blob->blob_id != 0)
47262306a36Sopenharmony_ci			return -EINVAL;
47362306a36Sopenharmony_ci
47462306a36Sopenharmony_ci		if (rc_blob->cmd_size != 0)
47562306a36Sopenharmony_ci			return -EINVAL;
47662306a36Sopenharmony_ci	}
47762306a36Sopenharmony_ci
47862306a36Sopenharmony_ci	params->blob_mem = rc_blob->blob_mem;
47962306a36Sopenharmony_ci	params->size = rc_blob->size;
48062306a36Sopenharmony_ci	params->blob = true;
48162306a36Sopenharmony_ci	params->blob_flags = rc_blob->blob_flags;
48262306a36Sopenharmony_ci	return 0;
48362306a36Sopenharmony_ci}
48462306a36Sopenharmony_ci
48562306a36Sopenharmony_cistatic int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
48662306a36Sopenharmony_ci						 void *data,
48762306a36Sopenharmony_ci						 struct drm_file *file)
48862306a36Sopenharmony_ci{
48962306a36Sopenharmony_ci	int ret = 0;
49062306a36Sopenharmony_ci	uint32_t handle = 0;
49162306a36Sopenharmony_ci	bool guest_blob = false;
49262306a36Sopenharmony_ci	bool host3d_blob = false;
49362306a36Sopenharmony_ci	struct drm_gem_object *obj;
49462306a36Sopenharmony_ci	struct virtio_gpu_object *bo;
49562306a36Sopenharmony_ci	struct virtio_gpu_object_params params = { 0 };
49662306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
49762306a36Sopenharmony_ci	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
49862306a36Sopenharmony_ci	struct drm_virtgpu_resource_create_blob *rc_blob = data;
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	if (verify_blob(vgdev, vfpriv, &params, rc_blob,
50162306a36Sopenharmony_ci			&guest_blob, &host3d_blob))
50262306a36Sopenharmony_ci		return -EINVAL;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	if (vgdev->has_virgl_3d)
50562306a36Sopenharmony_ci		virtio_gpu_create_context(dev, file);
50662306a36Sopenharmony_ci
50762306a36Sopenharmony_ci	if (rc_blob->cmd_size) {
50862306a36Sopenharmony_ci		void *buf;
50962306a36Sopenharmony_ci
51062306a36Sopenharmony_ci		buf = memdup_user(u64_to_user_ptr(rc_blob->cmd),
51162306a36Sopenharmony_ci				  rc_blob->cmd_size);
51262306a36Sopenharmony_ci
51362306a36Sopenharmony_ci		if (IS_ERR(buf))
51462306a36Sopenharmony_ci			return PTR_ERR(buf);
51562306a36Sopenharmony_ci
51662306a36Sopenharmony_ci		virtio_gpu_cmd_submit(vgdev, buf, rc_blob->cmd_size,
51762306a36Sopenharmony_ci				      vfpriv->ctx_id, NULL, NULL);
51862306a36Sopenharmony_ci	}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	if (guest_blob)
52162306a36Sopenharmony_ci		ret = virtio_gpu_object_create(vgdev, &params, &bo, NULL);
52262306a36Sopenharmony_ci	else if (!guest_blob && host3d_blob)
52362306a36Sopenharmony_ci		ret = virtio_gpu_vram_create(vgdev, &params, &bo);
52462306a36Sopenharmony_ci	else
52562306a36Sopenharmony_ci		return -EINVAL;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci	if (ret < 0)
52862306a36Sopenharmony_ci		return ret;
52962306a36Sopenharmony_ci
53062306a36Sopenharmony_ci	bo->guest_blob = guest_blob;
53162306a36Sopenharmony_ci	bo->host3d_blob = host3d_blob;
53262306a36Sopenharmony_ci	bo->blob_mem = rc_blob->blob_mem;
53362306a36Sopenharmony_ci	bo->blob_flags = rc_blob->blob_flags;
53462306a36Sopenharmony_ci
53562306a36Sopenharmony_ci	obj = &bo->base.base;
53662306a36Sopenharmony_ci	if (params.blob_flags & VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE) {
53762306a36Sopenharmony_ci		ret = virtio_gpu_resource_assign_uuid(vgdev, bo);
53862306a36Sopenharmony_ci		if (ret) {
53962306a36Sopenharmony_ci			drm_gem_object_release(obj);
54062306a36Sopenharmony_ci			return ret;
54162306a36Sopenharmony_ci		}
54262306a36Sopenharmony_ci	}
54362306a36Sopenharmony_ci
54462306a36Sopenharmony_ci	ret = drm_gem_handle_create(file, obj, &handle);
54562306a36Sopenharmony_ci	if (ret) {
54662306a36Sopenharmony_ci		drm_gem_object_release(obj);
54762306a36Sopenharmony_ci		return ret;
54862306a36Sopenharmony_ci	}
54962306a36Sopenharmony_ci
55062306a36Sopenharmony_ci	rc_blob->res_handle = bo->hw_res_handle;
55162306a36Sopenharmony_ci	rc_blob->bo_handle = handle;
55262306a36Sopenharmony_ci
55362306a36Sopenharmony_ci	/*
55462306a36Sopenharmony_ci	 * The handle owns the reference now.  But we must drop our
55562306a36Sopenharmony_ci	 * remaining reference *after* we no longer need to dereference
55662306a36Sopenharmony_ci	 * the obj.  Otherwise userspace could guess the handle and
55762306a36Sopenharmony_ci	 * race closing it from another thread.
55862306a36Sopenharmony_ci	 */
55962306a36Sopenharmony_ci	drm_gem_object_put(obj);
56062306a36Sopenharmony_ci
56162306a36Sopenharmony_ci	return 0;
56262306a36Sopenharmony_ci}
56362306a36Sopenharmony_ci
56462306a36Sopenharmony_cistatic int virtio_gpu_context_init_ioctl(struct drm_device *dev,
56562306a36Sopenharmony_ci					 void *data, struct drm_file *file)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	int ret = 0;
56862306a36Sopenharmony_ci	uint32_t num_params, i, param, value;
56962306a36Sopenharmony_ci	uint64_t valid_ring_mask;
57062306a36Sopenharmony_ci	size_t len;
57162306a36Sopenharmony_ci	struct drm_virtgpu_context_set_param *ctx_set_params = NULL;
57262306a36Sopenharmony_ci	struct virtio_gpu_device *vgdev = dev->dev_private;
57362306a36Sopenharmony_ci	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
57462306a36Sopenharmony_ci	struct drm_virtgpu_context_init *args = data;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	num_params = args->num_params;
57762306a36Sopenharmony_ci	len = num_params * sizeof(struct drm_virtgpu_context_set_param);
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	if (!vgdev->has_context_init || !vgdev->has_virgl_3d)
58062306a36Sopenharmony_ci		return -EINVAL;
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	/* Number of unique parameters supported at this time. */
58362306a36Sopenharmony_ci	if (num_params > 3)
58462306a36Sopenharmony_ci		return -EINVAL;
58562306a36Sopenharmony_ci
58662306a36Sopenharmony_ci	ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params),
58762306a36Sopenharmony_ci				     len);
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci	if (IS_ERR(ctx_set_params))
59062306a36Sopenharmony_ci		return PTR_ERR(ctx_set_params);
59162306a36Sopenharmony_ci
59262306a36Sopenharmony_ci	mutex_lock(&vfpriv->context_lock);
59362306a36Sopenharmony_ci	if (vfpriv->context_created) {
59462306a36Sopenharmony_ci		ret = -EEXIST;
59562306a36Sopenharmony_ci		goto out_unlock;
59662306a36Sopenharmony_ci	}
59762306a36Sopenharmony_ci
59862306a36Sopenharmony_ci	for (i = 0; i < num_params; i++) {
59962306a36Sopenharmony_ci		param = ctx_set_params[i].param;
60062306a36Sopenharmony_ci		value = ctx_set_params[i].value;
60162306a36Sopenharmony_ci
60262306a36Sopenharmony_ci		switch (param) {
60362306a36Sopenharmony_ci		case VIRTGPU_CONTEXT_PARAM_CAPSET_ID:
60462306a36Sopenharmony_ci			if (value > MAX_CAPSET_ID) {
60562306a36Sopenharmony_ci				ret = -EINVAL;
60662306a36Sopenharmony_ci				goto out_unlock;
60762306a36Sopenharmony_ci			}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci			if ((vgdev->capset_id_mask & (1ULL << value)) == 0) {
61062306a36Sopenharmony_ci				ret = -EINVAL;
61162306a36Sopenharmony_ci				goto out_unlock;
61262306a36Sopenharmony_ci			}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci			/* Context capset ID already set */
61562306a36Sopenharmony_ci			if (vfpriv->context_init &
61662306a36Sopenharmony_ci			    VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) {
61762306a36Sopenharmony_ci				ret = -EINVAL;
61862306a36Sopenharmony_ci				goto out_unlock;
61962306a36Sopenharmony_ci			}
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci			vfpriv->context_init |= value;
62262306a36Sopenharmony_ci			break;
62362306a36Sopenharmony_ci		case VIRTGPU_CONTEXT_PARAM_NUM_RINGS:
62462306a36Sopenharmony_ci			if (vfpriv->base_fence_ctx) {
62562306a36Sopenharmony_ci				ret = -EINVAL;
62662306a36Sopenharmony_ci				goto out_unlock;
62762306a36Sopenharmony_ci			}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci			if (value > MAX_RINGS) {
63062306a36Sopenharmony_ci				ret = -EINVAL;
63162306a36Sopenharmony_ci				goto out_unlock;
63262306a36Sopenharmony_ci			}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci			vfpriv->base_fence_ctx = dma_fence_context_alloc(value);
63562306a36Sopenharmony_ci			vfpriv->num_rings = value;
63662306a36Sopenharmony_ci			break;
63762306a36Sopenharmony_ci		case VIRTGPU_CONTEXT_PARAM_POLL_RINGS_MASK:
63862306a36Sopenharmony_ci			if (vfpriv->ring_idx_mask) {
63962306a36Sopenharmony_ci				ret = -EINVAL;
64062306a36Sopenharmony_ci				goto out_unlock;
64162306a36Sopenharmony_ci			}
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci			vfpriv->ring_idx_mask = value;
64462306a36Sopenharmony_ci			break;
64562306a36Sopenharmony_ci		default:
64662306a36Sopenharmony_ci			ret = -EINVAL;
64762306a36Sopenharmony_ci			goto out_unlock;
64862306a36Sopenharmony_ci		}
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	if (vfpriv->ring_idx_mask) {
65262306a36Sopenharmony_ci		valid_ring_mask = 0;
65362306a36Sopenharmony_ci		for (i = 0; i < vfpriv->num_rings; i++)
65462306a36Sopenharmony_ci			valid_ring_mask |= 1ULL << i;
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci		if (~valid_ring_mask & vfpriv->ring_idx_mask) {
65762306a36Sopenharmony_ci			ret = -EINVAL;
65862306a36Sopenharmony_ci			goto out_unlock;
65962306a36Sopenharmony_ci		}
66062306a36Sopenharmony_ci	}
66162306a36Sopenharmony_ci
66262306a36Sopenharmony_ci	virtio_gpu_create_context_locked(vgdev, vfpriv);
66362306a36Sopenharmony_ci	virtio_gpu_notify(vgdev);
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ciout_unlock:
66662306a36Sopenharmony_ci	mutex_unlock(&vfpriv->context_lock);
66762306a36Sopenharmony_ci	kfree(ctx_set_params);
66862306a36Sopenharmony_ci	return ret;
66962306a36Sopenharmony_ci}
67062306a36Sopenharmony_ci
67162306a36Sopenharmony_cistruct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
67262306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
67362306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
67462306a36Sopenharmony_ci
67562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
67662306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
67762306a36Sopenharmony_ci
67862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
67962306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
68262306a36Sopenharmony_ci			  virtio_gpu_resource_create_ioctl,
68362306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
68662306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
68762306a36Sopenharmony_ci
68862306a36Sopenharmony_ci	/* make transfer async to the main ring? - no sure, can we
68962306a36Sopenharmony_ci	 * thread these in the underlying GL
69062306a36Sopenharmony_ci	 */
69162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
69262306a36Sopenharmony_ci			  virtio_gpu_transfer_from_host_ioctl,
69362306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
69462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
69562306a36Sopenharmony_ci			  virtio_gpu_transfer_to_host_ioctl,
69662306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
69762306a36Sopenharmony_ci
69862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
69962306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
70062306a36Sopenharmony_ci
70162306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
70262306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB,
70562306a36Sopenharmony_ci			  virtio_gpu_resource_create_blob_ioctl,
70662306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl,
70962306a36Sopenharmony_ci			  DRM_RENDER_ALLOW),
71062306a36Sopenharmony_ci};
711