Merge tag 'tee-drv-dynamic-shm-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee into next/drivers
Pull "tee dynamic shm for v4.16" from Jens Wiklander:
This pull request enables dynamic shared memory support in the TEE
subsystem as a whole and in OP-TEE in particular.
Global Platform TEE specification [1] allows client applications
to register part of own memory as a shared buffer between
application and TEE. This allows fast zero-copy communication between
TEE and REE. But current implementation of TEE in Linux does not support
this feature.
Also, current implementation of OP-TEE transport uses fixed size
pre-shared buffer for all communications with OP-TEE OS. This is okay
in the most use cases. But this prevents use of OP-TEE in virtualized
environments, because:
a) We can't share the same buffer between different virtual machines
b) Physically contiguous memory as seen by VM can be non-contiguous
in reality (and as seen by OP-TEE OS) due to second stage of
MMU translation.
c) Size of this pre-shared buffer is limited.
So, first part of this pull request adds generic register/unregister
interface to tee subsystem. The second part adds necessary features into
OP-TEE driver, so it can use not only static pre-shared buffer, but
whole RAM to communicate with OP-TEE OS.
This change is backwards compatible allowing older secure world or
user space to work with newer kernels and vice versa.
[1] https://www.globalplatform.org/specificationsdevice.asp
* tag 'tee-drv-dynamic-shm-for-v4.16' of https://git.linaro.org/people/jens.wiklander/linux-tee:
tee: shm: inline tee_shm_get_id()
tee: use reference counting for tee_context
tee: optee: enable dynamic SHM support
tee: optee: add optee-specific shared pool implementation
tee: optee: store OP-TEE capabilities in private data
tee: optee: add registered buffers handling into RPC calls
tee: optee: add registered shared parameters handling
tee: optee: add shared buffer registration functions
tee: optee: add page list manipulation functions
tee: optee: Update protocol definitions
tee: shm: add page accessor functions
tee: shm: add accessors for buffer size and page offset
tee: add register user memory
tee: flexible shared memory pool creation
This commit is contained in:
@@ -54,6 +54,7 @@ static int tee_open(struct inode *inode, struct file *filp)
|
||||
goto err;
|
||||
}
|
||||
|
||||
kref_init(&ctx->refcount);
|
||||
ctx->teedev = teedev;
|
||||
INIT_LIST_HEAD(&ctx->list_shm);
|
||||
filp->private_data = ctx;
|
||||
@@ -68,19 +69,40 @@ err:
|
||||
return rc;
|
||||
}
|
||||
|
||||
void teedev_ctx_get(struct tee_context *ctx)
|
||||
{
|
||||
if (ctx->releasing)
|
||||
return;
|
||||
|
||||
kref_get(&ctx->refcount);
|
||||
}
|
||||
|
||||
static void teedev_ctx_release(struct kref *ref)
|
||||
{
|
||||
struct tee_context *ctx = container_of(ref, struct tee_context,
|
||||
refcount);
|
||||
ctx->releasing = true;
|
||||
ctx->teedev->desc->ops->release(ctx);
|
||||
kfree(ctx);
|
||||
}
|
||||
|
||||
void teedev_ctx_put(struct tee_context *ctx)
|
||||
{
|
||||
if (ctx->releasing)
|
||||
return;
|
||||
|
||||
kref_put(&ctx->refcount, teedev_ctx_release);
|
||||
}
|
||||
|
||||
static void teedev_close_context(struct tee_context *ctx)
|
||||
{
|
||||
tee_device_put(ctx->teedev);
|
||||
teedev_ctx_put(ctx);
|
||||
}
|
||||
|
||||
static int tee_release(struct inode *inode, struct file *filp)
|
||||
{
|
||||
struct tee_context *ctx = filp->private_data;
|
||||
struct tee_device *teedev = ctx->teedev;
|
||||
struct tee_shm *shm;
|
||||
|
||||
ctx->teedev->desc->ops->release(ctx);
|
||||
mutex_lock(&ctx->teedev->mutex);
|
||||
list_for_each_entry(shm, &ctx->list_shm, link)
|
||||
shm->ctx = NULL;
|
||||
mutex_unlock(&ctx->teedev->mutex);
|
||||
kfree(ctx);
|
||||
tee_device_put(teedev);
|
||||
teedev_close_context(filp->private_data);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -114,8 +136,6 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx,
|
||||
if (data.flags)
|
||||
return -EINVAL;
|
||||
|
||||
data.id = -1;
|
||||
|
||||
shm = tee_shm_alloc(ctx, data.size, TEE_SHM_MAPPED | TEE_SHM_DMA_BUF);
|
||||
if (IS_ERR(shm))
|
||||
return PTR_ERR(shm);
|
||||
@@ -138,6 +158,43 @@ static int tee_ioctl_shm_alloc(struct tee_context *ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
tee_ioctl_shm_register(struct tee_context *ctx,
|
||||
struct tee_ioctl_shm_register_data __user *udata)
|
||||
{
|
||||
long ret;
|
||||
struct tee_ioctl_shm_register_data data;
|
||||
struct tee_shm *shm;
|
||||
|
||||
if (copy_from_user(&data, udata, sizeof(data)))
|
||||
return -EFAULT;
|
||||
|
||||
/* Currently no input flags are supported */
|
||||
if (data.flags)
|
||||
return -EINVAL;
|
||||
|
||||
shm = tee_shm_register(ctx, data.addr, data.length,
|
||||
TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED);
|
||||
if (IS_ERR(shm))
|
||||
return PTR_ERR(shm);
|
||||
|
||||
data.id = shm->id;
|
||||
data.flags = shm->flags;
|
||||
data.length = shm->size;
|
||||
|
||||
if (copy_to_user(udata, &data, sizeof(data)))
|
||||
ret = -EFAULT;
|
||||
else
|
||||
ret = tee_shm_get_fd(shm);
|
||||
/*
|
||||
* When user space closes the file descriptor the shared memory
|
||||
* should be freed or if tee_shm_get_fd() failed then it will
|
||||
* be freed immediately.
|
||||
*/
|
||||
tee_shm_put(shm);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int params_from_user(struct tee_context *ctx, struct tee_param *params,
|
||||
size_t num_params,
|
||||
struct tee_ioctl_param __user *uparams)
|
||||
@@ -578,6 +635,8 @@ static long tee_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
|
||||
return tee_ioctl_version(ctx, uarg);
|
||||
case TEE_IOC_SHM_ALLOC:
|
||||
return tee_ioctl_shm_alloc(ctx, uarg);
|
||||
case TEE_IOC_SHM_REGISTER:
|
||||
return tee_ioctl_shm_register(ctx, uarg);
|
||||
case TEE_IOC_OPEN_SESSION:
|
||||
return tee_ioctl_open_session(ctx, uarg);
|
||||
case TEE_IOC_INVOKE:
|
||||
|
||||
Reference in New Issue
Block a user