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_MULTI_CORE_HALTING) ||
17 (CFG_HALT_CORES_SGI >= 8 && CFG_HALT_CORES_SGI < 16));
18
19 static enum itr_return __noreturn
multi_core_halt_it_handler(struct itr_handler * hdl __unused)20 multi_core_halt_it_handler(struct itr_handler *hdl __unused)
21 {
22 IMSG("Halting CPU %zu", get_core_pos());
23
24 while (true)
25 cpu_idle();
26 }
27
28 static struct itr_handler multi_core_halt_handler __nex_data = {
29 .it = CFG_HALT_CORES_SGI,
30 .handler = multi_core_halt_it_handler,
31 };
32 DECLARE_KEEP_PAGER(multi_core_halt_handler);
33
halt_other_cores(void)34 static void halt_other_cores(void)
35 {
36 struct itr_chip *chip = interrupt_get_main_chip_may_fail();
37
38 if (chip)
39 interrupt_raise_sgi(chip, CFG_HALT_CORES_SGI,
40 ITR_CPU_MASK_TO_OTHER_CPUS);
41 else
42 EMSG("Can't halt other cores, main interrupt chip not set");
43 }
44
init_multi_core_halt_handler(void)45 static TEE_Result init_multi_core_halt_handler(void)
46 {
47 if (!IS_ENABLED(CFG_MULTI_CORE_HALTING) || CFG_TEE_CORE_NB_CORE == 1)
48 return TEE_SUCCESS;
49
50 if (interrupt_add_handler_with_chip(interrupt_get_main_chip(),
51 &multi_core_halt_handler))
52 panic();
53
54 interrupt_enable(interrupt_get_main_chip(),
55 multi_core_halt_handler.it);
56
57 return TEE_SUCCESS;
58 }
59
60 nex_driver_init_late(init_multi_core_halt_handler);
61
__do_panic(const char * file __maybe_unused,const int line __maybe_unused,const char * func __maybe_unused,const char * msg __maybe_unused)62 void __do_panic(const char *file __maybe_unused,
63 const int line __maybe_unused,
64 const char *func __maybe_unused,
65 const char *msg __maybe_unused)
66 {
67 /* disable preemption */
68 (void)thread_mask_exceptions(THREAD_EXCP_ALL);
69
70 /* trace: Panic ['panic-string-message' ]at FILE:LINE [<FUNCTION>]" */
71 if (!file && !func && !msg)
72 EMSG_RAW("Panic");
73 else
74 EMSG_RAW("Panic %s%s%sat %s:%d %s%s%s",
75 msg ? "'" : "", msg ? msg : "", msg ? "' " : "",
76 file ? file : "?", file ? line : 0,
77 func ? "<" : "", func ? func : "", func ? ">" : "");
78
79 print_kernel_stack();
80
81 if (IS_ENABLED(CFG_HALT_CORES_ON_PANIC) && CFG_TEE_CORE_NB_CORE > 1)
82 halt_other_cores();
83
84 /* abort current execution */
85 while (1)
86 cpu_idle();
87 }
88
cpu_idle(void)89 void __weak cpu_idle(void)
90 {
91 }
92