2 * Copyright (c) 2014, STMicroelectronics International N.V.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License Version 2 as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
13 #include <linux/slab.h>
14 #include <linux/device.h>
15 #include <linux/types.h>
16 #include <linux/file.h>
17 #include <linux/atomic.h>
18 #include <linux/uaccess.h>
19 #include <linux/sched.h>
22 #include "tee_core_priv.h"
26 * tee_context_dump - Dump in a buffer the informations (ctx, sess & shm)
27 * associated to a tee.
29 int tee_context_dump(struct tee *tee, char *buff, size_t len)
31 struct list_head *ptr_ctx, *ptr_sess, *ptr_shm;
32 struct tee_context *ctx;
33 struct tee_session *sess;
42 if (len < 80 || list_empty(&tee->list_ctx))
45 mutex_lock(&tee->lock);
47 list_for_each(ptr_ctx, &tee->list_ctx) {
48 ctx = list_entry(ptr_ctx, struct tee_context, entry);
50 pos += sprintf(buff + pos,
51 "[%02d] ctx=%p (refcount=%d) (usr=%d)",
53 (int)atomic_read(&ctx->refcount.
56 pos += sprintf(buff + pos, "name=\"%s\" (tgid=%d)\n",
59 if ((len - pos) < 80) {
64 if (list_empty(&ctx->list_sess))
68 list_for_each(ptr_sess, &ctx->list_sess) {
69 sess = list_entry(ptr_sess,
73 pos += sprintf(buff + pos,
74 "[%02d.%d] sess=%p sessid=%08x\n",
78 if ((len - pos) < 80) {
86 if (list_empty(&ctx->list_shm))
90 list_for_each(ptr_shm, &ctx->list_shm) {
91 shm = list_entry(ptr_shm, struct tee_shm, entry);
93 pos += sprintf(buff + pos,
94 "[%02d.%d] shm=%p paddr=%p kaddr=%p",
98 pos += sprintf(buff + pos,
102 if ((len - pos) < 80) {
114 mutex_unlock(&tee->lock);
119 * tee_context_create - Allocate and create a new context.
120 * Reference on the back-end is requested.
122 struct tee_context *tee_context_create(struct tee *tee)
125 struct tee_context *ctx;
127 dev_dbg(_DEV(tee), "%s: >\n", __func__);
129 ctx = devm_kzalloc(_DEV(tee), sizeof(struct tee_context), GFP_KERNEL);
131 dev_err(_DEV(tee), "%s: tee_context allocation failed\n",
133 return ERR_PTR(-ENOMEM);
136 kref_init(&ctx->refcount);
137 INIT_LIST_HEAD(&ctx->list_sess);
138 INIT_LIST_HEAD(&ctx->list_shm);
141 snprintf(ctx->name, sizeof(ctx->name), "%s", current->comm);
142 ctx->tgid = current->tgid;
146 devm_kfree(_DEV(tee), ctx);
150 mutex_lock(&tee->lock);
151 tee_inc_stats(&tee->stats[TEE_STATS_CONTEXT_IDX]);
152 list_add_tail(&ctx->entry, &tee->list_ctx);
153 mutex_unlock(&tee->lock);
155 dev_dbg(_DEV(ctx->tee), "%s: < ctx=%p is created\n", __func__, ctx);
160 * _tee_context_do_release - Final function to release
161 * and free a context.
163 static void _tee_context_do_release(struct kref *kref)
165 struct tee_context *ctx;
168 ctx = container_of(kref, struct tee_context, refcount);
170 BUG_ON(!ctx || !ctx->tee);
174 dev_dbg(_DEV(tee), "%s: > ctx=%p\n", __func__, ctx);
176 mutex_lock(&tee->lock);
177 tee_dec_stats(&tee->stats[TEE_STATS_CONTEXT_IDX]);
178 list_del(&ctx->entry);
179 mutex_unlock(&tee->lock);
181 devm_kfree(_DEV(tee), ctx);
184 dev_dbg(_DEV(tee), "%s: < ctx=%p is destroyed\n", __func__, ctx);
188 * tee_context_get - Increase the reference count of
191 void tee_context_get(struct tee_context *ctx)
193 BUG_ON(!ctx || !ctx->tee);
195 kref_get(&ctx->refcount);
197 dev_dbg(_DEV(ctx->tee), "%s: ctx=%p, kref=%d\n", __func__,
198 ctx, (int)atomic_read(&ctx->refcount.refcount));
201 static int is_in_list(struct tee *tee, struct list_head *entry)
205 mutex_lock(&tee->lock);
206 if ((entry->next == LIST_POISON1) && (entry->prev == LIST_POISON2))
208 mutex_unlock(&tee->lock);
213 * tee_context_put - Decreases the reference count of
214 * the context. If 0, the final
215 * release function is called.
217 void tee_context_put(struct tee_context *ctx)
219 struct tee_context *_ctx = ctx;
222 BUG_ON(!ctx || !ctx->tee);
225 if (!is_in_list(tee, &ctx->entry))
228 kref_put(&ctx->refcount, _tee_context_do_release);
230 dev_dbg(_DEV(tee), "%s: ctx=%p, kref=%d\n", __func__,
231 _ctx, (int)atomic_read(&ctx->refcount.refcount));
235 * tee_context_destroy - Request to destroy a context.
237 void tee_context_destroy(struct tee_context *ctx)
241 if (!ctx || !ctx->tee)
246 dev_dbg(_DEV(tee), "%s: ctx=%p\n", __func__, ctx);
248 tee_context_put(ctx);
251 int tee_context_copy_from_client(const struct tee_context *ctx,
252 void *dest, const void *src, size_t size)
256 if (dest && src && (size > 0)) {
258 res = copy_from_user(dest, src, size);
260 memcpy(dest, src, size);
265 struct tee_shm *tee_context_alloc_shm_tmp(struct tee_context *ctx,
266 size_t size, const void *src,
271 type &= (TEEC_MEM_INPUT | TEEC_MEM_OUTPUT);
273 shm = tee_shm_alloc(ctx->tee, size,
274 TEE_SHM_MAPPED | TEE_SHM_TEMP | type);
275 if (IS_ERR_OR_NULL(shm)) {
276 dev_err(_DEV(ctx->tee), "%s: buffer allocation failed (%ld)\n",
277 __func__, PTR_ERR(shm));
283 if (type & TEEC_MEM_INPUT) {
284 if (tee_context_copy_from_client(ctx, shm->kaddr, src, size)) {
285 dev_err(_DEV(ctx->tee),
286 "%s: tee_context_copy_from_client failed\n",
295 struct tee_shm *tee_context_create_tmpref_buffer(struct tee_context *ctx,
297 const void *buffer, int type)
299 struct tee_shm *shm = NULL;
303 case TEEC_MEMREF_TEMP_OUTPUT:
304 flags = TEEC_MEM_OUTPUT;
306 case TEEC_MEMREF_TEMP_INPUT:
307 flags = TEEC_MEM_INPUT;
309 case TEEC_MEMREF_TEMP_INOUT:
310 flags = TEEC_MEM_INPUT | TEEC_MEM_OUTPUT;
315 shm = tee_context_alloc_shm_tmp(ctx, size, buffer, flags);