xref: /optee_os/core/kernel/panic.c (revision 7653887e496156c4bfd9dd9a1478d277f14ef128)
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 */
16*7653887eSGatien Chevallier static_assert(!IS_ENABLED(CFG_MULTI_CORE_HALTING) ||
17*7653887eSGatien Chevallier 	      (CFG_HALT_CORES_SGI >= 8 && CFG_HALT_CORES_SGI < 16));
182b719df0SGatien Chevallier 
192b719df0SGatien Chevallier static enum itr_return __noreturn
multi_core_halt_it_handler(struct itr_handler * hdl __unused)20*7653887eSGatien Chevallier multi_core_halt_it_handler(struct itr_handler *hdl __unused)
212b719df0SGatien Chevallier {
222b719df0SGatien Chevallier 	IMSG("Halting CPU %zu", get_core_pos());
232b719df0SGatien Chevallier 
242b719df0SGatien Chevallier 	while (true)
252b719df0SGatien Chevallier 		cpu_idle();
262b719df0SGatien Chevallier }
272b719df0SGatien Chevallier 
28*7653887eSGatien Chevallier static struct itr_handler multi_core_halt_handler __nex_data = {
29*7653887eSGatien Chevallier 	.it = CFG_HALT_CORES_SGI,
30*7653887eSGatien Chevallier 	.handler = multi_core_halt_it_handler,
312b719df0SGatien Chevallier };
32*7653887eSGatien Chevallier DECLARE_KEEP_PAGER(multi_core_halt_handler);
332b719df0SGatien Chevallier 
halt_other_cores(void)34*7653887eSGatien Chevallier static void halt_other_cores(void)
352b719df0SGatien Chevallier {
3601ef3c79SJens Wiklander 	struct itr_chip *chip = interrupt_get_main_chip_may_fail();
3701ef3c79SJens Wiklander 
3801ef3c79SJens Wiklander 	if (chip)
39*7653887eSGatien Chevallier 		interrupt_raise_sgi(chip, CFG_HALT_CORES_SGI,
402b719df0SGatien Chevallier 				    ITR_CPU_MASK_TO_OTHER_CPUS);
4101ef3c79SJens Wiklander 	else
42*7653887eSGatien Chevallier 		EMSG("Can't halt other cores, main interrupt chip not set");
432b719df0SGatien Chevallier }
442b719df0SGatien Chevallier 
init_multi_core_halt_handler(void)45*7653887eSGatien Chevallier static TEE_Result init_multi_core_halt_handler(void)
462b719df0SGatien Chevallier {
47*7653887eSGatien Chevallier 	if (!IS_ENABLED(CFG_MULTI_CORE_HALTING) || CFG_TEE_CORE_NB_CORE == 1)
482b719df0SGatien Chevallier 		return TEE_SUCCESS;
492b719df0SGatien Chevallier 
502b719df0SGatien Chevallier 	if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
51*7653887eSGatien Chevallier 					    &multi_core_halt_handler))
522b719df0SGatien Chevallier 		panic();
532b719df0SGatien Chevallier 
542b719df0SGatien Chevallier 	interrupt_enable(interrupt_get_main_chip(),
55*7653887eSGatien Chevallier 			 multi_core_halt_handler.it);
562b719df0SGatien Chevallier 
572b719df0SGatien Chevallier 	return TEE_SUCCESS;
582b719df0SGatien Chevallier }
592b719df0SGatien Chevallier 
60*7653887eSGatien Chevallier nex_driver_init_late(init_multi_core_halt_handler);
612b719df0SGatien Chevallier 
__do_panic(const char * file __maybe_unused,const int line __maybe_unused,const char * func __maybe_unused,const char * msg __maybe_unused)6287a092a7SEtienne Carriere void __do_panic(const char *file __maybe_unused,
6387a092a7SEtienne Carriere 		const int line __maybe_unused,
6487a092a7SEtienne Carriere 		const char *func __maybe_unused,
6587a092a7SEtienne Carriere 		const char *msg __maybe_unused)
66b0104773SPascal Brand {
67344ef8a4SAlvin Chang 	/* disable preemption */
6887a092a7SEtienne Carriere 	(void)thread_mask_exceptions(THREAD_EXCP_ALL);
69a046599aSJens Wiklander 
7087a092a7SEtienne Carriere 	/* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
7187a092a7SEtienne Carriere 	if (!file && !func && !msg)
7287a092a7SEtienne Carriere 		EMSG_RAW("Panic");
7387a092a7SEtienne Carriere 	else
7487a092a7SEtienne Carriere 		EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
7587a092a7SEtienne Carriere 			 msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
7687a092a7SEtienne Carriere 			 file ? file : "?", file ? line : 0,
7787a092a7SEtienne Carriere 			 func ? "<" : "", func ? func : "", func ? ">" : "");
7887a092a7SEtienne Carriere 
79e6f01334SJerome Forissier 	print_kernel_stack();
802b719df0SGatien Chevallier 
812b719df0SGatien Chevallier 	if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
82*7653887eSGatien Chevallier 		halt_other_cores();
832b719df0SGatien Chevallier 
8487a092a7SEtienne Carriere 	/* abort current execution */
85b0104773SPascal Brand 	while (1)
86927d81acSJerome Forissier 		cpu_idle();
87927d81acSJerome Forissier }
88927d81acSJerome Forissier 
cpu_idle(void)89927d81acSJerome Forissier void __weak cpu_idle(void)
90927d81acSJerome Forissier {
91b0104773SPascal Brand }
92