xref: /optee_os/core/arch/arm/kernel/abort.c (revision 29e6329118e799b8f1c21204a20889a334cd6909)
1 /*
2  * Copyright (c) 2015, Linaro Limited
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice,
9  * this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
19  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
21  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
22  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
23  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
24  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
25  * POSSIBILITY OF SUCH DAMAGE.
26  */
27 
28 #include <kernel/abort.h>
29 #include <kernel/misc.h>
30 #include <kernel/tee_ta_manager.h>
31 #include <kernel/panic.h>
32 #include <mm/core_mmu.h>
33 #include <mm/tee_pager.h>
34 #include <trace.h>
35 #include <arm.h>
36 
37 enum fault_type {
38 	FAULT_TYPE_USER_TA_PANIC,
39 	FAULT_TYPE_PAGEABLE,
40 	FAULT_TYPE_IGNORE,
41 };
42 
43 static __unused const char *abort_type_to_str(uint32_t abort_type)
44 {
45 	if (abort_type == ABORT_TYPE_DATA)
46 		return "data";
47 	if (abort_type == ABORT_TYPE_PREFETCH)
48 		return "prefetch";
49 	return "undef";
50 }
51 
52 static __unused void print_detailed_abort(struct abort_info *ai __unused,
53 				const char *ctx __unused)
54 {
55 	EMSG_RAW("\n");
56 	EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "\n",
57 		ctx, abort_type_to_str(ai->abort_type), ai->va);
58 #ifdef ARM32
59 	EMSG_RAW(" fsr 0x%08x  ttbr0 0x%08x  ttbr1 0x%08x  cidr 0x%X\n",
60 		 ai->fault_descr, read_ttbr0(), read_ttbr1(),
61 		 read_contextidr());
62 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
63 		 get_core_pos(), ai->regs->spsr);
64 	EMSG_RAW(" r0 0x%08x      r4 0x%08x    r8 0x%08x   r12 0x%08x\n",
65 		 ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip);
66 	EMSG_RAW(" r1 0x%08x      r5 0x%08x    r9 0x%08x    sp 0x%08x\n",
67 		 ai->regs->r1, ai->regs->r5, ai->regs->r9,
68 		 read_mode_sp(ai->regs->spsr & CPSR_MODE_MASK));
69 	EMSG_RAW(" r2 0x%08x      r6 0x%08x   r10 0x%08x    lr 0x%08x\n",
70 		 ai->regs->r2, ai->regs->r6, ai->regs->r10,
71 		 read_mode_lr(ai->regs->spsr & CPSR_MODE_MASK));
72 	EMSG_RAW(" r3 0x%08x      r7 0x%08x   r11 0x%08x    pc 0x%08x\n",
73 		 ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc);
74 #endif /*ARM32*/
75 #ifdef ARM64
76 	EMSG_RAW(" esr 0x%08x  ttbr0 0x%08" PRIx64 "   ttbr1 0x%08" PRIx64 "   cidr 0x%X\n",
77 		 ai->fault_descr, read_ttbr0_el1(), read_ttbr1_el1(),
78 		 read_contextidr_el1());
79 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
80 		 get_core_pos(), (uint32_t)ai->regs->spsr);
81 	EMSG_RAW("x0  %016" PRIx64 " x1  %016" PRIx64,
82 		 ai->regs->x0, ai->regs->x1);
83 	EMSG_RAW("x2  %016" PRIx64 " x3  %016" PRIx64,
84 		 ai->regs->x2, ai->regs->x3);
85 	EMSG_RAW("x4  %016" PRIx64 " x5  %016" PRIx64,
86 		 ai->regs->x4, ai->regs->x5);
87 	EMSG_RAW("x6  %016" PRIx64 " x7  %016" PRIx64,
88 		 ai->regs->x6, ai->regs->x7);
89 	EMSG_RAW("x8  %016" PRIx64 " x9  %016" PRIx64,
90 		 ai->regs->x8, ai->regs->x9);
91 	EMSG_RAW("x10 %016" PRIx64 " x11 %016" PRIx64,
92 		 ai->regs->x10, ai->regs->x11);
93 	EMSG_RAW("x12 %016" PRIx64 " x13 %016" PRIx64,
94 		 ai->regs->x12, ai->regs->x13);
95 	EMSG_RAW("x14 %016" PRIx64 " x15 %016" PRIx64,
96 		 ai->regs->x14, ai->regs->x15);
97 	EMSG_RAW("x16 %016" PRIx64 " x17 %016" PRIx64,
98 		 ai->regs->x16, ai->regs->x17);
99 	EMSG_RAW("x18 %016" PRIx64 " x19 %016" PRIx64,
100 		 ai->regs->x18, ai->regs->x19);
101 	EMSG_RAW("x20 %016" PRIx64 " x21 %016" PRIx64,
102 		 ai->regs->x20, ai->regs->x21);
103 	EMSG_RAW("x22 %016" PRIx64 " x23 %016" PRIx64,
104 		 ai->regs->x22, ai->regs->x23);
105 	EMSG_RAW("x24 %016" PRIx64 " x25 %016" PRIx64,
106 		 ai->regs->x24, ai->regs->x25);
107 	EMSG_RAW("x26 %016" PRIx64 " x27 %016" PRIx64,
108 		 ai->regs->x26, ai->regs->x27);
109 	EMSG_RAW("x28 %016" PRIx64 " x29 %016" PRIx64,
110 		 ai->regs->x28, ai->regs->x29);
111 	EMSG_RAW("x30 %016" PRIx64 " elr %016" PRIx64,
112 		 ai->regs->x30, ai->regs->elr);
113 	EMSG_RAW("sp_el0 %016" PRIx64, ai->regs->sp_el0);
114 #endif /*ARM64*/
115 }
116 
117 static void print_user_abort(struct abort_info *ai __unused)
118 {
119 #ifdef CFG_TEE_CORE_TA_TRACE
120 	print_detailed_abort(ai, "user TA");
121 	tee_ta_dump_current();
122 #endif
123 }
124 
125 void abort_print(struct abort_info *ai __unused)
126 {
127 #if (TRACE_LEVEL >= TRACE_INFO)
128 	print_detailed_abort(ai, "core");
129 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
130 }
131 
132 void abort_print_error(struct abort_info *ai __unused)
133 {
134 #if (TRACE_LEVEL >= TRACE_INFO)
135 	/* full verbose log at DEBUG level */
136 	print_detailed_abort(ai, "core");
137 #else
138 #ifdef ARM32
139 	EMSG("%s-abort at 0x%" PRIxVA "\n"
140 	     "FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X\n"
141 	     "CPUID 0x%x CPSR 0x%x (read from SPSR)",
142 	     abort_type_to_str(ai->abort_type),
143 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0(), read_contextidr(),
144 	     read_mpidr(), read_spsr());
145 #endif /*ARM32*/
146 #ifdef ARM64
147 	EMSG("%s-abort at 0x%" PRIxVA "\n"
148 	     "ESR 0x%x PC 0x%x TTBR0 0x%" PRIx64 " CONTEXIDR 0x%X\n"
149 	     "CPUID 0x%" PRIx64 " CPSR 0x%x (read from SPSR)",
150 	     abort_type_to_str(ai->abort_type),
151 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0_el1(),
152 	     read_contextidr_el1(),
153 	     read_mpidr_el1(), (uint32_t)ai->regs->spsr);
154 #endif /*ARM64*/
155 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
156 }
157 
158 #ifdef ARM32
159 static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs,
160 		struct abort_info *ai)
161 {
162 	switch (abort_type) {
163 	case ABORT_TYPE_DATA:
164 		ai->fault_descr = read_dfsr();
165 		ai->va = read_dfar();
166 		break;
167 	case ABORT_TYPE_PREFETCH:
168 		ai->fault_descr = read_ifsr();
169 		ai->va = read_ifar();
170 		break;
171 	default:
172 		ai->fault_descr = 0;
173 		ai->va = regs->elr;
174 		break;
175 	}
176 	ai->abort_type = abort_type;
177 	ai->pc = regs->elr;
178 	ai->regs = regs;
179 }
180 #endif /*ARM32*/
181 
182 #ifdef ARM64
183 static void set_abort_info(uint32_t abort_type __unused,
184 		struct thread_abort_regs *regs, struct abort_info *ai)
185 {
186 	ai->fault_descr = read_esr_el1();
187 	switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) {
188 	case ESR_EC_IABT_EL0:
189 	case ESR_EC_IABT_EL1:
190 		ai->abort_type = ABORT_TYPE_PREFETCH;
191 		ai->va = read_far_el1();
192 		break;
193 	case ESR_EC_DABT_EL0:
194 	case ESR_EC_DABT_EL1:
195 	case ESR_EC_SP_ALIGN:
196 		ai->abort_type = ABORT_TYPE_DATA;
197 		ai->va = read_far_el1();
198 		break;
199 	default:
200 		ai->abort_type = ABORT_TYPE_UNDEF;
201 		ai->va = regs->elr;
202 	}
203 	ai->pc = regs->elr;
204 	ai->regs = regs;
205 }
206 #endif /*ARM64*/
207 
208 #ifdef ARM32
209 static void handle_user_ta_panic(struct abort_info *ai)
210 {
211 	/*
212 	 * It was a user exception, stop user execution and return
213 	 * to TEE Core.
214 	 */
215 	ai->regs->r0 = TEE_ERROR_TARGET_DEAD;
216 	ai->regs->r1 = true;
217 	ai->regs->r2 = 0xdeadbeef;
218 	ai->regs->elr = (uint32_t)thread_unwind_user_mode;
219 	ai->regs->spsr = read_cpsr();
220 	ai->regs->spsr &= ~CPSR_MODE_MASK;
221 	ai->regs->spsr |= CPSR_MODE_SVC;
222 	ai->regs->spsr &= ~CPSR_FIA;
223 	ai->regs->spsr |= read_spsr() & CPSR_FIA;
224 	/* Select Thumb or ARM mode */
225 	if (ai->regs->elr & 1)
226 		ai->regs->spsr |= CPSR_T;
227 	else
228 		ai->regs->spsr &= ~CPSR_T;
229 }
230 #endif /*ARM32*/
231 
232 #ifdef ARM64
233 static void handle_user_ta_panic(struct abort_info *ai)
234 {
235 	uint32_t daif;
236 
237 	/*
238 	 * It was a user exception, stop user execution and return
239 	 * to TEE Core.
240 	 */
241 	ai->regs->x0 = TEE_ERROR_TARGET_DEAD;
242 	ai->regs->x1 = true;
243 	ai->regs->x2 = 0xdeadbeef;
244 	ai->regs->elr = (vaddr_t)thread_unwind_user_mode;
245 	ai->regs->sp_el0 = thread_get_saved_thread_sp();
246 
247 	daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK;
248 	/* XXX what about DAIF_D? */
249 	ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif);
250 }
251 #endif /*ARM64*/
252 
253 #ifdef ARM32
254 /* Returns true if the exception originated from user mode */
255 static bool is_user_exception(struct abort_info *ai)
256 {
257 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR;
258 }
259 #endif /*ARM32*/
260 
261 #ifdef ARM64
262 /* Returns true if the exception originated from user mode */
263 static bool is_user_exception(struct abort_info *ai)
264 {
265 	uint32_t spsr = ai->regs->spsr;
266 
267 	if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT))
268 		return true;
269 	if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) ==
270 	    SPSR_64_MODE_EL0)
271 		return true;
272 	return false;
273 }
274 #endif /*ARM64*/
275 
276 #ifdef ARM32
277 /* Returns true if the exception originated from abort mode */
278 static bool is_abort_in_abort_handler(struct abort_info *ai)
279 {
280 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_ABT;
281 }
282 #endif /*ARM32*/
283 
284 #ifdef ARM64
285 /* Returns true if the exception originated from abort mode */
286 static bool is_abort_in_abort_handler(struct abort_info *ai __unused)
287 {
288 	return false;
289 }
290 #endif /*ARM64*/
291 
292 static enum fault_type get_fault_type(struct abort_info *ai)
293 {
294 	if (is_user_exception(ai)) {
295 		print_user_abort(ai);
296 		DMSG("[abort] abort in User mode (TA will panic)");
297 		return FAULT_TYPE_USER_TA_PANIC;
298 	}
299 
300 	if (is_abort_in_abort_handler(ai)) {
301 		abort_print_error(ai);
302 		EMSG("[abort] abort in abort handler (trap CPU)");
303 		panic();
304 	}
305 
306 	if (ai->abort_type == ABORT_TYPE_UNDEF) {
307 		abort_print_error(ai);
308 		EMSG("[abort] undefined abort (trap CPU)");
309 		panic();
310 	}
311 
312 	switch (core_mmu_get_fault_type(ai->fault_descr)) {
313 	case CORE_MMU_FAULT_ALIGNMENT:
314 		abort_print_error(ai);
315 		EMSG("[abort] alignement fault!  (trap CPU)");
316 		panic();
317 		break;
318 
319 	case CORE_MMU_FAULT_ACCESS_BIT:
320 		abort_print_error(ai);
321 		EMSG("[abort] access bit fault!  (trap CPU)");
322 		panic();
323 		break;
324 
325 	case CORE_MMU_FAULT_DEBUG_EVENT:
326 		abort_print(ai);
327 		DMSG("[abort] Ignoring debug event!");
328 		return FAULT_TYPE_IGNORE;
329 
330 	case CORE_MMU_FAULT_TRANSLATION:
331 	case CORE_MMU_FAULT_WRITE_PERMISSION:
332 	case CORE_MMU_FAULT_READ_PERMISSION:
333 		return FAULT_TYPE_PAGEABLE;
334 
335 	case CORE_MMU_FAULT_ASYNC_EXTERNAL:
336 		abort_print(ai);
337 		DMSG("[abort] Ignoring async external abort!");
338 		return FAULT_TYPE_IGNORE;
339 
340 	case CORE_MMU_FAULT_OTHER:
341 	default:
342 		abort_print(ai);
343 		DMSG("[abort] Unhandled fault!");
344 		return FAULT_TYPE_IGNORE;
345 	}
346 }
347 
348 void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs)
349 {
350 	struct abort_info ai;
351 
352 	set_abort_info(abort_type, regs, &ai);
353 
354 	switch (get_fault_type(&ai)) {
355 	case FAULT_TYPE_IGNORE:
356 		break;
357 	case FAULT_TYPE_USER_TA_PANIC:
358 		handle_user_ta_panic(&ai);
359 		break;
360 	case FAULT_TYPE_PAGEABLE:
361 	default:
362 		tee_pager_handle_fault(&ai);
363 		break;
364 	}
365 }
366