xref: /optee_os/core/arch/arm/kernel/arch_scall.c (revision 12fc37711783247b0d05fdc271ef007f4930767b)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2014-2022, Linaro Limited
4  * Copyright (c) 2020, Arm Limited
5  */
6 
7 #include <kernel/abort.h>
8 #include <kernel/scall.h>
9 #include <kernel/thread.h>
10 #include <kernel/trace_ta.h>
11 #include <kernel/user_ta.h>
12 #include <mm/vm.h>
13 #include <types_ext.h>
14 
15 #define TA32_CONTEXT_MAX_SIZE		(14 * sizeof(uint32_t))
16 #define TA64_CONTEXT_MAX_SIZE		(2 * sizeof(uint64_t))
17 
18 #ifdef CFG_UNWIND
19 #ifdef ARM32
20 /* Get register values pushed onto the stack by _utee_panic() */
21 static void save_panic_regs_a32_ta(struct thread_specific_data *tsd,
22 				   uint32_t *pushed)
23 {
24 	tsd->abort_regs = (struct thread_abort_regs){
25 		.elr = pushed[0],
26 		.r0 = pushed[1],
27 		.r1 = pushed[2],
28 		.r2 = pushed[3],
29 		.r3 = pushed[4],
30 		.r4 = pushed[5],
31 		.r5 = pushed[6],
32 		.r6 = pushed[7],
33 		.r7 = pushed[8],
34 		.r8 = pushed[9],
35 		.r9 = pushed[10],
36 		.r10 = pushed[11],
37 		.r11 = pushed[12],
38 		.usr_sp = (uint32_t)pushed,
39 		.usr_lr = pushed[13],
40 		.spsr = read_spsr(),
41 	};
42 }
43 
44 void scall_save_panic_stack(struct thread_scall_regs *regs)
45 {
46 	struct thread_specific_data *tsd = thread_get_tsd();
47 	struct ts_session *s = ts_get_current_session();
48 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
49 
50 	tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC;
51 	tsd->abort_descr = 0;
52 	tsd->abort_va = 0;
53 
54 	if (vm_check_access_rights(&utc->uctx,
55 				   TEE_MEMORY_ACCESS_READ |
56 				   TEE_MEMORY_ACCESS_WRITE,
57 				   (uaddr_t)regs->r1, TA32_CONTEXT_MAX_SIZE)) {
58 		TAMSG_RAW("");
59 		TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA,
60 			  (uaddr_t)regs->r1);
61 		return;
62 	}
63 
64 	save_panic_regs_a32_ta(tsd, (uint32_t *)regs->r1);
65 }
66 #endif /*ARM32*/
67 
68 #ifdef ARM64
69 /* Get register values pushed onto the stack by _utee_panic() (32-bit TA) */
70 static void save_panic_regs_a32_ta(struct thread_specific_data *tsd,
71 				   uint32_t *pushed)
72 {
73 	tsd->abort_regs = (struct thread_abort_regs){
74 		.elr = pushed[0],
75 		.x0 = pushed[1],
76 		.x1 = pushed[2],
77 		.x2 = pushed[3],
78 		.x3 = pushed[4],
79 		.x4 = pushed[5],
80 		.x5 = pushed[6],
81 		.x6 = pushed[7],
82 		.x7 = pushed[8],
83 		.x8 = pushed[9],
84 		.x9 = pushed[10],
85 		.x10 = pushed[11],
86 		.x11 = pushed[12],
87 		.x13 = (uint64_t)pushed,
88 		.x14 = pushed[13],
89 		.spsr = (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT),
90 	};
91 }
92 
93 /* Get register values pushed onto the stack by _utee_panic() (64-bit TA) */
94 static void save_panic_regs_a64_ta(struct thread_specific_data *tsd,
95 				   uint64_t *pushed)
96 {
97 	tsd->abort_regs = (struct thread_abort_regs){
98 		.x29 = pushed[0],
99 		.elr = pushed[1],
100 		.spsr = (SPSR_64_MODE_EL0 << SPSR_64_MODE_EL_SHIFT),
101 	};
102 }
103 
104 void scall_save_panic_stack(struct thread_scall_regs *regs)
105 {
106 	struct thread_specific_data *tsd = thread_get_tsd();
107 	struct ts_session *s = ts_get_current_session();
108 	struct user_ta_ctx *utc = to_user_ta_ctx(s->ctx);
109 
110 	if (vm_check_access_rights(&utc->uctx,
111 				   TEE_MEMORY_ACCESS_READ |
112 				   TEE_MEMORY_ACCESS_WRITE,
113 				   (uaddr_t)regs->x1,
114 				   utc->uctx.is_32bit ?
115 				   TA32_CONTEXT_MAX_SIZE :
116 				   TA64_CONTEXT_MAX_SIZE)) {
117 		TAMSG_RAW("");
118 		TAMSG_RAW("Can't unwind invalid user stack 0x%"PRIxUA,
119 			  (uaddr_t)regs->x1);
120 		return;
121 	}
122 
123 	tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC;
124 	tsd->abort_descr = 0;
125 	tsd->abort_va = 0;
126 
127 	if (utc->uctx.is_32bit)
128 		save_panic_regs_a32_ta(tsd, (uint32_t *)regs->x1);
129 	else
130 		save_panic_regs_a64_ta(tsd, (uint64_t *)regs->x1);
131 }
132 #endif /*ARM64*/
133 
134 #else /* CFG_UNWIND */
135 void scall_save_panic_stack(struct thread_scall_regs *regs __unused)
136 {
137 	struct thread_specific_data *tsd = thread_get_tsd();
138 
139 	tsd->abort_type = ABORT_TYPE_USER_MODE_PANIC;
140 }
141 #endif /* CFG_UNWIND */
142