This is an automated email from the ASF dual-hosted git repository. xiaoxiang pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit a2a689fee046d2bdb14e4f6feba8d82cc9de9040 Author: George Poulios <gpoul...@census-labs.com> AuthorDate: Sat May 10 14:40:26 2025 +0300 drivers/misc/optee: Fix GP API compatibility Previous implementation was not compatible with GlobalPlatform API in the following ways: - Registered mem IDs would begin from negatives when it should have been greater than or equal to 0 - Register IOCTL would return 0 on success, when it should have been returning a file descriptor. - Register IOCTL would expect the user-space client to specify TEE_SHM_* flags dictating its behaviour when in fact, libteec never specifies flags. This commit fixes all those issues. It uses nuttx/idr.h instead of a linked list, and it uses `file_allocate` to provide file descriptors for registered shared memory. Upon close(fd), the memory is de-registered and freed accordingly. It also updates the documentation accordingly. Signed-off-by: George Poulios <gpoul...@census-labs.com> --- Documentation/guides/optee.rst | 46 +++--- drivers/misc/optee.c | 325 ++++++++++++++++++++++++----------------- drivers/misc/optee.h | 22 +-- drivers/misc/optee_smc.c | 7 +- include/nuttx/tee.h | 8 +- 5 files changed, 234 insertions(+), 174 deletions(-) diff --git a/Documentation/guides/optee.rst b/Documentation/guides/optee.rst index e133d9387a..ab1adac9b3 100644 --- a/Documentation/guides/optee.rst +++ b/Documentation/guides/optee.rst @@ -100,8 +100,8 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``). future, but until then, please refer to ``include/nuttx/tee.h`` for details. In short, for shared memory references, ``.a`` is the offset into the shared memory buffer, ``.b`` is the size of the buffer, and ``.c`` is the - the shared memory identifier (``.addr`` field used in - ``TEE_IOC_SHM_REGISTER``). + the shared memory identifier (``.id`` field returned by + ``TEE_IOC_SHM_ALLOC`` or ``TEE_IOC_SHM_REGISTER``). - ``TEE_IOC_CANCEL`` : Cancel a currently invoked command. @@ -113,8 +113,8 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``). - Expects a ``struct tee_ioctl_shm_alloc_data`` pointer with the ``.size`` field set, and ignoring the ``.flags`` field. Upon successful return, it returns the memory file descriptor one can use ``mmap()`` on (with - ``MAP_SHARED``). It also returns an identifier for the allocation - in ``.id``. + ``MAP_SHARED``). It also returns an identifier for use in memory references + (``tee_ioctl_param.c`` field) in ``.id``. - ``TEE_IOC_SHM_REGISTER`` : Register a shared memory reference with the secure OS. @@ -126,10 +126,9 @@ on success unless otherwise specified (see ``TEE_IOC_SHM_ALLOC``). ``TEE_SHM_SEC_REGISTER`` registers the memory with the secure OS for later use in memrefs and is automatically de-registered during driver close if ``TEE_SHM_REGISTER`` is also specified. ``.addr`` shall point to the (user) - memory to register and ``.size`` shall indicate its size. The identifier - used to register shared memory with the secure OS is the value of the - ``.addr`` field (what one needs to specify in ``tee_ioctl_param.c`` - during a ``TEE_IOC_INVOKE``). + memory to register and ``.size`` shall indicate its size. One may use the + returned ``.id`` field when specifying shared memory references + (``tee_ioctl_param.c`` field). Typical usage ============= @@ -167,7 +166,7 @@ Typical usage return ret; } - [...check ioc_ver accordingly...] + /* check ioc_ver accordingly */ #. Open a session with a Trusted Application @@ -188,7 +187,7 @@ Typical usage return ret; } - [...use ioc_opn.session returned...] + /* use ioc_opn.session returned */ #. Invoke a function of the Trusted Application @@ -222,7 +221,7 @@ Typical usage goto err_with_args; } - [...use result (if any) in ioc_args->params...] + /* use result (if any) in ioc_args->params */ #. Allocate shared memory through the driver @@ -253,22 +252,25 @@ Typical usage .. code-block:: c /* The following will fail if TEE_GEN_CAP_REG_MEM is not reported in - * the returned `ioc_ver.gen_caps` in step 1 above */ + * the returned `ioc_ver.gen_caps` in step 1 above + * Note: user memory used does not have to be allocated through IOCTL + */ struct tee_ioctl_shm_register_data ioc_reg = { 0 }; - ioc_reg.addr = (uintptr_t)ptr; - ioc_reg.length = ioc_alloc.size; - ioc_reg.flags = TEE_SHM_REGISTER | TEE_SHM_SEC_REGISTER; + ioc_reg.addr = (uintptr_t)<some user memory ptr>; + ioc_reg.length = <user memory size>; - ret = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg); - if (ret < 0) + memfd = ioctl(fd, TEE_IOC_SHM_REGISTER, (unsigned long)&ioc_reg); + if (memfd < 0) { - munmap(shm, ioc_alloc.size); - close(memfd); return ret; } + /* use ioc_reg.id returned in OP-TEE parameters (e.g. open, invoke) */ + + close(memfd); + #. Use the registered shared memory in an invocation .. code-block:: c @@ -292,8 +294,8 @@ Typical usage ioc_args->num_params = num_params; ioc_args->params[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT; ioc_args->params[0].a = 0; - ioc_args->params[0].b = ioc_alloc.size; - ioc_args->params[0].a = (uintptr_t)shm; + ioc_args->params[0].b = ioc_reg.length; + ioc_args->params[0].c = ioc_reg.id; ioc_buf.buf_ptr = (uintptr_t)ioc_args; ioc_buf.buf_len = ioc_args_len; @@ -304,4 +306,4 @@ Typical usage goto err_with_args; } - [...use result (if any) in ioc_args->params...] + /* use result (if any) in ioc_args->params */ diff --git a/drivers/misc/optee.c b/drivers/misc/optee.c index 5ec64ad049..e67854965a 100644 --- a/drivers/misc/optee.c +++ b/drivers/misc/optee.c @@ -144,6 +144,8 @@ static int optee_close(FAR struct file *filep); static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg); +static int optee_shm_close(FAR struct file *filep); + /**************************************************************************** * Private Data ****************************************************************************/ @@ -152,15 +154,35 @@ static int optee_ioctl(FAR struct file *filep, int cmd, static const struct file_operations g_optee_ops = { - optee_open, /* open */ - optee_close, /* close */ - NULL, /* read */ - NULL, /* write */ - NULL, /* seek */ - optee_ioctl, /* ioctl */ - NULL, /* mmap */ - NULL, /* truncate */ - NULL /* poll */ + optee_open, /* open */ + optee_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + optee_ioctl, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + NULL /* poll */ +}; + +static const struct file_operations g_optee_shm_ops = +{ + NULL, /* open */ + optee_shm_close, /* close */ + NULL, /* read */ + NULL, /* write */ + NULL, /* seek */ + NULL, /* ioctl */ + NULL, /* mmap */ + NULL, /* truncate */ + NULL /* poll */ +}; + +static struct inode g_optee_shm_inode = +{ + .i_flags = FSNODEFLAG_TYPE_SHM, /* could also be DRIVER; doesn't matter */ + .i_crefs = 1, /* inode never to be released */ + .u.i_ops = &g_optee_shm_ops }; /**************************************************************************** @@ -246,41 +268,6 @@ static bool optee_is_valid_range(FAR const void *va, size_t size) # define optee_is_valid_range(addr, size) (true) #endif -/**************************************************************************** - * Name: optee_shm_next_id - * - * Description: - * Return a unique ID for adding a new entry to the list of shared memory - * chunks registered with the driver. This function assumes all new items - * in the list are added to the head. It is NOT thread-safe. - * - * Parameters: - * priv - The driver's private data structure - * - * Returned Values: - * A unique ID for the next shared memory list entry to be added. - * - ****************************************************************************/ - -static inline int32_t optee_shm_next_id(FAR struct optee_priv_data *priv) -{ - FAR struct optee_shm_entry *shme; - int32_t next_id; - - if (list_is_empty(&priv->shm_list)) - { - next_id = INT32_MIN; - } - else - { - shme = list_first_entry(&priv->shm_list, struct optee_shm_entry, - node); - next_id = shme->shm.id + 1; - } - - return next_id; -} - /**************************************************************************** * Name: optee_shm_to_page_list * @@ -323,8 +310,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme, uint32_t list_size; uint32_t i = 0; - pgoff = shme->shm.addr & (pgsize - 1); - total_pages = (uint32_t)div_round_up(pgoff + shme->shm.length, pgsize); + pgoff = shme->addr & (pgsize - 1); + total_pages = (uint32_t)div_round_up(pgoff + shme->length, pgsize); list_size = div_round_up(total_pages, OPTEE_PAGES_ARRAY_LEN) * sizeof(struct optee_page_list_entry); @@ -340,7 +327,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme, } list_entry = (FAR struct optee_page_list_entry *)list; - page = ALIGN_DOWN(shme->shm.addr, pgsize); + page = ALIGN_DOWN(shme->addr, pgsize); while (total_pages) { list_entry->pages_array[i++] = optee_va_to_pa((FAR const void *)page); @@ -364,7 +351,7 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme, } /**************************************************************************** - * Name: optee_shm_sec_register + * Name: optee_shm_register * * Description: * Register specified shared memory entry with OP-TEE. @@ -380,8 +367,8 @@ optee_shm_to_page_list(FAR struct optee_shm_entry *shme, * ****************************************************************************/ -static int optee_shm_sec_register(FAR struct optee_priv_data *priv, - FAR struct optee_shm_entry *shme) +static int optee_shm_register(FAR struct optee_priv_data *priv, + FAR struct optee_shm_entry *shme) { FAR struct optee_msg_arg *msg; uintptr_t page_list_pa; @@ -404,8 +391,8 @@ static int optee_shm_sec_register(FAR struct optee_priv_data *priv, msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_TMEM_OUTPUT | OPTEE_MSG_ATTR_NONCONTIG; msg->params[0].u.tmem.buf_ptr = page_list_pa; - msg->params[0].u.tmem.shm_ref = shme->shm.addr; - msg->params[0].u.tmem.size = shme->shm.length; + msg->params[0].u.tmem.shm_ref = (uintptr_t)shme; + msg->params[0].u.tmem.size = shme->length; ret = optee_transport_call(priv, msg); if (ret < 0) @@ -426,7 +413,7 @@ errout_with_msg: } /**************************************************************************** - * Name: optee_shm_sec_unregister + * Name: optee_shm_unregister * * Description: * Unregister specified shared memory entry with OP-TEE. @@ -442,8 +429,8 @@ errout_with_msg: * ****************************************************************************/ -static int optee_shm_sec_unregister(FAR struct optee_priv_data *priv, - FAR struct optee_shm_entry *shme) +static int optee_shm_unregister(FAR struct optee_priv_data *priv, + FAR struct optee_shm_entry *shme) { FAR struct optee_msg_arg *msg; int ret = 0; @@ -456,7 +443,7 @@ static int optee_shm_sec_unregister(FAR struct optee_priv_data *priv, msg->cmd = OPTEE_MSG_CMD_UNREGISTER_SHM; msg->params[0].attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT; - msg->params[0].u.rmem.shm_ref = shme->shm.addr; + msg->params[0].u.rmem.shm_ref = (uintptr_t)shme; ret = optee_transport_call(priv, msg); if (ret < 0) @@ -474,6 +461,29 @@ errout_with_msg: return ret; } +/**************************************************************************** + * Name: optee_shm_close + * + * Description: + * shm close operation + * + * Parameters: + * filep - the file instance + * + * Returned Values: + * Always OK. + * + ****************************************************************************/ + +static int optee_shm_close(FAR struct file *filep) +{ + FAR struct optee_shm_entry *shme = filep->f_priv; + + optee_shm_free(shme); + filep->f_priv = NULL; + return 0; +} + /**************************************************************************** * Name: optee_open * @@ -499,8 +509,7 @@ static int optee_open(FAR struct file *filep) return ret; } - list_initialize(&priv->shm_list); - spin_lock_init(&priv->lock); + priv->shms = idr_init(); filep->f_priv = priv; return 0; } @@ -515,7 +524,7 @@ static int optee_open(FAR struct file *filep) * filep - the file instance * * Returned Values: - * OK on success; A negated errno value is returned on any failure. + * Always OK. * ****************************************************************************/ @@ -523,23 +532,75 @@ static int optee_close(FAR struct file *filep) { FAR struct optee_priv_data *priv = filep->f_priv; FAR struct optee_shm_entry *shme; - FAR struct optee_shm_entry *tmp; + int id = 0; - list_for_every_entry_safe(&priv->shm_list, shme, tmp, - struct optee_shm_entry, node) + idr_for_each_entry(priv->shms, shme, id) { - optee_shm_free(priv, shme); + optee_shm_free(shme); } + idr_destroy(priv->shms); optee_transport_close(priv); return 0; } -static int optee_to_msg_param(FAR struct optee_msg_param *mparams, +static int optee_memref_to_msg_param(FAR struct optee_priv_data *priv, + FAR struct optee_msg_param *mp, + FAR const struct tee_ioctl_param *p) +{ + FAR struct optee_shm_entry *shme; + + /* Warning: the case for non-registered memrefs below is a hack to work + * with openvela. Normally, non-registered memory should be specified as + * OPTEE_MSG_ATTR_TYPE_TMEM_* (note the 'T') and `buf_ptr` should be set + * to the physical address of buffer. + * + * Related openvela patches: + * - external_optee_optee_os@1a29df42 core/tee/entry_std.c#L160 + * - frameworks_security_optee_vela@54b377d5c compat/mobj_dyn_shm.c#L25 + * + * Ideally, in the future, this should be wrapped around some + * CONFIG_OPTEE_OPENVELA_COMPAT guard. + */ + + mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr - + TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; + if (p->c != TEE_MEMREF_NULL) + { + shme = idr_find(priv->shms, p->c); + if (shme == NULL) + { + return -EINVAL; + } + + if (shme->flags & TEE_SHM_REGISTER) + { + mp->u.rmem.shm_ref = (uintptr_t)shme; + } + else + { + /* hack to comply with openvela */ + + mp->u.rmem.shm_ref = shme->addr; + } + } + else + { + mp->u.rmem.shm_ref = 0; + } + + mp->u.rmem.size = p->b; + mp->u.rmem.offs = p->a; + return 0; +} + +static int optee_to_msg_param(FAR struct optee_priv_data *priv, + FAR struct optee_msg_param *mparams, size_t num_params, FAR const struct tee_ioctl_param *params) { size_t n; + int ret; for (n = 0; n < num_params; n++) { @@ -568,19 +629,11 @@ static int optee_to_msg_param(FAR struct optee_msg_param *mparams, case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT: case TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INOUT: - mp->attr = OPTEE_MSG_ATTR_TYPE_RMEM_INPUT + p->attr - - TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT; - if (p->c != TEE_MEMREF_NULL) - { - mp->u.rmem.shm_ref = p->c; - } - else + ret = optee_memref_to_msg_param(priv, mp, p); + if (ret < 0) { - mp->u.rmem.shm_ref = 0; + return ret; } - - mp->u.rmem.size = p->b; - mp->u.rmem.offs = p->a; break; default: return -EINVAL; @@ -719,7 +772,8 @@ static int optee_ioctl_open_session(FAR struct optee_priv_data *priv, memcpy(&msg->params[0].u.value, arg->uuid, sizeof(arg->uuid)); msg->params[1].u.value.c = arg->clnt_login; - ret = optee_to_msg_param(msg->params + 2, arg->num_params, arg->params); + ret = optee_to_msg_param(priv, msg->params + 2, arg->num_params, + arg->params); if (ret < 0) { goto errout_with_msg; @@ -731,8 +785,7 @@ static int optee_ioctl_open_session(FAR struct optee_priv_data *priv, goto errout_with_msg; } - ret = optee_from_msg_param(arg->params, arg->num_params, - msg->params + 2); + ret = optee_from_msg_param(arg->params, arg->num_params, msg->params + 2); if (ret < 0) { optee_close_session(priv, msg->session); @@ -798,7 +851,7 @@ static int optee_ioctl_invoke(FAR struct optee_priv_data *priv, msg->session = arg->session; msg->cancel_id = arg->cancel_id; - ret = optee_to_msg_param(msg->params, arg->num_params, arg->params); + ret = optee_to_msg_param(priv, msg->params, arg->num_params, arg->params); if (ret < 0) { goto errout_with_msg; @@ -873,9 +926,13 @@ static int optee_ioctl_cancel(FAR struct optee_priv_data *priv, } static int -optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data) +optee_ioctl_shm_alloc(FAR struct optee_priv_data *priv, + FAR struct tee_ioctl_shm_alloc_data *data) { + FAR struct optee_shm_entry *shme; + FAR void *addr; int memfd; + int ret; if (!optee_is_valid_range(data, sizeof(*data))) { @@ -890,21 +947,32 @@ optee_ioctl_shm_alloc(FAR struct tee_ioctl_shm_alloc_data *data) if (ftruncate(memfd, data->size) < 0) { + ret = get_errno(); goto err; } - data->id = (uintptr_t)mmap(NULL, data->size, PROT_READ | PROT_WRITE, - MAP_SHARED, memfd, 0); - if (data->id == (uintptr_t)MAP_FAILED) + addr = mmap(NULL, data->size, PROT_READ | PROT_WRITE, MAP_SHARED, + memfd, 0); + if (addr == MAP_FAILED) { + ret = get_errno(); goto err; } + ret = optee_shm_alloc(priv, addr, data->size, 0, &shme); + if (ret < 0) + { + goto err_with_mmap; + } + + data->id = shme->id; return memfd; +err_with_mmap: + munmap(addr, data->size); err: close(memfd); - return get_errno(); + return ret; } static int @@ -925,20 +993,27 @@ optee_ioctl_shm_register(FAR struct optee_priv_data *priv, return -EFAULT; } - if (rdata->flags & TEE_SHM_ALLOC) + if (rdata->flags) { return -EINVAL; } ret = optee_shm_alloc(priv, (FAR void *)(uintptr_t)rdata->addr, - rdata->length, rdata->flags, &shme); - if (ret) + rdata->length, TEE_SHM_REGISTER, &shme); + if (ret < 0) { return ret; } - rdata->id = shme->shm.id; - return 0; + ret = file_allocate(&g_optee_shm_inode, O_CLOEXEC, 0, shme, 0, true); + if (ret < 0) + { + optee_shm_free(shme); + return ret; + } + + rdata->id = shme->id; + return ret; } /**************************************************************************** @@ -975,7 +1050,7 @@ static int optee_ioctl(FAR struct file *filep, int cmd, unsigned long arg) case TEE_IOC_CANCEL: return optee_ioctl_cancel(priv, parg); case TEE_IOC_SHM_ALLOC: - return optee_ioctl_shm_alloc(parg); + return optee_ioctl_shm_alloc(priv, parg); case TEE_IOC_SHM_REGISTER: return optee_ioctl_shm_register(priv, parg); default: @@ -1031,7 +1106,7 @@ uintptr_t optee_va_to_pa(FAR const void *va) * Name: optee_shm_alloc * * Description: - * Allocate, register and/or add shared memory for use with OP-TEE calls. + * Allocate and/or register shared memory with the OP-TEE OS. * Shared memory entry suitable for use in shared memory linked list * returned in pass-by-reference `shmep` pointer. This function always * allocates a shared memory entry, regardless of flags. The rest of this @@ -1040,12 +1115,9 @@ uintptr_t optee_va_to_pa(FAR const void *va) * be allocated. In this case `addr` will be ignored. The allocated * buffer will be aligned to `priv->alignment`. `TEE_SHM_ALLOC` flag * is reserved for kernel use only. - * - If `TEE_SHM_SEC_REGISTER` is specified, then the memory specified by + * - If `TEE_SHM_REGISTER` is specified, then the memory specified by * `addr` or allocated through `TEE_SHM_ALLOC`, will be registered with * OP-TEE as dynamic shared memory. - * - If `TEE_SHM_REGISTER` is specified, then the memory specified by - * `addr` or allocated through `TEE_SHM_ALLOC`, will be added to the - * driver's private data structure linked list of shared memory chunks. * * Use `optee_shm_free()` to undo this operation, i.e. to free, * unregister, and/or remove from the list the entry returned in `shmep` @@ -1071,14 +1143,13 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr, FAR struct optee_shm_entry **shmep) { FAR struct optee_shm_entry *shme; - irqstate_t irqstate; FAR void *ptr; - int ret; + int ret = -ENOMEM; shme = kmm_zalloc(sizeof(struct optee_shm_entry)); if (shme == NULL) { - return -ENOMEM; + return ret; } if (flags & TEE_SHM_ALLOC) @@ -1099,36 +1170,34 @@ int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr, if (ptr == NULL) { - ret = -ENOMEM; goto err; } - shme->shm.addr = (uintptr_t)ptr; - shme->shm.length = size; - shme->shm.flags = flags; + shme->priv = priv; + shme->addr = (uintptr_t)ptr; + shme->length = size; + shme->flags = flags; + shme->id = idr_alloc(priv->shms, shme, 0, 0); - if (flags & TEE_SHM_SEC_REGISTER) + if (shme->id < 0) { - ret = optee_shm_sec_register(priv, shme); - if (ret < 0) - { - goto err; - } + goto err; } if (flags & TEE_SHM_REGISTER) { - irqstate = spin_lock_irqsave(&priv->lock); - - shme->shm.id = optee_shm_next_id(priv); - list_add_head(&priv->shm_list, &shme->node); - - spin_unlock_irqrestore(&priv->lock, irqstate); + ret = optee_shm_register(priv, shme); + if (ret < 0) + { + goto err_with_idr; + } } *shmep = shme; return 0; +err_with_idr: + idr_remove(priv->shms, shme->id); err: kmm_free(shme); if (flags & TEE_SHM_ALLOC) @@ -1146,7 +1215,6 @@ err: * Free and/or unregister shared memory allocated by `optee_shm_alloc()`. * * Parameters: - * priv - The driver's private data structure * shme - Pointer to shared memory entry to free. Can be NULL, in which * case, this is a no-op. * @@ -1155,38 +1223,31 @@ err: * ****************************************************************************/ -void optee_shm_free(FAR struct optee_priv_data *priv, - FAR struct optee_shm_entry *shme) +void optee_shm_free(FAR struct optee_shm_entry *shme) { - irqstate_t irqstate; - if (!shme) { return; } - if (shme->shm.flags & TEE_SHM_SEC_REGISTER) + if (shme->flags & TEE_SHM_REGISTER) { - optee_shm_sec_unregister(priv, shme); + optee_shm_unregister(shme->priv, shme); } - if (shme->shm.flags & TEE_SHM_REGISTER) + if (shme->flags & TEE_SHM_ALLOC) { - irqstate = spin_lock_irqsave(&priv->lock); - - if (list_in_list(&shme->node)) - { - list_delete(&shme->node); - } - - spin_unlock_irqrestore(&priv->lock, irqstate); + kmm_free((FAR void *)(uintptr_t)shme->addr); } - if (shme->shm.flags & TEE_SHM_ALLOC) + if (!(shme->flags & (TEE_SHM_ALLOC | TEE_SHM_REGISTER))) { - kmm_free((FAR void *)(uintptr_t)shme->shm.addr); + /* allocated by optee_ioctl_shm_alloc(), need to unmap */ + + munmap((FAR void *)(uintptr_t)shme->addr, shme->length); } + idr_remove(shme->priv->shms, shme->id); kmm_free(shme); } diff --git a/drivers/misc/optee.h b/drivers/misc/optee.h index 191af10232..59e2c1512e 100644 --- a/drivers/misc/optee.h +++ b/drivers/misc/optee.h @@ -30,8 +30,7 @@ #include <nuttx/config.h> #include <nuttx/compiler.h> #include <nuttx/tee.h> -#include <nuttx/list.h> -#include <nuttx/spinlock.h> +#include <nuttx/idr.h> #include "optee_msg.h" @@ -46,17 +45,19 @@ * Public Types ****************************************************************************/ -struct optee_shm_entry +struct optee_priv_data { - struct list_node node; - struct tee_ioctl_shm_register_data shm; + uintptr_t alignment; /* Transport-specified message alignment */ + FAR struct idr_s *shms; /* An RB tree of all shm entries */ }; -struct optee_priv_data +struct optee_shm_entry { - uintptr_t alignment; /* Transport-specified message alignment */ - struct list_node shm_list; /* A list of all shm registered */ - spinlock_t lock; /* Lock used to guard list accesses */ + FAR struct optee_priv_data *priv; + int32_t id; + uint64_t addr; + uint64_t length; + uint32_t flags; }; /**************************************************************************** @@ -80,8 +81,7 @@ uintptr_t optee_va_to_pa(FAR const void *va); int optee_shm_alloc(FAR struct optee_priv_data *priv, FAR void *addr, size_t size, uint32_t flags, FAR struct optee_shm_entry **shmep); -void optee_shm_free(FAR struct optee_priv_data *priv, - FAR struct optee_shm_entry *shme); +void optee_shm_free(FAR struct optee_shm_entry *shme); int optee_transport_init(void); int optee_transport_open(FAR struct optee_priv_data **priv); void optee_transport_close(FAR struct optee_priv_data *priv); diff --git a/drivers/misc/optee_smc.c b/drivers/misc/optee_smc.c index b4886a644a..3077a3b712 100644 --- a/drivers/misc/optee_smc.c +++ b/drivers/misc/optee_smc.c @@ -187,10 +187,9 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_, switch (rpc_func) { case OPTEE_SMC_RPC_FUNC_ALLOC: - if (!optee_shm_alloc(priv_, NULL, par->a1, - TEE_SHM_ALLOC | TEE_SHM_REGISTER, &shme)) + if (!optee_shm_alloc(priv_, NULL, par->a1, TEE_SHM_ALLOC, &shme)) { - shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->shm.addr); + shme_pa = optee_va_to_pa((FAR void *)(uintptr_t)shme->addr); reg_pair_from_64(shme_pa, &par->a1, &par->a2); reg_pair_from_64((uintptr_t)shme, &par->a4, &par->a5); } @@ -204,7 +203,7 @@ static void optee_smc_handle_rpc(FAR struct optee_priv_data *priv_, case OPTEE_SMC_RPC_FUNC_FREE: shme = (FAR struct optee_shm_entry *) reg_pair_to_uintptr(par->a1, par->a2); - optee_shm_free(priv_, shme); + optee_shm_free(shme); break; case OPTEE_SMC_RPC_FUNC_FOREIGN_INTR: diff --git a/include/nuttx/tee.h b/include/nuttx/tee.h index ed50eac0cb..860021e3fb 100644 --- a/include/nuttx/tee.h +++ b/include/nuttx/tee.h @@ -378,12 +378,10 @@ struct tee_iocl_supp_send_arg #define TEE_IOC_SUPPL_SEND _IOC(TEE_IOC_MAGIC << 8, TEE_IOC_BASE + 7) -/* Shared memory specific defines */ +/* Shared memory-specific defines */ -#define TEE_SHM_REGISTER (1 << 0) /* In list of shared memory */ -#define TEE_SHM_SEC_REGISTER (1 << 1) /* TEE notified of this memory */ -#define TEE_SHM_ALLOC (1 << 2) /* The memory is malloced() and must - * be freed() */ +#define TEE_SHM_ALLOC (1 << 0) /* Kernel-malloced and must freed */ +#define TEE_SHM_REGISTER (1 << 1) /* Registered with TEE OS */ /* struct tee_ioctl_shm_register_data - Shared memory register argument * addr: [in] Start address of shared memory to register