Example #1
0
/*
 * 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 = &param->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 = &param->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;
}
Example #2
0
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 = &param->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 = &param->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);
}