xref: /optee_os/core/kernel/panic.c (revision 344ef8a4deda8e7babc97387ef8c5b4b8215e72a)
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 
72b719df0SGatien Chevallier #include <initcall.h>
82b719df0SGatien Chevallier #include <kernel/interrupt.h>
92b719df0SGatien 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 
152b719df0SGatien Chevallier /* SGI number chosen to halt other cores must be in the secure SGI range */
162b719df0SGatien Chevallier static_assert(!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) ||
172b719df0SGatien Chevallier 	      (CFG_HALT_CORES_ON_PANIC_SGI >= 8 &&
182b719df0SGatien Chevallier 	       CFG_HALT_CORES_ON_PANIC_SGI < 16));
192b719df0SGatien Chevallier 
202b719df0SGatien Chevallier static enum itr_return __noreturn
212b719df0SGatien Chevallier multi_core_panic_it_handler(struct itr_handler *hdl __unused)
222b719df0SGatien Chevallier {
232b719df0SGatien Chevallier 	IMSG("Halting CPU %zu", get_core_pos());
242b719df0SGatien Chevallier 
252b719df0SGatien Chevallier 	while (true)
262b719df0SGatien Chevallier 		cpu_idle();
272b719df0SGatien Chevallier }
282b719df0SGatien Chevallier 
293d52f27cSJens Wiklander static struct itr_handler multi_core_panic_handler __nex_data = {
302b719df0SGatien Chevallier 	.it = CFG_HALT_CORES_ON_PANIC_SGI,
312b719df0SGatien Chevallier 	.handler = multi_core_panic_it_handler,
322b719df0SGatien Chevallier };
332b719df0SGatien Chevallier DECLARE_KEEP_PAGER(multi_core_panic_handler);
342b719df0SGatien Chevallier 
352b719df0SGatien Chevallier static void notify_other_cores(void)
362b719df0SGatien Chevallier {
3701ef3c79SJens Wiklander 	struct itr_chip *chip = interrupt_get_main_chip_may_fail();
3801ef3c79SJens Wiklander 
3901ef3c79SJens Wiklander 	if (chip)
4001ef3c79SJens Wiklander 		interrupt_raise_sgi(chip, CFG_HALT_CORES_ON_PANIC_SGI,
412b719df0SGatien Chevallier 				    ITR_CPU_MASK_TO_OTHER_CPUS);
4201ef3c79SJens Wiklander 	else
4301ef3c79SJens Wiklander 		EMSG("Can't notify other cores, main interrupt chip not set");
442b719df0SGatien Chevallier }
452b719df0SGatien Chevallier 
462b719df0SGatien Chevallier static TEE_Result init_multi_core_panic_handler(void)
472b719df0SGatien Chevallier {
482b719df0SGatien Chevallier 	if (!IS_ENABLED(CFG_HALT_CORES_ON_PANIC) || CFG_TEE_CORE_NB_CORE == 1)
492b719df0SGatien Chevallier 		return TEE_SUCCESS;
502b719df0SGatien Chevallier 
512b719df0SGatien Chevallier 	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
522b719df0SGatien Chevallier 					    &multi_core_panic_handler))
532b719df0SGatien Chevallier 		panic();
542b719df0SGatien Chevallier 
552b719df0SGatien Chevallier 	interrupt_enable(interrupt_get_main_chip(),
562b719df0SGatien Chevallier 			 multi_core_panic_handler.it);
572b719df0SGatien Chevallier 
582b719df0SGatien Chevallier 	return TEE_SUCCESS;
592b719df0SGatien Chevallier }
602b719df0SGatien Chevallier 
6149d0c90dSJens Wiklander nex_driver_init_late(init_multi_core_panic_handler);
622b719df0SGatien Chevallier 
6387a092a7SEtienne Carriere void __do_panic(const char *file __maybe_unused,
6487a092a7SEtienne Carriere 		const int line __maybe_unused,
6587a092a7SEtienne Carriere 		const char *func __maybe_unused,
6687a092a7SEtienne Carriere 		const char *msg __maybe_unused)
67b0104773SPascal Brand {
68*344ef8a4SAlvin Chang 	/* disable preemption */
6987a092a7SEtienne Carriere 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
70a046599aSJens Wiklander 
7187a092a7SEtienne Carriere 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
7287a092a7SEtienne Carriere 	if (!file && !func && !msg)
7387a092a7SEtienne Carriere 		EMSG_RAW("Panic");
7487a092a7SEtienne Carriere 	else
7587a092a7SEtienne Carriere 		EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
7687a092a7SEtienne Carriere 			 msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
7787a092a7SEtienne Carriere 			 file ? file : "?", file ? line : 0,
7887a092a7SEtienne Carriere 			 func ? "<" : "", func ? func : "", func ? ">" : "");
7987a092a7SEtienne Carriere 
80e6f01334SJerome Forissier 	print_kernel_stack();
812b719df0SGatien Chevallier 
822b719df0SGatien Chevallier 	if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
832b719df0SGatien Chevallier 		notify_other_cores();
842b719df0SGatien Chevallier 
8587a092a7SEtienne Carriere 	/* abort current execution */
86b0104773SPascal Brand 	while (1)
87927d81acSJerome Forissier 		cpu_idle();
88927d81acSJerome Forissier }
89927d81acSJerome Forissier 
90927d81acSJerome Forissier void __weak cpu_idle(void)
91927d81acSJerome Forissier {
92b0104773SPascal Brand }
93