Commit 5d41f1b3 authored by Jens Wiklander's avatar Jens Wiklander
Browse files

tee: replace tee_shm_alloc()



tee_shm_alloc() is replaced by three new functions,

tee_shm_alloc_user_buf() - for user mode allocations, replacing passing
the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF

tee_shm_alloc_kernel_buf() - for kernel mode allocations, slightly
optimized compared to using the flags TEE_SHM_MAPPED | TEE_SHM_DMA_BUF.

tee_shm_alloc_priv_buf() - primarily for TEE driver internal use.

This also makes the interface easier to use as we can get rid of the
somewhat hard to use flags parameter.

The TEE subsystem and the TEE drivers are updated to use the new
functions instead.

Reviewed-by: default avatarSumit Garg <sumit.garg@linaro.org>
Signed-off-by: default avatarJens Wiklander <jens.wiklander@linaro.org>
parent d88e0493
Loading
Loading
Loading
Loading
+1 −1
Original line number Original line Diff line number Diff line
@@ -120,7 +120,7 @@ struct tee_shm *optee_get_msg_arg(struct tee_context *ctx, size_t num_params,
	if (optee->rpc_arg_count)
	if (optee->rpc_arg_count)
		sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);
		sz += OPTEE_MSG_GET_ARG_SIZE(optee->rpc_arg_count);


	shm = tee_shm_alloc(ctx, sz, TEE_SHM_MAPPED | TEE_SHM_PRIV);
	shm = tee_shm_alloc_priv_buf(ctx, sz);
	if (IS_ERR(shm))
	if (IS_ERR(shm))
		return shm;
		return shm;


+2 −3
Original line number Original line Diff line number Diff line
@@ -121,10 +121,9 @@ static int __optee_enumerate_devices(u32 func)
	if (rc < 0 || !shm_size)
	if (rc < 0 || !shm_size)
		goto out_sess;
		goto out_sess;


	device_shm = tee_shm_alloc(ctx, shm_size,
	device_shm = tee_shm_alloc_kernel_buf(ctx, shm_size);
				   TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
	if (IS_ERR(device_shm)) {
	if (IS_ERR(device_shm)) {
		pr_err("tee_shm_alloc failed\n");
		pr_err("tee_shm_alloc_kernel_buf failed\n");
		rc = PTR_ERR(device_shm);
		rc = PTR_ERR(device_shm);
		goto out_sess;
		goto out_sess;
	}
	}
+2 −2
Original line number Original line Diff line number Diff line
@@ -440,8 +440,8 @@ static void handle_ffa_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
		shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
		shm = optee_rpc_cmd_alloc_suppl(ctx, arg->params[0].u.value.b);
		break;
		break;
	case OPTEE_RPC_SHM_TYPE_KERNEL:
	case OPTEE_RPC_SHM_TYPE_KERNEL:
		shm = tee_shm_alloc(optee->ctx, arg->params[0].u.value.b,
		shm = tee_shm_alloc_priv_buf(optee->ctx,
				    TEE_SHM_MAPPED | TEE_SHM_PRIV);
					     arg->params[0].u.value.b);
		break;
		break;
	default:
	default:
		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
+2 −4
Original line number Original line Diff line number Diff line
@@ -661,8 +661,7 @@ static void handle_rpc_func_cmd_shm_alloc(struct tee_context *ctx,
		shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
		shm = optee_rpc_cmd_alloc_suppl(ctx, sz);
		break;
		break;
	case OPTEE_RPC_SHM_TYPE_KERNEL:
	case OPTEE_RPC_SHM_TYPE_KERNEL:
		shm = tee_shm_alloc(optee->ctx, sz,
		shm = tee_shm_alloc_priv_buf(optee->ctx, sz);
				    TEE_SHM_MAPPED | TEE_SHM_PRIV);
		break;
		break;
	default:
	default:
		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
		arg->ret = TEEC_ERROR_BAD_PARAMETERS;
@@ -787,8 +786,7 @@ static void optee_handle_rpc(struct tee_context *ctx,


	switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
	switch (OPTEE_SMC_RETURN_GET_RPC_FUNC(param->a0)) {
	case OPTEE_SMC_RPC_FUNC_ALLOC:
	case OPTEE_SMC_RPC_FUNC_ALLOC:
		shm = tee_shm_alloc(optee->ctx, param->a1,
		shm = tee_shm_alloc_priv_buf(optee->ctx, param->a1);
				    TEE_SHM_MAPPED | TEE_SHM_PRIV);
		if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
		if (!IS_ERR(shm) && !tee_shm_get_pa(shm, 0, &pa)) {
			reg_pair_from_64(&param->a1, &param->a2, pa);
			reg_pair_from_64(&param->a1, &param->a2, pa);
			reg_pair_from_64(&param->a4, &param->a5,
			reg_pair_from_64(&param->a4, &param->a5,
+68 −40
Original line number Original line Diff line number Diff line
@@ -49,25 +49,14 @@ static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm)
	tee_device_put(teedev);
	tee_device_put(teedev);
}
}


struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
static struct tee_shm *shm_alloc_helper(struct tee_context *ctx, size_t size,
					size_t align, u32 flags, int id)
{
{
	struct tee_device *teedev = ctx->teedev;
	struct tee_device *teedev = ctx->teedev;
	struct tee_shm *shm;
	struct tee_shm *shm;
	size_t align;
	void *ret;
	void *ret;
	int rc;
	int rc;


	if (!(flags & TEE_SHM_MAPPED)) {
		dev_err(teedev->dev.parent,
			"only mapped allocations supported\n");
		return ERR_PTR(-EINVAL);
	}

	if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) {
		dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags);
		return ERR_PTR(-EINVAL);
	}

	if (!tee_device_get(teedev))
	if (!tee_device_get(teedev))
		return ERR_PTR(-EINVAL);
		return ERR_PTR(-EINVAL);


@@ -84,18 +73,16 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
	}
	}


	refcount_set(&shm->refcount, 1);
	refcount_set(&shm->refcount, 1);
	shm->flags = flags | TEE_SHM_POOL;
	shm->flags = flags;
	shm->ctx = ctx;
	shm->id = id;
	if (flags & TEE_SHM_DMA_BUF) {

		align = PAGE_SIZE;
	/*
	/*
		 * Request to register the shm in the pool allocator below
	 * We're assigning this as it is needed if the shm is to be
		 * if supported.
	 * registered. If this function returns OK then the caller expected
	 * to call teedev_ctx_get() or clear shm->ctx in case it's not
	 * needed any longer.
	 */
	 */
		shm->flags |= TEE_SHM_REGISTER;
	shm->ctx = ctx;
	} else {
		align = 2 * sizeof(long);
	}


	rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
	rc = teedev->pool->ops->alloc(teedev->pool, shm, size, align);
	if (rc) {
	if (rc) {
@@ -103,28 +90,14 @@ struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
		goto err_kfree;
		goto err_kfree;
	}
	}


	if (flags & TEE_SHM_DMA_BUF) {
		mutex_lock(&teedev->mutex);
		shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
		mutex_unlock(&teedev->mutex);
		if (shm->id < 0) {
			ret = ERR_PTR(shm->id);
			goto err_pool_free;
		}
	}

	teedev_ctx_get(ctx);
	teedev_ctx_get(ctx);

	return shm;
	return shm;
err_pool_free:
	teedev->pool->ops->free(teedev->pool, shm);
err_kfree:
err_kfree:
	kfree(shm);
	kfree(shm);
err_dev_put:
err_dev_put:
	tee_device_put(teedev);
	tee_device_put(teedev);
	return ret;
	return ret;
}
}
EXPORT_SYMBOL_GPL(tee_shm_alloc);


/**
/**
 * tee_shm_alloc_user_buf() - Allocate shared memory for user space
 * tee_shm_alloc_user_buf() - Allocate shared memory for user space
@@ -140,7 +113,36 @@ EXPORT_SYMBOL_GPL(tee_shm_alloc);
 */
 */
struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
{
{
	return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
	u32 flags = TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_REGISTER |
		    TEE_SHM_POOL;
	struct tee_device *teedev = ctx->teedev;
	struct tee_shm *shm;
	void *ret;
	int id;

	mutex_lock(&teedev->mutex);
	id = idr_alloc(&teedev->idr, NULL, 1, 0, GFP_KERNEL);
	mutex_unlock(&teedev->mutex);
	if (id < 0)
		return ERR_PTR(id);

	shm = shm_alloc_helper(ctx, size, PAGE_SIZE, flags, id);
	if (IS_ERR(shm)) {
		mutex_lock(&teedev->mutex);
		idr_remove(&teedev->idr, id);
		mutex_unlock(&teedev->mutex);
		return shm;
	}

	mutex_lock(&teedev->mutex);
	ret = idr_replace(&teedev->idr, shm, id);
	mutex_unlock(&teedev->mutex);
	if (IS_ERR(ret)) {
		tee_shm_free(shm);
		return ret;
	}

	return shm;
}
}


/**
/**
@@ -157,10 +159,36 @@ struct tee_shm *tee_shm_alloc_user_buf(struct tee_context *ctx, size_t size)
 */
 */
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size)
{
{
	return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED);
	u32 flags = TEE_SHM_MAPPED | TEE_SHM_REGISTER | TEE_SHM_POOL;

	return shm_alloc_helper(ctx, size, PAGE_SIZE, flags, -1);
}
}
EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);
EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf);


/**
 * tee_shm_alloc_priv_buf() - Allocate shared memory for a privately shared
 *			      kernel buffer
 * @ctx:	Context that allocates the shared memory
 * @size:	Requested size of shared memory
 *
 * This function returns similar shared memory as
 * tee_shm_alloc_kernel_buf(), but with the difference that the memory
 * might not be registered in secure world in case the driver supports
 * passing memory not registered in advance.
 *
 * This function should normally only be used internally in the TEE
 * drivers.
 *
 * @returns a pointer to 'struct tee_shm'
 */
struct tee_shm *tee_shm_alloc_priv_buf(struct tee_context *ctx, size_t size)
{
	u32 flags = TEE_SHM_MAPPED | TEE_SHM_PRIV | TEE_SHM_POOL;

	return shm_alloc_helper(ctx, size, sizeof(long) * 2, flags, -1);
}
EXPORT_SYMBOL_GPL(tee_shm_alloc_priv_buf);

struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
				 size_t length, u32 flags)
				 size_t length, u32 flags)
{
{
Loading