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