123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382 |
- /*
- * File : mips_excpt.c
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2008 - 2012, RT-Thread Development Team
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Change Logs:
- * Date Author Notes
- * 2016年9月7日 Urey the first version
- */
- #include <rtthread.h>
- #include <rthw.h>
- #include <stdio.h>
- #include "mips.h"
- #include "mips_excpt.h"
- extern int backtrace(void);
- int backtrace_ctx(mips_reg_ctx *ctx);
- extern long list_thread(void);
- const static char *regstr[] = {
- "$0 zero", "$1 at", "$2 v0", "$3 v1", "$4 a0", "$5 a1", "$6 a2", "$7 a3",
- "$8 t0", "$9 t1", "$10 t2", "$11 t3", "$12 t4", "$13 t5", "$14 t6", "$15 t7",
- "$16 s0", "$17 s1", "$18 s2", "$19 s3", "$20 s4", "$21 s5", "$22 s6", "$23 s7",
- "$24 t8", "$25 t9", "$26 k0", "$27 k1", "$28 gp", "$29 sp", "$30 fp", "$31 ra"
- };
- static const char *cause_strings[32] =
- {
- /* 0 */ "Int",
- /* 1 */ "TLB Mods",
- /* 2 */ "TLB Load",
- /* 3 */ "TLB Store",
- /* 4 */ "Address Load",
- /* 5 */ "Address Store",
- /* 6 */ "Instruction Bus Error",
- /* 7 */ "Data Bus Error",
- /* 8 */ "Syscall",
- /* 9 */ "Breakpoint",
- /* 10 */ "Reserved Instruction",
- /* 11 */ "Coprocessor Unuseable",
- /* 12 */ "Overflow",
- /* 13 */ "Trap",
- /* 14 */ "Instruction Virtual Coherency Error",
- /* 15 */ "FP Exception",
- /* 16 */ "Reserved 16",
- /* 17 */ "Reserved 17",
- /* 18 */ "Reserved 18",
- /* 19 */ "Reserved 19",
- /* 20 */ "Reserved 20",
- /* 21 */ "Reserved 21",
- /* 22 */ "Reserved 22",
- /* 23 */ "Watch",
- /* 24 */ "Reserved 24",
- /* 25 */ "Reserved 25",
- /* 26 */ "Reserved 26",
- /* 27 */ "Reserved 27",
- /* 28 */ "Reserved 28",
- /* 29 */ "Reserved 29",
- /* 30 */ "Reserved 30",
- /* 31 */ "Data Virtual Coherency Error"
- };
- /**
- * exception handle table
- */
- exception_func_t sys_exception_handlers[32];
- static void mod_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("tlb modification exception\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void tlbl_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("tlb exception: load\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void tlbs_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("tlb exception: store\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void adel_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("address error exception: load\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- rt_kprintf("current thread: %.*s\n", RT_NAME_MAX, rt_thread_self()->name);
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void ades_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("address error exception: store\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void fpe_handler(mips_reg_ctx *regs)
- {
- rt_kprintf("floating point exception\n");
- rt_kprintf("exception happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- printf("-----------------------------------------------------\n");
- printf("BACKTRACE:\n");
- backtrace();
- printf("-----------------------------------------------------\n");
- rt_hw_cpu_shutdown();
- }
- static void unhandled_exception_handle(mips_reg_ctx *regs)
- {
- int i;
- unsigned int cause = read_c0_cause();
- unsigned int exc = (cause >> 2) & 0x1f;
- rt_kprintf("exception happens, epc: 0x%08x\n", regs->CP0EPC);
- rt_kprintf(" cause: 0x%08x\n", regs->CP0Cause);
- for (i = 0; i < 32; i++)
- {
- if (i % 4 == 0)
- printf("\n");
- printf("%8s %08x ", regstr[i], regs->regs[i]);
- }
- printf("\n");
- list_thread();
- rt_hw_cpu_shutdown();
- }
- static void install_default_exception_handler(void)
- {
- int i;
- for (i=0; i<sizeof(sys_exception_handlers)/sizeof(sys_exception_handlers[0]); i++)
- sys_exception_handlers[i] = (exception_func_t)unhandled_exception_handle;
- sys_exception_handlers[EX_MOD] = mod_handler;
- sys_exception_handlers[EX_TLBL] = tlbl_handler;
- sys_exception_handlers[EX_TLBS] = tlbs_handler;
- sys_exception_handlers[EX_ADEL] = adel_handler;
- sys_exception_handlers[EX_ADES] = ades_handler;
- sys_exception_handlers[EX_FPE] = fpe_handler;
- }
- int rt_hw_exception_init(void)
- {
- /* install the default exception handler */
- install_default_exception_handler();
- return RT_EOK;
- }
- /**
- * setup the exception handle
- */
- exception_func_t rt_set_except_vector(int n, exception_func_t func)
- {
- exception_func_t old_handler = sys_exception_handlers[n];
- if ((n == 0) || (n > 32) || (!func))
- {
- return 0;
- }
- sys_exception_handlers[n] = func;
- return old_handler;
- }
- void mips_exception_handler(mips_reg_ctx *ctx)
- {
- static int read_epc_count = 0;
- static int epc_save = 0;
- int i;
- unsigned int epc;
- //如果 read_epc_count>0 说明 c_except_handler 在读 epc 时重入了,即读 epc 导致了一个新的异常
- if (read_epc_count > 0)
- {
- printf("ERROR: read epc fail when except handle\n");
- epc = epc_save;
- read_epc_count = 0;
- }
- else
- {
- read_epc_count++;
- epc_save = 0;
- epc = read_c0_epc();
- epc_save = epc;
- if (epc != 0)
- {
- printf("-----------------------------------------------------\n");
- for (i = 0; i < 4; i++)
- {
- printf("%08x:\t%08x\n",
- (epc - 4 * 4 + i * 4),
- *(unsigned int *) ((epc - 4 * 4 + i * 4) | 0xa0000000));
- }
- for (i = 0; i < 4; i++)
- {
- printf("%08x:\t%08x\n",
- (epc + i * 4),
- *(unsigned int *) ((epc + i * 4) | 0xa0000000));
- }
- printf("-----------------------------------------------------\n");
- }
- read_epc_count--;
- }
- printf("-----------------------------------------------------\n");
- unsigned int cause = read_c0_cause();
- unsigned int exc = (cause >> 2) & 0x1f;
- printf("CAUSE=%08x --> %s\n", cause, cause_strings[exc]);
- printf("EPC=%08x\n", epc);
- for (i = 0; i < 32; i++)
- {
- if ((i != 0) && (i % 4 == 0))
- printf("\n");
- printf("%8s %08x ", regstr[i], ctx->regs[i]);
- }
- printf("\n-----------------------------------------------------\n");
- printf("%s: \t %8x\n","CP0Status ", ctx->CP0Status);
- printf("%s: \t %8x\n","CP0DataHI ", ctx->CP0DataHI);
- printf("%s: \t %8x\n","CP0DataLO ", ctx->CP0DataLO);
- printf("%s: \t %8x\n","CP0BadVAddr", ctx->CP0BadVAddr);
- printf("%s: \t %8x\n","CP0Cause ", ctx->CP0Cause);
- printf("%s: \t %8x\n","CP0EPC ", ctx->CP0EPC);
- printf("-----------------------------------------------------\n");
- #if 0
- switch (exc)
- {
- case EX_MOD:
- /* TLB modified */
- break;
- case EX_TLBL: /* TLB exc(load or ifetch) */
- case EX_TLBS: /* TLB exception (store) */
- break;
- case EX_ADEL: /* Address err(load or ifetch) */
- case EX_ADES: /* Address error (store) */
- break;
- case EX_IBE: /* Instruction Bus Error */
- case EX_DBE: /* Data Bus Error */
- break;
- case EX_SYS: /* Syscall */
- break;
- case EX_BP: /* Breakpoint */
- case EX_TR: /* Trap instruction */
- break;
- case EX_RI: /* Reserved instruction */
- break;
- case EX_FPE: /* floating point exception */
- break;
- case EX_CPU: /* CoProcessor Unusable */
- break;
- case EX_OV: /* OVerflow */
- case EX_C2E: /* COP2 exception */
- case EX_MDMX: /* MDMX exception */
- case EX_WATCH: /* Watch exception */
- case EX_MCHECK: /* Machine check exception */
- case EX_CacheErr: /* Cache error caused re-entry */
- /* to Debug Mode */
- break;
- default:
- rt_kprintf("Unknow exception: %d\r\n", exc);
- break;
- }
- #else
- sys_exception_handlers[exc](ctx);
- #endif
- rt_hw_cpu_shutdown();
- }
- void mips_cache_error_handler (unsigned int Addr)
- {
- rt_kprintf("cache exception happens, epc: 0x%08x\n", read_c0_epc());
- list_thread();
- rt_hw_cpu_shutdown();
- }
- void mips_tlb_refill_handler(void)
- {
- rt_kprintf("tlb-miss happens, epc: 0x%08x\n", read_c0_epc());
- rt_kprintf(" cause: 0x%08x\n", read_c0_cause());
- list_thread();
- rt_kprintf("current thread: %s\n", rt_thread_self()->name);
- rt_hw_cpu_shutdown();
- }
|