diff options
author | Volodymyr Babchuk <vlad.babchuk@gmail.com> | 2017-11-29 07:48:36 -0500 |
---|---|---|
committer | Jens Wiklander <jens.wiklander@linaro.org> | 2017-12-15 07:36:17 -0500 |
commit | f58e236c9d665ad0af99c908de4a9b6f07e74dda (patch) | |
tree | 582adc8b1612ca8f18a3260155883ad7c78e8ac8 /drivers/tee | |
parent | abd135ba215c05ca84f9809e6047db25fc28b835 (diff) |
tee: optee: enable dynamic SHM support
Previous patches added various features that are needed for dynamic SHM.
Dynamic SHM allows Normal World to share any buffers with OP-TEE.
While original design suggested to use pre-allocated region (usually of
1M to 2M of size), this new approach allows to use all non-secure RAM for
command buffers, RPC allocations and TA parameters.
This patch checks capability OPTEE_SMC_SEC_CAP_DYNAMIC_SHM. If it was set
by OP-TEE, then kernel part of OP-TEE will use kernel page allocator
to allocate command buffers. Also it will set TEE_GEN_CAP_REG_MEM
capability to tell userspace that it supports shared memory registration.
Signed-off-by: Volodymyr Babchuk <vlad.babchuk@gmail.com>
Signed-off-by: Jens Wiklander <jens.wiklander@linaro.org>
Diffstat (limited to 'drivers/tee')
-rw-r--r-- | drivers/tee/optee/core.c | 69 |
1 files changed, 51 insertions, 18 deletions
diff --git a/drivers/tee/optee/core.c b/drivers/tee/optee/core.c index 863c2a33d404..a60ae778ccb8 100644 --- a/drivers/tee/optee/core.c +++ b/drivers/tee/optee/core.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include "optee_private.h" | 29 | #include "optee_private.h" |
30 | #include "optee_smc.h" | 30 | #include "optee_smc.h" |
31 | #include "shm_pool.h" | ||
31 | 32 | ||
32 | #define DRIVER_NAME "optee" | 33 | #define DRIVER_NAME "optee" |
33 | 34 | ||
@@ -219,6 +220,10 @@ static void optee_get_version(struct tee_device *teedev, | |||
219 | .impl_caps = TEE_OPTEE_CAP_TZ, | 220 | .impl_caps = TEE_OPTEE_CAP_TZ, |
220 | .gen_caps = TEE_GEN_CAP_GP, | 221 | .gen_caps = TEE_GEN_CAP_GP, |
221 | }; | 222 | }; |
223 | struct optee *optee = tee_get_drvdata(teedev); | ||
224 | |||
225 | if (optee->sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) | ||
226 | v.gen_caps |= TEE_GEN_CAP_REG_MEM; | ||
222 | *vers = v; | 227 | *vers = v; |
223 | } | 228 | } |
224 | 229 | ||
@@ -397,21 +402,22 @@ static bool optee_msg_exchange_capabilities(optee_invoke_fn *invoke_fn, | |||
397 | } | 402 | } |
398 | 403 | ||
399 | static struct tee_shm_pool * | 404 | static struct tee_shm_pool * |
400 | optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) | 405 | optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm, |
406 | u32 sec_caps) | ||
401 | { | 407 | { |
402 | union { | 408 | union { |
403 | struct arm_smccc_res smccc; | 409 | struct arm_smccc_res smccc; |
404 | struct optee_smc_get_shm_config_result result; | 410 | struct optee_smc_get_shm_config_result result; |
405 | } res; | 411 | } res; |
406 | struct tee_shm_pool *pool; | ||
407 | unsigned long vaddr; | 412 | unsigned long vaddr; |
408 | phys_addr_t paddr; | 413 | phys_addr_t paddr; |
409 | size_t size; | 414 | size_t size; |
410 | phys_addr_t begin; | 415 | phys_addr_t begin; |
411 | phys_addr_t end; | 416 | phys_addr_t end; |
412 | void *va; | 417 | void *va; |
413 | struct tee_shm_pool_mem_info priv_info; | 418 | struct tee_shm_pool_mgr *priv_mgr; |
414 | struct tee_shm_pool_mem_info dmabuf_info; | 419 | struct tee_shm_pool_mgr *dmabuf_mgr; |
420 | void *rc; | ||
415 | 421 | ||
416 | invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); | 422 | invoke_fn(OPTEE_SMC_GET_SHM_CONFIG, 0, 0, 0, 0, 0, 0, 0, &res.smccc); |
417 | if (res.result.status != OPTEE_SMC_RETURN_OK) { | 423 | if (res.result.status != OPTEE_SMC_RETURN_OK) { |
@@ -441,22 +447,49 @@ optee_config_shm_memremap(optee_invoke_fn *invoke_fn, void **memremaped_shm) | |||
441 | } | 447 | } |
442 | vaddr = (unsigned long)va; | 448 | vaddr = (unsigned long)va; |
443 | 449 | ||
444 | priv_info.vaddr = vaddr; | 450 | /* |
445 | priv_info.paddr = paddr; | 451 | * If OP-TEE can work with unregistered SHM, we will use own pool |
446 | priv_info.size = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; | 452 | * for private shm |
447 | dmabuf_info.vaddr = vaddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; | 453 | */ |
448 | dmabuf_info.paddr = paddr + OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; | 454 | if (sec_caps & OPTEE_SMC_SEC_CAP_DYNAMIC_SHM) { |
449 | dmabuf_info.size = size - OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; | 455 | rc = optee_shm_pool_alloc_pages(); |
450 | 456 | if (IS_ERR(rc)) | |
451 | pool = tee_shm_pool_alloc_res_mem(&priv_info, &dmabuf_info); | 457 | goto err_memunmap; |
452 | if (IS_ERR(pool)) { | 458 | priv_mgr = rc; |
453 | memunmap(va); | 459 | } else { |
454 | goto out; | 460 | const size_t sz = OPTEE_SHM_NUM_PRIV_PAGES * PAGE_SIZE; |
461 | |||
462 | rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, sz, | ||
463 | 3 /* 8 bytes aligned */); | ||
464 | if (IS_ERR(rc)) | ||
465 | goto err_memunmap; | ||
466 | priv_mgr = rc; | ||
467 | |||
468 | vaddr += sz; | ||
469 | paddr += sz; | ||
470 | size -= sz; | ||
455 | } | 471 | } |
456 | 472 | ||
473 | rc = tee_shm_pool_mgr_alloc_res_mem(vaddr, paddr, size, PAGE_SHIFT); | ||
474 | if (IS_ERR(rc)) | ||
475 | goto err_free_priv_mgr; | ||
476 | dmabuf_mgr = rc; | ||
477 | |||
478 | rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr); | ||
479 | if (IS_ERR(rc)) | ||
480 | goto err_free_dmabuf_mgr; | ||
481 | |||
457 | *memremaped_shm = va; | 482 | *memremaped_shm = va; |
458 | out: | 483 | |
459 | return pool; | 484 | return rc; |
485 | |||
486 | err_free_dmabuf_mgr: | ||
487 | tee_shm_pool_mgr_destroy(dmabuf_mgr); | ||
488 | err_free_priv_mgr: | ||
489 | tee_shm_pool_mgr_destroy(priv_mgr); | ||
490 | err_memunmap: | ||
491 | memunmap(va); | ||
492 | return rc; | ||
460 | } | 493 | } |
461 | 494 | ||
462 | /* Simple wrapper functions to be able to use a function pointer */ | 495 | /* Simple wrapper functions to be able to use a function pointer */ |
@@ -534,7 +567,7 @@ static struct optee *optee_probe(struct device_node *np) | |||
534 | if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) | 567 | if (!(sec_caps & OPTEE_SMC_SEC_CAP_HAVE_RESERVED_SHM)) |
535 | return ERR_PTR(-EINVAL); | 568 | return ERR_PTR(-EINVAL); |
536 | 569 | ||
537 | pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm); | 570 | pool = optee_config_shm_memremap(invoke_fn, &memremaped_shm, sec_caps); |
538 | if (IS_ERR(pool)) | 571 | if (IS_ERR(pool)) |
539 | return (void *)pool; | 572 | return (void *)pool; |
540 | 573 | ||