| From b6d6ee5e2a37c8ed0a4ca24e2707fd262f6e2325 Mon Sep 17 00:00:00 2001 |
| From: Anthoine Bourgeois <anthoine.bourgeois@gmail.com> |
| Date: Fri, 27 Mar 2020 10:20:27 +0000 |
| Subject: [PATCH] CHROMIUM: 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> |
| |
| BUG=b:176158390 |
| TEST=glxgears and vkcube |
| |
| Change-Id: I869f00def1efcf3aeee93b6c660a70b2e6888e9e |
| Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/kernel/+/2645219 |
| Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org> |
| Tested-by: Chia-I Wu <olv@google.com> |
| Commit-Queue: Chia-I Wu <olv@google.com> |
| --- |
| drivers/gpu/drm/virtio/virtgpu_drv.h | 6 +- |
| drivers/gpu/drm/virtio/virtgpu_ioctl.c | 94 ++++++++++++++++++++++++-- |
| drivers/gpu/drm/virtio/virtgpu_vq.c | 4 +- |
| 3 files changed, 96 insertions(+), 8 deletions(-) |
| |
| diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h |
| index c1273465b975..1d367052dd48 100644 |
| --- a/drivers/gpu/drm/virtio/virtgpu_drv.h |
| +++ b/drivers/gpu/drm/virtio/virtgpu_drv.h |
| @@ -266,12 +266,13 @@ struct virtio_gpu_device { |
| |
| struct virtio_gpu_fpriv { |
| uint32_t ctx_id; |
| + uint32_t context_init; |
| bool context_created; |
| struct mutex context_lock; |
| }; |
| |
| /* 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]; |
| void virtio_gpu_create_context(struct drm_device *dev, struct drm_file *file); |
| |
| @@ -347,7 +348,8 @@ int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev, |
| struct virtio_gpu_drv_cap_cache **cache_p); |
| 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, |
| - 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, |
| uint32_t id); |
| void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev, |
| diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c |
| index c588461e9098..06ff916f9573 100644 |
| --- a/drivers/gpu/drm/virtio/virtgpu_ioctl.c |
| +++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c |
| @@ -38,20 +38,30 @@ |
| VIRTGPU_BLOB_FLAG_USE_SHAREABLE | \ |
| 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) |
| { |
| struct virtio_gpu_device *vgdev = dev->dev_private; |
| struct virtio_gpu_fpriv *vfpriv = file->driver_priv; |
| - char dbgname[TASK_COMM_LEN]; |
| |
| mutex_lock(&vfpriv->context_lock); |
| if (vfpriv->context_created) |
| goto out_unlock; |
| |
| - get_task_comm(dbgname, current); |
| - virtio_gpu_cmd_context_create(vgdev, vfpriv->ctx_id, |
| - strlen(dbgname), dbgname); |
| - vfpriv->context_created = true; |
| + virtio_gpu_create_context_locked(vgdev, vfpriv); |
| |
| out_unlock: |
| mutex_unlock(&vfpriv->context_lock); |
| @@ -226,6 +236,12 @@ static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data, |
| case VIRTGPU_PARAM_CROSS_DEVICE: |
| value = vgdev->has_resource_assign_uuid ? 1 : 0; |
| break; |
| + case VIRTGPU_PARAM_CONTEXT_INIT: |
| + value = vgdev->has_context_init ? 1 : 0; |
| + break; |
| + case VIRTGPU_PARAM_SUPPORTED_CAPSET_IDs: |
| + value = vgdev->capset_id_mask; |
| + break; |
| default: |
| return -EINVAL; |
| } |
| @@ -696,6 +712,71 @@ static int virtio_gpu_resource_create_blob_ioctl(struct drm_device *dev, |
| 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; |
| + 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) |
| + return -EINVAL; |
| + |
| + if ((vgdev->capset_id_mask & (1 << value)) == 0) |
| + return -EINVAL; |
| + |
| + /* Context capset ID already set */ |
| + if (vfpriv->context_init & |
| + VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK) |
| + return -EINVAL; |
| + |
| + vfpriv->context_init |= value; |
| + break; |
| + default: |
| + return -EINVAL; |
| + } |
| + } |
| + |
| + virtio_gpu_create_context_locked(vgdev, vfpriv); |
| + virtio_gpu_notify(vgdev); |
| + |
| +out_unlock: |
| + mutex_unlock(&vfpriv->context_lock); |
| + return ret; |
| +} |
| + |
| struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { |
| DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl, |
| DRM_RENDER_ALLOW), |
| @@ -733,4 +814,7 @@ struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = { |
| DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE_BLOB, |
| virtio_gpu_resource_create_blob_ioctl, |
| DRM_RENDER_ALLOW), |
| + |
| + DRM_IOCTL_DEF_DRV(VIRTGPU_CONTEXT_INIT, virtio_gpu_context_init_ioctl, |
| + DRM_RENDER_ALLOW), |
| }; |
| diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c |
| index 73e10d854040..2bc6ff810661 100644 |
| --- a/drivers/gpu/drm/virtio/virtgpu_vq.c |
| +++ b/drivers/gpu/drm/virtio/virtgpu_vq.c |
| @@ -914,7 +914,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, |
| - 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_vbuffer *vbuf; |
| @@ -925,6 +926,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.ctx_id = cpu_to_le32(id); |
| 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); |
| cmd_p->debug_name[sizeof(cmd_p->debug_name) - 1] = 0; |
| virtio_gpu_queue_ctrl_buffer(vgdev, vbuf); |
| -- |
| 2.17.1 |
| |