summaryrefslogtreecommitdiff
path: root/drivers/tee
diff options
context:
space:
mode:
authorCedric Neveux <cedric.neveux@nxp.com>2018-10-23 13:52:54 +0200
committerJason Liu <jason.hui.liu@nxp.com>2019-02-12 10:35:16 +0800
commit46a30aca7f5cbbb7f3f952634c7ebcb63014d520 (patch)
tree059587591d54aa69732f5ec9cea4f5361f2026e9 /drivers/tee
parent24f3cee476a47145a30b2d1bf5ac315ae803c176 (diff)
MLK-20052 L2 Cache TEE/Linux shared mutex
Modification of the L2 Cache operations to use a TEE/Linux Shared mutex Signed-off-by: Cedric Neveux <cedric.neveux@nxp.com>
Diffstat (limited to 'drivers/tee')
-rw-r--r--drivers/tee/optee/core.c79
-rw-r--r--drivers/tee/optee/optee_smc.h43
2 files changed, 122 insertions, 0 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c
index d0dd09219795..3f01459529eb 100644
--- a/drivers/tee/optee/core.c
+++ b/drivers/tee/optee/core.c
@@ -29,6 +29,10 @@
#include "optee_private.h"
#include "optee_smc.h"
+#ifdef CONFIG_OUTER_CACHE
+#include <asm/outercache.h>
+#endif
+
#define DRIVER_NAME "optee"
#define OPTEE_SHM_NUM_PRIV_PAGES 1
@@ -404,6 +408,70 @@ out:
return pool;
}
+#ifdef CONFIG_OUTER_CACHE
+/**
+ * @brief Call the TEE to get a shared mutex between TEE and Linux to
+ * do Outer Cache maintenance
+ *
+ * @param[in] invoke_fn Reference to the SMC call function
+ *
+ * @retval 0 Success
+ * @retval -EINVAL Invalid value
+ * @retval -ENOMEM Not enought memory
+ */
+static int optee_outercache_mutex(optee_invoke_fn *invoke_fn)
+{
+ struct arm_smccc_res res;
+
+ int ret = -EINVAL;
+ void *vaddr = NULL;
+ phys_addr_t paddr = 0;
+
+ /* Get the Physical Address of the mutex allocated in the SHM */
+ invoke_fn(OPTEE_SMC_L2CC_MUTEX,
+ OPTEE_SMC_L2CC_MUTEX_GET_ADDR, 0, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0 != OPTEE_SMC_RETURN_OK) {
+ pr_warn("no TZ l2cc mutex service supported\n");
+ goto out;
+ }
+
+ paddr = (unsigned long)reg_pair_to_ptr(res.a2, res.a3);
+ pr_debug("outer cache shared mutex paddr 0x%lx\n", (unsigned long)paddr);
+
+ /* Remap the Mutex into a cacheable area */
+ vaddr = memremap(paddr, sizeof(u32), MEMREMAP_WB);
+ if (vaddr == NULL) {
+ pr_warn("TZ l2cc mutex: ioremap failed\n");
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ pr_debug("outer cache shared mutex vaddr %p\n", vaddr);
+
+ if (outer_mutex(vaddr)) {
+ pr_warn("TZ l2cc mutex: outer cache refused\n");
+ goto out;
+ }
+
+ invoke_fn(OPTEE_SMC_L2CC_MUTEX,
+ OPTEE_SMC_L2CC_MUTEX_ENABLE, 0, 0, 0, 0, 0, 0, &res);
+
+ if (res.a0 != OPTEE_SMC_RETURN_OK) {
+ pr_warn("TZ l2cc mutex disabled: TZ enable failed\n");
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+ pr_info("teetz outer mutex: ret=%d pa=0x%lx va=0x%p\n",
+ ret, (unsigned long)paddr, vaddr);
+
+ return ret;
+}
+#endif
+
/* Simple wrapper functions to be able to use a function pointer */
static void optee_smccc_smc(unsigned long a0, unsigned long a1,
unsigned long a2, unsigned long a3,
@@ -483,6 +551,17 @@ static struct optee *optee_probe(struct device_node *np)
if (IS_ERR(pool))
return (void *)pool;
+#ifdef CONFIG_OUTER_CACHE
+
+ /* Try to get a Share Mutex to do L2 Cache maintenance */
+ if (of_find_compatible_node(NULL, NULL, "arm,pl310-cache")) {
+ rc = optee_outercache_mutex(invoke_fn);
+ if (rc)
+ goto err;
+ }
+
+#endif
+
optee = kzalloc(sizeof(*optee), GFP_KERNEL);
if (!optee) {
rc = -ENOMEM;
diff --git a/drivers/tee/optee/optee_smc.h b/drivers/tee/optee/optee_smc.h
index 069c8e1429de..e47b53376616 100644
--- a/drivers/tee/optee/optee_smc.h
+++ b/drivers/tee/optee/optee_smc.h
@@ -198,6 +198,49 @@ struct optee_smc_get_shm_config_result {
};
/*
+ * Configures L2CC mutex
+ *
+ * Disables, enables usage of L2CC mutex. Returns or sets physical address
+ * of L2CC mutex.
+ *
+ * Call register usage:
+ * a0 SMC Function ID, OPTEE_SMC_L2CC_MUTEX
+ * a1 OPTEE_SMC_L2CC_MUTEX_GET_ADDR Get physical address of mutex
+ * OPTEE_SMC_L2CC_MUTEX_SET_ADDR Set physical address of mutex
+ * OPTEE_SMC_L2CC_MUTEX_ENABLE Enable usage of mutex
+ * OPTEE_SMC_L2CC_MUTEX_DISABLE Disable usage of mutex
+ * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, upper 32bit of a 64bit
+ * physical address of mutex
+ * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_SET_ADDR, lower 32bit of a 64bit
+ * physical address of mutex
+ * a3-6 Not used
+ * a7 Hypervisor Client ID register
+ *
+ * Have config return register usage:
+ * a0 OPTEE_SMC_RETURN_OK
+ * a1 Preserved
+ * a2 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, upper 32bit of a 64bit
+ * physical address of mutex
+ * a3 if a1 == OPTEE_SMC_L2CC_MUTEX_GET_ADDR, lower 32bit of a 64bit
+ * physical address of mutex
+ * a3-7 Preserved
+ *
+ * Error return register usage:
+ * a0 OPTEE_SMC_RETURN_ENOTAVAIL Physical address not available
+ * OPTEE_SMC_RETURN_EBADADDR Bad supplied physical address
+ * OPTEE_SMC_RETURN_EBADCMD Unsupported value in a1
+ * a1-7 Preserved
+ */
+#define OPTEE_SMC_L2CC_MUTEX_GET_ADDR 0
+#define OPTEE_SMC_L2CC_MUTEX_SET_ADDR 1
+#define OPTEE_SMC_L2CC_MUTEX_ENABLE 2
+#define OPTEE_SMC_L2CC_MUTEX_DISABLE 3
+
+#define OPTEE_SMC_FUNCID_L2CC_MUTEX 8
+#define OPTEE_SMC_L2CC_MUTEX \
+ OPTEE_SMC_FAST_CALL_VAL(OPTEE_SMC_FUNCID_L2CC_MUTEX)
+
+/*
* Exchanges capabilities between normal world and secure world
*
* Call register usage: