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