xref: /linux/drivers/tee/amdtee/core.c (revision 297d9111e9fcf47dd1dcc6f79bba915f35378d01)
1 // SPDX-License-Identifier: MIT
2 /*
3  * Copyright 2019 Advanced Micro Devices, Inc.
4  */
5 
6  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
7 
8 #include <linux/errno.h>
9 #include <linux/device.h>
10 #include <linux/firmware.h>
11 #include <linux/io.h>
12 #include <linux/mm.h>
13 #include <linux/module.h>
14 #include <linux/psp-tee.h>
15 #include <linux/slab.h>
16 #include <linux/string.h>
17 #include <linux/tee_core.h>
18 #include <linux/types.h>
19 #include <linux/uaccess.h>
20 
21 #include "amdtee_private.h"
22 
23 static struct amdtee_driver_data *drv_data;
24 static DEFINE_MUTEX(session_list_mutex);
25 
amdtee_get_version(struct tee_device * teedev,struct tee_ioctl_version_data * vers)26 static void amdtee_get_version(struct tee_device *teedev,
27 			       struct tee_ioctl_version_data *vers)
28 {
29 	struct tee_ioctl_version_data v = {
30 		.impl_id = TEE_IMPL_ID_AMDTEE,
31 		.impl_caps = 0,
32 		.gen_caps = TEE_GEN_CAP_GP,
33 	};
34 	*vers = v;
35 }
36 
amdtee_open(struct tee_context * ctx)37 static int amdtee_open(struct tee_context *ctx)
38 {
39 	struct amdtee_context_data *ctxdata;
40 
41 	ctxdata = kzalloc(sizeof(*ctxdata), GFP_KERNEL);
42 	if (!ctxdata)
43 		return -ENOMEM;
44 
45 	INIT_LIST_HEAD(&ctxdata->sess_list);
46 	INIT_LIST_HEAD(&ctxdata->shm_list);
47 	mutex_init(&ctxdata->shm_mutex);
48 
49 	ctx->data = ctxdata;
50 	return 0;
51 }
52 
release_session(struct amdtee_session * sess)53 static void release_session(struct amdtee_session *sess)
54 {
55 	int i;
56 
57 	/* Close any open session */
58 	for (i = 0; i < TEE_NUM_SESSIONS; ++i) {
59 		/* Check if session entry 'i' is valid */
60 		if (!test_bit(i, sess->sess_mask))
61 			continue;
62 
63 		handle_close_session(sess->ta_handle, sess->session_info[i]);
64 		handle_unload_ta(sess->ta_handle);
65 	}
66 
67 	kfree(sess);
68 }
69 
amdtee_release(struct tee_context * ctx)70 static void amdtee_release(struct tee_context *ctx)
71 {
72 	struct amdtee_context_data *ctxdata = ctx->data;
73 
74 	if (!ctxdata)
75 		return;
76 
77 	while (true) {
78 		struct amdtee_session *sess;
79 
80 		sess = list_first_entry_or_null(&ctxdata->sess_list,
81 						struct amdtee_session,
82 						list_node);
83 
84 		if (!sess)
85 			break;
86 
87 		list_del(&sess->list_node);
88 		release_session(sess);
89 	}
90 	mutex_destroy(&ctxdata->shm_mutex);
91 	kfree(ctxdata);
92 
93 	ctx->data = NULL;
94 }
95 
96 /**
97  * alloc_session() - Allocate a session structure
98  * @ctxdata:    TEE Context data structure
99  * @session:    Session ID for which 'struct amdtee_session' structure is to be
100  *              allocated.
101  *
102  * Scans the TEE context's session list to check if TA is already loaded in to
103  * TEE. If yes, returns the 'session' structure for that TA. Else allocates,
104  * initializes a new 'session' structure and adds it to context's session list.
105  *
106  * The caller must hold a mutex.
107  *
108  * Returns:
109  * 'struct amdtee_session *' on success and NULL on failure.
110  */
alloc_session(struct amdtee_context_data * ctxdata,u32 session)111 static struct amdtee_session *alloc_session(struct amdtee_context_data *ctxdata,
112 					    u32 session)
113 {
114 	struct amdtee_session *sess;
115 	u32 ta_handle = get_ta_handle(session);
116 
117 	/* Scan session list to check if TA is already loaded in to TEE */
118 	list_for_each_entry(sess, &ctxdata->sess_list, list_node)
119 		if (sess->ta_handle == ta_handle) {
120 			kref_get(&sess->refcount);
121 			return sess;
122 		}
123 
124 	/* Allocate a new session and add to list */
125 	sess = kzalloc(sizeof(*sess), GFP_KERNEL);
126 	if (sess) {
127 		sess->ta_handle = ta_handle;
128 		kref_init(&sess->refcount);
129 		spin_lock_init(&sess->lock);
130 		list_add(&sess->list_node, &ctxdata->sess_list);
131 	}
132 
133 	return sess;
134 }
135 
136 /* Requires mutex to be held */
find_session(struct amdtee_context_data * ctxdata,u32 session)137 static struct amdtee_session *find_session(struct amdtee_context_data *ctxdata,
138 					   u32 session)
139 {
140 	u32 ta_handle = get_ta_handle(session);
141 	u32 index = get_session_index(session);
142 	struct amdtee_session *sess;
143 
144 	if (index >= TEE_NUM_SESSIONS)
145 		return NULL;
146 
147 	list_for_each_entry(sess, &ctxdata->sess_list, list_node)
148 		if (ta_handle == sess->ta_handle &&
149 		    test_bit(index, sess->sess_mask))
150 			return sess;
151 
152 	return NULL;
153 }
154 
get_buffer_id(struct tee_shm * shm)155 u32 get_buffer_id(struct tee_shm *shm)
156 {
157 	struct amdtee_context_data *ctxdata = shm->ctx->data;
158 	struct amdtee_shm_data *shmdata;
159 	u32 buf_id = 0;
160 
161 	mutex_lock(&ctxdata->shm_mutex);
162 	list_for_each_entry(shmdata, &ctxdata->shm_list, shm_node)
163 		if (shmdata->kaddr == shm->kaddr) {
164 			buf_id = shmdata->buf_id;
165 			break;
166 		}
167 	mutex_unlock(&ctxdata->shm_mutex);
168 
169 	return buf_id;
170 }
171 
172 static DEFINE_MUTEX(drv_mutex);
copy_ta_binary(struct tee_context * ctx,void * ptr,void ** ta,size_t * ta_size)173 static int copy_ta_binary(struct tee_context *ctx, void *ptr, void **ta,
174 			  size_t *ta_size)
175 {
176 	const struct firmware *fw;
177 	char fw_name[TA_PATH_MAX];
178 	struct {
179 		u32 lo;
180 		u16 mid;
181 		u16 hi_ver;
182 		u8 seq_n[8];
183 	} *uuid = ptr;
184 	int n, rc = 0;
185 
186 	n = snprintf(fw_name, TA_PATH_MAX,
187 		     "%s/%08x-%04x-%04x-%02x%02x%02x%02x%02x%02x%02x%02x.bin",
188 		     TA_LOAD_PATH, uuid->lo, uuid->mid, uuid->hi_ver,
189 		     uuid->seq_n[0], uuid->seq_n[1],
190 		     uuid->seq_n[2], uuid->seq_n[3],
191 		     uuid->seq_n[4], uuid->seq_n[5],
192 		     uuid->seq_n[6], uuid->seq_n[7]);
193 	if (n < 0 || n >= TA_PATH_MAX) {
194 		pr_err("failed to get firmware name\n");
195 		return -EINVAL;
196 	}
197 
198 	mutex_lock(&drv_mutex);
199 	n = request_firmware(&fw, fw_name, &ctx->teedev->dev);
200 	if (n) {
201 		pr_err("failed to load firmware %s\n", fw_name);
202 		rc = -ENOMEM;
203 		goto unlock;
204 	}
205 
206 	*ta_size = roundup(fw->size, PAGE_SIZE);
207 	*ta = (void *)__get_free_pages(GFP_KERNEL, get_order(*ta_size));
208 	if (!*ta) {
209 		pr_err("%s: get_free_pages failed\n", __func__);
210 		rc = -ENOMEM;
211 		goto rel_fw;
212 	}
213 
214 	memcpy(*ta, fw->data, fw->size);
215 rel_fw:
216 	release_firmware(fw);
217 unlock:
218 	mutex_unlock(&drv_mutex);
219 	return rc;
220 }
221 
222 /* mutex must be held by caller */
destroy_session(struct kref * ref)223 static void destroy_session(struct kref *ref)
224 {
225 	struct amdtee_session *sess = container_of(ref, struct amdtee_session,
226 						   refcount);
227 
228 	list_del(&sess->list_node);
229 	mutex_unlock(&session_list_mutex);
230 	kfree(sess);
231 }
232 
amdtee_open_session(struct tee_context * ctx,struct tee_ioctl_open_session_arg * arg,struct tee_param * param)233 int amdtee_open_session(struct tee_context *ctx,
234 			struct tee_ioctl_open_session_arg *arg,
235 			struct tee_param *param)
236 {
237 	struct amdtee_context_data *ctxdata = ctx->data;
238 	struct amdtee_session *sess = NULL;
239 	u32 session_info, ta_handle;
240 	size_t ta_size;
241 	int rc, i;
242 	void *ta;
243 
244 	if (arg->clnt_login != TEE_IOCTL_LOGIN_PUBLIC) {
245 		pr_err("unsupported client login method\n");
246 		return -EINVAL;
247 	}
248 
249 	rc = copy_ta_binary(ctx, &arg->uuid[0], &ta, &ta_size);
250 	if (rc) {
251 		pr_err("failed to copy TA binary\n");
252 		return rc;
253 	}
254 
255 	/* Load the TA binary into TEE environment */
256 	handle_load_ta(ta, ta_size, arg);
257 	if (arg->ret != TEEC_SUCCESS)
258 		goto out;
259 
260 	ta_handle = get_ta_handle(arg->session);
261 
262 	mutex_lock(&session_list_mutex);
263 	sess = alloc_session(ctxdata, arg->session);
264 	mutex_unlock(&session_list_mutex);
265 
266 	if (!sess) {
267 		handle_unload_ta(ta_handle);
268 		rc = -ENOMEM;
269 		goto out;
270 	}
271 
272 	/* Open session with loaded TA */
273 	handle_open_session(arg, &session_info, param);
274 	if (arg->ret != TEEC_SUCCESS) {
275 		pr_err("open_session failed %d\n", arg->ret);
276 		handle_unload_ta(ta_handle);
277 		kref_put_mutex(&sess->refcount, destroy_session,
278 			       &session_list_mutex);
279 		goto out;
280 	}
281 
282 	/* Find an empty session index for the given TA */
283 	spin_lock(&sess->lock);
284 	i = find_first_zero_bit(sess->sess_mask, TEE_NUM_SESSIONS);
285 	if (i < TEE_NUM_SESSIONS) {
286 		sess->session_info[i] = session_info;
287 		set_session_id(ta_handle, i, &arg->session);
288 		set_bit(i, sess->sess_mask);
289 	}
290 	spin_unlock(&sess->lock);
291 
292 	if (i >= TEE_NUM_SESSIONS) {
293 		pr_err("reached maximum session count %d\n", TEE_NUM_SESSIONS);
294 		handle_close_session(ta_handle, session_info);
295 		handle_unload_ta(ta_handle);
296 		kref_put_mutex(&sess->refcount, destroy_session,
297 			       &session_list_mutex);
298 		rc = -ENOMEM;
299 		goto out;
300 	}
301 
302 out:
303 	free_pages((u64)ta, get_order(ta_size));
304 	return rc;
305 }
306 
amdtee_close_session(struct tee_context * ctx,u32 session)307 int amdtee_close_session(struct tee_context *ctx, u32 session)
308 {
309 	struct amdtee_context_data *ctxdata = ctx->data;
310 	u32 i, ta_handle, session_info;
311 	struct amdtee_session *sess;
312 
313 	pr_debug("%s: sid = 0x%x\n", __func__, session);
314 
315 	/*
316 	 * Check that the session is valid and clear the session
317 	 * usage bit
318 	 */
319 	mutex_lock(&session_list_mutex);
320 	sess = find_session(ctxdata, session);
321 	if (sess) {
322 		ta_handle = get_ta_handle(session);
323 		i = get_session_index(session);
324 		session_info = sess->session_info[i];
325 		spin_lock(&sess->lock);
326 		clear_bit(i, sess->sess_mask);
327 		spin_unlock(&sess->lock);
328 	}
329 	mutex_unlock(&session_list_mutex);
330 
331 	if (!sess)
332 		return -EINVAL;
333 
334 	/* Close the session */
335 	handle_close_session(ta_handle, session_info);
336 	handle_unload_ta(ta_handle);
337 
338 	kref_put_mutex(&sess->refcount, destroy_session, &session_list_mutex);
339 
340 	return 0;
341 }
342 
amdtee_map_shmem(struct tee_shm * shm)343 int amdtee_map_shmem(struct tee_shm *shm)
344 {
345 	struct amdtee_context_data *ctxdata;
346 	struct amdtee_shm_data *shmnode;
347 	struct shmem_desc shmem;
348 	int rc, count;
349 	u32 buf_id;
350 
351 	if (!shm)
352 		return -EINVAL;
353 
354 	shmnode = kmalloc(sizeof(*shmnode), GFP_KERNEL);
355 	if (!shmnode)
356 		return -ENOMEM;
357 
358 	count = 1;
359 	shmem.kaddr = shm->kaddr;
360 	shmem.size = shm->size;
361 
362 	/*
363 	 * Send a MAP command to TEE and get the corresponding
364 	 * buffer Id
365 	 */
366 	rc = handle_map_shmem(count, &shmem, &buf_id);
367 	if (rc) {
368 		pr_err("map_shmem failed: ret = %d\n", rc);
369 		kfree(shmnode);
370 		return rc;
371 	}
372 
373 	shmnode->kaddr = shm->kaddr;
374 	shmnode->buf_id = buf_id;
375 	ctxdata = shm->ctx->data;
376 	mutex_lock(&ctxdata->shm_mutex);
377 	list_add(&shmnode->shm_node, &ctxdata->shm_list);
378 	mutex_unlock(&ctxdata->shm_mutex);
379 
380 	pr_debug("buf_id :[%x] kaddr[%p]\n", shmnode->buf_id, shmnode->kaddr);
381 
382 	return 0;
383 }
384 
amdtee_unmap_shmem(struct tee_shm * shm)385 void amdtee_unmap_shmem(struct tee_shm *shm)
386 {
387 	struct amdtee_context_data *ctxdata;
388 	struct amdtee_shm_data *shmnode;
389 	u32 buf_id;
390 
391 	if (!shm)
392 		return;
393 
394 	buf_id = get_buffer_id(shm);
395 	/* Unmap the shared memory from TEE */
396 	handle_unmap_shmem(buf_id);
397 
398 	ctxdata = shm->ctx->data;
399 	mutex_lock(&ctxdata->shm_mutex);
400 	list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node)
401 		if (buf_id == shmnode->buf_id) {
402 			list_del(&shmnode->shm_node);
403 			kfree(shmnode);
404 			break;
405 		}
406 	mutex_unlock(&ctxdata->shm_mutex);
407 }
408 
amdtee_invoke_func(struct tee_context * ctx,struct tee_ioctl_invoke_arg * arg,struct tee_param * param)409 int amdtee_invoke_func(struct tee_context *ctx,
410 		       struct tee_ioctl_invoke_arg *arg,
411 		       struct tee_param *param)
412 {
413 	struct amdtee_context_data *ctxdata = ctx->data;
414 	struct amdtee_session *sess;
415 	u32 i, session_info;
416 
417 	/* Check that the session is valid */
418 	mutex_lock(&session_list_mutex);
419 	sess = find_session(ctxdata, arg->session);
420 	if (sess) {
421 		i = get_session_index(arg->session);
422 		session_info = sess->session_info[i];
423 	}
424 	mutex_unlock(&session_list_mutex);
425 
426 	if (!sess)
427 		return -EINVAL;
428 
429 	handle_invoke_cmd(arg, session_info, param);
430 
431 	return 0;
432 }
433 
amdtee_cancel_req(struct tee_context * ctx,u32 cancel_id,u32 session)434 int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32 session)
435 {
436 	return -EINVAL;
437 }
438 
439 static const struct tee_driver_ops amdtee_ops = {
440 	.get_version = amdtee_get_version,
441 	.open = amdtee_open,
442 	.release = amdtee_release,
443 	.open_session = amdtee_open_session,
444 	.close_session = amdtee_close_session,
445 	.invoke_func = amdtee_invoke_func,
446 	.cancel_req = amdtee_cancel_req,
447 };
448 
449 static const struct tee_desc amdtee_desc = {
450 	.name = DRIVER_NAME "-clnt",
451 	.ops = &amdtee_ops,
452 	.owner = THIS_MODULE,
453 };
454 
amdtee_driver_init(void)455 static int __init amdtee_driver_init(void)
456 {
457 	struct tee_device *teedev;
458 	struct tee_shm_pool *pool;
459 	struct amdtee *amdtee;
460 	int rc;
461 
462 	rc = psp_check_tee_status();
463 	if (rc) {
464 		pr_err("tee not present\n");
465 		return rc;
466 	}
467 
468 	drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL);
469 	if (!drv_data)
470 		return -ENOMEM;
471 
472 	amdtee = kzalloc(sizeof(*amdtee), GFP_KERNEL);
473 	if (!amdtee) {
474 		rc = -ENOMEM;
475 		goto err_kfree_drv_data;
476 	}
477 
478 	pool = amdtee_config_shm();
479 	if (IS_ERR(pool)) {
480 		pr_err("shared pool configuration error\n");
481 		rc = PTR_ERR(pool);
482 		goto err_kfree_amdtee;
483 	}
484 
485 	teedev = tee_device_alloc(&amdtee_desc, NULL, pool, amdtee);
486 	if (IS_ERR(teedev)) {
487 		rc = PTR_ERR(teedev);
488 		goto err_free_pool;
489 	}
490 	amdtee->teedev = teedev;
491 
492 	rc = tee_device_register(amdtee->teedev);
493 	if (rc)
494 		goto err_device_unregister;
495 
496 	amdtee->pool = pool;
497 
498 	drv_data->amdtee = amdtee;
499 
500 	return 0;
501 
502 err_device_unregister:
503 	tee_device_unregister(amdtee->teedev);
504 
505 err_free_pool:
506 	tee_shm_pool_free(pool);
507 
508 err_kfree_amdtee:
509 	kfree(amdtee);
510 
511 err_kfree_drv_data:
512 	kfree(drv_data);
513 	drv_data = NULL;
514 
515 	pr_err("initialization failed\n");
516 	return rc;
517 }
518 module_init(amdtee_driver_init);
519 
amdtee_driver_exit(void)520 static void __exit amdtee_driver_exit(void)
521 {
522 	struct amdtee *amdtee;
523 
524 	if (!drv_data || !drv_data->amdtee)
525 		return;
526 
527 	amdtee = drv_data->amdtee;
528 
529 	tee_device_unregister(amdtee->teedev);
530 	tee_shm_pool_free(amdtee->pool);
531 }
532 module_exit(amdtee_driver_exit);
533 
534 MODULE_AUTHOR(DRIVER_AUTHOR);
535 MODULE_DESCRIPTION("AMD-TEE driver");
536 MODULE_VERSION("1.0");
537 MODULE_LICENSE("Dual MIT/GPL");
538