summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-17 11:31:22 (UTC)
committerSebastian Huber <sebastian.huber@embedded-brains.de>2012-11-21 15:38:28 (UTC)
commit7e32b62a59ae91d67096c03b592dfd691ab32214 (patch)
tree94b4398d93cef2f50c804aee0c80100c37708ac9
parent3fbcadfbf74ce3e1d3e41b2edd80e291a58f60f7 (diff)
downloadrtems-7e32b62a59ae91d67096c03b592dfd691ab32214.tar.bz2
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.
-rw-r--r--c/src/lib/libcpu/powerpc/Makefile.am1
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_global_handler.c197
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c183
-rw-r--r--c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors.h4
-rw-r--r--cpukit/score/include/rtems/score/interr.h9
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@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@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@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