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() */
save_panic_regs_a32_ta(struct thread_specific_data * tsd,uint32_t * pushed)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
scall_save_panic_stack(struct thread_scall_regs * regs)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) */
save_panic_regs_a32_ta(struct thread_specific_data * tsd,uint32_t * pushed)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) */
save_panic_regs_a64_ta(struct thread_specific_data * tsd,uint64_t * pushed)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
scall_save_panic_stack(struct thread_scall_regs * regs)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 */
scall_save_panic_stack(struct thread_scall_regs * regs __unused)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