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