blob: 3cf3114364da873891117310e51e87fdf08c5249 [file] [log] [blame]
Andrew Boie71ce8ce2019-07-11 14:18:28 -07001/*
2 * Copyright (c) 2019 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +02007#include <zephyr/kernel.h>
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +02008
Andrew Boie71ce8ce2019-07-11 14:18:28 -07009#include <kernel_internal.h>
Gerard Marull-Paretascffefc82022-05-06 11:04:23 +020010#include <zephyr/kernel_structs.h>
11#include <zephyr/sys/__assert.h>
12#include <zephyr/arch/cpu.h>
13#include <zephyr/logging/log_ctrl.h>
14#include <zephyr/logging/log.h>
15#include <zephyr/fatal.h>
16#include <zephyr/debug/coredump.h>
Andrew Boie71ce8ce2019-07-11 14:18:28 -070017
Krzysztof Chruscinski3ed80832020-11-26 19:32:34 +010018LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
Andrew Boie8a9e8e02019-07-15 22:03:56 -070019
Andrew Boie71ce8ce2019-07-11 14:18:28 -070020/* LCOV_EXCL_START */
Andrew Boie4f77c2a2019-11-07 12:43:29 -080021FUNC_NORETURN __weak void arch_system_halt(unsigned int reason)
Andrew Boie71ce8ce2019-07-11 14:18:28 -070022{
23 ARG_UNUSED(reason);
24
25 /* TODO: What's the best way to totally halt the system if SMP
26 * is enabled?
27 */
28
Andrew Boie4f77c2a2019-11-07 12:43:29 -080029 (void)arch_irq_lock();
Andrew Boie71ce8ce2019-07-11 14:18:28 -070030 for (;;) {
Andrew Boie90e65362019-09-06 07:57:41 -070031 /* Spin endlessly */
Andrew Boie71ce8ce2019-07-11 14:18:28 -070032 }
33}
34/* LCOV_EXCL_STOP */
35
36/* LCOV_EXCL_START */
37__weak void k_sys_fatal_error_handler(unsigned int reason,
Yong Cong Sine54b27b2024-06-01 00:07:14 +080038 const struct arch_esf *esf)
Andrew Boie71ce8ce2019-07-11 14:18:28 -070039{
40 ARG_UNUSED(esf);
41
42 LOG_PANIC();
Andrew Boiea470ba12019-08-07 09:06:23 +020043 LOG_ERR("Halting system");
Andrew Boie4f77c2a2019-11-07 12:43:29 -080044 arch_system_halt(reason);
Anas Nashif05315ea2023-12-19 08:37:58 -050045 CODE_UNREACHABLE;
Andrew Boie71ce8ce2019-07-11 14:18:28 -070046}
47/* LCOV_EXCL_STOP */
48
49static const char *thread_name_get(struct k_thread *thread)
50{
Anas Nashif3f4f3f62021-03-29 17:13:47 -040051 const char *thread_name = (thread != NULL) ? k_thread_name_get(thread) : NULL;
Andrew Boie71ce8ce2019-07-11 14:18:28 -070052
Anas Nashif3f4f3f62021-03-29 17:13:47 -040053 if ((thread_name == NULL) || (thread_name[0] == '\0')) {
Andrew Boie71ce8ce2019-07-11 14:18:28 -070054 thread_name = "unknown";
55 }
56
57 return thread_name;
58}
59
60static const char *reason_to_str(unsigned int reason)
61{
62 switch (reason) {
63 case K_ERR_CPU_EXCEPTION:
64 return "CPU exception";
65 case K_ERR_SPURIOUS_IRQ:
66 return "Unhandled interrupt";
67 case K_ERR_STACK_CHK_FAIL:
68 return "Stack overflow";
69 case K_ERR_KERNEL_OOPS:
70 return "Kernel oops";
71 case K_ERR_KERNEL_PANIC:
72 return "Kernel panic";
73 default:
74 return "Unknown error";
75 }
76}
77
Peng Su1084f482019-08-22 17:12:26 +080078/* LCOV_EXCL_START */
Andrew Boie00bf76e2019-08-06 12:10:49 -070079FUNC_NORETURN void k_fatal_halt(unsigned int reason)
80{
Andrew Boie4f77c2a2019-11-07 12:43:29 -080081 arch_system_halt(reason);
Andrew Boie00bf76e2019-08-06 12:10:49 -070082}
Peng Su1084f482019-08-22 17:12:26 +080083/* LCOV_EXCL_STOP */
84
Yong Cong Sine54b27b2024-06-01 00:07:14 +080085void z_fatal_error(unsigned int reason, const struct arch_esf *esf)
Andrew Boie71ce8ce2019-07-11 14:18:28 -070086{
Andy Ross81531442020-02-06 12:58:53 -080087 /* We can't allow this code to be preempted, but don't need to
88 * synchronize between CPUs, so an arch-layer lock is
89 * appropriate.
90 */
91 unsigned int key = arch_irq_lock();
Krzysztof Chruscinski1ba23ca2021-04-14 13:38:01 +020092 struct k_thread *thread = IS_ENABLED(CONFIG_MULTITHREADING) ?
Flavio Ceolin711c1712023-09-28 16:17:06 -070093 _current : NULL;
Andrew Boie71ce8ce2019-07-11 14:18:28 -070094
Anas Nashif3d33d762020-12-07 11:56:32 -050095 /* twister looks for the "ZEPHYR FATAL ERROR" string, don't
96 * change it without also updating twister
Andrew Boie81ef42d2019-07-16 15:29:46 -070097 */
Andrew Boie91468b52019-11-06 13:03:38 -080098 LOG_ERR(">>> ZEPHYR FATAL ERROR %d: %s on CPU %d", reason,
Flavio Ceolin121d0512023-09-28 16:21:06 -070099 reason_to_str(reason), _current_cpu->id);
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700100
101 /* FIXME: This doesn't seem to work as expected on all arches.
102 * Need a reliable way to determine whether the fault happened when
103 * an IRQ or exception was being handled, or thread context.
104 *
105 * See #17656
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700106 */
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200107#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION)
Ioannis Glaropoulos49fb5d02020-03-09 20:36:21 +0100108 if ((esf != NULL) && arch_is_in_nested_exception(esf)) {
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200109 LOG_ERR("Fault during interrupt handling\n");
110 }
Simon Heinbcd1d192024-03-08 12:00:10 +0100111#endif /* CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION */
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700112
Krzysztof Chruściński28b4bab2024-07-08 12:24:50 +0200113 if (IS_ENABLED(CONFIG_MULTITHREADING)) {
114 LOG_ERR("Current thread: %p (%s)", thread, thread_name_get(thread));
115 }
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700116
Daniel Leungd3218ca2021-01-21 10:11:44 -0800117 coredump(reason, esf, thread);
Daniel Leung49206a82020-08-07 10:47:37 -0700118
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700119 k_sys_fatal_error_handler(reason, esf);
120
121 /* If the system fatal error handler returns, then kill the faulting
122 * thread; a policy decision was made not to hang the system.
123 *
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200124 * Policy for fatal errors in ISRs: unconditionally panic.
125 *
126 * There is one exception to this policy: a stack sentinel
127 * check may be performed (on behalf of the current thread)
128 * during ISR exit, but in this case the thread should be
129 * aborted.
130 *
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700131 * Note that k_thread_abort() returns on some architectures but
132 * not others; e.g. on ARC, x86_64, Xtensa with ASM2, ARM
133 */
134 if (!IS_ENABLED(CONFIG_TEST)) {
135 __ASSERT(reason != K_ERR_KERNEL_PANIC,
136 "Attempted to recover from a kernel panic condition");
137 /* FIXME: #17656 */
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200138#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION)
Ioannis Glaropoulos49fb5d02020-03-09 20:36:21 +0100139 if ((esf != NULL) && arch_is_in_nested_exception(esf)) {
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200140#if defined(CONFIG_STACK_SENTINEL)
141 if (reason != K_ERR_STACK_CHK_FAIL) {
142 __ASSERT(0,
143 "Attempted to recover from a fatal error in ISR");
144 }
145#endif /* CONFIG_STACK_SENTINEL */
146 }
147#endif /* CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION */
148 } else {
149 /* Test mode */
150#if defined(CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION)
Ioannis Glaropoulos1c56f872020-03-09 22:35:50 +0100151 if ((esf != NULL) && arch_is_in_nested_exception(esf)) {
152 /* Abort the thread only on STACK Sentinel check fail. */
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200153#if defined(CONFIG_STACK_SENTINEL)
Ioannis Glaropoulos1c56f872020-03-09 22:35:50 +0100154 if (reason != K_ERR_STACK_CHK_FAIL) {
Ioannis Glaropoulos3a3364e2020-02-14 15:32:53 +0100155 arch_irq_unlock(key);
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200156 return;
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200157 }
Ioannis Glaropoulos1c56f872020-03-09 22:35:50 +0100158#else
159 arch_irq_unlock(key);
160 return;
161#endif /* CONFIG_STACK_SENTINEL */
162 } else {
163 /* Abort the thread only if the fault is not due to
164 * a spurious ISR handler triggered.
165 */
166 if (reason == K_ERR_SPURIOUS_IRQ) {
167 arch_irq_unlock(key);
168 return;
169 }
170 }
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200171#endif /*CONFIG_ARCH_HAS_NESTED_EXCEPTION_DETECTION */
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700172 }
Ioannis Glaropoulosdf029232019-10-07 11:24:36 +0200173
Andy Ross81531442020-02-06 12:58:53 -0800174 arch_irq_unlock(key);
Krzysztof Chruscinski1ba23ca2021-04-14 13:38:01 +0200175
176 if (IS_ENABLED(CONFIG_MULTITHREADING)) {
177 k_thread_abort(thread);
178 }
Andrew Boie71ce8ce2019-07-11 14:18:28 -0700179}