Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm: add sudo flag to submit ioctl

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>

+90
+13
drivers/gpu/drm/msm/Kconfig
··· 28 28 that can be parsed by envytools demsm tool. If enabled, register 29 29 logging can be switched on via msm.reglog=y module param. 30 30 31 + config DRM_MSM_GPU_SUDO 32 + bool "Enable SUDO flag on submits" 33 + depends on DRM_MSM && EXPERT 34 + default n 35 + help 36 + Enable userspace that has CAP_SYS_RAWIO to submit GPU commands 37 + that are run from RB instead of IB1. This essentially gives 38 + userspace kernel level access, but is useful for firmware 39 + debugging. 40 + 41 + Only use this if you are a driver developer. This should *not* 42 + be enabled for production kernels. If unsure, say N. 43 + 31 44 config DRM_MSM_HDMI_HDCP 32 45 bool "Enable HDMI HDCP support in MSM DRM driver" 33 46 depends on DRM_MSM && QCOM_SCM
+65
drivers/gpu/drm/msm/adreno/a5xx_gpu.c
··· 140 140 gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr); 141 141 } 142 142 143 + static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit *submit, 144 + struct msm_file_private *ctx) 145 + { 146 + struct msm_drm_private *priv = gpu->dev->dev_private; 147 + struct msm_ringbuffer *ring = submit->ring; 148 + struct msm_gem_object *obj; 149 + uint32_t *ptr, dwords; 150 + unsigned int i; 151 + 152 + for (i = 0; i < submit->nr_cmds; i++) { 153 + switch (submit->cmd[i].type) { 154 + case MSM_SUBMIT_CMD_IB_TARGET_BUF: 155 + break; 156 + case MSM_SUBMIT_CMD_CTX_RESTORE_BUF: 157 + if (priv->lastctx == ctx) 158 + break; 159 + case MSM_SUBMIT_CMD_BUF: 160 + /* copy commands into RB: */ 161 + obj = submit->bos[submit->cmd[i].idx].obj; 162 + dwords = submit->cmd[i].size; 163 + 164 + ptr = msm_gem_get_vaddr(&obj->base); 165 + 166 + /* _get_vaddr() shouldn't fail at this point, 167 + * since we've already mapped it once in 168 + * submit_reloc() 169 + */ 170 + if (WARN_ON(!ptr)) 171 + return; 172 + 173 + for (i = 0; i < dwords; i++) { 174 + /* normally the OUT_PKTn() would wait 175 + * for space for the packet. But since 176 + * we just OUT_RING() the whole thing, 177 + * need to call adreno_wait_ring() 178 + * ourself: 179 + */ 180 + adreno_wait_ring(ring, 1); 181 + OUT_RING(ring, ptr[i]); 182 + } 183 + 184 + msm_gem_put_vaddr(&obj->base); 185 + 186 + break; 187 + } 188 + } 189 + 190 + a5xx_flush(gpu, ring); 191 + a5xx_preempt_trigger(gpu); 192 + 193 + /* we might not necessarily have a cmd from userspace to 194 + * trigger an event to know that submit has completed, so 195 + * do this manually: 196 + */ 197 + a5xx_idle(gpu, ring); 198 + ring->memptrs->fence = submit->seqno; 199 + msm_gpu_retire(gpu); 200 + } 201 + 143 202 static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit, 144 203 struct msm_file_private *ctx) 145 204 { ··· 207 148 struct msm_drm_private *priv = gpu->dev->dev_private; 208 149 struct msm_ringbuffer *ring = submit->ring; 209 150 unsigned int i, ibs = 0; 151 + 152 + if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) { 153 + priv->lastctx = NULL; 154 + a5xx_submit_in_rb(gpu, submit, ctx); 155 + return; 156 + } 210 157 211 158 OUT_PKT7(ring, CP_PREEMPT_ENABLE_GLOBAL, 1); 212 159 OUT_RING(ring, 0x02);
+1
drivers/gpu/drm/msm/msm_gem.h
··· 146 146 struct msm_gpu_submitqueue *queue; 147 147 struct pid *pid; /* submitting process */ 148 148 bool valid; /* true if no cmdstream patching needed */ 149 + bool in_rb; /* "sudo" mode, copy cmds into RB */ 149 150 struct msm_ringbuffer *ring; 150 151 unsigned int nr_cmds; 151 152 unsigned int nr_bos;
+9
drivers/gpu/drm/msm/msm_gem_submit.c
··· 430 430 if (MSM_PIPE_FLAGS(args->flags) & ~MSM_SUBMIT_FLAGS) 431 431 return -EINVAL; 432 432 433 + if (args->flags & MSM_SUBMIT_SUDO) { 434 + if (!IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) || 435 + !capable(CAP_SYS_RAWIO)) 436 + return -EINVAL; 437 + } 438 + 433 439 queue = msm_submitqueue_get(ctx, args->queueid); 434 440 if (!queue) 435 441 return -ENOENT; ··· 476 470 ret = -ENOMEM; 477 471 goto out_unlock; 478 472 } 473 + 474 + if (args->flags & MSM_SUBMIT_SUDO) 475 + submit->in_rb = true; 479 476 480 477 ret = submit_lookup_objects(submit, args, file); 481 478 if (ret)
+2
include/uapi/drm/msm_drm.h
··· 201 201 #define MSM_SUBMIT_NO_IMPLICIT 0x80000000 /* disable implicit sync */ 202 202 #define MSM_SUBMIT_FENCE_FD_IN 0x40000000 /* enable input fence_fd */ 203 203 #define MSM_SUBMIT_FENCE_FD_OUT 0x20000000 /* enable output fence_fd */ 204 + #define MSM_SUBMIT_SUDO 0x10000000 /* run submitted cmds from RB */ 204 205 #define MSM_SUBMIT_FLAGS ( \ 205 206 MSM_SUBMIT_NO_IMPLICIT | \ 206 207 MSM_SUBMIT_FENCE_FD_IN | \ 207 208 MSM_SUBMIT_FENCE_FD_OUT | \ 209 + MSM_SUBMIT_SUDO | \ 208 210 0) 209 211 210 212 /* Each cmdstream submit consists of a table of buffers involved, and