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