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