xref: /optee_os/core/arch/arm/kernel/abort.c (revision 3276098dd4bfdd21da5b85e992a5bbd9a35ea69e)
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 __maybe_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 __maybe_unused void print_detailed_abort(
53 				struct abort_info *ai __maybe_unused,
54 				const char *ctx __maybe_unused)
55 {
56 	EMSG_RAW("\n");
57 	EMSG_RAW("%s %s-abort at address 0x%" PRIxVA "\n",
58 		ctx, abort_type_to_str(ai->abort_type), ai->va);
59 #ifdef ARM32
60 	EMSG_RAW(" fsr 0x%08x  ttbr0 0x%08x  ttbr1 0x%08x  cidr 0x%X\n",
61 		 ai->fault_descr, read_ttbr0(), read_ttbr1(),
62 		 read_contextidr());
63 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
64 		 get_core_pos(), ai->regs->spsr);
65 	EMSG_RAW(" r0 0x%08x      r4 0x%08x    r8 0x%08x   r12 0x%08x\n",
66 		 ai->regs->r0, ai->regs->r4, ai->regs->r8, ai->regs->ip);
67 	EMSG_RAW(" r1 0x%08x      r5 0x%08x    r9 0x%08x    sp 0x%08x\n",
68 		 ai->regs->r1, ai->regs->r5, ai->regs->r9,
69 		 read_mode_sp(ai->regs->spsr & CPSR_MODE_MASK));
70 	EMSG_RAW(" r2 0x%08x      r6 0x%08x   r10 0x%08x    lr 0x%08x\n",
71 		 ai->regs->r2, ai->regs->r6, ai->regs->r10,
72 		 read_mode_lr(ai->regs->spsr & CPSR_MODE_MASK));
73 	EMSG_RAW(" r3 0x%08x      r7 0x%08x   r11 0x%08x    pc 0x%08x\n",
74 		 ai->regs->r3, ai->regs->r7, ai->regs->r11, ai->pc);
75 #endif /*ARM32*/
76 #ifdef ARM64
77 	EMSG_RAW(" esr 0x%08x  ttbr0 0x%08" PRIx64 "   ttbr1 0x%08" PRIx64 "   cidr 0x%X\n",
78 		 ai->fault_descr, read_ttbr0_el1(), read_ttbr1_el1(),
79 		 read_contextidr_el1());
80 	EMSG_RAW(" cpu #%zu          cpsr 0x%08x\n",
81 		 get_core_pos(), (uint32_t)ai->regs->spsr);
82 	EMSG_RAW("x0  %016" PRIx64 " x1  %016" PRIx64,
83 		 ai->regs->x0, ai->regs->x1);
84 	EMSG_RAW("x2  %016" PRIx64 " x3  %016" PRIx64,
85 		 ai->regs->x2, ai->regs->x3);
86 	EMSG_RAW("x4  %016" PRIx64 " x5  %016" PRIx64,
87 		 ai->regs->x4, ai->regs->x5);
88 	EMSG_RAW("x6  %016" PRIx64 " x7  %016" PRIx64,
89 		 ai->regs->x6, ai->regs->x7);
90 	EMSG_RAW("x8  %016" PRIx64 " x9  %016" PRIx64,
91 		 ai->regs->x8, ai->regs->x9);
92 	EMSG_RAW("x10 %016" PRIx64 " x11 %016" PRIx64,
93 		 ai->regs->x10, ai->regs->x11);
94 	EMSG_RAW("x12 %016" PRIx64 " x13 %016" PRIx64,
95 		 ai->regs->x12, ai->regs->x13);
96 	EMSG_RAW("x14 %016" PRIx64 " x15 %016" PRIx64,
97 		 ai->regs->x14, ai->regs->x15);
98 	EMSG_RAW("x16 %016" PRIx64 " x17 %016" PRIx64,
99 		 ai->regs->x16, ai->regs->x17);
100 	EMSG_RAW("x18 %016" PRIx64 " x19 %016" PRIx64,
101 		 ai->regs->x18, ai->regs->x19);
102 	EMSG_RAW("x20 %016" PRIx64 " x21 %016" PRIx64,
103 		 ai->regs->x20, ai->regs->x21);
104 	EMSG_RAW("x22 %016" PRIx64 " x23 %016" PRIx64,
105 		 ai->regs->x22, ai->regs->x23);
106 	EMSG_RAW("x24 %016" PRIx64 " x25 %016" PRIx64,
107 		 ai->regs->x24, ai->regs->x25);
108 	EMSG_RAW("x26 %016" PRIx64 " x27 %016" PRIx64,
109 		 ai->regs->x26, ai->regs->x27);
110 	EMSG_RAW("x28 %016" PRIx64 " x29 %016" PRIx64,
111 		 ai->regs->x28, ai->regs->x29);
112 	EMSG_RAW("x30 %016" PRIx64 " elr %016" PRIx64,
113 		 ai->regs->x30, ai->regs->elr);
114 	EMSG_RAW("sp_el0 %016" PRIx64, ai->regs->sp_el0);
115 #endif /*ARM64*/
116 }
117 
118 static void print_user_abort(struct abort_info *ai __maybe_unused)
119 {
120 #ifdef CFG_TEE_CORE_TA_TRACE
121 	print_detailed_abort(ai, "user TA");
122 	tee_ta_dump_current();
123 #endif
124 }
125 
126 void abort_print(struct abort_info *ai __maybe_unused)
127 {
128 #if (TRACE_LEVEL >= TRACE_INFO)
129 	print_detailed_abort(ai, "core");
130 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
131 }
132 
133 void abort_print_error(struct abort_info *ai __maybe_unused)
134 {
135 #if (TRACE_LEVEL >= TRACE_INFO)
136 	/* full verbose log at DEBUG level */
137 	print_detailed_abort(ai, "core");
138 #else
139 #ifdef ARM32
140 	EMSG("%s-abort at 0x%" PRIxVA "\n"
141 	     "FSR 0x%x PC 0x%x TTBR0 0x%X CONTEXIDR 0x%X\n"
142 	     "CPUID 0x%x CPSR 0x%x (read from SPSR)",
143 	     abort_type_to_str(ai->abort_type),
144 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0(), read_contextidr(),
145 	     read_mpidr(), read_spsr());
146 #endif /*ARM32*/
147 #ifdef ARM64
148 	EMSG("%s-abort at 0x%" PRIxVA "\n"
149 	     "ESR 0x%x PC 0x%x TTBR0 0x%" PRIx64 " CONTEXIDR 0x%X\n"
150 	     "CPUID 0x%" PRIx64 " CPSR 0x%x (read from SPSR)",
151 	     abort_type_to_str(ai->abort_type),
152 	     ai->va, ai->fault_descr, ai->pc, read_ttbr0_el1(),
153 	     read_contextidr_el1(),
154 	     read_mpidr_el1(), (uint32_t)ai->regs->spsr);
155 #endif /*ARM64*/
156 #endif /*TRACE_LEVEL >= TRACE_DEBUG*/
157 }
158 
159 #ifdef ARM32
160 static void set_abort_info(uint32_t abort_type, struct thread_abort_regs *regs,
161 		struct abort_info *ai)
162 {
163 	switch (abort_type) {
164 	case ABORT_TYPE_DATA:
165 		ai->fault_descr = read_dfsr();
166 		ai->va = read_dfar();
167 		break;
168 	case ABORT_TYPE_PREFETCH:
169 		ai->fault_descr = read_ifsr();
170 		ai->va = read_ifar();
171 		break;
172 	default:
173 		ai->fault_descr = 0;
174 		ai->va = regs->elr;
175 		break;
176 	}
177 	ai->abort_type = abort_type;
178 	ai->pc = regs->elr;
179 	ai->regs = regs;
180 }
181 #endif /*ARM32*/
182 
183 #ifdef ARM64
184 static void set_abort_info(uint32_t abort_type __unused,
185 		struct thread_abort_regs *regs, struct abort_info *ai)
186 {
187 	ai->fault_descr = read_esr_el1();
188 	switch ((ai->fault_descr >> ESR_EC_SHIFT) & ESR_EC_MASK) {
189 	case ESR_EC_IABT_EL0:
190 	case ESR_EC_IABT_EL1:
191 		ai->abort_type = ABORT_TYPE_PREFETCH;
192 		ai->va = read_far_el1();
193 		break;
194 	case ESR_EC_DABT_EL0:
195 	case ESR_EC_DABT_EL1:
196 	case ESR_EC_SP_ALIGN:
197 		ai->abort_type = ABORT_TYPE_DATA;
198 		ai->va = read_far_el1();
199 		break;
200 	default:
201 		ai->abort_type = ABORT_TYPE_UNDEF;
202 		ai->va = regs->elr;
203 	}
204 	ai->pc = regs->elr;
205 	ai->regs = regs;
206 }
207 #endif /*ARM64*/
208 
209 #ifdef ARM32
210 static void handle_user_ta_panic(struct abort_info *ai)
211 {
212 	/*
213 	 * It was a user exception, stop user execution and return
214 	 * to TEE Core.
215 	 */
216 	ai->regs->r0 = TEE_ERROR_TARGET_DEAD;
217 	ai->regs->r1 = true;
218 	ai->regs->r2 = 0xdeadbeef;
219 	ai->regs->elr = (uint32_t)thread_unwind_user_mode;
220 	ai->regs->spsr = read_cpsr();
221 	ai->regs->spsr &= ~CPSR_MODE_MASK;
222 	ai->regs->spsr |= CPSR_MODE_SVC;
223 	ai->regs->spsr &= ~CPSR_FIA;
224 	ai->regs->spsr |= read_spsr() & CPSR_FIA;
225 	/* Select Thumb or ARM mode */
226 	if (ai->regs->elr & 1)
227 		ai->regs->spsr |= CPSR_T;
228 	else
229 		ai->regs->spsr &= ~CPSR_T;
230 }
231 #endif /*ARM32*/
232 
233 #ifdef ARM64
234 static void handle_user_ta_panic(struct abort_info *ai)
235 {
236 	uint32_t daif;
237 
238 	/*
239 	 * It was a user exception, stop user execution and return
240 	 * to TEE Core.
241 	 */
242 	ai->regs->x0 = TEE_ERROR_TARGET_DEAD;
243 	ai->regs->x1 = true;
244 	ai->regs->x2 = 0xdeadbeef;
245 	ai->regs->elr = (vaddr_t)thread_unwind_user_mode;
246 	ai->regs->sp_el0 = thread_get_saved_thread_sp();
247 
248 	daif = (ai->regs->spsr >> SPSR_32_AIF_SHIFT) & SPSR_32_AIF_MASK;
249 	/* XXX what about DAIF_D? */
250 	ai->regs->spsr = SPSR_64(SPSR_64_MODE_EL1, SPSR_64_MODE_SP_EL0, daif);
251 }
252 #endif /*ARM64*/
253 
254 #ifdef ARM32
255 /* Returns true if the exception originated from user mode */
256 static bool is_user_exception(struct abort_info *ai)
257 {
258 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_USR;
259 }
260 #endif /*ARM32*/
261 
262 #ifdef ARM64
263 /* Returns true if the exception originated from user mode */
264 static bool is_user_exception(struct abort_info *ai)
265 {
266 	uint32_t spsr = ai->regs->spsr;
267 
268 	if (spsr & (SPSR_MODE_RW_32 << SPSR_MODE_RW_SHIFT))
269 		return true;
270 	if (((spsr >> SPSR_64_MODE_EL_SHIFT) & SPSR_64_MODE_EL_MASK) ==
271 	    SPSR_64_MODE_EL0)
272 		return true;
273 	return false;
274 }
275 #endif /*ARM64*/
276 
277 #ifdef ARM32
278 /* Returns true if the exception originated from abort mode */
279 static bool is_abort_in_abort_handler(struct abort_info *ai)
280 {
281 	return (ai->regs->spsr & ARM32_CPSR_MODE_MASK) == ARM32_CPSR_MODE_ABT;
282 }
283 #endif /*ARM32*/
284 
285 #ifdef ARM64
286 /* Returns true if the exception originated from abort mode */
287 static bool is_abort_in_abort_handler(struct abort_info *ai __unused)
288 {
289 	return false;
290 }
291 #endif /*ARM64*/
292 
293 static enum fault_type get_fault_type(struct abort_info *ai)
294 {
295 	if (is_user_exception(ai)) {
296 		print_user_abort(ai);
297 		DMSG("[abort] abort in User mode (TA will panic)");
298 		return FAULT_TYPE_USER_TA_PANIC;
299 	}
300 
301 	if (is_abort_in_abort_handler(ai)) {
302 		abort_print_error(ai);
303 		EMSG("[abort] abort in abort handler (trap CPU)");
304 		panic();
305 	}
306 
307 	if (ai->abort_type == ABORT_TYPE_UNDEF) {
308 		abort_print_error(ai);
309 		EMSG("[abort] undefined abort (trap CPU)");
310 		panic();
311 	}
312 
313 	switch (core_mmu_get_fault_type(ai->fault_descr)) {
314 	case CORE_MMU_FAULT_ALIGNMENT:
315 		abort_print_error(ai);
316 		EMSG("[abort] alignement fault!  (trap CPU)");
317 		panic();
318 		break;
319 
320 	case CORE_MMU_FAULT_ACCESS_BIT:
321 		abort_print_error(ai);
322 		EMSG("[abort] access bit fault!  (trap CPU)");
323 		panic();
324 		break;
325 
326 	case CORE_MMU_FAULT_DEBUG_EVENT:
327 		abort_print(ai);
328 		DMSG("[abort] Ignoring debug event!");
329 		return FAULT_TYPE_IGNORE;
330 
331 	case CORE_MMU_FAULT_TRANSLATION:
332 	case CORE_MMU_FAULT_WRITE_PERMISSION:
333 	case CORE_MMU_FAULT_READ_PERMISSION:
334 		return FAULT_TYPE_PAGEABLE;
335 
336 	case CORE_MMU_FAULT_ASYNC_EXTERNAL:
337 		abort_print(ai);
338 		DMSG("[abort] Ignoring async external abort!");
339 		return FAULT_TYPE_IGNORE;
340 
341 	case CORE_MMU_FAULT_OTHER:
342 	default:
343 		abort_print(ai);
344 		DMSG("[abort] Unhandled fault!");
345 		return FAULT_TYPE_IGNORE;
346 	}
347 }
348 
349 void abort_handler(uint32_t abort_type, struct thread_abort_regs *regs)
350 {
351 	struct abort_info ai;
352 
353 	set_abort_info(abort_type, regs, &ai);
354 
355 	switch (get_fault_type(&ai)) {
356 	case FAULT_TYPE_IGNORE:
357 		break;
358 	case FAULT_TYPE_USER_TA_PANIC:
359 		handle_user_ta_panic(&ai);
360 		break;
361 	case FAULT_TYPE_PAGEABLE:
362 	default:
363 		tee_pager_handle_fault(&ai);
364 		break;
365 	}
366 }
367