[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