From 9733b072a12a422e2bf17bc7ba8b39769853d4a2 Mon Sep 17 00:00:00 2001 From: Volodymyr Babchuk Date: Fri, 7 Sep 2018 21:37:07 +0300 Subject: optee: allow to work without static shared memory On virtualized systems it is possible that OP-TEE will provide only dynamic shared memory support. So it is fine to boot without static SHM enabled if dymanic one is supported. Signed-off-by: Volodymyr Babchuk Signed-off-by: Jens Wiklander --- drivers/tee/optee/core.c | 80 +++++++++++++++++++++++++++++------------------- 1 file changed, 49 insertions(+), 31 deletions(-) (limited to 'drivers/tee') diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 947f9b28de9e..fdce6293e03d 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c @@ -419,9 +419,35 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, return true; } +static struct tee_shm_pool *optee_config_dyn_shm(void) +{ + struct tee_shm_pool_mgr *priv_mgr; + struct tee_shm_pool_mgr *dmabuf_mgr; + void *rc; + + rc = optee_shm_pool_alloc_pages(); + if (IS_ERR(rc)) + return rc; + priv_mgr = rc; + + rc = optee_shm_pool_alloc_pages(); + if (IS_ERR(rc)) { + tee_shm_pool_mgr_destroy(priv_mgr); + return rc; + } + dmabuf_mgr = rc; + + rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); + if (IS_ERR(rc)) { + tee_shm_pool_mgr_destroy(priv_mgr); + tee_shm_pool_mgr_destroy(dmabuf_mgr); + } + + return rc; +} + static struct tee_shm_pool * -optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm, - u32 sec_caps) +optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) { union { struct arm_smccc_res smccc; @@ -436,10 +462,11 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm, struct tee_shm_pool_mgr *priv_mgr; struct tee_shm_pool_mgr *dmabuf_mgr; void *rc; + const int sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); if (res.result.status != OPTEE_SMC_RETURN_OK) { - pr_info("shm service not available\n"); + pr_err("static shm service not available\n"); return ERR_PTR(-ENOENT); } @@ -465,28 +492,15 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm, } vaddr = (unsigned long)va; - /* - * If OP-TEE can work with unregistered SHM, we will use own pool - * for private shm - */ - if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) { - rc = optee_shm_pool_alloc_pages(); - if (IS_ERR(rc)) - goto err_memunmap; - priv_mgr = rc; - } else { - const size_t sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; - - rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz, - 3 /* 8 bytes aligned */); - if (IS_ERR(rc)) - goto err_memunmap; - priv_mgr = rc; - - vaddr += sz; - paddr += sz; - size -= sz; - } + rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz, + 3 /* 8 bytes aligned */); + if (IS_ERR(rc)) + goto err_memunmap; + priv_mgr = rc; + + vaddr += sz; + paddr += sz; + size -= sz; rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT); if (IS_ERR(rc)) @@ -552,7 +566,7 @@ static optee_invoke_fn *get_invoke_func(struct device_node *np) static struct optee *optee_probe(struct device_node *np) { optee_invoke_fn *invoke_fn; - struct tee_shm_pool *pool; + struct tee_shm_pool *pool = ERR_PTR(-EINVAL); struct optee *optee = NULL; void *memremaped_shm = NULL; struct tee_device *teedev; @@ -581,13 +595,17 @@ static struct optee *optee_probe(struct device_node *np) } /* - * We have no other option for shared memory, if secure world - * doesn't have any reserved memory we can use we can't continue. + * Try to use dynamic shared memory if possible */ - if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) - return ERR_PTR(-EINVAL); + if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) + pool = optee_config_dyn_shm(); + + /* + * If dynamic shared memory is not available or failed - try static one + */ + if (IS_ERR(pool) && (sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) + pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm); - pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps); if (IS_ERR(pool)) return (void *)pool; -- cgit