diff options
author | Cedric Neveux <cedric.neveux@nxp.com> | 2018-10-23 13:52:54 +0200 |
---|---|---|
committer | Jason Liu <jason.hui.liu@nxp.com> | 2019-02-12 10:35:16 +0800 |
commit | 46a30aca7f5cbbb7f3f952634c7ebcb63014d520 (patch) | |
tree | 059587591d54aa69732f5ec9cea4f5361f2026e9 /drivers/tee | |
parent | 24f3cee476a47145a30b2d1bf5ac315ae803c176 (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.c | 79 | ||||
-rw-r--r-- | drivers/tee/optee/optee_smc.h | 43 |
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: |