mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	drm/virtio: implement context init: support init ioctl
This implements the context initialization ioctl. A list of params is passed in by userspace, and kernel driver validates them. The only currently supported param is VIRTGPU_CONTEXT_PARAM_CAPSET_ID. If the context has already been initialized, -EEXIST is returned. This happens after Linux userspace does dumb_create + followed by opening the Mesa virgl driver with the same virtgpu instance. However, for most applications, 3D contexts will be explicitly initialized when the feature is available. Signed-off-by: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> Acked-by: Lingfeng Yang <lfy@google.com> Link: http://patchwork.freedesktop.org/patch/msgid/20210921232024.817-6-gurchetansingh@chromium.org Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
		
							parent
							
								
									6198770a1f
								
							
						
					
					
						commit
						4fb530e5ca
					
				
					 3 changed files with 98 additions and 8 deletions
				
			
		| 
						 | 
					@ -259,12 +259,13 @@ struct virtio_gpu_device {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct virtio_gpu_fpriv {
 | 
					struct virtio_gpu_fpriv {
 | 
				
			||||||
	uint32_t ctx_id;
 | 
						uint32_t ctx_id;
 | 
				
			||||||
 | 
						uint32_t context_init;
 | 
				
			||||||
	bool context_created;
 | 
						bool context_created;
 | 
				
			||||||
	struct mutex context_lock;
 | 
						struct mutex context_lock;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* virtgpu_ioctl.c */
 | 
					/* virtgpu_ioctl.c */
 | 
				
			||||||
#define DRM_VIRTIO_NUM_IOCTLS 11
 | 
					#define DRM_VIRTIO_NUM_IOCTLS 12
 | 
				
			||||||
extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 | 
					extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 | 
				
			||||||
void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file);
 | 
					void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -342,7 +343,8 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
 | 
				
			||||||
			      struct virtio_gpu_drv_cap_cache **cache_p);
 | 
								      struct virtio_gpu_drv_cap_cache **cache_p);
 | 
				
			||||||
int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev);
 | 
					int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev);
 | 
				
			||||||
void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
 | 
					void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
 | 
				
			||||||
				   uint32_t nlen, const char *name);
 | 
									   uint32_t context_init, uint32_t nlen,
 | 
				
			||||||
 | 
									   const char *name);
 | 
				
			||||||
void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
 | 
					void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
 | 
				
			||||||
				    uint32_t id);
 | 
									    uint32_t id);
 | 
				
			||||||
void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
 | 
					void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,20 +38,30 @@
 | 
				
			||||||
				    VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
 | 
									    VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \
 | 
				
			||||||
				    VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
 | 
									    VIRTGPU_BLOB_FLAG_USE_CROSS_DEVICE)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Must be called with &virtio_gpu_fpriv.struct_mutex held. */
 | 
				
			||||||
 | 
					static void virtio_gpu_create_context_locked(struct virtio_gpu_device *vgdev,
 | 
				
			||||||
 | 
										     struct virtio_gpu_fpriv *vfpriv)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						char dbgname[TASK_COMM_LEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						get_task_comm(dbgname, current);
 | 
				
			||||||
 | 
						virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,
 | 
				
			||||||
 | 
									      vfpriv->context_init, strlen(dbgname),
 | 
				
			||||||
 | 
									      dbgname);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vfpriv->context_created = true;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)
 | 
					void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct virtio_gpu_device *vgdev = dev->dev_private;
 | 
						struct virtio_gpu_device *vgdev = dev->dev_private;
 | 
				
			||||||
	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
 | 
						struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
 | 
				
			||||||
	char dbgname[TASK_COMM_LEN];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&vfpriv->context_lock);
 | 
						mutex_lock(&vfpriv->context_lock);
 | 
				
			||||||
	if (vfpriv->context_created)
 | 
						if (vfpriv->context_created)
 | 
				
			||||||
		goto out_unlock;
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	get_task_comm(dbgname, current);
 | 
						virtio_gpu_create_context_locked(vgdev, vfpriv);
 | 
				
			||||||
	virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id,
 | 
					 | 
				
			||||||
				      strlen(dbgname), dbgname);
 | 
					 | 
				
			||||||
	vfpriv->context_created = true;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_unlock:
 | 
					out_unlock:
 | 
				
			||||||
	mutex_unlock(&vfpriv->context_lock);
 | 
						mutex_unlock(&vfpriv->context_lock);
 | 
				
			||||||
| 
						 | 
					@ -662,6 +672,79 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev,
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int virtio_gpu_context_init_ioctl(struct drm_device *dev,
 | 
				
			||||||
 | 
										 void *data, struct drm_file *file)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						int ret = 0;
 | 
				
			||||||
 | 
						uint32_t num_params, i, param, value;
 | 
				
			||||||
 | 
						size_t len;
 | 
				
			||||||
 | 
						struct drm_virtgpu_context_set_param *ctx_set_params = NULL;
 | 
				
			||||||
 | 
						struct virtio_gpu_device *vgdev = dev->dev_private;
 | 
				
			||||||
 | 
						struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
 | 
				
			||||||
 | 
						struct drm_virtgpu_context_init *args = data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						num_params = args->num_params;
 | 
				
			||||||
 | 
						len = num_params * sizeof(struct drm_virtgpu_context_set_param);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (!vgdev->has_context_init || !vgdev->has_virgl_3d)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Number of unique parameters supported at this time. */
 | 
				
			||||||
 | 
						if (num_params > 1)
 | 
				
			||||||
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ctx_set_params = memdup_user(u64_to_user_ptr(args->ctx_set_params),
 | 
				
			||||||
 | 
									     len);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (IS_ERR(ctx_set_params))
 | 
				
			||||||
 | 
							return PTR_ERR(ctx_set_params);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mutex_lock(&vfpriv->context_lock);
 | 
				
			||||||
 | 
						if (vfpriv->context_created) {
 | 
				
			||||||
 | 
							ret = -EEXIST;
 | 
				
			||||||
 | 
							goto out_unlock;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < num_params; i++) {
 | 
				
			||||||
 | 
							param = ctx_set_params[i].param;
 | 
				
			||||||
 | 
							value = ctx_set_params[i].value;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (param) {
 | 
				
			||||||
 | 
							case VIRTGPU_CONTEXT_PARAM_CAPSET_ID:
 | 
				
			||||||
 | 
								if (value > MAX_CAPSET_ID) {
 | 
				
			||||||
 | 
									ret = -EINVAL;
 | 
				
			||||||
 | 
									goto out_unlock;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if ((vgdev->capset_id_mask & (1 << value)) == 0) {
 | 
				
			||||||
 | 
									ret = -EINVAL;
 | 
				
			||||||
 | 
									goto out_unlock;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								/* Context capset ID already set */
 | 
				
			||||||
 | 
								if (vfpriv->context_init &
 | 
				
			||||||
 | 
								    VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) {
 | 
				
			||||||
 | 
									ret = -EINVAL;
 | 
				
			||||||
 | 
									goto out_unlock;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								vfpriv->context_init |= value;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								ret = -EINVAL;
 | 
				
			||||||
 | 
								goto out_unlock;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						virtio_gpu_create_context_locked(vgdev, vfpriv);
 | 
				
			||||||
 | 
						virtio_gpu_notify(vgdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					out_unlock:
 | 
				
			||||||
 | 
						mutex_unlock(&vfpriv->context_lock);
 | 
				
			||||||
 | 
						kfree(ctx_set_params);
 | 
				
			||||||
 | 
						return ret;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
 | 
					struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
 | 
				
			||||||
	DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
 | 
						DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
 | 
				
			||||||
			  DRM_RENDER_ALLOW),
 | 
								  DRM_RENDER_ALLOW),
 | 
				
			||||||
| 
						 | 
					@ -698,4 +781,7 @@ struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
 | 
				
			||||||
	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB,
 | 
						DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB,
 | 
				
			||||||
			  virtio_gpu_resource_create_blob_ioctl,
 | 
								  virtio_gpu_resource_create_blob_ioctl,
 | 
				
			||||||
			  DRM_RENDER_ALLOW),
 | 
								  DRM_RENDER_ALLOW),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl,
 | 
				
			||||||
 | 
								  DRM_RENDER_ALLOW),
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -911,7 +911,8 @@ int virtio_gpu_cmd_get_edids(struct virtio_gpu_device *vgdev)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
 | 
					void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
 | 
				
			||||||
				   uint32_t nlen, const char *name)
 | 
									   uint32_t context_init, uint32_t nlen,
 | 
				
			||||||
 | 
									   const char *name)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct virtio_gpu_ctx_create *cmd_p;
 | 
						struct virtio_gpu_ctx_create *cmd_p;
 | 
				
			||||||
	struct virtio_gpu_vbuffer *vbuf;
 | 
						struct virtio_gpu_vbuffer *vbuf;
 | 
				
			||||||
| 
						 | 
					@ -922,6 +923,7 @@ void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
 | 
				
			||||||
	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
 | 
						cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
 | 
				
			||||||
	cmd_p->hdr.ctx_id = cpu_to_le32(id);
 | 
						cmd_p->hdr.ctx_id = cpu_to_le32(id);
 | 
				
			||||||
	cmd_p->nlen = cpu_to_le32(nlen);
 | 
						cmd_p->nlen = cpu_to_le32(nlen);
 | 
				
			||||||
 | 
						cmd_p->context_init = cpu_to_le32(context_init);
 | 
				
			||||||
	strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1);
 | 
						strncpy(cmd_p->debug_name, name, sizeof(cmd_p->debug_name) - 1);
 | 
				
			||||||
	cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0;
 | 
						cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0;
 | 
				
			||||||
	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
 | 
						virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue