diff options
Diffstat (limited to 'c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c')
-rw-r--r-- | c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c new file mode 100644 index 0000000000..116199332c --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c @@ -0,0 +1,215 @@ +/** + * @file + * + * @ingroup ppc_exc + * + * @brief PowerPC Exceptions implementation. + */ + +/* + * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr) + * Canon Centre Recherche France. + * + * Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c". + * + * The license and distribution terms for this file may be + * found in found in the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + * + * $Id$ + */ + +#include <bsp/vectors.h> + +exception_handler_t globalExceptHdl = C_exception_handler; + +/* T. Straumann: provide a stack trace + * <strauman@slac.stanford.edu>, 6/26/2001 + */ +typedef struct LRFrameRec_ { + struct LRFrameRec_ *frameLink; + unsigned long *lr; +} LRFrameRec, *LRFrame; + +#define STACK_CLAMP 50 /* in case we have a corrupted bottom */ + +static uint32_t ppc_exc_get_DAR_dflt(void) +{ + if (ppc_cpu_is_60x()) + return PPC_SPECIAL_PURPOSE_REGISTER(DAR); + else + switch (ppc_cpu_is_bookE()) { + default: + break; + case PPC_BOOKE_STD: + case PPC_BOOKE_E500: + return PPC_SPECIAL_PURPOSE_REGISTER(DEAR_BOOKE); + case PPC_BOOKE_405: + return PPC_SPECIAL_PURPOSE_REGISTER(DEAR_405); + } + return 0xdeadbeef; +} + +uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt; + +void BSP_printStackTrace(BSP_Exception_frame *excPtr) +{ + LRFrame f; + int i; + LRFrame sp; + void *lr; + + printk("Stack Trace: \n "); + if (excPtr) { + printk("IP: 0x%08x, ", excPtr->EXC_SRR0); + sp = (LRFrame) excPtr->GPR1; + lr = (void *) excPtr->EXC_LR; + } else { + /* there's no macro for this */ + __asm__ __volatile__("mr %0, 1":"=r"(sp)); + lr = (LRFrame) ppc_link_register(); + } + printk("LR: 0x%08x\n", lr); + for (f = (LRFrame) sp, i = 0; f->frameLink && i < STACK_CLAMP; f = f->frameLink) { + printk("--^ 0x%08x", (long) (f->frameLink->lr)); + if (!(++i % 5)) + printk("\n"); + } + if (i >= STACK_CLAMP) { + printk("Too many stack frames (stack possibly corrupted), giving up...\n"); + } else { + if (i % 5) + printk("\n"); + } +} + +void C_exception_handler(BSP_Exception_frame *excPtr) +{ + static int nest = 0; + + int recoverable = 0; + rtems_id id = 0; + int synch; + unsigned n; + rtems_status_code sc; + + /* Catch recursion */ + nest++; + + if (nest > 2) { + /* maybe printk() or dereferencing excPtr caused an exception; + * die silently... + */ + while (1); + } + + synch = (int) excPtr->_EXC_number >= 0; + n = excPtr->_EXC_number & 0x7fff; + + printk("Exception handler called for exception %d (0x%x)\n", n, n); + printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0); + printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1); + + if (nest > 1) { + printk("Recursion in the exception handler detected; I'll spin now...\n"); + while (1); + } + + /* Try to find out more about the context where this happened */ + printk("\t Context: "); + if (rtems_interrupt_is_in_progress()) { + printk("ISR"); + } else if (!_Thread_Executing) { + printk("Initialization (_Thread_Executing not available yet)"); + } else { + if (RTEMS_SUCCESSFUL != (sc = rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id))) { + printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc); + id = 0; + } else { + printk("Task ID 0x%08x", id); + } + } + printk("\n"); + + /* Dump registers */ + + printk("\t R0 = %08x", excPtr->GPR0); + if (synch) { + printk(" R1 = %08x", excPtr->GPR1); + printk(" R2 = %08x", excPtr->GPR2); + } else { + printk(" "); + printk(" "); + } + printk(" R3 = %08x\n", excPtr->GPR3); + printk("\t R4 = %08x", excPtr->GPR4); + printk(" R5 = %08x", excPtr->GPR5); + printk(" R6 = %08x", excPtr->GPR6); + printk(" R7 = %08x\n", excPtr->GPR7); + printk("\t R8 = %08x", excPtr->GPR8); + printk(" R9 = %08x", excPtr->GPR9); + printk(" R10 = %08x", excPtr->GPR10); + printk(" R11 = %08x\n", excPtr->GPR11); + printk("\t R12 = %08x", excPtr->GPR12); + if (synch) { + printk(" R13 = %08x", excPtr->GPR13); + printk(" R14 = %08x", excPtr->GPR14); + printk(" R15 = %08x\n", excPtr->GPR15); + printk("\t R16 = %08x", excPtr->GPR16); + printk(" R17 = %08x", excPtr->GPR17); + printk(" R18 = %08x", excPtr->GPR18); + printk(" R19 = %08x\n", excPtr->GPR19); + printk("\t R20 = %08x", excPtr->GPR20); + printk(" R21 = %08x", excPtr->GPR21); + printk(" R22 = %08x", excPtr->GPR22); + printk(" R23 = %08x\n", excPtr->GPR23); + printk("\t R24 = %08x", excPtr->GPR24); + printk(" R25 = %08x", excPtr->GPR25); + printk(" R26 = %08x", excPtr->GPR26); + printk(" R27 = %08x\n", excPtr->GPR27); + printk("\t R28 = %08x", excPtr->GPR28); + printk(" R29 = %08x", excPtr->GPR29); + printk(" R30 = %08x", excPtr->GPR30); + printk(" R31 = %08x\n", excPtr->GPR31); + } else { + printk("\n"); + } + printk("\t CR = %08x\n", excPtr->EXC_CR); + printk("\t CTR = %08x\n", excPtr->EXC_CTR); + printk("\t XER = %08x\n", excPtr->EXC_XER); + printk("\t LR = %08x\n", excPtr->EXC_LR); + + /* Would be great to print DAR but unfortunately, + * that is not portable across different CPUs. + * AFAIK on classic PPC DAR is SPR 19, on the + * 405 we have DEAR = SPR 0x3d5 and booE says + * DEAR = SPR 61 :-( + */ + if (ppc_exc_get_DAR) { + printk("\t DAR = %08x\n", ppc_exc_get_DAR()); + } + + BSP_printStackTrace(excPtr); + + if (excPtr->_EXC_number == ASM_DEC_VECTOR) + recoverable = 1; + if (excPtr->_EXC_number == ASM_SYS_VECTOR) +#ifdef TEST_RAW_EXCEPTION_CODE + recoverable = 1; +#else + recoverable = 0; +#endif + if (!recoverable) { + if (id) { + printk("Suspending faulting task (0x%08x)\n", id); + /* Unnest here because rtems_task_suspend() never returns */ + nest--; + rtems_task_suspend(id); + } else { + printk("unrecoverable exception!!! Push reset button\n"); + while (1); + } + } else { + nest--; + } +} |