1 /*
2 * File : mips_excpt.c
3 * This file is part of RT-Thread RTOS
4 * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 *
20 * Change Logs:
21 * Date Author Notes
22 * 2016��9��7�� Urey the first version
23 */
24
25 #include <rtthread.h>
26 #include <rthw.h>
27 #include <stdio.h>
28
29 #include "mips.h"
30 #include "mips_excpt.h"
31
32 extern int backtrace(void);
33 int backtrace_ctx(mips_reg_ctx *ctx);
34
35 extern long list_thread(void);
36
37 const static char *regstr[] = {
38 "$0 zero", "$1 at", "$2 v0", "$3 v1", "$4 a0", "$5 a1", "$6 a2", "$7 a3",
39 "$8 t0", "$9 t1", "$10 t2", "$11 t3", "$12 t4", "$13 t5", "$14 t6", "$15 t7",
40 "$16 s0", "$17 s1", "$18 s2", "$19 s3", "$20 s4", "$21 s5", "$22 s6", "$23 s7",
41 "$24 t8", "$25 t9", "$26 k0", "$27 k1", "$28 gp", "$29 sp", "$30 fp", "$31 ra"
42 };
43
44 static const char *cause_strings[32] =
45 {
46 /* 0 */ "Int",
47 /* 1 */ "TLB Mods",
48 /* 2 */ "TLB Load",
49 /* 3 */ "TLB Store",
50 /* 4 */ "Address Load",
51 /* 5 */ "Address Store",
52 /* 6 */ "Instruction Bus Error",
53 /* 7 */ "Data Bus Error",
54 /* 8 */ "Syscall",
55 /* 9 */ "Breakpoint",
56 /* 10 */ "Reserved Instruction",
57 /* 11 */ "Coprocessor Unuseable",
58 /* 12 */ "Overflow",
59 /* 13 */ "Trap",
60 /* 14 */ "Instruction Virtual Coherency Error",
61 /* 15 */ "FP Exception",
62 /* 16 */ "Reserved 16",
63 /* 17 */ "Reserved 17",
64 /* 18 */ "Reserved 18",
65 /* 19 */ "Reserved 19",
66 /* 20 */ "Reserved 20",
67 /* 21 */ "Reserved 21",
68 /* 22 */ "Reserved 22",
69 /* 23 */ "Watch",
70 /* 24 */ "Reserved 24",
71 /* 25 */ "Reserved 25",
72 /* 26 */ "Reserved 26",
73 /* 27 */ "Reserved 27",
74 /* 28 */ "Reserved 28",
75 /* 29 */ "Reserved 29",
76 /* 30 */ "Reserved 30",
77 /* 31 */ "Data Virtual Coherency Error"
78 };
79
80
81 /**
82 * exception handle table
83 */
84 exception_func_t sys_exception_handlers[32];
85
mod_handler(mips_reg_ctx * regs)86 static void mod_handler(mips_reg_ctx *regs)
87 {
88 rt_kprintf("tlb modification exception\n");
89 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
90 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
91
92 list_thread();
93
94 printf("-----------------------------------------------------\n");
95 printf("BACKTRACE:\n");
96 backtrace();
97 printf("-----------------------------------------------------\n");
98
99 rt_hw_cpu_shutdown();
100 }
101
tlbl_handler(mips_reg_ctx * regs)102 static void tlbl_handler(mips_reg_ctx *regs)
103 {
104 rt_kprintf("tlb exception: load\n");
105 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
106 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
107
108 list_thread();
109
110 printf("-----------------------------------------------------\n");
111 printf("BACKTRACE:\n");
112 backtrace();
113 printf("-----------------------------------------------------\n");
114
115 rt_hw_cpu_shutdown();
116 }
117
tlbs_handler(mips_reg_ctx * regs)118 static void tlbs_handler(mips_reg_ctx *regs)
119 {
120 rt_kprintf("tlb exception: store\n");
121 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
122 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
123
124 list_thread();
125
126 printf("-----------------------------------------------------\n");
127 printf("BACKTRACE:\n");
128 backtrace();
129 printf("-----------------------------------------------------\n");
130
131 rt_hw_cpu_shutdown();
132 }
133
adel_handler(mips_reg_ctx * regs)134 static void adel_handler(mips_reg_ctx *regs)
135 {
136 rt_kprintf("address error exception: load\n");
137 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
138 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
139
140 list_thread();
141 rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, rt_thread_self()->name);
142
143 printf("-----------------------------------------------------\n");
144 printf("BACKTRACE:\n");
145 backtrace();
146 printf("-----------------------------------------------------\n");
147
148 rt_hw_cpu_shutdown();
149 }
150
ades_handler(mips_reg_ctx * regs)151 static void ades_handler(mips_reg_ctx *regs)
152 {
153 rt_kprintf("address error exception: store\n");
154 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
155 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
156
157 list_thread();
158
159 printf("-----------------------------------------------------\n");
160 printf("BACKTRACE:\n");
161 backtrace();
162 printf("-----------------------------------------------------\n");
163
164 rt_hw_cpu_shutdown();
165 }
166
fpe_handler(mips_reg_ctx * regs)167 static void fpe_handler(mips_reg_ctx *regs)
168 {
169 rt_kprintf("floating point exception\n");
170 rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
171 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
172
173 list_thread();
174
175 printf("-----------------------------------------------------\n");
176 printf("BACKTRACE:\n");
177 backtrace();
178 printf("-----------------------------------------------------\n");
179
180 rt_hw_cpu_shutdown();
181 }
182
183
unhandled_exception_handle(mips_reg_ctx * regs)184 static void unhandled_exception_handle(mips_reg_ctx *regs)
185 {
186 int i;
187 unsigned int cause = read_c0_cause();
188 unsigned int exc = (cause >> 2) & 0x1f;
189
190 rt_kprintf("exception happens, epc: 0x%08x\n", regs->CP0EPC);
191 rt_kprintf(" cause: 0x%08x\n", regs->CP0Cause);
192
193 for (i = 0; i < 32; i++)
194 {
195 if (i % 4 == 0)
196 printf("\n");
197 printf("%8s %08x ", regstr[i], regs->regs[i]);
198 }
199 printf("\n");
200
201 list_thread();
202 rt_hw_cpu_shutdown();
203 }
204
install_default_exception_handler(void)205 static void install_default_exception_handler(void)
206 {
207 int i;
208
209 for (i=0; i<sizeof(sys_exception_handlers)/sizeof(sys_exception_handlers[0]); i++)
210 sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle;
211
212 sys_exception_handlers[EX_MOD] = mod_handler;
213 sys_exception_handlers[EX_TLBL] = tlbl_handler;
214 sys_exception_handlers[EX_TLBS] = tlbs_handler;
215 sys_exception_handlers[EX_ADEL] = adel_handler;
216 sys_exception_handlers[EX_ADES] = ades_handler;
217 sys_exception_handlers[EX_FPE] = fpe_handler;
218 }
219
rt_hw_exception_init(void)220 int rt_hw_exception_init(void)
221 {
222 /* install the default exception handler */
223 install_default_exception_handler();
224
225 return RT_EOK;
226 }
227
228 /**
229 * setup the exception handle
230 */
rt_set_except_vector(int n,exception_func_t func)231 exception_func_t rt_set_except_vector(int n, exception_func_t func)
232 {
233 exception_func_t old_handler = sys_exception_handlers[n];
234
235 if ((n == 0) || (n > 32) || (!func))
236 {
237 return 0;
238 }
239
240 sys_exception_handlers[n] = func;
241
242 return old_handler;
243 }
244
mips_exception_handler(mips_reg_ctx * ctx)245 void mips_exception_handler(mips_reg_ctx *ctx)
246 {
247 static int read_epc_count = 0;
248 static int epc_save = 0;
249 int i;
250 unsigned int epc;
251
252 //��� read_epc_count>0 ˵�� c_except_handler �ڶ� epc ʱ�����ˣ����� epc ������һ���µ��쳣
253 if (read_epc_count > 0)
254 {
255 printf("ERROR: read epc fail when except handle\n");
256 epc = epc_save;
257 read_epc_count = 0;
258 }
259 else
260 {
261 read_epc_count++;
262 epc_save = 0;
263 epc = read_c0_epc();
264 epc_save = epc;
265
266 if (epc != 0)
267 {
268 printf("-----------------------------------------------------\n");
269 for (i = 0; i < 4; i++)
270 {
271 printf("%08x:\t%08x\n",
272 (epc - 4 * 4 + i * 4),
273 *(unsigned int *) ((epc - 4 * 4 + i * 4) | 0xa0000000));
274 }
275 for (i = 0; i < 4; i++)
276 {
277 printf("%08x:\t%08x\n",
278 (epc + i * 4),
279 *(unsigned int *) ((epc + i * 4) | 0xa0000000));
280 }
281 printf("-----------------------------------------------------\n");
282 }
283
284 read_epc_count--;
285 }
286
287 printf("-----------------------------------------------------\n");
288 unsigned int cause = read_c0_cause();
289 unsigned int exc = (cause >> 2) & 0x1f;
290 printf("CAUSE=%08x --> %s\n", cause, cause_strings[exc]);
291 printf("EPC=%08x\n", epc);
292
293 for (i = 0; i < 32; i++)
294 {
295 if ((i != 0) && (i % 4 == 0))
296 printf("\n");
297 printf("%8s %08x ", regstr[i], ctx->regs[i]);
298 }
299 printf("\n-----------------------------------------------------\n");
300 printf("%s: \t %8x\n","CP0Status ", ctx->CP0Status);
301 printf("%s: \t %8x\n","CP0DataHI ", ctx->CP0DataHI);
302 printf("%s: \t %8x\n","CP0DataLO ", ctx->CP0DataLO);
303 printf("%s: \t %8x\n","CP0BadVAddr", ctx->CP0BadVAddr);
304 printf("%s: \t %8x\n","CP0Cause ", ctx->CP0Cause);
305 printf("%s: \t %8x\n","CP0EPC ", ctx->CP0EPC);
306 printf("-----------------------------------------------------\n");
307
308 #if 0
309 switch (exc)
310 {
311 case EX_MOD:
312 /* TLB modified */
313 break;
314
315 case EX_TLBL: /* TLB exc(load or ifetch) */
316 case EX_TLBS: /* TLB exception (store) */
317
318 break;
319
320 case EX_ADEL: /* Address err(load or ifetch) */
321 case EX_ADES: /* Address error (store) */
322
323 break;
324
325 case EX_IBE: /* Instruction Bus Error */
326 case EX_DBE: /* Data Bus Error */
327
328 break;
329
330 case EX_SYS: /* Syscall */
331
332 break;
333
334 case EX_BP: /* Breakpoint */
335 case EX_TR: /* Trap instruction */
336
337 break;
338 case EX_RI: /* Reserved instruction */
339
340 break;
341 case EX_FPE: /* floating point exception */
342 break;
343
344 case EX_CPU: /* CoProcessor Unusable */
345
346 break;
347 case EX_OV: /* OVerflow */
348 case EX_C2E: /* COP2 exception */
349 case EX_MDMX: /* MDMX exception */
350 case EX_WATCH: /* Watch exception */
351 case EX_MCHECK: /* Machine check exception */
352 case EX_CacheErr: /* Cache error caused re-entry */
353 /* to Debug Mode */
354
355 break;
356 default:
357 rt_kprintf("Unknow exception: %d\r\n", exc);
358 break;
359 }
360 #else
361 sys_exception_handlers[exc](ctx);
362 #endif
363
364 rt_hw_cpu_shutdown();
365 }
366
367
mips_cache_error_handler(unsigned int Addr)368 void mips_cache_error_handler (unsigned int Addr)
369 {
370 rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc());
371 list_thread();
372 rt_hw_cpu_shutdown();
373 }
374
mips_tlb_refill_handler(void)375 void mips_tlb_refill_handler(void)
376 {
377 rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc());
378 rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
379 list_thread();
380 rt_kprintf("current thread: %s\n", rt_thread_self()->name);
381 rt_hw_cpu_shutdown();
382 }
383