xref: /optee_os/core/arch/arm/kernel/stmm_sp.c (revision 77bdbf67c42209142ef43129e01113d29d9c62f6)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2019, Linaro Limited
4  * Copyright (c) 2020, Arm Limited.
5  */
6 
7 #include <crypto/crypto.h>
8 #include <ffa.h>
9 #include <keep.h>
10 #include <kernel/abort.h>
11 #include <kernel/stmm_sp.h>
12 #include <kernel/user_mode_ctx.h>
13 #include <mm/fobj.h>
14 #include <mm/mobj.h>
15 #include <mm/vm.h>
16 #include <pta_stmm.h>
17 #include <tee_api_defines_extensions.h>
18 #include <tee/tee_pobj.h>
19 #include <tee/tee_svc.h>
20 #include <tee/tee_svc_storage.h>
21 #include <zlib.h>
22 
23 #include "thread_private.h"
24 
25 #ifdef ARM64
26 #define SVC_REGS_A0(_regs)	((_regs)->x0)
27 #define SVC_REGS_A1(_regs)	((_regs)->x1)
28 #define SVC_REGS_A2(_regs)	((_regs)->x2)
29 #define SVC_REGS_A3(_regs)	((_regs)->x3)
30 #define SVC_REGS_A4(_regs)	((_regs)->x4)
31 #define SVC_REGS_A5(_regs)	((_regs)->x5)
32 #define SVC_REGS_A6(_regs)	((_regs)->x6)
33 #define SVC_REGS_A7(_regs)	((_regs)->x7)
34 #define __FFA_SVC_RPMB_READ		FFA_SVC_RPMB_READ
35 #define __FFA_SVC_RPMB_WRITE		FFA_SVC_RPMB_WRITE
36 #define __FFA_SVC_MEMORY_ATTRIBUTES_GET	FFA_SVC_MEMORY_ATTRIBUTES_GET_64
37 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET	FFA_SVC_MEMORY_ATTRIBUTES_SET_64
38 #define __FFA_MSG_SEND_DIRECT_RESP	FFA_MSG_SEND_DIRECT_RESP_64
39 #define __FFA_MSG_SEND_DIRECT_REQ	FFA_MSG_SEND_DIRECT_REQ_64
40 #endif
41 #ifdef ARM32
42 #define SVC_REGS_A0(_regs)	((_regs)->r0)
43 #define SVC_REGS_A1(_regs)	((_regs)->r1)
44 #define SVC_REGS_A2(_regs)	((_regs)->r2)
45 #define SVC_REGS_A3(_regs)	((_regs)->r3)
46 #define SVC_REGS_A4(_regs)	((_regs)->r4)
47 #define SVC_REGS_A5(_regs)	((_regs)->r5)
48 #define SVC_REGS_A6(_regs)	((_regs)->r6)
49 #define SVC_REGS_A7(_regs)	((_regs)->r7)
50 #define __FFA_SVC_RPMB_READ		FFA_SVC_RPMB_READ_32
51 #define __FFA_SVC_RPMB_WRITE		FFA_SVC_RPMB_WRITE_32
52 #define __FFA_SVC_MEMORY_ATTRIBUTES_GET	FFA_SVC_MEMORY_ATTRIBUTES_GET_32
53 #define __FFA_SVC_MEMORY_ATTRIBUTES_SET	FFA_SVC_MEMORY_ATTRIBUTES_SET_32
54 #define __FFA_MSG_SEND_DIRECT_RESP	FFA_MSG_SEND_DIRECT_RESP_32
55 #define __FFA_MSG_SEND_DIRECT_REQ	FFA_MSG_SEND_DIRECT_REQ_32
56 #endif
57 
58 static const TEE_UUID stmm_uuid = PTA_STMM_UUID;
59 
60 /*
61  * Once a complete FFA spec is added, these will become discoverable.
62  * Until then these are considered part of the internal ABI between
63  * OP-TEE and StMM.
64  */
65 static const uint16_t stmm_id = 1U;
66 static const uint16_t stmm_pta_id = 2U;
67 static const uint16_t mem_mgr_id = 3U;
68 static const uint16_t ffa_storage_id = 4U;
69 
70 static const unsigned int stmm_stack_size = 4 * SMALL_PAGE_SIZE;
71 static const unsigned int stmm_heap_size = 398 * SMALL_PAGE_SIZE;
72 static const unsigned int stmm_sec_buf_size = SMALL_PAGE_SIZE;
73 static const unsigned int stmm_ns_comm_buf_size = SMALL_PAGE_SIZE;
74 
75 extern unsigned char stmm_image[];
76 extern const unsigned int stmm_image_size;
77 extern const unsigned int stmm_image_uncompressed_size;
78 
79 /* Indirect reference to unlink stmm_sp_ops from pager unpaged sections */
80 static const struct ts_ops stmm_sp_ops;
81 const struct ts_ops *stmm_sp_ops_ptr;
82 
83 static struct stmm_ctx *stmm_alloc_ctx(const TEE_UUID *uuid)
84 {
85 	TEE_Result res = TEE_SUCCESS;
86 	struct stmm_ctx *spc = NULL;
87 
88 	spc = calloc(1, sizeof(*spc));
89 	if (!spc)
90 		return NULL;
91 
92 	spc->ta_ctx.ts_ctx.ops = &stmm_sp_ops;
93 	spc->ta_ctx.ts_ctx.uuid = *uuid;
94 	spc->ta_ctx.flags = TA_FLAG_SINGLE_INSTANCE |
95 			    TA_FLAG_INSTANCE_KEEP_ALIVE;
96 	spc->uctx.ts_ctx = &spc->ta_ctx.ts_ctx;
97 
98 	res = vm_info_init(&spc->uctx);
99 	if (res) {
100 		free(spc);
101 		return NULL;
102 	}
103 
104 	spc->ta_ctx.ref_count = 1;
105 	condvar_init(&spc->ta_ctx.busy_cv);
106 	stmm_sp_ops_ptr = &stmm_sp_ops;
107 
108 	return spc;
109 }
110 
111 static TEE_Result stmm_enter_user_mode(struct stmm_ctx *spc)
112 {
113 	uint32_t exceptions = 0;
114 	uint32_t panic_code = 0;
115 	uint32_t panicked = 0;
116 	uint64_t cntkctl = 0;
117 
118 	exceptions = thread_mask_exceptions(THREAD_EXCP_ALL);
119 	cntkctl = read_cntkctl();
120 	write_cntkctl(cntkctl | CNTKCTL_PL0PCTEN);
121 	__thread_enter_user_mode(&spc->regs, &panicked, &panic_code);
122 	write_cntkctl(cntkctl);
123 	thread_unmask_exceptions(exceptions);
124 
125 	thread_user_clear_vfp(&spc->uctx);
126 
127 	if (panicked) {
128 		abort_print_current_ts();
129 		DMSG("stmm panicked with code %#"PRIx32, panic_code);
130 		return TEE_ERROR_TARGET_DEAD;
131 	}
132 
133 	return TEE_SUCCESS;
134 }
135 
136 #ifdef ARM64
137 static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0,
138 			   unsigned long a1, unsigned long sp, unsigned long pc)
139 {
140 	spc->regs.x[0] = a0;
141 	spc->regs.x[1] = a1;
142 	spc->regs.sp = sp;
143 	spc->regs.pc = pc;
144 }
145 #endif
146 
147 #ifdef ARM32
148 static uint32_t __maybe_unused get_spsr(void)
149 {
150 	uint32_t s = 0;
151 
152 	s = read_cpsr();
153 	s &= ~(CPSR_MODE_MASK | CPSR_T | ARM32_CPSR_IT_MASK);
154 	s |= CPSR_MODE_USR;
155 
156 	return s;
157 }
158 
159 static void init_stmm_regs(struct stmm_ctx *spc, unsigned long a0,
160 			   unsigned long a1, unsigned long sp, unsigned long pc)
161 {
162 	spc->regs.r0 = a0;
163 	spc->regs.r1 = a1;
164 	spc->regs.usr_sp = sp;
165 	spc->regs.cpsr = get_spsr();
166 	spc->regs.pc = pc;
167 }
168 #endif
169 
170 static TEE_Result alloc_and_map_sp_fobj(struct stmm_ctx *spc, size_t sz,
171 					uint32_t prot, vaddr_t *va)
172 {
173 	size_t num_pgs = ROUNDUP(sz, SMALL_PAGE_SIZE) / SMALL_PAGE_SIZE;
174 	struct fobj *fobj = fobj_ta_mem_alloc(num_pgs);
175 	struct mobj *mobj = mobj_with_fobj_alloc(fobj, NULL);
176 	TEE_Result res = TEE_SUCCESS;
177 
178 	fobj_put(fobj);
179 	if (!mobj)
180 		return TEE_ERROR_OUT_OF_MEMORY;
181 
182 	res = vm_map(&spc->uctx, va, num_pgs * SMALL_PAGE_SIZE,
183 		     prot, 0, mobj, 0);
184 	if (res)
185 		mobj_put(mobj);
186 
187 	return TEE_SUCCESS;
188 }
189 
190 static void *zalloc(void *opaque __unused, unsigned int items,
191 		    unsigned int size)
192 {
193 	return malloc(items * size);
194 }
195 
196 static void zfree(void *opaque __unused, void *address)
197 {
198 	free(address);
199 }
200 
201 static void uncompress_image(void *dst, size_t dst_size, void *src,
202 			     size_t src_size)
203 {
204 	z_stream strm = {
205 		.next_in = src,
206 		.avail_in = src_size,
207 		.next_out = dst,
208 		.avail_out = dst_size,
209 		.zalloc = zalloc,
210 		.zfree = zfree,
211 	};
212 
213 	if (inflateInit(&strm) != Z_OK)
214 		panic("inflateInit");
215 
216 	if (inflate(&strm, Z_SYNC_FLUSH) != Z_STREAM_END)
217 		panic("inflate");
218 
219 	if (inflateEnd(&strm) != Z_OK)
220 		panic("inflateEnd");
221 }
222 
223 static TEE_Result load_stmm(struct stmm_ctx *spc)
224 {
225 	struct stmm_boot_info *boot_info = NULL;
226 	struct stmm_mp_info *mp_info = NULL;
227 	TEE_Result res = TEE_SUCCESS;
228 	vaddr_t sp_addr = 0;
229 	vaddr_t image_addr = 0;
230 	vaddr_t heap_addr = 0;
231 	vaddr_t stack_addr = 0;
232 	vaddr_t sec_buf_addr = 0;
233 	vaddr_t comm_buf_addr = 0;
234 	unsigned int sp_size = 0;
235 	unsigned int uncompressed_size_roundup = 0;
236 
237 	uncompressed_size_roundup = ROUNDUP(stmm_image_uncompressed_size,
238 					    SMALL_PAGE_SIZE);
239 	sp_size = uncompressed_size_roundup + stmm_stack_size +
240 		  stmm_heap_size + stmm_sec_buf_size;
241 	res = alloc_and_map_sp_fobj(spc, sp_size,
242 				    TEE_MATTR_PRW, &sp_addr);
243 	if (res)
244 		return res;
245 
246 	res = alloc_and_map_sp_fobj(spc, stmm_ns_comm_buf_size,
247 				    TEE_MATTR_URW | TEE_MATTR_PRW,
248 				    &comm_buf_addr);
249 	/*
250 	 * We don't need to free the previous instance here, they'll all be
251 	 * handled during the destruction call (stmm_ctx_destroy())
252 	 */
253 	if (res)
254 		return res;
255 
256 	image_addr = sp_addr;
257 	heap_addr = image_addr + uncompressed_size_roundup;
258 	stack_addr = heap_addr + stmm_heap_size;
259 	sec_buf_addr = stack_addr + stmm_stack_size;
260 
261 	vm_set_ctx(&spc->ta_ctx.ts_ctx);
262 	uncompress_image((void *)image_addr, stmm_image_uncompressed_size,
263 			 stmm_image, stmm_image_size);
264 
265 	res = vm_set_prot(&spc->uctx, image_addr, uncompressed_size_roundup,
266 			  TEE_MATTR_URX | TEE_MATTR_PR);
267 	if (res)
268 		return res;
269 
270 	res = vm_set_prot(&spc->uctx, heap_addr, stmm_heap_size,
271 			  TEE_MATTR_URW | TEE_MATTR_PRW);
272 	if (res)
273 		return res;
274 
275 	res = vm_set_prot(&spc->uctx, stack_addr, stmm_stack_size,
276 			  TEE_MATTR_URW | TEE_MATTR_PRW);
277 	if (res)
278 		return res;
279 
280 	res = vm_set_prot(&spc->uctx, sec_buf_addr, stmm_sec_buf_size,
281 			  TEE_MATTR_URW | TEE_MATTR_PRW);
282 	if (res)
283 		return res;
284 
285 	DMSG("stmm load address %#"PRIxVA, image_addr);
286 
287 	boot_info = (struct stmm_boot_info *)sec_buf_addr;
288 	mp_info = (struct stmm_mp_info *)(boot_info + 1);
289 	*boot_info = (struct stmm_boot_info){
290 		.h.type = STMM_PARAM_SP_IMAGE_BOOT_INFO,
291 		.h.version = STMM_PARAM_VERSION_1,
292 		.h.size = sizeof(struct stmm_boot_info),
293 		.h.attr = 0,
294 		.sp_mem_base = sp_addr,
295 		.sp_mem_limit = sp_addr + sp_size,
296 		.sp_image_base = image_addr,
297 		.sp_stack_base = stack_addr,
298 		.sp_heap_base = heap_addr,
299 		.sp_ns_comm_buf_base = comm_buf_addr,
300 		.sp_shared_buf_base = sec_buf_addr,
301 		.sp_image_size = stmm_image_size,
302 		.sp_pcpu_stack_size = stmm_stack_size,
303 		.sp_heap_size = stmm_heap_size,
304 		.sp_ns_comm_buf_size = stmm_ns_comm_buf_size,
305 		.sp_shared_buf_size = stmm_sec_buf_size,
306 		.num_sp_mem_regions = 6,
307 		.num_cpus = 1,
308 		.mp_info = mp_info,
309 	};
310 	mp_info->mpidr = read_mpidr();
311 	mp_info->linear_id = 0;
312 	mp_info->flags = MP_INFO_FLAG_PRIMARY_CPU;
313 	spc->ns_comm_buf_addr = comm_buf_addr;
314 	spc->ns_comm_buf_size = stmm_ns_comm_buf_size;
315 
316 	init_stmm_regs(spc, sec_buf_addr,
317 		       (vaddr_t)(mp_info + 1) - sec_buf_addr,
318 		       stack_addr + stmm_stack_size, image_addr);
319 
320 	return stmm_enter_user_mode(spc);
321 }
322 
323 TEE_Result stmm_init_session(const TEE_UUID *uuid, struct tee_ta_session *sess)
324 {
325 	struct stmm_ctx *spc = NULL;
326 	TEE_Result res = TEE_SUCCESS;
327 
328 	if (memcmp(uuid, &stmm_uuid, sizeof(*uuid)))
329 		return TEE_ERROR_ITEM_NOT_FOUND;
330 
331 	spc = stmm_alloc_ctx(uuid);
332 	if (!spc)
333 		return TEE_ERROR_OUT_OF_MEMORY;
334 
335 	spc->is_initializing = true;
336 
337 	mutex_lock(&tee_ta_mutex);
338 	sess->ts_sess.ctx = &spc->ta_ctx.ts_ctx;
339 	sess->ts_sess.handle_svc = sess->ts_sess.ctx->ops->handle_svc;
340 	mutex_unlock(&tee_ta_mutex);
341 
342 	ts_push_current_session(&sess->ts_sess);
343 	res = load_stmm(spc);
344 	ts_pop_current_session();
345 	vm_set_ctx(NULL);
346 	if (res) {
347 		sess->ts_sess.ctx = NULL;
348 		spc->ta_ctx.ts_ctx.ops->destroy(&spc->ta_ctx.ts_ctx);
349 
350 		return res;
351 	}
352 
353 	mutex_lock(&tee_ta_mutex);
354 	spc->is_initializing = false;
355 	TAILQ_INSERT_TAIL(&tee_ctxes, &spc->ta_ctx, link);
356 	mutex_unlock(&tee_ta_mutex);
357 
358 	return TEE_SUCCESS;
359 }
360 
361 static TEE_Result stmm_enter_open_session(struct ts_session *s)
362 {
363 	struct stmm_ctx *spc = to_stmm_ctx(s->ctx);
364 	struct tee_ta_session *ta_sess = to_ta_session(s);
365 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_NONE,
366 						TEE_PARAM_TYPE_NONE,
367 						TEE_PARAM_TYPE_NONE,
368 						TEE_PARAM_TYPE_NONE);
369 
370 	if (ta_sess->param->types != exp_pt)
371 		return TEE_ERROR_BAD_PARAMETERS;
372 
373 	if (spc->is_initializing) {
374 		/* StMM is initialized in stmm_init_session() */
375 		ta_sess->err_origin = TEE_ORIGIN_TEE;
376 		return TEE_ERROR_BAD_STATE;
377 	}
378 
379 	return TEE_SUCCESS;
380 }
381 
382 static TEE_Result stmm_enter_invoke_cmd(struct ts_session *s, uint32_t cmd)
383 {
384 	struct stmm_ctx *spc = to_stmm_ctx(s->ctx);
385 	struct tee_ta_session *ta_sess = to_ta_session(s);
386 	TEE_Result res = TEE_SUCCESS;
387 	TEE_Result __maybe_unused tmp_res = TEE_SUCCESS;
388 	unsigned int ns_buf_size = 0;
389 	struct param_mem *mem = NULL;
390 	void *va = NULL;
391 	const uint32_t exp_pt = TEE_PARAM_TYPES(TEE_PARAM_TYPE_MEMREF_INOUT,
392 						TEE_PARAM_TYPE_VALUE_OUTPUT,
393 						TEE_PARAM_TYPE_NONE,
394 						TEE_PARAM_TYPE_NONE);
395 
396 	if (cmd != PTA_STMM_CMD_COMMUNICATE)
397 		return TEE_ERROR_BAD_PARAMETERS;
398 
399 	if (ta_sess->param->types != exp_pt)
400 		return TEE_ERROR_BAD_PARAMETERS;
401 
402 	mem = &ta_sess->param->u[0].mem;
403 	ns_buf_size = mem->size;
404 	if (ns_buf_size > spc->ns_comm_buf_size) {
405 		mem->size = spc->ns_comm_buf_size;
406 		return TEE_ERROR_EXCESS_DATA;
407 	}
408 
409 	res = mobj_inc_map(mem->mobj);
410 	if (res)
411 		return res;
412 
413 	va = mobj_get_va(mem->mobj, mem->offs);
414 	if (!va) {
415 		EMSG("Can't get a valid VA for NS buffer");
416 		res = TEE_ERROR_BAD_PARAMETERS;
417 		goto out_va;
418 	}
419 
420 #ifdef ARM64
421 	spc->regs.x[0] = __FFA_MSG_SEND_DIRECT_REQ;
422 	spc->regs.x[1] = (stmm_pta_id << 16) | stmm_id;
423 	spc->regs.x[2] = FFA_PARAM_MBZ;
424 	spc->regs.x[3] = spc->ns_comm_buf_addr;
425 	spc->regs.x[4] = ns_buf_size;
426 	spc->regs.x[5] = 0;
427 	spc->regs.x[6] = 0;
428 	spc->regs.x[7] = 0;
429 #endif
430 #ifdef ARM32
431 	spc->regs.r0 = __FFA_MSG_SEND_DIRECT_REQ;
432 	spc->regs.r1 = (stmm_pta_id << 16) | stmm_id;
433 	spc->regs.r2 = FFA_PARAM_MBZ;
434 	spc->regs.r3 = spc->ns_comm_buf_addr;
435 	spc->regs.r4 = ns_buf_size;
436 	spc->regs.r5 = 0;
437 	spc->regs.r6 = 0;
438 	spc->regs.r7 = 0;
439 #endif
440 
441 	ts_push_current_session(s);
442 
443 	memcpy((void *)spc->ns_comm_buf_addr, va, ns_buf_size);
444 
445 	res = stmm_enter_user_mode(spc);
446 	if (res)
447 		goto out_session;
448 	/*
449 	 * Copy the SPM response from secure partition back to the non-secure
450 	 * buffer of the client that called us.
451 	 */
452 #ifdef ARM64
453 	ta_sess->param->u[1].val.a = spc->regs.x[4];
454 #endif
455 #ifdef ARM32
456 	ta_sess->param->u[1].val.a = spc->regs.r4;
457 #endif
458 
459 	memcpy(va, (void *)spc->ns_comm_buf_addr, ns_buf_size);
460 
461 out_session:
462 	ts_pop_current_session();
463 out_va:
464 	tmp_res = mobj_dec_map(mem->mobj);
465 	assert(!tmp_res);
466 
467 	return res;
468 }
469 
470 static void stmm_enter_close_session(struct ts_session *s __unused)
471 {
472 }
473 
474 static void stmm_dump_state(struct ts_ctx *ctx)
475 {
476 	user_mode_ctx_print_mappings(to_user_mode_ctx(ctx));
477 }
478 DECLARE_KEEP_PAGER(stmm_dump_state);
479 
480 static uint32_t stmm_get_instance_id(struct ts_ctx *ctx)
481 {
482 	return to_stmm_ctx(ctx)->uctx.vm_info.asid;
483 }
484 
485 static void stmm_ctx_destroy(struct ts_ctx *ctx)
486 {
487 	struct stmm_ctx *spc = to_stmm_ctx(ctx);
488 
489 	tee_pager_rem_um_areas(&spc->uctx);
490 	vm_info_final(&spc->uctx);
491 	free(spc);
492 }
493 
494 static uint32_t sp_svc_get_mem_attr(vaddr_t va)
495 {
496 	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
497 	struct ts_session *sess = NULL;
498 	struct stmm_ctx *spc = NULL;
499 	uint16_t attrs = 0;
500 	uint16_t perm = 0;
501 
502 	if (!va)
503 		goto err;
504 
505 	sess = ts_get_current_session();
506 	spc = to_stmm_ctx(sess->ctx);
507 
508 	res = vm_get_prot(&spc->uctx, va, SMALL_PAGE_SIZE, &attrs);
509 	if (res)
510 		goto err;
511 
512 	if (attrs & TEE_MATTR_UR)
513 		perm |= STMM_MEM_ATTR_ACCESS_RO;
514 	else if (attrs & TEE_MATTR_UW)
515 		perm |= STMM_MEM_ATTR_ACCESS_RW;
516 
517 	if (attrs & TEE_MATTR_UX)
518 		perm |= STMM_MEM_ATTR_EXEC;
519 
520 	return perm;
521 err:
522 	return STMM_RET_DENIED;
523 }
524 
525 static int sp_svc_set_mem_attr(vaddr_t va, unsigned int nr_pages, uint32_t perm)
526 {
527 	TEE_Result res = TEE_ERROR_BAD_PARAMETERS;
528 	struct ts_session *sess = NULL;
529 	struct stmm_ctx *spc = NULL;
530 	size_t sz = 0;
531 	uint32_t prot = 0;
532 
533 	if (!va || !nr_pages || MUL_OVERFLOW(nr_pages, SMALL_PAGE_SIZE, &sz))
534 		return STMM_RET_INVALID_PARAM;
535 
536 	if (perm & ~STMM_MEM_ATTR_ALL)
537 		return STMM_RET_INVALID_PARAM;
538 
539 	sess = ts_get_current_session();
540 	spc = to_stmm_ctx(sess->ctx);
541 
542 	if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RO)
543 		prot |= TEE_MATTR_UR;
544 	else if ((perm & STMM_MEM_ATTR_ACCESS_MASK) == STMM_MEM_ATTR_ACCESS_RW)
545 		prot |= TEE_MATTR_URW;
546 
547 	if ((perm & STMM_MEM_ATTR_EXEC_NEVER) == STMM_MEM_ATTR_EXEC)
548 		prot |= TEE_MATTR_UX;
549 
550 	res = vm_set_prot(&spc->uctx, va, sz, prot);
551 	if (res)
552 		return STMM_RET_DENIED;
553 
554 	return STMM_RET_SUCCESS;
555 }
556 
557 #ifdef ARM64
558 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_svc_regs *svc_regs)
559 {
560 	size_t n = 0;
561 
562 	/* Save the return values from StMM */
563 	for (n = 0; n <= 7; n++)
564 		spc->regs.x[n] = *(&svc_regs->x0 + n);
565 
566 	spc->regs.sp = svc_regs->sp_el0;
567 	spc->regs.pc = svc_regs->elr;
568 	spc->regs.cpsr = svc_regs->spsr;
569 }
570 #endif
571 
572 #ifdef ARM32
573 static void save_sp_ctx(struct stmm_ctx *spc, struct thread_svc_regs *svc_regs)
574 {
575 	spc->regs.r0 = svc_regs->r0;
576 	spc->regs.r1 = svc_regs->r1;
577 	spc->regs.r2 = svc_regs->r2;
578 	spc->regs.r3 = svc_regs->r3;
579 	spc->regs.r4 = svc_regs->r4;
580 	spc->regs.r5 = svc_regs->r5;
581 	spc->regs.r6 = svc_regs->r6;
582 	spc->regs.r7 = svc_regs->r7;
583 	spc->regs.pc = svc_regs->lr;
584 	spc->regs.cpsr = svc_regs->spsr;
585 	spc->regs.usr_sp = thread_get_usr_sp();
586 }
587 #endif
588 
589 static void return_from_sp_helper(bool panic, uint32_t panic_code,
590 				  struct thread_svc_regs *svc_regs)
591 {
592 	struct ts_session *sess = ts_get_current_session();
593 	struct stmm_ctx *spc = to_stmm_ctx(sess->ctx);
594 
595 	if (panic)
596 		spc->ta_ctx.panicked = true;
597 	else
598 		save_sp_ctx(spc, svc_regs);
599 
600 	SVC_REGS_A0(svc_regs) = 0;
601 	SVC_REGS_A1(svc_regs) = panic;
602 	SVC_REGS_A2(svc_regs) = panic_code;
603 }
604 
605 static void service_compose_direct_resp(struct thread_svc_regs *regs,
606 					uint32_t ret_val)
607 {
608 	uint16_t src_id = 0;
609 	uint16_t dst_id = 0;
610 
611 	/* extract from request */
612 	src_id = (SVC_REGS_A1(regs) >> 16) & UINT16_MAX;
613 	dst_id = SVC_REGS_A1(regs) & UINT16_MAX;
614 
615 	/* compose message */
616 	SVC_REGS_A0(regs) = __FFA_MSG_SEND_DIRECT_RESP;
617 	/* swap endpoint ids */
618 	SVC_REGS_A1(regs) = SHIFT_U32(dst_id, 16) | src_id;
619 	SVC_REGS_A2(regs) = FFA_PARAM_MBZ;
620 	SVC_REGS_A3(regs) = ret_val;
621 	SVC_REGS_A4(regs) = 0;
622 	SVC_REGS_A5(regs) = 0;
623 	SVC_REGS_A6(regs) = 0;
624 	SVC_REGS_A7(regs) = 0;
625 }
626 
627 /*
628  * Combined read from secure partition, this will open, read and
629  * close the file object.
630  */
631 static TEE_Result sec_storage_obj_read(unsigned long storage_id, char *obj_id,
632 				       unsigned long obj_id_len, void *data,
633 				       unsigned long len, unsigned long offset,
634 				       unsigned long flags)
635 {
636 	const struct tee_file_operations *fops = NULL;
637 	TEE_Result res = TEE_ERROR_BAD_STATE;
638 	struct ts_session *sess = NULL;
639 	struct tee_file_handle *fh = NULL;
640 	struct stmm_ctx *spc = NULL;
641 	struct tee_pobj *po = NULL;
642 	size_t file_size = 0;
643 	size_t read_len = 0;
644 
645 	fops = tee_svc_storage_file_ops(storage_id);
646 	if (!fops)
647 		return TEE_ERROR_ITEM_NOT_FOUND;
648 
649 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
650 		return TEE_ERROR_BAD_PARAMETERS;
651 
652 	sess = ts_get_current_session();
653 	spc = to_stmm_ctx(sess->ctx);
654 	res = vm_check_access_rights(&spc->uctx,
655 				     TEE_MEMORY_ACCESS_WRITE |
656 				     TEE_MEMORY_ACCESS_ANY_OWNER,
657 				     (uaddr_t)data, len);
658 	if (res != TEE_SUCCESS)
659 		return res;
660 
661 	res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags,
662 			   false, fops, &po);
663 	if (res != TEE_SUCCESS)
664 		return res;
665 
666 	res = po->fops->open(po, &file_size, &fh);
667 	if (res != TEE_SUCCESS)
668 		goto out;
669 
670 	read_len = len;
671 	res = po->fops->read(fh, offset, data, &read_len);
672 	if (res == TEE_ERROR_CORRUPT_OBJECT) {
673 		EMSG("Object corrupt");
674 		po->fops->remove(po);
675 	} else if (res == TEE_SUCCESS && len != read_len) {
676 		res = TEE_ERROR_CORRUPT_OBJECT;
677 	}
678 
679 	po->fops->close(&fh);
680 
681 out:
682 	tee_pobj_release(po);
683 
684 	return res;
685 }
686 
687 /*
688  * Combined write from secure partition, this will create/open, write and
689  * close the file object.
690  */
691 static TEE_Result sec_storage_obj_write(unsigned long storage_id, char *obj_id,
692 					unsigned long obj_id_len, void *data,
693 					unsigned long len, unsigned long offset,
694 					unsigned long flags)
695 
696 {
697 	const struct tee_file_operations *fops = NULL;
698 	struct ts_session *sess = NULL;
699 	struct tee_file_handle *fh = NULL;
700 	struct stmm_ctx *spc = NULL;
701 	TEE_Result res = TEE_SUCCESS;
702 	struct tee_pobj *po = NULL;
703 
704 	fops = tee_svc_storage_file_ops(storage_id);
705 	if (!fops)
706 		return TEE_ERROR_ITEM_NOT_FOUND;
707 
708 	if (obj_id_len > TEE_OBJECT_ID_MAX_LEN)
709 		return TEE_ERROR_BAD_PARAMETERS;
710 
711 	sess = ts_get_current_session();
712 	spc = to_stmm_ctx(sess->ctx);
713 	res = vm_check_access_rights(&spc->uctx,
714 				     TEE_MEMORY_ACCESS_READ |
715 				     TEE_MEMORY_ACCESS_ANY_OWNER,
716 				     (uaddr_t)data, len);
717 	if (res != TEE_SUCCESS)
718 		return res;
719 
720 	res = tee_pobj_get(&sess->ctx->uuid, obj_id, obj_id_len, flags,
721 			   false, fops, &po);
722 	if (res != TEE_SUCCESS)
723 		return res;
724 
725 	res = po->fops->open(po, NULL, &fh);
726 	if (res == TEE_ERROR_ITEM_NOT_FOUND)
727 		res = po->fops->create(po, false, NULL, 0, NULL, 0, NULL, 0,
728 				       &fh);
729 	if (res == TEE_SUCCESS) {
730 		res = po->fops->write(fh, offset, data, len);
731 		po->fops->close(&fh);
732 	}
733 
734 	tee_pobj_release(po);
735 
736 	return res;
737 }
738 
739 static void stmm_handle_mem_mgr_service(struct thread_svc_regs *regs)
740 {
741 	uint32_t action = SVC_REGS_A3(regs);
742 	uintptr_t va = SVC_REGS_A4(regs);
743 	uint32_t nr_pages = SVC_REGS_A5(regs);
744 	uint32_t perm = SVC_REGS_A6(regs);
745 
746 	switch (action) {
747 	case __FFA_SVC_MEMORY_ATTRIBUTES_GET:
748 		service_compose_direct_resp(regs, sp_svc_get_mem_attr(va));
749 		break;
750 	case __FFA_SVC_MEMORY_ATTRIBUTES_SET:
751 		service_compose_direct_resp(regs,
752 					    sp_svc_set_mem_attr(va, nr_pages,
753 								perm));
754 		break;
755 	default:
756 		EMSG("Undefined service id %#"PRIx32, action);
757 		service_compose_direct_resp(regs, STMM_RET_INVALID_PARAM);
758 		break;
759 	}
760 }
761 
762 static uint32_t tee2stmm_ret_val(TEE_Result res)
763 {
764 	switch (res) {
765 	case TEE_SUCCESS:
766 		return STMM_RET_SUCCESS;
767 	case TEE_ERROR_NOT_SUPPORTED:
768 		return STMM_RET_NOT_SUPPORTED;
769 	case TEE_ERROR_ACCESS_DENIED:
770 		return STMM_RET_DENIED;
771 	case TEE_ERROR_OUT_OF_MEMORY:
772 		return STMM_RET_NO_MEM;
773 	case TEE_ERROR_BAD_PARAMETERS:
774 	default:
775 		return STMM_RET_INVALID_PARAM;
776 	}
777 }
778 
779 #define FILENAME "EFI_VARS"
780 static void stmm_handle_storage_service(struct thread_svc_regs *regs)
781 {
782 	uint32_t flags = TEE_DATA_FLAG_ACCESS_READ |
783 			 TEE_DATA_FLAG_ACCESS_WRITE |
784 			 TEE_DATA_FLAG_SHARE_READ |
785 			 TEE_DATA_FLAG_SHARE_WRITE;
786 	uint32_t action = SVC_REGS_A3(regs);
787 	void *va = (void *)SVC_REGS_A4(regs);
788 	unsigned long len = SVC_REGS_A5(regs);
789 	unsigned long offset = SVC_REGS_A6(regs);
790 	char obj_id[] = FILENAME;
791 	size_t obj_id_len = strlen(obj_id);
792 	TEE_Result res = TEE_SUCCESS;
793 	uint32_t stmm_rc = STMM_RET_INVALID_PARAM;
794 
795 	switch (action) {
796 	case __FFA_SVC_RPMB_READ:
797 		DMSG("RPMB read");
798 		res = sec_storage_obj_read(TEE_STORAGE_PRIVATE_RPMB, obj_id,
799 					   obj_id_len, va, len, offset, flags);
800 		stmm_rc = tee2stmm_ret_val(res);
801 		break;
802 	case __FFA_SVC_RPMB_WRITE:
803 		DMSG("RPMB write");
804 		res = sec_storage_obj_write(TEE_STORAGE_PRIVATE_RPMB, obj_id,
805 					    obj_id_len, va, len, offset, flags);
806 		stmm_rc = tee2stmm_ret_val(res);
807 		break;
808 	default:
809 		EMSG("Undefined service id %#"PRIx32, action);
810 		break;
811 	}
812 
813 	service_compose_direct_resp(regs, stmm_rc);
814 }
815 
816 static void spm_eret_error(int32_t error_code, struct thread_svc_regs *regs)
817 {
818 	SVC_REGS_A0(regs) = FFA_ERROR;
819 	SVC_REGS_A1(regs) = FFA_PARAM_MBZ;
820 	SVC_REGS_A2(regs) = error_code;
821 	SVC_REGS_A3(regs) = FFA_PARAM_MBZ;
822 	SVC_REGS_A4(regs) = FFA_PARAM_MBZ;
823 	SVC_REGS_A5(regs) = FFA_PARAM_MBZ;
824 	SVC_REGS_A6(regs) = FFA_PARAM_MBZ;
825 	SVC_REGS_A7(regs) = FFA_PARAM_MBZ;
826 }
827 
828 static void spm_handle_direct_req(struct thread_svc_regs *regs)
829 {
830 	uint16_t dst_id = SVC_REGS_A1(regs) & UINT16_MAX;
831 
832 	if (dst_id == mem_mgr_id) {
833 		stmm_handle_mem_mgr_service(regs);
834 	} else if (dst_id == ffa_storage_id) {
835 		stmm_handle_storage_service(regs);
836 	} else {
837 		EMSG("Undefined endpoint id %#"PRIx16, dst_id);
838 		spm_eret_error(STMM_RET_INVALID_PARAM, regs);
839 	}
840 }
841 
842 /* Return true if returning to SP, false if returning to caller */
843 static bool spm_handle_svc(struct thread_svc_regs *regs)
844 {
845 #ifdef ARM64
846 	uint64_t *a0 = &regs->x0;
847 #endif
848 #ifdef ARM32
849 	uint32_t *a0 = &regs->r0;
850 #endif
851 
852 	switch (*a0) {
853 	case FFA_VERSION:
854 		DMSG("Received FFA version");
855 		*a0 = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, FFA_VERSION_MINOR);
856 		return true;
857 	case __FFA_MSG_SEND_DIRECT_RESP:
858 		DMSG("Received FFA direct response");
859 		return_from_sp_helper(false, 0, regs);
860 		return false;
861 	case __FFA_MSG_SEND_DIRECT_REQ:
862 		DMSG("Received FFA direct request");
863 		spm_handle_direct_req(regs);
864 		return true;
865 	default:
866 		EMSG("Undefined syscall %#"PRIx32, (uint32_t)*a0);
867 		return_from_sp_helper(true /*panic*/, 0xabcd, regs);
868 		return false;
869 	}
870 }
871 
872 static const struct ts_ops stmm_sp_ops __rodata_unpaged = {
873 	.enter_open_session = stmm_enter_open_session,
874 	.enter_invoke_cmd = stmm_enter_invoke_cmd,
875 	.enter_close_session = stmm_enter_close_session,
876 	.dump_state = stmm_dump_state,
877 	.destroy = stmm_ctx_destroy,
878 	.get_instance_id = stmm_get_instance_id,
879 	.handle_svc = spm_handle_svc,
880 };
881