123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512 |
- #include <stdlib.h>
- #include <unistd.h>
- // #include <stdio.h>
- #include <string.h>
- #include <mips/cpu.h>
- #include <mips/fpa.h>
- #include <mips/hal.h>
- #include <mips/uhi_syscalls.h>
- #include "hv_chip_Config.h"
- /* Defined in .ld file */
- static char __use_excpt_boot = 1;
- static char __flush_to_zero = 1;
- /*
- * Write a string, a formatted number, then a string.
- */
- static void putsnds (const char *pre, reg_t value, int digits, const char *post){
- char buf[digits];
- int shift;
- int idx = 0;
- if (pre != NULL){
- Hv_Chip_DebugUartPuts(pre);
- }
- for (shift = ((digits - 1) * 4) ; shift >= 0 ; shift -= 4)
- buf[idx++] = "0123456789ABCDEF"[(value >> shift) & 0xf];
- Hv_Chip_DebugUartWrite (1, buf, digits);
- if (post != NULL){
- Hv_Chip_DebugUartPuts(post);
- }
- }
- static void putsns (const char *pre, reg_t value, const char *post) {
- putsnds (pre, value, sizeof (reg_t) * 2, post);
- }
- # define WRITE(MSG) Hv_Chip_DebugUartWrite(1, (MSG), strlen (MSG))
- # define PUTSNDS(PRE, VALUE, DIGITS, POST) \
- putsnds ((PRE), (VALUE), (DIGITS), (POST))
- # define PUTSNS(PRE, VALUE, POST) \
- putsns ((PRE), (VALUE), (POST))
- int32_t _MIPS_HAL_NOMIPS16
- __uhi_exception (struct gpctx *ctx, int32_t abi)
- {
- register struct gpctx *arg1 asm ("$4") = ctx;
- register int32_t arg2 asm ("$5") = abi;
- register int32_t op asm ("$25") = __MIPS_UHI_EXCEPTION;
- register int32_t ret asm ("$2") = __MIPS_UHI_SYSCALL_NUM;
- __asm__ __volatile__ (" # %0 = __uhi_exception(%1, %2) op=%3\n"
- SYSCALL (__MIPS_UHI_SYSCALL_NUM)
- : "+r" (ret)
- : "r" (arg1), "r" (arg2), "r" (op)
- : "$3");
- return ret;
- }
- /* Forward a UHI SYSCALL operation to SDBPP interface. */
- int _MIPS_HAL_NOMIPS16
- __uhi_indirect (struct gpctx *ctx)
- {
- register reg_t arg1 asm ("$4") = ctx->r[C_CTX_REGNO(4)];
- register reg_t arg2 asm ("$5") = ctx->r[C_CTX_REGNO(5)];
- register reg_t arg3 asm ("$6") = ctx->r[C_CTX_REGNO(6)];
- register reg_t arg4 asm ("$7") = ctx->r[C_CTX_REGNO(7)];
- register reg_t op asm ("$25") = ctx->r[C_CTX_REGNO(25)];
- register reg_t ret1 asm ("$2") = 1;
- register reg_t ret2 asm ("$3");
- __asm__ __volatile__(" # UHI indirect\n"
- "\tsdbbp 1"
- : "+r" (ret1), "=r" (ret2), "+r" (arg1), "+r" (arg2)
- : "r" (arg3), "r" (arg4), "r" (op));
- ctx->r[C_CTX_REGNO(2)] = ret1;
- ctx->r[C_CTX_REGNO(3)] = ret2;
- ctx->r[C_CTX_REGNO(4)] = arg1;
- ctx->r[C_CTX_REGNO(5)] = arg2;
- /* Handled, move on. SYSCALL is 4-bytes in all ISAs. */
- ctx->epc += 4;
- return 1; /* exception handled */
- }
- #define BT_ABS(X) ((X)>=0?(X):(-(X)))
- #define FRAME_DEPTH 50
- int __backtrace_mips32(struct gpctx *ctx, int depth)
- {
- volatile unsigned int *addr;
- volatile unsigned int *ra;
- volatile unsigned int *sp;
- volatile unsigned int ra_offset;
- volatile unsigned int stack_size;
- volatile unsigned int bt = 0;
- unsigned int bt_done = 0;
- if(depth < 0)
- {
- return -1;
- }
- ra = (volatile unsigned int *)ctx->ra;
- sp = (volatile unsigned int *)ctx->sp;
- if(((unsigned int)ra >= 0xC0000000) || ((unsigned int)ra < 0x80000000)
- || ((unsigned int)sp >= 0xC0000000) || ((unsigned int)sp < 0x80000000)){
- return -1;
- }
- for(bt=0;bt<depth&&ra;bt++)
- {
- ra_offset = 0;
- stack_size = 0;
- for(addr=ra; ra_offset==0||stack_size==0; addr--)
- {
- switch(*addr&0xffff0000)
- {
- case 0x27bd0000:
- stack_size = BT_ABS((short)(*addr&0xffff));
- if(stack_size != 0){
- PUTSNS("[BackTrace]-[", (reg_t)(bt), NULL);
- PUTSNS("]-[0x", (reg_t)addr, NULL);
- WRITE ("]\n");
- }
- if(bt_done){
- return bt;
- }
- break;
- case 0xafbf0000:
- ra_offset = (short)(*addr&0xffff);
- break;
- default:
- break;
- }
- if(*addr == 0x0c0002b4){
- bt_done = 1;
- }
- }
- ra =(unsigned int *)*((unsigned int *)((unsigned int)sp + ra_offset));
- sp =(unsigned int *)((unsigned int)sp + stack_size);
- if(((unsigned int)ra >= 0xC0000000) || ((unsigned int)ra < 0x80000000)
- || ((unsigned int)sp >= 0xC0000000) || ((unsigned int)sp < 0x80000000)){
- return -1;
- }
- }
- return bt;
- }
- #ifdef SW_DUMMY_DEBUG
- int sw_dummy_debug = 0;
- void dumpGPR2R(struct gpctx *ctx)
- {
- if (sw_dummy_debug)
- {
- sw_dummy_debug = 1;
- return;
- }
- /* Dump registers */
- HV_WT32 (SW_DUMMY_AT, ctx->at);
- HV_WT32 (SW_DUMMY_V0, ctx->v[0]);
- HV_WT32 (SW_DUMMY_V1, ctx->v[1]);
- HV_WT32 (SW_DUMMY_A0, ctx->a[0]);
- HV_WT32 (SW_DUMMY_A1, ctx->a[1]);
- HV_WT32 (SW_DUMMY_A2, ctx->a[2]);
- HV_WT32 (SW_DUMMY_A3, ctx->a[3]);
- HV_WT32 (SW_DUMMY_T0, ctx->t[0]);
- HV_WT32 (SW_DUMMY_T1, ctx->t[1]);
- HV_WT32 (SW_DUMMY_T2, ctx->t[2]);
- HV_WT32 (SW_DUMMY_T3, ctx->t[3]);
- HV_WT32 (SW_DUMMY_T4, ctx->t[4]);
- HV_WT32 (SW_DUMMY_T5, ctx->t[5]);
- HV_WT32 (SW_DUMMY_T6, ctx->t[6]);
- HV_WT32 (SW_DUMMY_T7, ctx->t[7]);
- HV_WT32 (SW_DUMMY_S0, ctx->s[0]);
- HV_WT32 (SW_DUMMY_S1, ctx->s[1]);
- HV_WT32 (SW_DUMMY_S2, ctx->s[2]);
- HV_WT32 (SW_DUMMY_S3, ctx->s[3]);
- HV_WT32 (SW_DUMMY_S4, ctx->s[4]);
- HV_WT32 (SW_DUMMY_S5, ctx->s[5]);
- HV_WT32 (SW_DUMMY_S6, ctx->s[6]);
- HV_WT32 (SW_DUMMY_S7, ctx->s[7]);
- HV_WT32 (SW_DUMMY_T8, ctx->t2[0]);
- HV_WT32 (SW_DUMMY_T9, ctx->t2[1]);
- HV_WT32 (SW_DUMMY_K0, ctx->k[0]);
- HV_WT32 (SW_DUMMY_K1, ctx->k[1]);
- HV_WT32 (SW_DUMMY_GP, ctx->gp);
- HV_WT32 (SW_DUMMY_SP, ctx->sp);
- HV_WT32 (SW_DUMMY_FP, ctx->fp);
- HV_WT32 (SW_DUMMY_RA, ctx->ra);
- HV_WT32 (SW_DUMMY_EPC, ctx->epc);
- HV_WT32 (SW_DUMMY_BADVADDR, ctx->badvaddr);
- HV_WT32 (SW_DUMMY_STATUS, ctx->status);
- HV_WT32 (SW_DUMMY_CAUSE, ctx->cause);
- HV_WT32 (SW_DUMMY_BADPISTR, ctx->badinstr);
- HV_WT32 (SW_DUMMY_BADPISTR, ctx->badpinstr);
- #ifdef HV_SCALER_DEBUG_VERSION
- while(1);
- #endif
- }
- #endif
- void dumpGPR(struct gpctx *ctx)
- {
- /* Dump registers */
- PUTSNS (" 0:\t", 0, "\t");
- PUTSNS ("at:\t", ctx->at, "\t");
- PUTSNS ("v0:\t", ctx->v[0], "\t");
- PUTSNS ("v1:\t", ctx->v[1], "\n");
- PUTSNS ("a0:\t", ctx->a[0], "\t");
- PUTSNS ("a1:\t", ctx->a[1], "\t");
- PUTSNS ("a2:\t", ctx->a[2], "\t");
- PUTSNS ("a3:\t", ctx->a[3], "\n");
- PUTSNS ("t0:\t", ctx->t[0], "\t");
- PUTSNS ("t1:\t", ctx->t[1], "\t");
- PUTSNS ("t2:\t", ctx->t[2], "\t");
- PUTSNS ("t3:\t", ctx->t[3], "\n");
- PUTSNS ("t4:\t", ctx->t[4], "\t");
- PUTSNS ("t5:\t", ctx->t[5], "\t");
- PUTSNS ("t6:\t", ctx->t[6], "\t");
- PUTSNS ("t7:\t", ctx->t[7], "\n");
- PUTSNS ("s0:\t", ctx->s[0], "\t");
- PUTSNS ("s1:\t", ctx->s[1], "\t");
- PUTSNS ("s2:\t", ctx->s[2], "\t");
- PUTSNS ("s3:\t", ctx->s[3], "\n");
- PUTSNS ("s4:\t", ctx->s[4], "\t");
- PUTSNS ("s5:\t", ctx->s[5], "\t");
- PUTSNS ("s6:\t", ctx->s[6], "\t");
- PUTSNS ("s7:\t", ctx->s[7], "\n");
- PUTSNS ("t8:\t", ctx->t2[0],"\t");
- PUTSNS ("t9:\t", ctx->t2[1],"\t");
- PUTSNS ("k0:\t", ctx->k[0], "\t");
- PUTSNS ("k1:\t", ctx->k[1], "\n");
- PUTSNS ("gp:\t", ctx->gp, "\t");
- PUTSNS ("sp:\t", ctx->sp, "\t");
- PUTSNS ("fp:\t", ctx->fp, "\t");
- PUTSNS ("ra:\t", ctx->ra, "\n");
- #if __mips_isa_rev < 6
- PUTSNS ("hi:\t", ctx->hi, "\t");
- PUTSNS ("lo:\t", ctx->lo, "\n");
- #endif
- PUTSNS ("epc: \t", ctx->epc, "\n");
- PUTSNS ("BadVAddr: \t", ctx->badvaddr, "\n");
- PUTSNDS ("Status: \t", ctx->status, 8, "\n");
- PUTSNDS ("Cause: \t", ctx->cause, 8, "\n");
- PUTSNDS ("BadInstr: \t", ctx->badinstr, 8, "\n");
- PUTSNDS ("BadPInstr:\t", ctx->badpinstr,8, "\n");
- __backtrace_mips32(ctx, FRAME_DEPTH);
- #ifdef SW_DUMMY_DEBUG
- dumpGPR2R(ctx);
- #endif
- }
- /* Handle an exception */
- void __exception_handle(struct gpctx *ctx, int exception)
- {
- switch (exception)
- {
- case EXC_MOD:
- {
- Hv_Chip_DebugUartPuts ("TLB modification exception\n");
- break;
- }
- case EXC_TLBL:
- {
- Hv_Chip_DebugUartPuts ("TLB error on load from ");
- dumpGPR(ctx);
- //PUTSNS (" @0x", ctx->epc, "\n");
- break;
- }
- case EXC_TLBS:
- {
- Hv_Chip_DebugUartPuts ("TLB error on store to ");
- dumpGPR(ctx);
- //PUTSNS (" @0x", ctx->epc, "\n");
- break;
- }
- case EXC_ADEL:
- {
- Hv_Chip_DebugUartPuts ("Address error on load from \n");
- dumpGPR(ctx);
- //PUTSNS (" @0x", ctx->epc, "\n");
- break;
- }
- case EXC_ADES:
- {
- Hv_Chip_DebugUartPuts ("Address error on store to \n");
- dumpGPR(ctx);
- //PUTSNS (" @0x", ctx->epc, "\n");
- break;
- }
- case EXC_IBE:
- {
- Hv_Chip_DebugUartPuts ("Instruction bus error\n");
- break;
- }
- case EXC_DBE:
- {
- Hv_Chip_DebugUartPuts ("Data bus error\n");
- dumpGPR(ctx);
- break;
- }
- case EXC_SYS:
- {
- /* Process a UHI SYSCALL, all other SYSCALLs should have been processed
- by our caller. __use_excpt_boot has following values:
- 0 = Do not use exception handler present in boot.
- 1 = Use exception handler present in boot if BEV
- is 0 at startup.
- 2 = Always use exception handler present in boot. */
- /* Special handling for boot/low level failures. */
- if (ctx->t2[1] == __MIPS_UHI_BOOTFAIL)
- {
- switch (ctx->a[0])
- {
- case __MIPS_UHI_BF_CACHE:
- {
- Hv_Chip_DebugUartPuts ("L2 cache configuration error\n");
- break;
- }
- default:
- {
- Hv_Chip_DebugUartPuts ("Unknown boot failure error\n");
- break;
- }
- }
- /* These are unrecoverable. Abort. */
- ctx->epc = (sreg_t)(long)&__exit;
- /* Exit code of 255 */
- ctx->a[0] = 0xff;
- return;
- }
- if (((long) __use_excpt_boot == 2
- || ((long) __use_excpt_boot == 1
- && __get_startup_BEV
- && __get_startup_BEV () == 0))
- && __chain_uhi_excpt)
- {
- /* This will not return. */
- __chain_uhi_excpt (ctx);
- }
- else
- {
- __uhi_indirect (ctx);
- }
- return;
- }
- case EXC_BP:
- {
- /* Return from exception handler if breakpoint is handled. */
- if (__uhi_break && __uhi_break (ctx))
- return;
- Hv_Chip_DebugUartPuts ("Breakpoint \n");
- break;
- }
- case EXC_RI:
- {
- Hv_Chip_DebugUartPuts ("Illegal instruction \n");
- break;
- }
- case EXC_CPU:
- {
- Hv_Chip_DebugUartPuts ("Coprocessor unusable\n");
- break;
- }
- case EXC_OVF:
- {
- Hv_Chip_DebugUartPuts ("Overflow\n");
- break;
- }
- case EXC_TRAP:
- {
- dumpGPR(ctx);
- Hv_Chip_DebugUartPuts ("Trap\n");
- break;
- }
- case EXC_MSAFPE:
- {
- Hv_Chip_DebugUartPuts ("MSA Floating point error\n");
- break;
- }
- case EXC_FPE:
- {
- /* Turn on flush to zero the first time we hit an unimplemented
- operation. If we hit it again then stop. */
- if (__flush_to_zero
- && (fpa_getsr () & FPA_CSR_UNI_X)
- && (fpa_getsr () & FPA_CSR_FS) == 0)
- {
- unsigned int sr = fpa_getsr ();
- sr &= ~FPA_CSR_UNI_X;
- sr |= FPA_CSR_FS;
- fpa_setsr (sr);
- return;
- }
- //Hv_Chip_DebugUartPuts ("Floating point error\n");
- break;
- }
- case EXC_IS1:
- {
- //Hv_Chip_DebugUartPuts ("Implementation specific exception (16)\n");
- break;
- }
- case EXC_IS2:
- {
- //Hv_Chip_DebugUartPuts ("Implementation specific exception (17)\n");
- break;
- }
- case EXC_C2E:
- {
- Hv_Chip_DebugUartPuts ("Precise Coprocessor 2 exception\n");
- break;
- }
- case EXC_TLBRI:
- {
- Hv_Chip_DebugUartPuts ("TLB read inhibit exception\n");
- break;
- }
- case EXC_TLBXI:
- {
- Hv_Chip_DebugUartPuts ("TLB execute inhibit exception\n");
- break;
- }
- case EXC_MSAU:
- {
- //Hv_Chip_DebugUartPuts ("MSA unusable \n");
- break;
- }
- case EXC_MDMX:
- {
- //Hv_Chip_DebugUartPuts ("MDMX exception \n");
- break;
- }
- case EXC_WATCH:
- {
- //Hv_Chip_DebugUartPuts ("Watchpoint\n");
- break;
- }
- case EXC_MCHECK:
- {
- //Hv_Chip_DebugUartPuts ("Machine check error\n");
- break;
- }
- case EXC_THREAD:
- {
- Hv_Chip_DebugUartPuts ("Thread exception\n");
- break;
- }
- case EXC_DSPU:
- {
- //Hv_Chip_DebugUartPuts ("DSP unusable\n");
- break;
- }
- case EXC_RES30:
- {
- //Hv_Chip_DebugUartPuts ("Cache error\n");
- break;
- }
- default:
- {
- //Hv_Chip_DebugUartPuts ("Unhandled exception " "\n");
- break;
- }
- }
- /* Raise UHI exception which may or may not return. */
- if (__uhi_exception (ctx, UHI_ABI) != 0)
- {
- /* The exception was acknowledged but not handled. Abort. */
- ctx->epc = (sreg_t)(long)&__exit;
- /* Exit code of 255 */
- ctx->a[0] = 0xff;
- }
- return;
- }
|