drm/msm: add sudo flag to submit ioctl
authorRob Clark <robdclark@gmail.com>
Wed, 13 Dec 2017 20:12:57 +0000 (15:12 -0500)
committerRob Clark <robdclark@gmail.com>
Tue, 20 Feb 2018 15:41:20 +0000 (10:41 -0500)
This flags cause cmdstream to be executed from the ringbuffer (RB)
instead of IB1.  Normally not something you'd ever want to do, but
it is super useful for firmware debugging.

Hidden behind CAP_SYS_RAWIO and a default=n kconfig option which
depends on EXPERT (and has a suitably scary warning), to prevent
it from being used on accident.

Signed-off-by: Rob Clark <robdclark@gmail.com>
drivers/gpu/drm/msm/Kconfig
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
drivers/gpu/drm/msm/msm_gem.h
drivers/gpu/drm/msm/msm_gem_submit.c
include/uapi/drm/msm_drm.h

index 99d39b2aefa675941d42c86b3c9b5a4d2cda937b..3065cb290aa8e56b3383030a274aa89af79290ec 100644 (file)
@@ -28,6 +28,19 @@ config DRM_MSM_REGISTER_LOGGING
          that can be parsed by envytools demsm tool.  If enabled, register
          logging can be switched on via msm.reglog=y module param.
 
+config DRM_MSM_GPU_SUDO
+       bool "Enable SUDO flag on submits"
+       depends on DRM_MSM && EXPERT
+       default n
+       help
+         Enable userspace that has CAP_SYS_RAWIO to submit GPU commands
+         that are run from RB instead of IB1.  This essentially gives
+         userspace kernel level access, but is useful for firmware
+         debugging.
+
+         Only use this if you are a driver developer.  This should *not*
+         be enabled for production kernels.  If unsure, say N.
+
 config DRM_MSM_HDMI_HDCP
        bool "Enable HDMI HDCP support in MSM DRM driver"
        depends on DRM_MSM && QCOM_SCM
index 579c28c8c9940b030d72aca4485d659d54123db3..fa08b4897a5602d5f07642e169348a10a4b8ded2 100644 (file)
@@ -140,6 +140,65 @@ static void a5xx_flush(struct msm_gpu *gpu, struct msm_ringbuffer *ring)
                gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr);
 }
 
+static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit,
+       struct msm_file_private *ctx)
+{
+       struct msm_drm_private *priv = gpu->dev->dev_private;
+       struct msm_ringbuffer *ring = submit->ring;
+       struct msm_gem_object *obj;
+       uint32_t *ptr, dwords;
+       unsigned int i;
+
+       for (i = 0; i < submit->nr_cmds; i++) {
+               switch (submit->cmd[i].type) {
+               case MSM_SUBMIT_CMD_IB_TARGET_BUF:
+                       break;
+               case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
+                       if (priv->lastctx == ctx)
+                               break;
+               case MSM_SUBMIT_CMD_BUF:
+                       /* copy commands into RB: */
+                       obj = submit->bos[submit->cmd[i].idx].obj;
+                       dwords = submit->cmd[i].size;
+
+                       ptr = msm_gem_get_vaddr(&obj->base);
+
+                       /* _get_vaddr() shouldn't fail at this point,
+                        * since we've already mapped it once in
+                        * submit_reloc()
+                        */
+                       if (WARN_ON(!ptr))
+                               return;
+
+                       for (i = 0; i < dwords; i++) {
+                               /* normally the OUT_PKTn() would wait
+                                * for space for the packet.  But since
+                                * we just OUT_RING() the whole thing,
+                                * need to call adreno_wait_ring()
+                                * ourself:
+                                */
+                               adreno_wait_ring(ring, 1);
+                               OUT_RING(ring, ptr[i]);
+                       }
+
+                       msm_gem_put_vaddr(&obj->base);
+
+                       break;
+               }
+       }
+
+       a5xx_flush(gpu, ring);
+       a5xx_preempt_trigger(gpu);
+
+       /* we might not necessarily have a cmd from userspace to
+        * trigger an event to know that submit has completed, so
+        * do this manually:
+        */
+       a5xx_idle(gpu, ring);
+       ring->memptrs->fence = submit->seqno;
+       msm_gpu_retire(gpu);
+}
+
 static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
        struct msm_file_private *ctx)
 {
@@ -149,6 +208,12 @@ static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
        struct msm_ringbuffer *ring = submit->ring;
        unsigned int i, ibs = 0;
 
+       if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
+               priv->lastctx = NULL;
+               a5xx_submit_in_rb(gpu, submit, ctx);
+               return;
+       }
+
        OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1);
        OUT_RING(ring, 0x02);
 
index 9320e184b48d762aa56ad274cd6911b71b91098e..c5d9bd3e47a8d20100f4c29da961aba368fb8752 100644 (file)
@@ -146,6 +146,7 @@ struct msm_gem_submit {
        struct msm_gpu_submitqueue *queue;
        struct pid *pid;    /* submitting process */
        bool valid;         /* true if no cmdstream patching needed */
+       bool in_rb;         /* "sudo" mode, copy cmds into RB */
        struct msm_ringbuffer *ring;
        unsigned int nr_cmds;
        unsigned int nr_bos;
index b8dc8f96caf221413ebfe65ff1eaf5b6a2b97b8b..7bd83e0afa971e13de295e7595ac1abd0902c2a9 100644 (file)
@@ -430,6 +430,12 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
        if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS)
                return -EINVAL;
 
+       if (args->flags & MSM_SUBMIT_SUDO) {
+               if (!IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) ||
+                   !capable(CAP_SYS_RAWIO))
+                       return -EINVAL;
+       }
+
        queue = msm_submitqueue_get(ctx, args->queueid);
        if (!queue)
                return -ENOENT;
@@ -471,6 +477,9 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
                goto out_unlock;
        }
 
+       if (args->flags & MSM_SUBMIT_SUDO)
+               submit->in_rb = true;
+
        ret = submit_lookup_objects(submit, args, file);
        if (ret)
                goto out;
index bbbaffad772d3330907425879d2d03ba2a392fdc..c06d0a5bdd808235850c2d3ac54c2eb07ef561b1 100644 (file)
@@ -201,10 +201,12 @@ struct drm_msm_gem_submit_bo {
 #define MSM_SUBMIT_NO_IMPLICIT   0x80000000 /* disable implicit sync */
 #define MSM_SUBMIT_FENCE_FD_IN   0x40000000 /* enable input fence_fd */
 #define MSM_SUBMIT_FENCE_FD_OUT  0x20000000 /* enable output fence_fd */
+#define MSM_SUBMIT_SUDO          0x10000000 /* run submitted cmds from RB */
 #define MSM_SUBMIT_FLAGS                ( \
                MSM_SUBMIT_NO_IMPLICIT   | \
                MSM_SUBMIT_FENCE_FD_IN   | \
                MSM_SUBMIT_FENCE_FD_OUT  | \
+               MSM_SUBMIT_SUDO          | \
                0)
 
 /* Each cmdstream submit consists of a table of buffers involved, and