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 61*49d0c90dSJens 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 { 6887a092a7SEtienne Carriere /* disable prehemption */ 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