xref: /optee_os/core/kernel/panic.c (revision 79f8990d9d28539864d8f97f9f1cb32e289e595f)
1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2016, Linaro Limited
4  * Copyright (c) 2014, STMicroelectronics International N.V.
5  */
6 
7 #include <initcall.h>
8 #include <kernel/interrupt.h>
9 #include <kernel/misc.h>
10 #include <kernel/panic.h>
11 #include <kernel/thread.h>
12 #include <kernel/unwind.h>
13 #include <trace.h>
14 
15 /* SGI number chosen to halt other cores must be in the secure SGI range */
16 static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) ||
17 	      (CFG_HALT_CORES_ON_PANIC_SGI >= 8 &&
18 	       CFG_HALT_CORES_ON_PANIC_SGI < 16));
19 
20 static enum itr_return __noreturn
21 multi_core_panic_it_handler(struct itr_handler *hdl __unused)
22 {
23 	IMSG("Halting CPU %zu", get_core_pos());
24 
25 	while (true)
26 		cpu_idle();
27 }
28 
29 static struct itr_handler multi_core_panic_handler = {
30 	.it = CFG_HALT_CORES_ON_PANIC_SGI,
31 	.handler = multi_core_panic_it_handler,
32 };
33 DECLARE_KEEP_PAGER(multi_core_panic_handler);
34 
35 static void notify_other_cores(void)
36 {
37 	struct itr_chip *chip = interrupt_get_main_chip_may_fail();
38 
39 	if (chip)
40 		interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI,
41 				    ITR_CPU_MASK_TO_OTHER_CPUS);
42 	else
43 		EMSG("Can't notify other cores, main interrupt chip not set");
44 }
45 
46 static TEE_Result init_multi_core_panic_handler(void)
47 {
48 	if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1)
49 		return TEE_SUCCESS;
50 
51 	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
52 					    &multi_core_panic_handler))
53 		panic();
54 
55 	interrupt_enable(interrupt_get_main_chip(),
56 			 multi_core_panic_handler.it);
57 
58 	return TEE_SUCCESS;
59 }
60 
61 boot_final(init_multi_core_panic_handler);
62 
63 void __do_panic(const char *file __maybe_unused,
64 		const int line __maybe_unused,
65 		const char *func __maybe_unused,
66 		const char *msg __maybe_unused)
67 {
68 	/* disable prehemption */
69 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
70 
71 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
72 	if (!file && !func && !msg)
73 		EMSG_RAW("Panic");
74 	else
75 		EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
76 			 msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
77 			 file ? file : "?", file ? line : 0,
78 			 func ? "<" : "", func ? func : "", func ? ">" : "");
79 
80 	print_kernel_stack();
81 
82 	if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
83 		notify_other_cores();
84 
85 	/* abort current execution */
86 	while (1)
87 		cpu_idle();
88 }
89 
90 void __weak cpu_idle(void)
91 {
92 }
93