drm/msm/a6xx: Add zap shader load
authorJordan Crouse <jcrouse@codeaurora.org>
Fri, 19 Apr 2019 19:46:15 +0000 (13:46 -0600)
committerRob Clark <robdclark@chromium.org>
Sun, 21 Apr 2019 14:37:17 +0000 (07:37 -0700)
The a6xx GPU powers on in secure mode which restricts what memory it can
write to. To get out of secure mode the GPU driver can write to
REG_A6XX_RBBM_SECVID_TRUST_CNTL but on targets that are "secure" that
register region is blocked and writes will cause the system to go down.

For those targets we need to execute a special sequence that involves
loadinga special shader that clears the GPU registers and use a PM4
sequence to pull the GPU out of secure. Add support for loading the zap
shader and executing the secure sequence. For targets that do not support
SCM or the specific SCM sequence this should fail and we would fall back
to writing the register.

Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@chromium.org>
drivers/gpu/drm/msm/adreno/a6xx_gpu.c
drivers/gpu/drm/msm/adreno/adreno_device.c

index 576559a3a523b5d0ac0f843d0bc08fe230917aa1..7028bb784427e2a2326acf27b125607a3f9d28a4 100644 (file)
@@ -10,6 +10,8 @@
 
 #include <linux/devfreq.h>
 
+#define GPU_PAS_ID 13
+
 static inline bool _a6xx_check_idle(struct msm_gpu *gpu)
 {
        struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
@@ -343,6 +345,20 @@ static int a6xx_ucode_init(struct msm_gpu *gpu)
        return 0;
 }
 
+static int a6xx_zap_shader_init(struct msm_gpu *gpu)
+{
+       static bool loaded;
+       int ret;
+
+       if (loaded)
+               return 0;
+
+       ret = adreno_zap_shader_load(gpu, GPU_PAS_ID);
+
+       loaded = !ret;
+       return ret;
+}
+
 #define A6XX_INT_MASK (A6XX_RBBM_INT_0_MASK_CP_AHB_ERROR | \
          A6XX_RBBM_INT_0_MASK_RBBM_ATB_ASYNCFIFO_OVERFLOW | \
          A6XX_RBBM_INT_0_MASK_CP_HW_ERROR | \
@@ -491,7 +507,27 @@ static int a6xx_hw_init(struct msm_gpu *gpu)
        if (ret)
                goto out;
 
-       gpu_write(gpu, REG_A6XX_RBBM_SECVID_TRUST_CNTL, 0x0);
+       /*
+        * Try to load a zap shader into the secure world. If successful
+        * we can use the CP to switch out of secure mode. If not then we
+        * have no resource but to try to switch ourselves out manually. If we
+        * guessed wrong then access to the RBBM_SECVID_TRUST_CNTL register will
+        * be blocked and a permissions violation will soon follow.
+        */
+       ret = a6xx_zap_shader_init(gpu);
+       if (!ret) {
+               OUT_PKT7(gpu->rb[0], CP_SET_SECURE_MODE, 1);
+               OUT_RING(gpu->rb[0], 0x00000000);
+
+               a6xx_flush(gpu, gpu->rb[0]);
+               if (!a6xx_idle(gpu, gpu->rb[0]))
+                       return -EINVAL;
+       } else {
+               /* Print a warning so if we die, we know why */
+               dev_warn_once(gpu->dev->dev,
+                       "Zap shader not enabled - using SECVID_TRUST_CNTL instead\n");
+               gpu_write(gpu, REG_A6XX_RBBM_SECVID_TRUST_CNTL, 0x0);
+       }
 
 out:
        /*
index 0d87db75b7107a39b86eebb084e3699302320d40..b907245d3d96ff59a56e03f227c845d82736c1e3 100644 (file)
@@ -155,6 +155,7 @@ static const struct adreno_info gpulist[] = {
                .gmem = SZ_1M,
                .inactive_period = DRM_MSM_INACTIVE_PERIOD,
                .init = a6xx_gpu_init,
+               .zapfw = "a630_zap.mdt",
        },
 };