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