/* * tee_mmu_map - alloc and fill mmu mapping table for a user TA (uTA). * * param - Contains the physical addr of the input buffers * Returns logical addresses * * Allocate a table to store the N first section entries of the MMU L1 table * used to map the target user TA, and clear table to 0. * Load mapping for the TA stack_heap area, code area and params area (params * are the 4 GP TEE TA invoke parameters buffer). */ TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param) { TEE_Result res = TEE_SUCCESS; paddr_t pa = 0; uintptr_t smem; size_t n; TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); res = tee_mmu_umap_init(ctx->mmu); if (res != TEE_SUCCESS) goto exit; /* * Map stack */ smem = tee_mm_get_smem(ctx->mm_stack); if (core_va2pa((void *)smem, &pa)) { res = TEE_ERROR_SECURITY; goto exit; } tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_HEAP_STACK_IDX, CORE_MMU_USER_CODE_SIZE, pa, tee_mm_get_bytes(ctx->mm_stack), TEE_MMU_UDATA_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR); /* * Map code */ smem = tee_mm_get_smem(ctx->mm); if (core_va2pa((void *)smem, &pa)) { res = TEE_ERROR_SECURITY; goto exit; } tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_CODE_IDX, CORE_MMU_USER_CODE_SIZE, pa, tee_mm_get_bytes(ctx->mm), TEE_MMU_UCODE_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR); for (n = 0; n < 4; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); TEE_Param *p = ¶m->params[n]; uint32_t attr = TEE_MMU_UDATA_ATTR; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if (p->memref.size == 0) continue; if (tee_pbuf_is_non_sec(p->memref.buffer, p->memref.size)) attr &= ~TEE_MATTR_SECURE; if (param->param_attr[n] & TEESMC_ATTR_CACHE_I_WRITE_THR) attr |= TEE_MATTR_I_WRITE_THR; if (param->param_attr[n] & TEESMC_ATTR_CACHE_I_WRITE_BACK) attr |= TEE_MATTR_I_WRITE_BACK; if (param->param_attr[n] & TEESMC_ATTR_CACHE_O_WRITE_THR) attr |= TEE_MATTR_O_WRITE_THR; if (param->param_attr[n] & TEESMC_ATTR_CACHE_O_WRITE_BACK) attr |= TEE_MATTR_O_WRITE_BACK; res = tee_mmu_umap_add_param(ctx->mmu, (paddr_t)p->memref.buffer, p->memref.size, attr); if (res != TEE_SUCCESS) goto exit; } res = tee_mmu_umap_set_vas(ctx->mmu); if (res != TEE_SUCCESS) goto exit; for (n = 0; n < 4; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); TEE_Param *p = ¶m->params[n]; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if (p->memref.size == 0) continue; res = tee_mmu_user_pa2va(ctx, (paddr_t)p->memref.buffer, &p->memref.buffer); if (res != TEE_SUCCESS) goto exit; } ctx->mmu->ta_private_vmem_start = ctx->mmu->table[0].va; n = TEE_MMU_UMAP_MAX_ENTRIES; do { n--; } while (n && !ctx->mmu->table[n].size); ctx->mmu->ta_private_vmem_end = ctx->mmu->table[n].va + ctx->mmu->table[n].size; exit: if (res != TEE_SUCCESS) tee_mmu_umap_clear(ctx->mmu); return res; }
TEE_Result tee_mmu_map_param(struct user_ta_ctx *utc, struct tee_ta_param *param) { TEE_Result res = TEE_SUCCESS; size_t n; /* Clear all the param entries as they can hold old information */ memset(utc->mmu->table + TEE_MMU_UMAP_PARAM_IDX, 0, (TEE_MMU_UMAP_MAX_ENTRIES - TEE_MMU_UMAP_PARAM_IDX) * sizeof(struct tee_mmap_region)); for (n = 0; n < 4; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); TEE_Param *p = ¶m->params[n]; uint32_t attr = TEE_MMU_UDATA_ATTR; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if(param_type == TEE_PARAM_TYPE_MEMREF_INPUT) attr = TEE_MMU_UDATA_RATTR; if (p->memref.size == 0) continue; if (tee_pbuf_is_non_sec(p->memref.buffer, p->memref.size)) attr &= ~TEE_MATTR_SECURE; if (param->param_attr[n] == OPTEE_SMC_SHM_CACHED) attr |= TEE_MATTR_CACHE_CACHED << TEE_MATTR_CACHE_SHIFT; else attr |= TEE_MATTR_CACHE_NONCACHE << TEE_MATTR_CACHE_SHIFT; res = tee_mmu_umap_add_param(utc->mmu, (paddr_t)p->memref.buffer, p->memref.size, attr); if (res != TEE_SUCCESS) return res; } res = tee_mmu_umap_set_vas(utc->mmu); if (res != TEE_SUCCESS) return res; for (n = 0; n < 4; n++) { uint32_t param_type = TEE_PARAM_TYPE_GET(param->types, n); TEE_Param *p = ¶m->params[n]; if (param_type != TEE_PARAM_TYPE_MEMREF_INPUT && param_type != TEE_PARAM_TYPE_MEMREF_OUTPUT && param_type != TEE_PARAM_TYPE_MEMREF_INOUT) continue; if (p->memref.size == 0) continue; res = tee_mmu_user_pa2va_helper(utc, (paddr_t)p->memref.buffer, &p->memref.buffer); if (res != TEE_SUCCESS) return res; } utc->mmu->ta_private_vmem_start = utc->mmu->table[0].va; n = TEE_MMU_UMAP_MAX_ENTRIES; do { n--; } while (n && !utc->mmu->table[n].size); utc->mmu->ta_private_vmem_end = utc->mmu->table[n].va + utc->mmu->table[n].size; return check_pgt_avail(utc->mmu->ta_private_vmem_start, utc->mmu->ta_private_vmem_end); }