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