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