From: Rijo Thomas Rijo-john.Thomas@amd.com
Allocate shared memory using psp_tee_alloc_buffer(), and free shared memory using psp_tee_free_buffer().
As part of cleanup, memory allocation using get_free_pages() is replaced with DMA APIs.
Signed-off-by: Rijo Thomas Rijo-john.Thomas@amd.com Signed-off-by: Jeshwanth Kumar JESHWANTHKUMAR.NK@amd.com --- drivers/tee/amdtee/amdtee_private.h | 18 +++---- drivers/tee/amdtee/call.c | 74 +++++++++++++---------------- drivers/tee/amdtee/core.c | 72 +++++++++++++++++----------- drivers/tee/amdtee/shm_pool.c | 21 ++------ 4 files changed, 89 insertions(+), 96 deletions(-)
diff --git a/drivers/tee/amdtee/amdtee_private.h b/drivers/tee/amdtee/amdtee_private.h index 6d0f7062bb87..e2bb0a21942c 100644 --- a/drivers/tee/amdtee/amdtee_private.h +++ b/drivers/tee/amdtee/amdtee_private.h @@ -13,6 +13,7 @@ #include <linux/kref.h> #include <linux/types.h> #include "amdtee_if.h" +#include <linux/psp-tee.h>
#define DRIVER_NAME "amdtee" #define DRIVER_AUTHOR "AMD-TEE Linux driver team" @@ -78,19 +79,14 @@ struct amdtee_driver_data { struct amdtee *amdtee; };
-struct shmem_desc { - void *kaddr; - u64 size; -}; - /** * struct amdtee_shm_data - Shared memory data - * @kaddr: Kernel virtual address of shared memory + * @shm_buf: Pointer to shared memory buffer * @buf_id: Buffer id of memory mapped by TEE_CMD_ID_MAP_SHARED_MEM */ struct amdtee_shm_data { struct list_head shm_node; - void *kaddr; + struct psp_tee_buffer *shm_buf; u32 buf_id; };
@@ -145,11 +141,11 @@ int amdtee_invoke_func(struct tee_context *ctx,
int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session);
-int amdtee_map_shmem(struct tee_shm *shm); +int amdtee_alloc_shmem(struct tee_shm *shm);
-void amdtee_unmap_shmem(struct tee_shm *shm); +void amdtee_free_shmem(struct tee_shm *shm);
-int handle_load_ta(void *data, u32 size, +int handle_load_ta(struct psp_tee_buffer *buf, struct tee_ioctl_open_session_arg *arg);
int handle_unload_ta(u32 ta_handle); @@ -159,7 +155,7 @@ int handle_open_session(struct tee_ioctl_open_session_arg *arg, u32 *info,
int handle_close_session(u32 ta_handle, u32 info);
-int handle_map_shmem(u32 count, struct shmem_desc *start, u32 *buf_id); +int handle_map_shmem(struct psp_tee_buffer *shm_buf, u32 *buf_id);
void handle_unmap_shmem(u32 buf_id);
diff --git a/drivers/tee/amdtee/call.c b/drivers/tee/amdtee/call.c index e9b63dcb3194..031d37cc975c 100644 --- a/drivers/tee/amdtee/call.c +++ b/drivers/tee/amdtee/call.c @@ -283,53 +283,44 @@ int handle_invoke_cmd(struct tee_ioctl_invoke_arg *arg, u32 sinfo, return ret; }
-int handle_map_shmem(u32 count, struct shmem_desc *start, u32 *buf_id) +int handle_map_shmem(struct psp_tee_buffer *shm_buf, u32 *buf_id) { struct tee_cmd_map_shared_mem *cmd; - phys_addr_t paddr; - int ret, i; u32 status; + int ret;
- if (!count || !start || !buf_id) + if (!shm_buf || !shm_buf->vaddr || !buf_id) return -EINVAL;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); if (!cmd) return -ENOMEM;
- /* Size must be page aligned */ - for (i = 0; i < count ; i++) { - if (!start[i].kaddr || (start[i].size & (PAGE_SIZE - 1))) { - ret = -EINVAL; - goto free_cmd; - } - - if ((u64)start[i].kaddr & (PAGE_SIZE - 1)) { - pr_err("map shared memory: page unaligned. addr 0x%llx", - (u64)start[i].kaddr); - ret = -EINVAL; - goto free_cmd; - } + /* Size and address must be page aligned */ + if (shm_buf->size & (PAGE_SIZE - 1)) { + ret = -EINVAL; + goto free_cmd; }
- cmd->sg_list.count = count; - - /* Create buffer list */ - for (i = 0; i < count ; i++) { - paddr = __psp_pa(start[i].kaddr); - cmd->sg_list.buf[i].hi_addr = upper_32_bits(paddr); - cmd->sg_list.buf[i].low_addr = lower_32_bits(paddr); - cmd->sg_list.buf[i].size = start[i].size; - cmd->sg_list.size += cmd->sg_list.buf[i].size; - - pr_debug("buf[%d]:hi addr = 0x%x\n", i, - cmd->sg_list.buf[i].hi_addr); - pr_debug("buf[%d]:low addr = 0x%x\n", i, - cmd->sg_list.buf[i].low_addr); - pr_debug("buf[%d]:size = 0x%x\n", i, cmd->sg_list.buf[i].size); - pr_debug("list size = 0x%x\n", cmd->sg_list.size); + if ((u64)shm_buf->vaddr & (PAGE_SIZE - 1)) { + pr_err("map shared memory: page unaligned. addr 0x%llx", + (u64)shm_buf->vaddr); + ret = -EINVAL; + goto free_cmd; }
+ /* Update sg list */ + cmd->sg_list.count = 1; + cmd->sg_list.buf[0].hi_addr = upper_32_bits(shm_buf->paddr); + cmd->sg_list.buf[0].low_addr = lower_32_bits(shm_buf->paddr); + cmd->sg_list.buf[0].size = shm_buf->size; + cmd->sg_list.size = cmd->sg_list.buf[0].size; + + pr_debug("buf: hi addr = 0x%x\n", cmd->sg_list.buf[0].hi_addr); + pr_debug("buf: low addr = 0x%x\n", cmd->sg_list.buf[0].low_addr); + pr_debug("buf: size = 0x%x\n", cmd->sg_list.buf[0].size); + pr_debug("list size = 0x%x\n", cmd->sg_list.size); + *buf_id = 0;
ret = psp_tee_process_cmd(TEE_CMD_ID_MAP_SHARED_MEM, (void *)cmd, @@ -396,25 +387,24 @@ int handle_open_session(struct tee_ioctl_open_session_arg *arg, u32 *info, return ret; }
-int handle_load_ta(void *data, u32 size, struct tee_ioctl_open_session_arg *arg) +int handle_load_ta(struct psp_tee_buffer *buf, + struct tee_ioctl_open_session_arg *arg) { struct tee_cmd_unload_ta unload_cmd = {}; struct tee_cmd_load_ta load_cmd = {}; - phys_addr_t blob; int ret;
- if (size == 0 || !data || !arg) + if (buf->size == 0 || !buf->paddr || !arg) return -EINVAL;
- blob = __psp_pa(data); - if (blob & (PAGE_SIZE - 1)) { - pr_err("load TA: page unaligned. blob 0x%llx", blob); + if (buf->dma & (PAGE_SIZE - 1)) { + pr_err("load TA: page unaligned. addr 0x%llx", buf->dma); return -EINVAL; }
- load_cmd.hi_addr = upper_32_bits(blob); - load_cmd.low_addr = lower_32_bits(blob); - load_cmd.size = size; + load_cmd.hi_addr = upper_32_bits(buf->paddr); + load_cmd.low_addr = lower_32_bits(buf->paddr); + load_cmd.size = buf->size;
mutex_lock(&ta_refcount_mutex);
diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c index 3c15f6a9e91c..37784360fc10 100644 --- a/drivers/tee/amdtee/core.c +++ b/drivers/tee/amdtee/core.c @@ -17,6 +17,7 @@ #include "amdtee_private.h" #include "../tee_private.h" #include <linux/psp-tee.h> +#include <linux/psp.h>
static struct amdtee_driver_data *drv_data; static DEFINE_MUTEX(session_list_mutex); @@ -158,7 +159,8 @@ u32 get_buffer_id(struct tee_shm *shm)
mutex_lock(&ctxdata->shm_mutex); list_for_each_entry(shmdata, &ctxdata->shm_list, shm_node) - if (shmdata->kaddr == shm->kaddr) { + if (shmdata->shm_buf && + shmdata->shm_buf->vaddr == shm->kaddr) { buf_id = shmdata->buf_id; break; } @@ -168,11 +170,13 @@ u32 get_buffer_id(struct tee_shm *shm) }
static DEFINE_MUTEX(drv_mutex); -static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta, - size_t *ta_size) +static int copy_ta_binary(struct tee_context *ctx, void *ptr, + struct psp_tee_buffer **bufp) { const struct firmware *fw; char fw_name[TA_PATH_MAX]; + struct psp_tee_buffer *buf; + unsigned long size; struct { u32 lo; u16 mid; @@ -201,15 +205,16 @@ static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta, goto unlock; }
- *ta_size = roundup(fw->size, PAGE_SIZE); - *ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size)); - if (!*ta) { - pr_err("%s: get_free_pages failed\n", __func__); + size = roundup(fw->size, PAGE_SIZE); + buf = psp_tee_alloc_buffer(size, GFP_KERNEL); + if (!buf) { + pr_err("TA binary memory allocation failed\n"); rc = -ENOMEM; goto rel_fw; } + memcpy(buf->vaddr, fw->data, fw->size); + *bufp = buf;
- memcpy(*ta, fw->data, fw->size); rel_fw: release_firmware(fw); unlock: @@ -234,24 +239,23 @@ int amdtee_open_session(struct tee_context *ctx, { struct amdtee_context_data *ctxdata = ctx->data; struct amdtee_session *sess = NULL; + struct psp_tee_buffer *buf; u32 session_info, ta_handle; - size_t ta_size; int rc, i; - void *ta;
if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) { pr_err("unsupported client login method\n"); return -EINVAL; }
- rc = copy_ta_binary(ctx, &arg->uuid[0], &ta, &ta_size); + rc = copy_ta_binary(ctx, &arg->uuid[0], &buf); if (rc) { pr_err("failed to copy TA binary\n"); return rc; }
/* Load the TA binary into TEE environment */ - handle_load_ta(ta, ta_size, arg); + handle_load_ta(buf, arg); if (arg->ret != TEEC_SUCCESS) goto out;
@@ -298,7 +302,7 @@ int amdtee_open_session(struct tee_context *ctx, }
out: - free_pages((u64)ta, get_order(ta_size)); + psp_tee_free_buffer(buf); return rc; }
@@ -338,51 +342,62 @@ int amdtee_close_session(struct tee_context *ctx, u32 session) return 0; }
-int amdtee_map_shmem(struct tee_shm *shm) +int amdtee_alloc_shmem(struct tee_shm *shm) { struct amdtee_context_data *ctxdata; struct amdtee_shm_data *shmnode; - struct shmem_desc shmem; - int rc, count; + struct psp_tee_buffer *shm_buf; u32 buf_id; + int rc;
if (!shm) return -EINVAL;
- shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL); - if (!shmnode) + shm_buf = psp_tee_alloc_buffer(shm->size, GFP_KERNEL | __GFP_ZERO); + if (!shm_buf) return -ENOMEM;
- count = 1; - shmem.kaddr = shm->kaddr; - shmem.size = shm->size; + shm->kaddr = shm_buf->vaddr; + shm->paddr = __psp_pa(shm_buf->vaddr); + + shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL); + if (!shmnode) { + rc = -ENOMEM; + goto free_dmabuf; + }
/* * Send a MAP command to TEE and get the corresponding * buffer Id */ - rc = handle_map_shmem(count, &shmem, &buf_id); + rc = handle_map_shmem(shm_buf, &buf_id); if (rc) { pr_err("map_shmem failed: ret = %d\n", rc); - kfree(shmnode); - return rc; + goto free_shmnode; }
- shmnode->kaddr = shm->kaddr; + shmnode->shm_buf = shm_buf; shmnode->buf_id = buf_id; ctxdata = shm->ctx->data; mutex_lock(&ctxdata->shm_mutex); list_add(&shmnode->shm_node, &ctxdata->shm_list); mutex_unlock(&ctxdata->shm_mutex);
- pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr); + pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shm->kaddr);
return 0; + +free_shmnode: + kfree(shmnode); +free_dmabuf: + psp_tee_free_buffer(shm_buf); + return rc; }
-void amdtee_unmap_shmem(struct tee_shm *shm) +void amdtee_free_shmem(struct tee_shm *shm) { struct amdtee_context_data *ctxdata; + struct psp_tee_buffer *shm_buf = NULL; struct amdtee_shm_data *shmnode; u32 buf_id;
@@ -390,6 +405,7 @@ void amdtee_unmap_shmem(struct tee_shm *shm) return;
buf_id = get_buffer_id(shm); + /* Unmap the shared memory from TEE */ handle_unmap_shmem(buf_id);
@@ -398,10 +414,12 @@ void amdtee_unmap_shmem(struct tee_shm *shm) list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node) if (buf_id == shmnode->buf_id) { list_del(&shmnode->shm_node); + shm_buf = shmnode->shm_buf; kfree(shmnode); break; } mutex_unlock(&ctxdata->shm_mutex); + psp_tee_free_buffer(shm_buf); }
int amdtee_invoke_func(struct tee_context *ctx, diff --git a/drivers/tee/amdtee/shm_pool.c b/drivers/tee/amdtee/shm_pool.c index f0303126f199..443874c82611 100644 --- a/drivers/tee/amdtee/shm_pool.c +++ b/drivers/tee/amdtee/shm_pool.c @@ -12,25 +12,13 @@ static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, size_t size, size_t align) { unsigned int order = get_order(size); - unsigned long va; int rc;
- /* - * Ignore alignment since this is already going to be page aligned - * and there's no need for any larger alignment. - */ - va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order); - if (!va) - return -ENOMEM; - - shm->kaddr = (void *)va; - shm->paddr = __psp_pa((void *)va); shm->size = PAGE_SIZE << order;
- /* Map the allocated memory in to TEE */ - rc = amdtee_map_shmem(shm); + /* Allocate and map memory in to TEE */ + rc = amdtee_alloc_shmem(shm); if (rc) { - free_pages(va, order); shm->kaddr = NULL; return rc; } @@ -41,8 +29,9 @@ static int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm, static void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm) { /* Unmap the shared memory from TEE */ - amdtee_unmap_shmem(shm); - free_pages((unsigned long)shm->kaddr, get_order(shm->size)); + amdtee_free_shmem(shm); + + shm->size = 0; shm->kaddr = NULL; }