1 /*
2 * Copyright (c) 2016 Cadence Design Systems, Inc.
3 * SPDX-License-Identifier: Apache-2.0
4 */
5
6 #include <zephyr/kernel.h>
7 #include <zephyr/arch/cpu.h>
8 #include <zephyr/kernel_structs.h>
9 #include <inttypes.h>
10 #include <xtensa/config/specreg.h>
11 #include <xtensa_backtrace.h>
12 #include <zephyr/arch/common/exc_handle.h>
13
14 #include <xtensa_internal.h>
15
16 #include <zephyr/logging/log.h>
17 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
18
19 #if defined(CONFIG_SIMULATOR_XTENSA) || defined(XT_SIMULATOR)
20 #include <xtensa/simcall.h>
21 #endif
22
xtensa_exccause(unsigned int cause_code)23 char *xtensa_exccause(unsigned int cause_code)
24 {
25 #if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
26 switch (cause_code) {
27 case 0:
28 return "illegal instruction";
29 case 1:
30 return "syscall";
31 case 2:
32 return "instr fetch error";
33 case 3:
34 return "load/store error";
35 case 4:
36 return "level-1 interrupt";
37 case 5:
38 return "alloca";
39 case 6:
40 return "divide by zero";
41 case 8:
42 return "privileged";
43 case 9:
44 return "load/store alignment";
45 case 12:
46 return "instr PIF data error";
47 case 13:
48 return "load/store PIF data error";
49 case 14:
50 return "instr PIF addr error";
51 case 15:
52 return "load/store PIF addr error";
53 case 16:
54 return "instr TLB miss";
55 case 17:
56 return "instr TLB multi hit";
57 case 18:
58 return "instr fetch privilege";
59 case 20:
60 return "inst fetch prohibited";
61 case 24:
62 return "load/store TLB miss";
63 case 25:
64 return "load/store TLB multi hit";
65 case 26:
66 return "load/store privilege";
67 case 28:
68 return "load prohibited";
69 case 29:
70 return "store prohibited";
71 case 32: case 33: case 34: case 35: case 36: case 37: case 38: case 39:
72 return "coprocessor disabled";
73 case 63:
74 /* i.e. z_except_reason */
75 return "zephyr exception";
76 case 64:
77 return "kernel oops";
78 default:
79 return "unknown/reserved";
80 }
81 #else
82 ARG_UNUSED(cause_code);
83 return "na";
84 #endif
85 }
86
xtensa_fatal_error(unsigned int reason,const struct arch_esf * esf)87 void xtensa_fatal_error(unsigned int reason, const struct arch_esf *esf)
88 {
89 #ifdef CONFIG_EXCEPTION_DEBUG
90 if (esf != NULL) {
91 /* Don't want to get elbowed by xtensa_switch
92 * in between printing registers and dumping them;
93 * corrupts backtrace
94 */
95 unsigned int key = arch_irq_lock();
96
97 xtensa_dump_stack(esf);
98
99
100 #if defined(CONFIG_XTENSA_ENABLE_BACKTRACE)
101 #if XCHAL_HAVE_WINDOWED
102 xtensa_backtrace_print(100, (int *)esf);
103 #endif
104 #endif
105 arch_irq_unlock(key);
106 }
107 #endif /* CONFIG_EXCEPTION_DEBUG */
108
109 z_fatal_error(reason, esf);
110 }
111
112 #if defined(CONFIG_SIMULATOR_XTENSA) || defined(XT_SIMULATOR)
xtensa_simulator_exit(int return_code)113 void xtensa_simulator_exit(int return_code)
114 {
115 __asm__ (
116 "mov a3, %[code]\n\t"
117 "movi a2, %[call]\n\t"
118 "simcall\n\t"
119 :
120 : [code] "r" (return_code), [call] "i" (SYS_exit)
121 : "a3", "a2");
122
123 CODE_UNREACHABLE;
124 }
125
arch_system_halt(unsigned int reason)126 FUNC_NORETURN void arch_system_halt(unsigned int reason)
127 {
128 xtensa_simulator_exit(255 - reason);
129 CODE_UNREACHABLE;
130 }
131 #endif
132
arch_syscall_oops(void * ssf)133 FUNC_NORETURN void arch_syscall_oops(void *ssf)
134 {
135 xtensa_arch_kernel_oops(K_ERR_KERNEL_OOPS, ssf);
136
137 CODE_UNREACHABLE;
138 }
139
140 #ifdef CONFIG_USERSPACE
z_impl_xtensa_user_fault(unsigned int reason)141 void z_impl_xtensa_user_fault(unsigned int reason)
142 {
143 if ((_current->base.user_options & K_USER) != 0) {
144 if ((reason != K_ERR_KERNEL_OOPS) &&
145 (reason != K_ERR_STACK_CHK_FAIL)) {
146 reason = K_ERR_KERNEL_OOPS;
147 }
148 }
149 xtensa_arch_except(reason);
150 }
151
z_vrfy_xtensa_user_fault(unsigned int reason)152 static void z_vrfy_xtensa_user_fault(unsigned int reason)
153 {
154 z_impl_xtensa_user_fault(reason);
155 }
156
157 #include <zephyr/syscalls/xtensa_user_fault_mrsh.c>
158
159 #endif /* CONFIG_USERSPACE */
160