1 /*
2 * Copyright (c) 2016 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/arch/cpu.h>
9 #include <zephyr/kernel_structs.h>
10 #include <inttypes.h>
11 #include <zephyr/logging/log.h>
12 LOG_MODULE_DECLARE(os, CONFIG_KERNEL_LOG_LEVEL);
13
z_nios2_fatal_error(unsigned int reason,const z_arch_esf_t * esf)14 FUNC_NORETURN void z_nios2_fatal_error(unsigned int reason,
15 const z_arch_esf_t *esf)
16 {
17 if (esf != NULL) {
18 /* Subtract 4 from EA since we added 4 earlier so that the
19 * faulting instruction isn't retried.
20 *
21 * TODO: Only caller-saved registers get saved upon exception
22 * entry. We may want to introduce a config option to save and
23 * dump all registers, at the expense of some stack space.
24 */
25 LOG_ERR("Faulting instruction: 0x%08x", esf->instr - 4);
26 LOG_ERR(" r1: 0x%08x r2: 0x%08x r3: 0x%08x r4: 0x%08x",
27 esf->r1, esf->r2, esf->r3, esf->r4);
28 LOG_ERR(" r5: 0x%08x r6: 0x%08x r7: 0x%08x r8: 0x%08x",
29 esf->r5, esf->r6, esf->r7, esf->r8);
30 LOG_ERR(" r9: 0x%08x r10: 0x%08x r11: 0x%08x r12: 0x%08x",
31 esf->r9, esf->r10, esf->r11, esf->r12);
32 LOG_ERR(" r13: 0x%08x r14: 0x%08x r15: 0x%08x ra: 0x%08x",
33 esf->r13, esf->r14, esf->r15, esf->ra);
34 LOG_ERR("estatus: %08x", esf->estatus);
35 }
36
37 z_fatal_error(reason, esf);
38 CODE_UNREACHABLE;
39 }
40
41 #if defined(CONFIG_EXTRA_EXCEPTION_INFO) && \
42 (defined(CONFIG_PRINTK) || defined(CONFIG_LOG)) \
43 && defined(ALT_CPU_HAS_EXTRA_EXCEPTION_INFO)
cause_str(uint32_t cause_code)44 static char *cause_str(uint32_t cause_code)
45 {
46 switch (cause_code) {
47 case 0:
48 return "reset";
49 case 1:
50 return "processor-only reset request";
51 case 2:
52 return "interrupt";
53 case 3:
54 return "trap";
55 case 4:
56 return "unimplemented instruction";
57 case 5:
58 return "illegal instruction";
59 case 6:
60 return "misaligned data address";
61 case 7:
62 return "misaligned destination address";
63 case 8:
64 return "division error";
65 case 9:
66 return "supervisor-only instruction address";
67 case 10:
68 return "supervisor-only instruction";
69 case 11:
70 return "supervisor-only data address";
71 case 12:
72 return "TLB miss";
73 case 13:
74 return "TLB permission violation (execute)";
75 case 14:
76 return "TLB permission violation (read)";
77 case 15:
78 return "TLB permission violation (write)";
79 case 16:
80 return "MPU region violation (instruction)";
81 case 17:
82 return "MPU region violation (data)";
83 case 18:
84 return "ECC TLB error";
85 case 19:
86 return "ECC fetch error (instruction)";
87 case 20:
88 return "ECC register file error";
89 case 21:
90 return "ECC data error";
91 case 22:
92 return "ECC data cache writeback error";
93 case 23:
94 return "bus instruction fetch error";
95 case 24:
96 return "bus data region violation";
97 default:
98 return "unknown";
99 }
100 }
101 #endif
102
_Fault(const z_arch_esf_t * esf)103 FUNC_NORETURN void _Fault(const z_arch_esf_t *esf)
104 {
105 #if defined(CONFIG_PRINTK) || defined(CONFIG_LOG)
106 /* Unfortunately, completely unavailable on Nios II/e cores */
107 #ifdef ALT_CPU_HAS_EXTRA_EXCEPTION_INFO
108 uint32_t exc_reg, badaddr_reg, eccftl;
109 enum nios2_exception_cause cause;
110
111 exc_reg = z_nios2_creg_read(NIOS2_CR_EXCEPTION);
112
113 /* Bit 31 indicates potentially fatal ECC error */
114 eccftl = (exc_reg & NIOS2_EXCEPTION_REG_ECCFTL_MASK) != 0U;
115
116 /* Bits 2-6 contain the cause code */
117 cause = (exc_reg & NIOS2_EXCEPTION_REG_CAUSE_MASK)
118 >> NIOS2_EXCEPTION_REG_CAUSE_OFST;
119
120 LOG_ERR("Exception cause: %d ECCFTL: 0x%x", cause, eccftl);
121 #if CONFIG_EXTRA_EXCEPTION_INFO
122 LOG_ERR("reason: %s", cause_str(cause));
123 #endif
124 if (BIT(cause) & NIOS2_BADADDR_CAUSE_MASK) {
125 badaddr_reg = z_nios2_creg_read(NIOS2_CR_BADADDR);
126 LOG_ERR("Badaddr: 0x%x", badaddr_reg);
127 }
128 #endif /* ALT_CPU_HAS_EXTRA_EXCEPTION_INFO */
129 #endif /* CONFIG_PRINTK || CONFIG_LOG */
130
131 z_nios2_fatal_error(K_ERR_CPU_EXCEPTION, esf);
132 }
133
134 #ifdef ALT_CPU_HAS_DEBUG_STUB
arch_system_halt(unsigned int reason)135 FUNC_NORETURN void arch_system_halt(unsigned int reason)
136 {
137 ARG_UNUSED(reason);
138
139 z_nios2_break();
140 CODE_UNREACHABLE;
141 }
142 #endif
143