From 7e32b62a59ae91d67096c03b592dfd691ab32214 Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Sat, 17 Nov 2012 12:31:22 +0100 Subject: score: Add RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION Add ppc_exc_print_frame_and_context() which prints an exception frame and the context via printk(). The global exception handler will call now rtems_fatal() with source RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION. The fatal code will contain the pointer value to the exception frame. --- c/src/lib/libcpu/powerpc/Makefile.am | 1 + .../bspsupport/ppc_exc_global_handler.c | 197 +-------------------- .../new-exceptions/bspsupport/ppc_exc_print.c | 183 +++++++++++++++++++ .../powerpc/new-exceptions/bspsupport/vectors.h | 4 +- cpukit/score/include/rtems/score/interr.h | 9 + 5 files changed, 200 insertions(+), 194 deletions(-) create mode 100644 c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am index 462beec49d..4401b5f5b7 100644 --- a/c/src/lib/libcpu/powerpc/Makefile.am +++ b/c/src/lib/libcpu/powerpc/Makefile.am @@ -36,6 +36,7 @@ new_exceptions_exc_bspsupport_rel_SOURCES = \ new-exceptions/bspsupport/ppc_exc_hdl.c \ new-exceptions/bspsupport/ppc_exc_initialize.c \ new-exceptions/bspsupport/ppc_exc_global_handler.c \ + new-exceptions/bspsupport/ppc_exc_print.c \ new-exceptions/bspsupport/ppc_exc_categories.c \ new-exceptions/bspsupport/ppc_exc_address.c \ new-exceptions/bspsupport/ppc_exc_alignment.c \ 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 index b7d4299c22..255e401175 100644 --- 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 @@ -19,201 +19,12 @@ #include -#ifndef __SPE__ - #define GET_GPR(gpr) (gpr) -#else - #define GET_GPR(gpr) ((int) ((gpr) >> 32)) -#endif - exception_handler_t globalExceptHdl = C_exception_handler; -/* T. Straumann: provide a stack trace - * , 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(PPC_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) GET_GPR(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", GET_GPR(excPtr->GPR0)); - if (synch) { - printk(" R1 = %08x", GET_GPR(excPtr->GPR1)); - printk(" R2 = %08x", GET_GPR(excPtr->GPR2)); - } else { - printk(" "); - printk(" "); - } - printk(" R3 = %08x\n", GET_GPR(excPtr->GPR3)); - printk("\t R4 = %08x", GET_GPR(excPtr->GPR4)); - printk(" R5 = %08x", GET_GPR(excPtr->GPR5)); - printk(" R6 = %08x", GET_GPR(excPtr->GPR6)); - printk(" R7 = %08x\n", GET_GPR(excPtr->GPR7)); - printk("\t R8 = %08x", GET_GPR(excPtr->GPR8)); - printk(" R9 = %08x", GET_GPR(excPtr->GPR9)); - printk(" R10 = %08x", GET_GPR(excPtr->GPR10)); - printk(" R11 = %08x\n", GET_GPR(excPtr->GPR11)); - printk("\t R12 = %08x", GET_GPR(excPtr->GPR12)); - if (synch) { - printk(" R13 = %08x", GET_GPR(excPtr->GPR13)); - printk(" R14 = %08x", GET_GPR(excPtr->GPR14)); - printk(" R15 = %08x\n", GET_GPR(excPtr->GPR15)); - printk("\t R16 = %08x", GET_GPR(excPtr->GPR16)); - printk(" R17 = %08x", GET_GPR(excPtr->GPR17)); - printk(" R18 = %08x", GET_GPR(excPtr->GPR18)); - printk(" R19 = %08x\n", GET_GPR(excPtr->GPR19)); - printk("\t R20 = %08x", GET_GPR(excPtr->GPR20)); - printk(" R21 = %08x", GET_GPR(excPtr->GPR21)); - printk(" R22 = %08x", GET_GPR(excPtr->GPR22)); - printk(" R23 = %08x\n", GET_GPR(excPtr->GPR23)); - printk("\t R24 = %08x", GET_GPR(excPtr->GPR24)); - printk(" R25 = %08x", GET_GPR(excPtr->GPR25)); - printk(" R26 = %08x", GET_GPR(excPtr->GPR26)); - printk(" R27 = %08x\n", GET_GPR(excPtr->GPR27)); - printk("\t R28 = %08x", GET_GPR(excPtr->GPR28)); - printk(" R29 = %08x", GET_GPR(excPtr->GPR29)); - printk(" R30 = %08x", GET_GPR(excPtr->GPR30)); - printk(" R31 = %08x\n", GET_GPR(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--; - } + rtems_fatal( + RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION, + (rtems_fatal_code) excPtr + ); } diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c new file mode 100644 index 0000000000..e1bbf12909 --- /dev/null +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c @@ -0,0 +1,183 @@ +/** + * @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 the file LICENSE in this distribution or at + * http://www.rtems.com/license/LICENSE. + */ + +#include + +#ifndef __SPE__ + #define GET_GPR(gpr) (gpr) +#else + #define GET_GPR(gpr) ((int) ((gpr) >> 32)) +#endif + +/* T. Straumann: provide a stack trace + * , 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(PPC_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(const 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) GET_GPR(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 ppc_exc_print_frame_and_context(const BSP_Exception_frame *excPtr) +{ + const Thread_Control *executing = _Thread_Executing; + bool synch = (int) excPtr->_EXC_number >= 0; + unsigned n = excPtr->_EXC_number & 0x7fff; + + printk("exception vector %d (0x%x)\n", n, n); + printk(" next PC or address of fault = 0x%08x\n", excPtr->EXC_SRR0); + printk(" saved MSR = 0x%08x\n", excPtr->EXC_SRR1); + + /* Try to find out more about the context where this happened */ + printk( + " context = %s, ISR nest level = %u\n", + _ISR_Nest_level == 0 ? "task" : "interrupt", + _ISR_Nest_level + ); + printk( + " thread dispatch disable level = %u\n", + _Thread_Dispatch_disable_level + ); + + /* Dump registers */ + + printk(" R0 = 0x%08x", GET_GPR(excPtr->GPR0)); + if (synch) { + printk(" R1 = 0x%08x", GET_GPR(excPtr->GPR1)); + printk(" R2 = 0x%08x", GET_GPR(excPtr->GPR2)); + } else { + printk(" "); + printk(" "); + } + printk(" R3 = 0x%08x\n", GET_GPR(excPtr->GPR3)); + printk(" R4 = 0x%08x", GET_GPR(excPtr->GPR4)); + printk(" R5 = 0x%08x", GET_GPR(excPtr->GPR5)); + printk(" R6 = 0x%08x", GET_GPR(excPtr->GPR6)); + printk(" R7 = 0x%08x\n", GET_GPR(excPtr->GPR7)); + printk(" R8 = 0x%08x", GET_GPR(excPtr->GPR8)); + printk(" R9 = 0x%08x", GET_GPR(excPtr->GPR9)); + printk(" R10 = 0x%08x", GET_GPR(excPtr->GPR10)); + printk(" R11 = 0x%08x\n", GET_GPR(excPtr->GPR11)); + printk(" R12 = 0x%08x", GET_GPR(excPtr->GPR12)); + if (synch) { + printk(" R13 = 0x%08x", GET_GPR(excPtr->GPR13)); + printk(" R14 = 0x%08x", GET_GPR(excPtr->GPR14)); + printk(" R15 = 0x%08x\n", GET_GPR(excPtr->GPR15)); + printk(" R16 = 0x%08x", GET_GPR(excPtr->GPR16)); + printk(" R17 = 0x%08x", GET_GPR(excPtr->GPR17)); + printk(" R18 = 0x%08x", GET_GPR(excPtr->GPR18)); + printk(" R19 = 0x%08x\n", GET_GPR(excPtr->GPR19)); + printk(" R20 = 0x%08x", GET_GPR(excPtr->GPR20)); + printk(" R21 = 0x%08x", GET_GPR(excPtr->GPR21)); + printk(" R22 = 0x%08x", GET_GPR(excPtr->GPR22)); + printk(" R23 = 0x%08x\n", GET_GPR(excPtr->GPR23)); + printk(" R24 = 0x%08x", GET_GPR(excPtr->GPR24)); + printk(" R25 = 0x%08x", GET_GPR(excPtr->GPR25)); + printk(" R26 = 0x%08x", GET_GPR(excPtr->GPR26)); + printk(" R27 = 0x%08x\n", GET_GPR(excPtr->GPR27)); + printk(" R28 = 0x%08x", GET_GPR(excPtr->GPR28)); + printk(" R29 = 0x%08x", GET_GPR(excPtr->GPR29)); + printk(" R30 = 0x%08x", GET_GPR(excPtr->GPR30)); + printk(" R31 = 0x%08x\n", GET_GPR(excPtr->GPR31)); + } else { + printk("\n"); + } + printk(" CR = 0x%08x\n", excPtr->EXC_CR); + printk(" CTR = 0x%08x\n", excPtr->EXC_CTR); + printk(" XER = 0x%08x\n", excPtr->EXC_XER); + printk(" LR = 0x%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 != NULL) { + printk(" DAR = 0x%08x\n", ppc_exc_get_DAR()); + } + + if (executing != NULL) { + const char *name = (const char *) &executing->Object.name; + + printk( + " executing thread ID = 0x%08x, name = %c%c%c%c\n", + executing->Object.id, + name [0], + name [1], + name [2], + name [3] + ); + } else { + printk(" executing thread pointer is NULL"); + } + + BSP_printStackTrace(excPtr); +} diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors.h b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors.h index 9ba72db7a8..e62dfbd4f4 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors.h +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors.h @@ -319,7 +319,9 @@ extern exception_handler_t globalExceptHdl; */ void C_exception_handler(BSP_Exception_frame* excPtr); -void BSP_printStackTrace(BSP_Exception_frame *excPtr); +void ppc_exc_print_frame_and_context(const BSP_Exception_frame *excPtr); + +void BSP_printStackTrace(const BSP_Exception_frame *excPtr); /** * @brief Exception categories. diff --git a/cpukit/score/include/rtems/score/interr.h b/cpukit/score/include/rtems/score/interr.h index 94306b59a5..b92b5be040 100644 --- a/cpukit/score/include/rtems/score/interr.h +++ b/cpukit/score/include/rtems/score/interr.h @@ -97,6 +97,15 @@ typedef enum { */ RTEMS_FATAL_SOURCE_STACK_CHECKER, + /** + * @brief Fatal source of the PowerPC exceptions. + * + * The fatal code is the pointer value of the exception frame pointer. + * + * @see BSP_Exception_frame. + */ + RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION, + /** * @brief The last available fatal source. * -- cgit v1.2.3