xref: /optee_os/core/arch/arm/kernel/abort.c (revision 0de9a5fb2f86132c703c27f603125e1e5f29b5a2)
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 <kernel/user_ta.h>
33 #include <mm/core_mmu.h>
34 #include <mm/tee_pager.h>
35 #include <tee/tee_svc.h>
36 #include <trace.h>
37 #include <arm.h>
38 
39 enum fault_type {
40 	FAULT_TYPE_USER_TA_PANIC,
41 	FAULT_TYPE_USER_TA_VFP,
42 	FAULT_TYPE_PAGEABLE,
43 	FAULT_TYPE_IGNORE,
44 };
45 
46 static __maybe_unused const char *abort_type_to_str(uint32_t abort_type)
47 {
48 	if (abort_type == ABORT_TYPE_DATA)
49 		return "data";
50 	if (abort_type == ABORT_TYPE_PREFETCH)
51 		return "prefetch";
52 	return "undef";
53 }
54 
55 static __maybe_unused void print_detailed_abort(
56 				struct abort_info *ai __maybe_unused,
57 				const char *ctx __maybe_unused)
58 {
59 	EMSG_RAW("\n");
60 	EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "\n",
61 		ctx, abort_type_to_str(ai->abort_type), ai->va);
62 #ifdef ARM32
63 	EMSG_RAW(" fsr 0x%08x  ttbr0 0x%08x  ttbr1 0x%08x  cidr 0x%X\n",
64 		 ai->fault_descr, read_ttbr0(), read_ttbr1(),
65 		 read_contextidr());
66 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
67 		 get_core_pos(), ai->regs->spsr);
68 	EMSG_RAW(" r0 0x%08x      r4 0x%08x    r8 0x%08x   r12 0x%08x\n",
69 		 ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip);
70 	EMSG_RAW(" r1 0x%08x      r5 0x%08x    r9 0x%08x    sp 0x%08x\n",
71 		 ai->regs->r1, ai->regs->r5, ai->regs->r9,
72 		 read_mode_sp(ai->regs->spsr & CPSR_MODE_MASK));
73 	EMSG_RAW(" r2 0x%08x      r6 0x%08x   r10 0x%08x    lr 0x%08x\n",
74 		 ai->regs->r2, ai->regs->r6, ai->regs->r10,
75 		 read_mode_lr(ai->regs->spsr & CPSR_MODE_MASK));
76 	EMSG_RAW(" r3 0x%08x      r7 0x%08x   r11 0x%08x    pc 0x%08x\n",
77 		 ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc);
78 #endif /*ARM32*/
79 #ifdef ARM64
80 	EMSG_RAW(" esr 0x%08x  ttbr0 0x%08" PRIx64 "   ttbr1 0x%08" PRIx64 "   cidr 0x%X\n",
81 		 ai->fault_descr, read_ttbr0_el1(), read_ttbr1_el1(),
82 		 read_contextidr_el1());
83 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
84 		 get_core_pos(), (uint32_t)ai->regs->spsr);
85 	EMSG_RAW("x0  %016" PRIx64 " x1  %016" PRIx64,
86 		 ai->regs->x0, ai->regs->x1);
87 	EMSG_RAW("x2  %016" PRIx64 " x3  %016" PRIx64,
88 		 ai->regs->x2, ai->regs->x3);
89 	EMSG_RAW("x4  %016" PRIx64 " x5  %016" PRIx64,
90 		 ai->regs->x4, ai->regs->x5);
91 	EMSG_RAW("x6  %016" PRIx64 " x7  %016" PRIx64,
92 		 ai->regs->x6, ai->regs->x7);
93 	EMSG_RAW("x8  %016" PRIx64 " x9  %016" PRIx64,
94 		 ai->regs->x8, ai->regs->x9);
95 	EMSG_RAW("x10 %016" PRIx64 " x11 %016" PRIx64,
96 		 ai->regs->x10, ai->regs->x11);
97 	EMSG_RAW("x12 %016" PRIx64 " x13 %016" PRIx64,
98 		 ai->regs->x12, ai->regs->x13);
99 	EMSG_RAW("x14 %016" PRIx64 " x15 %016" PRIx64,
100 		 ai->regs->x14, ai->regs->x15);
101 	EMSG_RAW("x16 %016" PRIx64 " x17 %016" PRIx64,
102 		 ai->regs->x16, ai->regs->x17);
103 	EMSG_RAW("x18 %016" PRIx64 " x19 %016" PRIx64,
104 		 ai->regs->x18, ai->regs->x19);
105 	EMSG_RAW("x20 %016" PRIx64 " x21 %016" PRIx64,
106 		 ai->regs->x20, ai->regs->x21);
107 	EMSG_RAW("x22 %016" PRIx64 " x23 %016" PRIx64,
108 		 ai->regs->x22, ai->regs->x23);
109 	EMSG_RAW("x24 %016" PRIx64 " x25 %016" PRIx64,
110 		 ai->regs->x24, ai->regs->x25);
111 	EMSG_RAW("x26 %016" PRIx64 " x27 %016" PRIx64,
112 		 ai->regs->x26, ai->regs->x27);
113 	EMSG_RAW("x28 %016" PRIx64 " x29 %016" PRIx64,
114 		 ai->regs->x28, ai->regs->x29);
115 	EMSG_RAW("x30 %016" PRIx64 " elr %016" PRIx64,
116 		 ai->regs->x30, ai->regs->elr);
117 	EMSG_RAW("sp_el0 %016" PRIx64, ai->regs->sp_el0);
118 #endif /*ARM64*/
119 }
120 
121 static void print_user_abort(struct abort_info *ai __maybe_unused)
122 {
123 #ifdef CFG_TEE_CORE_TA_TRACE
124 	print_detailed_abort(ai, "user TA");
125 	tee_ta_dump_current();
126 #endif
127 }
128 
129 void abort_print(struct abort_info *ai __maybe_unused)
130 {
131 #if (TRACE_LEVEL >= TRACE_INFO)
132 	print_detailed_abort(ai, "core");
133 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
134 }
135 
136 void abort_print_error(struct abort_info *ai __maybe_unused)
137 {
138 #if (TRACE_LEVEL >= TRACE_INFO)
139 	/* full verbose log at DEBUG level */
140 	print_detailed_abort(ai, "core");
141 #else
142 #ifdef ARM32
143 	EMSG("%s-abort at 0x%" PRIxVA "\n"
144 	     "FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X\n"
145 	     "CPUID 0x%x CPSR 0x%x (read from SPSR)",
146 	     abort_type_to_str(ai->abort_type),
147 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0(), read_contextidr(),
148 	     read_mpidr(), read_spsr());
149 #endif /*ARM32*/
150 #ifdef ARM64
151 	EMSG("%s-abort at 0x%" PRIxVA "\n"
152 	     "ESR 0x%x PC 0x%x TTBR0 0x%" PRIx64 " CONTEXIDR 0x%X\n"
153 	     "CPUID 0x%" PRIx64 " CPSR 0x%x (read from SPSR)",
154 	     abort_type_to_str(ai->abort_type),
155 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0_el1(),
156 	     read_contextidr_el1(),
157 	     read_mpidr_el1(), (uint32_t)ai->regs->spsr);
158 #endif /*ARM64*/
159 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
160 }
161 
162 #ifdef ARM32
163 static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs,
164 		struct abort_info *ai)
165 {
166 	switch (abort_type) {
167 	case ABORT_TYPE_DATA:
168 		ai->fault_descr = read_dfsr();
169 		ai->va = read_dfar();
170 		break;
171 	case ABORT_TYPE_PREFETCH:
172 		ai->fault_descr = read_ifsr();
173 		ai->va = read_ifar();
174 		break;
175 	default:
176 		ai->fault_descr = 0;
177 		ai->va = regs->elr;
178 		break;
179 	}
180 	ai->abort_type = abort_type;
181 	ai->pc = regs->elr;
182 	ai->regs = regs;
183 }
184 #endif /*ARM32*/
185 
186 #ifdef ARM64
187 static void set_abort_info(uint32_t abort_type __unused,
188 		struct thread_abort_regs *regs, struct abort_info *ai)
189 {
190 	ai->fault_descr = read_esr_el1();
191 	switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) {
192 	case ESR_EC_IABT_EL0:
193 	case ESR_EC_IABT_EL1:
194 		ai->abort_type = ABORT_TYPE_PREFETCH;
195 		ai->va = read_far_el1();
196 		break;
197 	case ESR_EC_DABT_EL0:
198 	case ESR_EC_DABT_EL1:
199 	case ESR_EC_SP_ALIGN:
200 		ai->abort_type = ABORT_TYPE_DATA;
201 		ai->va = read_far_el1();
202 		break;
203 	default:
204 		ai->abort_type = ABORT_TYPE_UNDEF;
205 		ai->va = regs->elr;
206 	}
207 	ai->pc = regs->elr;
208 	ai->regs = regs;
209 }
210 #endif /*ARM64*/
211 
212 #ifdef ARM32
213 static void handle_user_ta_panic(struct abort_info *ai)
214 {
215 	/*
216 	 * It was a user exception, stop user execution and return
217 	 * to TEE Core.
218 	 */
219 	ai->regs->r0 = TEE_ERROR_TARGET_DEAD;
220 	ai->regs->r1 = true;
221 	ai->regs->r2 = 0xdeadbeef;
222 	ai->regs->elr = (uint32_t)thread_unwind_user_mode;
223 	ai->regs->spsr = read_cpsr();
224 	ai->regs->spsr &= ~CPSR_MODE_MASK;
225 	ai->regs->spsr |= CPSR_MODE_SVC;
226 	ai->regs->spsr &= ~CPSR_FIA;
227 	ai->regs->spsr |= read_spsr() & CPSR_FIA;
228 	/* Select Thumb or ARM mode */
229 	if (ai->regs->elr & 1)
230 		ai->regs->spsr |= CPSR_T;
231 	else
232 		ai->regs->spsr &= ~CPSR_T;
233 }
234 #endif /*ARM32*/
235 
236 #ifdef ARM64
237 static void handle_user_ta_panic(struct abort_info *ai)
238 {
239 	uint32_t daif;
240 
241 	/*
242 	 * It was a user exception, stop user execution and return
243 	 * to TEE Core.
244 	 */
245 	ai->regs->x0 = TEE_ERROR_TARGET_DEAD;
246 	ai->regs->x1 = true;
247 	ai->regs->x2 = 0xdeadbeef;
248 	ai->regs->elr = (vaddr_t)thread_unwind_user_mode;
249 	ai->regs->sp_el0 = thread_get_saved_thread_sp();
250 
251 	daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK;
252 	/* XXX what about DAIF_D? */
253 	ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif);
254 }
255 #endif /*ARM64*/
256 
257 #ifdef CFG_WITH_VFP
258 static void handle_user_ta_vfp(void)
259 {
260 	TEE_Result res;
261 	struct tee_ta_session *s;
262 
263 	res = tee_ta_get_current_session(&s);
264 	if (res != TEE_SUCCESS)
265 		panic();
266 
267 	thread_user_enable_vfp(&to_user_ta_ctx(s->ctx)->vfp);
268 }
269 #endif /*CFG_WITH_VFP*/
270 
271 #ifdef ARM32
272 /* Returns true if the exception originated from user mode */
273 static bool is_user_exception(struct abort_info *ai)
274 {
275 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR;
276 }
277 #endif /*ARM32*/
278 
279 #ifdef ARM64
280 /* Returns true if the exception originated from user mode */
281 static bool is_user_exception(struct abort_info *ai)
282 {
283 	uint32_t spsr = ai->regs->spsr;
284 
285 	if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT))
286 		return true;
287 	if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) ==
288 	    SPSR_64_MODE_EL0)
289 		return true;
290 	return false;
291 }
292 #endif /*ARM64*/
293 
294 #ifdef ARM32
295 /* Returns true if the exception originated from abort mode */
296 static bool is_abort_in_abort_handler(struct abort_info *ai)
297 {
298 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_ABT;
299 }
300 #endif /*ARM32*/
301 
302 #ifdef ARM64
303 /* Returns true if the exception originated from abort mode */
304 static bool is_abort_in_abort_handler(struct abort_info *ai __unused)
305 {
306 	return false;
307 }
308 #endif /*ARM64*/
309 
310 #ifdef ARM32
311 
312 #define T32_INSTR(w1, w0) \
313 	((((uint32_t)(w0) & 0xffff) << 16) | ((uint32_t)(w1) & 0xffff))
314 
315 #define T32_VTRANS32_MASK	T32_INSTR(0xff << 8, (7 << 9) | 1 << 4)
316 #define T32_VTRANS32_VAL	T32_INSTR(0xee << 8, (5 << 9) | 1 << 4)
317 
318 #define T32_VTRANS64_MASK	T32_INSTR((0xff << 8) | (7 << 5), 7 << 9)
319 #define T32_VTRANS64_VAL	T32_INSTR((0xec << 8) | (2 << 5), 5 << 9)
320 
321 #define T32_VLDST_MASK		T32_INSTR((0xff << 8) | (1 << 4), 0)
322 #define T32_VLDST_VAL		T32_INSTR( 0xf9 << 8            , 0)
323 
324 #define T32_VXLDST_MASK		T32_INSTR(0xfc << 8, 7 << 9)
325 #define T32_VXLDST_VAL		T32_INSTR(0xec << 8, 5 << 9)
326 
327 #define T32_VPROC_MASK		T32_INSTR(0xef << 8, 0)
328 #define T32_VPROC_VAL		T32_VPROC_MASK
329 
330 #define A32_INSTR(x)		((uint32_t)(x))
331 
332 #define A32_VTRANS32_MASK	A32_INSTR((0xf << 24) | (7 << 9) | (1 << 4))
333 #define A32_VTRANS32_VAL	A32_INSTR((0xe << 24) | (5 << 9) | (1 << 4))
334 
335 #define A32_VTRANS64_MASK	A32_INSTR((0x7f << 21) | (7 << 9))
336 #define A32_VTRANS64_VAL	A32_INSTR((0x62 << 21) | (5 << 9))
337 
338 #define A32_VLDST_MASK		A32_INSTR((0xff  << 24) | (1 << 20))
339 #define A32_VLDST_VAL		A32_INSTR((0xf4  << 24))
340 
341 #define A32_VXLDST_MASK		A32_INSTR((7 << 25) | (7 << 9))
342 #define A32_VXLDST_VAL		A32_INSTR((6 << 25) | (5 << 9))
343 
344 #define A32_VPROC_MASK		A32_INSTR(0x7f << 25)
345 #define A32_VPROC_VAL		A32_INSTR(0x79 << 25)
346 
347 static bool is_vfp_fault(struct abort_info *ai)
348 {
349 	TEE_Result res;
350 	uint32_t instr;
351 
352 	if ((ai->abort_type != ABORT_TYPE_UNDEF) || vfp_is_enabled())
353 		return false;
354 
355 	res = tee_svc_copy_from_user(NULL, &instr, (void *)ai->pc,
356 				     sizeof(instr));
357 	if (res != TEE_SUCCESS)
358 		return false;
359 
360 	if (ai->regs->spsr & CPSR_T) {
361 		/* Thumb mode */
362 		return ((instr & T32_VTRANS32_MASK) == T32_VTRANS32_VAL) ||
363 		       ((instr & T32_VTRANS64_MASK) == T32_VTRANS64_VAL) ||
364 		       ((instr & T32_VLDST_MASK) == T32_VLDST_VAL) ||
365 		       ((instr & T32_VXLDST_MASK) == T32_VXLDST_VAL) ||
366 		       ((instr & T32_VPROC_MASK) == T32_VPROC_VAL);
367 	} else {
368 		/* ARM mode */
369 		return ((instr & A32_VTRANS32_MASK) == A32_VTRANS32_VAL) ||
370 		       ((instr & A32_VTRANS64_MASK) == A32_VTRANS64_VAL) ||
371 		       ((instr & A32_VLDST_MASK) == A32_VLDST_VAL) ||
372 		       ((instr & A32_VXLDST_MASK) == A32_VXLDST_VAL) ||
373 		       ((instr & A32_VPROC_MASK) == A32_VPROC_VAL);
374 	}
375 }
376 #endif /*ARM32*/
377 
378 #ifdef ARM64
379 static bool is_vfp_fault(struct abort_info *ai)
380 {
381 	switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) {
382 	case ESR_EC_FP_ASIMD:
383 	case ESR_EC_AARCH32_FP:
384 	case ESR_EC_AARCH64_FP:
385 		return true;
386 	default:
387 		return false;
388 	}
389 }
390 #endif /*ARM64*/
391 
392 static enum fault_type get_fault_type(struct abort_info *ai)
393 {
394 	if (is_user_exception(ai)) {
395 		if (is_vfp_fault(ai))
396 			return FAULT_TYPE_USER_TA_VFP;
397 		print_user_abort(ai);
398 		DMSG("[abort] abort in User mode (TA will panic)");
399 		return FAULT_TYPE_USER_TA_PANIC;
400 	}
401 
402 	if (is_abort_in_abort_handler(ai)) {
403 		abort_print_error(ai);
404 		EMSG("[abort] abort in abort handler (trap CPU)");
405 		panic();
406 	}
407 
408 	if (ai->abort_type == ABORT_TYPE_UNDEF) {
409 		abort_print_error(ai);
410 		EMSG("[abort] undefined abort (trap CPU)");
411 		panic();
412 	}
413 
414 	switch (core_mmu_get_fault_type(ai->fault_descr)) {
415 	case CORE_MMU_FAULT_ALIGNMENT:
416 		abort_print_error(ai);
417 		EMSG("[abort] alignement fault!  (trap CPU)");
418 		panic();
419 		break;
420 
421 	case CORE_MMU_FAULT_ACCESS_BIT:
422 		abort_print_error(ai);
423 		EMSG("[abort] access bit fault!  (trap CPU)");
424 		panic();
425 		break;
426 
427 	case CORE_MMU_FAULT_DEBUG_EVENT:
428 		abort_print(ai);
429 		DMSG("[abort] Ignoring debug event!");
430 		return FAULT_TYPE_IGNORE;
431 
432 	case CORE_MMU_FAULT_TRANSLATION:
433 	case CORE_MMU_FAULT_WRITE_PERMISSION:
434 	case CORE_MMU_FAULT_READ_PERMISSION:
435 		return FAULT_TYPE_PAGEABLE;
436 
437 	case CORE_MMU_FAULT_ASYNC_EXTERNAL:
438 		abort_print(ai);
439 		DMSG("[abort] Ignoring async external abort!");
440 		return FAULT_TYPE_IGNORE;
441 
442 	case CORE_MMU_FAULT_OTHER:
443 	default:
444 		abort_print(ai);
445 		DMSG("[abort] Unhandled fault!");
446 		return FAULT_TYPE_IGNORE;
447 	}
448 }
449 
450 void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs)
451 {
452 	struct abort_info ai;
453 
454 	set_abort_info(abort_type, regs, &ai);
455 
456 	switch (get_fault_type(&ai)) {
457 	case FAULT_TYPE_IGNORE:
458 		break;
459 	case FAULT_TYPE_USER_TA_PANIC:
460 		vfp_disable();
461 		handle_user_ta_panic(&ai);
462 		break;
463 #ifdef CFG_WITH_VFP
464 	case FAULT_TYPE_USER_TA_VFP:
465 		handle_user_ta_vfp();
466 		break;
467 #endif
468 	case FAULT_TYPE_PAGEABLE:
469 	default:
470 		thread_kernel_save_vfp();
471 		tee_pager_handle_fault(&ai);
472 		thread_kernel_restore_vfp();
473 		break;
474 	}
475 }
476