xref: /optee_os/core/kernel/panic.c (revision 2b719df0fc1c2fc22ee5fa94bcd0dafd696f1384)
11bb92983SJerome Forissier // SPDX-License-Identifier: BSD-2-Clause
2b0104773SPascal Brand /*
387a092a7SEtienne Carriere  * Copyright (c) 2016, Linaro Limited
4b0104773SPascal Brand  * Copyright (c) 2014, STMicroelectronics International N.V.
5b0104773SPascal Brand  */
6b0104773SPascal Brand 
7*2b719df0SGatien Chevallier #include <initcall.h>
8*2b719df0SGatien Chevallier #include <kernel/interrupt.h>
9*2b719df0SGatien Chevallier #include <kernel/misc.h>
10b0104773SPascal Brand #include <kernel/panic.h>
11a046599aSJens Wiklander #include <kernel/thread.h>
12e6f01334SJerome Forissier #include <kernel/unwind.h>
134de4bebcSJens Wiklander #include <trace.h>
14b0104773SPascal Brand 
15*2b719df0SGatien Chevallier /* SGI number chosen to halt other cores must be in the secure SGI range */
16*2b719df0SGatien Chevallier static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) ||
17*2b719df0SGatien Chevallier 	      (CFG_HALT_CORES_ON_PANIC_SGI >= 8 &&
18*2b719df0SGatien Chevallier 	       CFG_HALT_CORES_ON_PANIC_SGI < 16));
19*2b719df0SGatien Chevallier 
20*2b719df0SGatien Chevallier static enum itr_return __noreturn
21*2b719df0SGatien Chevallier multi_core_panic_it_handler(struct itr_handler *hdl __unused)
22*2b719df0SGatien Chevallier {
23*2b719df0SGatien Chevallier 	IMSG("Halting CPU %zu", get_core_pos());
24*2b719df0SGatien Chevallier 
25*2b719df0SGatien Chevallier 	while (true)
26*2b719df0SGatien Chevallier 		cpu_idle();
27*2b719df0SGatien Chevallier }
28*2b719df0SGatien Chevallier 
29*2b719df0SGatien Chevallier static struct itr_handler multi_core_panic_handler = {
30*2b719df0SGatien Chevallier 	.it = CFG_HALT_CORES_ON_PANIC_SGI,
31*2b719df0SGatien Chevallier 	.handler = multi_core_panic_it_handler,
32*2b719df0SGatien Chevallier };
33*2b719df0SGatien Chevallier DECLARE_KEEP_PAGER(multi_core_panic_handler);
34*2b719df0SGatien Chevallier 
35*2b719df0SGatien Chevallier static void notify_other_cores(void)
36*2b719df0SGatien Chevallier {
37*2b719df0SGatien Chevallier 	interrupt_raise_sgi(interrupt_get_main_chip(),
38*2b719df0SGatien Chevallier 			    CFG_HALT_CORES_ON_PANIC_SGI,
39*2b719df0SGatien Chevallier 			    ITR_CPU_MASK_TO_OTHER_CPUS);
40*2b719df0SGatien Chevallier }
41*2b719df0SGatien Chevallier 
42*2b719df0SGatien Chevallier static TEE_Result init_multi_core_panic_handler(void)
43*2b719df0SGatien Chevallier {
44*2b719df0SGatien Chevallier 	if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1)
45*2b719df0SGatien Chevallier 		return TEE_SUCCESS;
46*2b719df0SGatien Chevallier 
47*2b719df0SGatien Chevallier 	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
48*2b719df0SGatien Chevallier 					    &multi_core_panic_handler))
49*2b719df0SGatien Chevallier 		panic();
50*2b719df0SGatien Chevallier 
51*2b719df0SGatien Chevallier 	interrupt_enable(interrupt_get_main_chip(),
52*2b719df0SGatien Chevallier 			 multi_core_panic_handler.it);
53*2b719df0SGatien Chevallier 
54*2b719df0SGatien Chevallier 	return TEE_SUCCESS;
55*2b719df0SGatien Chevallier }
56*2b719df0SGatien Chevallier 
57*2b719df0SGatien Chevallier boot_final(init_multi_core_panic_handler);
58*2b719df0SGatien Chevallier 
5987a092a7SEtienne Carriere void __do_panic(const char *file __maybe_unused,
6087a092a7SEtienne Carriere 		const int line __maybe_unused,
6187a092a7SEtienne Carriere 		const char *func __maybe_unused,
6287a092a7SEtienne Carriere 		const char *msg __maybe_unused)
63b0104773SPascal Brand {
6487a092a7SEtienne Carriere 	/* disable prehemption */
6587a092a7SEtienne Carriere 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
66a046599aSJens Wiklander 
6787a092a7SEtienne Carriere 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
6887a092a7SEtienne Carriere 	if (!file && !func && !msg)
6987a092a7SEtienne Carriere 		EMSG_RAW("Panic");
7087a092a7SEtienne Carriere 	else
7187a092a7SEtienne Carriere 		EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
7287a092a7SEtienne Carriere 			 msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
7387a092a7SEtienne Carriere 			 file ? file : "?", file ? line : 0,
7487a092a7SEtienne Carriere 			 func ? "<" : "", func ? func : "", func ? ">" : "");
7587a092a7SEtienne Carriere 
76e6f01334SJerome Forissier 	print_kernel_stack();
77*2b719df0SGatien Chevallier 
78*2b719df0SGatien Chevallier 	if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
79*2b719df0SGatien Chevallier 		notify_other_cores();
80*2b719df0SGatien Chevallier 
8187a092a7SEtienne Carriere 	/* abort current execution */
82b0104773SPascal Brand 	while (1)
83927d81acSJerome Forissier 		cpu_idle();
84927d81acSJerome Forissier }
85927d81acSJerome Forissier 
86927d81acSJerome Forissier void __weak cpu_idle(void)
87927d81acSJerome Forissier {
88b0104773SPascal Brand }
89