xref: /nrf52832-nimble/rt-thread/libcpu/mips/x1000/mips_excpt.c (revision 104654410c56c573564690304ae786df310c91fc)
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