[rtems commit] score: Add RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION
Joel Sherrill
joel.sherrill at OARcorp.com
Wed Nov 21 21:39:30 UTC 2012
There is similar code for the x86.
Why is there a generic constant name with a processor name in it?
This seems like something that should be in a CPU specific path
or use a more general name and the CPU/BSP can provide the
specific handler which takes a void * which is the exception frame
pointer.
On 11/21/2012 9:36 AM, Sebastian Huber wrote:
> Module: rtems
> Branch: master
> Commit: 7e32b62a59ae91d67096c03b592dfd691ab32214
> Changeset: http://git.rtems.org/rtems/commit/?id=7e32b62a59ae91d67096c03b592dfd691ab32214
>
> Author: Sebastian Huber <sebastian.huber at embedded-brains.de>
> Date: Sat Nov 17 12:31:22 2012 +0100
>
> 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(-)
>
> diff --git a/c/src/lib/libcpu/powerpc/Makefile.am b/c/src/lib/libcpu/powerpc/Makefile.am
> index 462beec..4401b5f 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 b7d4299..255e401 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 <bsp/vectors.h>
>
> -#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
> - * <strauman at 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(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 0000000..e1bbf12
> --- /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 at 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 <bsp/vectors.h>
> +
> +#ifndef __SPE__
> + #define GET_GPR(gpr) (gpr)
> +#else
> + #define GET_GPR(gpr) ((int) ((gpr) >> 32))
> +#endif
> +
> +/* T. Straumann: provide a stack trace
> + * <strauman at 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(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 9ba72db..e62dfbd 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 94306b5..b92b5be 100644
> --- a/cpukit/score/include/rtems/score/interr.h
> +++ b/cpukit/score/include/rtems/score/interr.h
> @@ -98,6 +98,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.
> *
> * This enum value ensures that the enum type needs at least 32-bits for
>
> _______________________________________________
> rtems-vc mailing list
> rtems-vc at rtems.org
> http://www.rtems.org/mailman/listinfo/rtems-vc
--
Joel Sherrill, Ph.D. Director of Research & Development
joel.sherrill at OARcorp.com On-Line Applications Research
Ask me about RTEMS: a free RTOS Huntsville AL 35805
Support Available (256) 722-9985
More information about the devel
mailing list