g2d: add support for Secure DRM of Exynos9820
authorCho KyongHo <pullip.cho@samsung.com>
Mon, 5 Mar 2018 08:00:47 +0000 (17:00 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:28:05 +0000 (14:28 +0900)
Protected contents of Secure DRM are processed by G2D if post image
prosessing is needed. G2D in Exynos9810 needs help of the secure world
due to the lack of prevention of protected contents leak to non-secure
world.
G2D in Exynos9820 does not need the help of the secure world because
it is guaranteed that G2D does not leak the protected contents.

Change-Id: I11028c774fe8b59cd21f7c6f391ae1949fd78767
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/gpu/exynos/g2d/g2d.h
drivers/gpu/exynos/g2d/g2d_command.c
drivers/gpu/exynos/g2d/g2d_drv.c
drivers/gpu/exynos/g2d/g2d_regs.c
drivers/gpu/exynos/g2d/g2d_regs.h
drivers/gpu/exynos/g2d/g2d_task.c

index afb69d2820ae70481efca082cab45eb72e38c9ca..c7546cdd0293f02d4d32bbaaca0575c420c7b164 100644 (file)
@@ -72,8 +72,14 @@ struct g2d_dvfs_table {
        u32 freq;
 };
 
+/*
+ * Proved that G2D does not leak protected conents that it is processing.
+ */
+#define G2D_DEVICE_CAPS_SELF_PROTECTION                1
+
 struct g2d_device {
        unsigned long           state;
+       unsigned long           caps;
 
        struct miscdevice       misc[2];
        struct device           *dev;
index e4e816987aa3512c4e51ae5a40f5b9acad7fa0fe..d22b2cb4f949e270d96051193b02535bacca9978 100644 (file)
@@ -130,10 +130,11 @@ static void g2d_set_hwfc_commands(struct g2d_task *task)
 
 static void g2d_set_start_commands(struct g2d_task *task)
 {
+       bool self_prot = task->g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
        struct g2d_reg *regs = page_address(task->cmd_page);
        unsigned int n;
 
-       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+       if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
                return;
 
        /*
index d21a6ea7f781ad8d237a95ff2f7150db63e59621..fdf577358c13454cb2d036beba3e02ff2cb70e3f 100644 (file)
@@ -750,8 +750,27 @@ static int g2d_parse_dt(struct g2d_device *g2d_dev)
        return 0;
 }
 
+struct g2d_device_data {
+       unsigned long caps;
+};
+
+const struct g2d_device_data g2d_9820_data __initconst = {
+       .caps = G2D_DEVICE_CAPS_SELF_PROTECTION,
+};
+
+static const struct of_device_id of_g2d_match[] __refconst = {
+       {
+               .compatible = "samsung,exynos9810-g2d",
+       }, {
+               .compatible = "samsung,exynos9820-g2d",
+               .data = &g2d_9820_data,
+       },
+       {},
+};
+
 static int g2d_probe(struct platform_device *pdev)
 {
+       const struct of_device_id *of_id;
        struct g2d_device *g2d_dev;
        struct resource *res;
        __u32 version;
@@ -797,6 +816,13 @@ static int g2d_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       of_id = of_match_node(of_g2d_match, pdev->dev.of_node);
+       if (of_id->data) {
+               const struct g2d_device_data *devdata = of_id->data;
+
+               g2d_dev->caps = devdata->caps;
+       }
+
        ret = iovmm_activate(&pdev->dev);
        if (ret < 0) {
                dev_err(&pdev->dev, "Failed to activate iommu\n");
@@ -933,13 +959,6 @@ static const struct dev_pm_ops g2d_pm_ops = {
        SET_RUNTIME_PM_OPS(NULL, g2d_runtime_resume, g2d_runtime_suspend)
 };
 
-static const struct of_device_id of_g2d_match[] = {
-       {
-               .compatible = "samsung,exynos9810-g2d",
-       },
-       {},
-};
-
 static struct platform_driver g2d_driver = {
        .probe          = g2d_probe,
        .remove         = g2d_remove,
index 376f374ae4cea9755dcbc044000e0e507e016747..7e3540c749d4c3aea6f97869412804dc898c0c75 100644 (file)
@@ -67,18 +67,35 @@ static void g2d_hw_push_task_by_smc(struct g2d_device *g2d_dev,
 
 void g2d_hw_push_task(struct g2d_device *g2d_dev, struct g2d_task *task)
 {
-       u32 state;
+       bool self_prot = g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
+       u32 state = g2d_hw_get_job_state(g2d_dev, task->job_id);
 
-       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)) {
-               g2d_hw_push_task_by_smc(g2d_dev, task);
-               return;
-       }
-
-       state = g2d_hw_get_job_state(g2d_dev, task->job_id);
        if (state != G2D_JOB_STATE_DONE)
                dev_err(g2d_dev->dev, "%s: Unexpected state %#x of JOB %d\n",
                        __func__, state, task->job_id);
 
+       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION)) {
+               unsigned int i;
+
+               if (!self_prot) {
+                       g2d_hw_push_task_by_smc(g2d_dev, task);
+                       return;
+               }
+
+               state = 0;
+
+               for (i = 0; i < task->num_source; i++)
+                       if (task->source[i].flags & G2D_LAYERFLAG_SECURE)
+                               state |= 1 << i;
+
+               if ((task->target.flags & G2D_LAYERFLAG_SECURE) || state)
+                       state |= 1 << 24;
+
+               writel_relaxed(state,
+                              g2d_dev->reg +
+                              G2D_JOBn_LAYER_SECURE_REG(task->job_id));
+       }
+
        writel_relaxed(G2D_JOB_HEADER_DATA(task->priority, task->job_id),
                        g2d_dev->reg + G2D_JOB_HEADER_REG);
 
index 4bae0619adf0074ed1039916f7db52b05ad221c5..432e2075356b3db0ddf2b07e032d66272ffb503a 100644 (file)
@@ -47,6 +47,9 @@
 #define G2D_BITBLT_COMMAND_REG                 0x104
 #define G2D_LAYER_UPDATE_REG                   0x108
 
+/* G2D Secure mode registers */
+#define G2D_JOBn_LAYER_SECURE_REG(n)           (0x9004 + (n) * 8)
+
 /* HWFC related Registers */
 #define G2D_HWFC_CAPTURE_IDX_REG               0x8000
 #define G2D_HWFC_ENCODING_IDX_REG              0x8004
index b8d2178340728297d354492fcbdce58053fd572c..53162351ddd57c092645a10ed30a176558d60fd5 100644 (file)
 #include "g2d_debug.h"
 #include "g2d_secure.h"
 
-static void g2d_secure_enable(void)
+static void g2d_secure_enable(bool self_prot)
 {
-       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+       if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
                exynos_smc(SMC_PROTECTION_SET, 0, G2D_ALWAYS_S, 1);
 }
 
-static void g2d_secure_disable(void)
+static void g2d_secure_disable(bool self_prot)
 {
-       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+       if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
                exynos_smc(SMC_PROTECTION_SET, 0, G2D_ALWAYS_S, 0);
 }
 
 static int g2d_map_cmd_data(struct g2d_task *task)
 {
+       bool self_prot = task->g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION;
        struct scatterlist sgl;
 
-       if (IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
+       if (!self_prot && IS_ENABLED(CONFIG_EXYNOS_CONTENT_PATH_PROTECTION))
                return 0;
 
        /* mapping the command data */
@@ -117,7 +118,7 @@ static void g2d_finish_task(struct g2d_device *g2d_dev,
        g2d_stamp_task(task, G2D_STAMP_STATE_DONE,
                (int)ktime_us_delta(task->ktime_end, task->ktime_begin));
 
-       g2d_secure_disable();
+       g2d_secure_disable(g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION);
 
        clk_disable(g2d_dev->clock);
 
@@ -165,7 +166,7 @@ void g2d_flush_all_tasks(struct g2d_device *g2d_dev)
 
 static void g2d_execute_task(struct g2d_device *g2d_dev, struct g2d_task *task)
 {
-       g2d_secure_enable();
+       g2d_secure_enable(g2d_dev->caps & G2D_DEVICE_CAPS_SELF_PROTECTION);
 
        list_move_tail(&task->node, &g2d_dev->tasks_active);
        change_task_state_active(task);