[rtems commit] score: Add RTEMS_FATAL_SOURCE_POWERPC_EXCEPTION

Sebastian Huber sebh at rtems.org
Wed Nov 21 15:36:30 UTC 2012


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




More information about the vc mailing list