source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_print.c @ 73f8d93

Last change on this file since 73f8d93 was 73f8d93, checked in by Sebastian Huber <sebastian.huber@…>, on Feb 15, 2017 at 10:09:50 AM

bsps/powerpc: Fix warnings

  • Property mode set to 100644
File size: 6.9 KB
Line 
1/**
2 * @file
3 *
4 * @ingroup ppc_exc
5 *
6 * @brief PowerPC Exceptions implementation.
7 */
8
9/*
10 * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
11 *                    Canon Centre Recherche France.
12 *
13 * Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
14 *
15 * The license and distribution terms for this file may be
16 * found in the file LICENSE in this distribution or at
17 * http://www.rtems.org/license/LICENSE.
18 */
19
20#include <bsp/vectors.h>
21
22#include <rtems/score/threaddispatch.h>
23
24#include <inttypes.h>
25
26#ifndef __SPE__
27  #define GET_GPR(gpr) (gpr)
28#else
29  #define GET_GPR(gpr) ((int) ((gpr) >> 32))
30#endif
31
32/* T. Straumann: provide a stack trace
33 * <strauman@slac.stanford.edu>, 6/26/2001
34 */
35typedef struct LRFrameRec_ {
36  struct LRFrameRec_ *frameLink;
37  unsigned long *lr;
38} LRFrameRec, *LRFrame;
39
40#define STACK_CLAMP 50          /* in case we have a corrupted bottom */
41
42static uint32_t ppc_exc_get_DAR_dflt(void)
43{
44  if (ppc_cpu_is_60x())
45    return PPC_SPECIAL_PURPOSE_REGISTER(PPC_DAR);
46  else
47    switch (ppc_cpu_is_bookE()) {
48      default:
49        break;
50      case PPC_BOOKE_STD:
51      case PPC_BOOKE_E500:
52        return PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_DEAR);
53      case PPC_BOOKE_405:
54        return PPC_SPECIAL_PURPOSE_REGISTER(PPC405_DEAR);
55    }
56  return 0xdeadbeef;
57}
58
59uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt;
60
61void BSP_printStackTrace(const BSP_Exception_frame *excPtr)
62{
63  LRFrame f;
64  int i;
65  LRFrame sp;
66  void *lr;
67
68  printk("Stack Trace: \n  ");
69  if (excPtr) {
70    printk("IP: 0x%08" PRIu32 ", ", excPtr->EXC_SRR0);
71    sp = (LRFrame) GET_GPR(excPtr->GPR1);
72    lr = (void *) excPtr->EXC_LR;
73  } else {
74    /* there's no macro for this */
75    __asm__ __volatile__("mr %0, 1":"=r"(sp));
76    lr = (LRFrame) ppc_link_register();
77  }
78  printk("LR: 0x%08" PRIuPTR "\n", (uintptr_t) lr);
79  for (f = (LRFrame) sp, i = 0; f->frameLink && i < STACK_CLAMP; f = f->frameLink) {
80    printk("--^ 0x%08" PRIuPTR "", (uintptr_t) (f->frameLink->lr));
81    if (!(++i % 5))
82      printk("\n");
83  }
84  if (i >= STACK_CLAMP) {
85    printk("Too many stack frames (stack possibly corrupted), giving up...\n");
86  } else {
87    if (i % 5)
88      printk("\n");
89  }
90}
91
92void _CPU_Exception_frame_print(const CPU_Exception_frame *excPtr)
93{
94  const Thread_Control *executing = _Thread_Executing;
95  bool synch = (int) excPtr->_EXC_number >= 0;
96  unsigned n = excPtr->_EXC_number & 0x7fff;
97
98  printk("exception vector %d (0x%x)\n", n, n);
99  printk("  next PC or address of fault = 0x%08" PRIu32 "\n", excPtr->EXC_SRR0);
100  printk("  saved MSR = 0x%08" PRIu32 "\n", excPtr->EXC_SRR1);
101
102  /* Try to find out more about the context where this happened */
103  printk(
104    "  context = %s, ISR nest level = %" PRIu32 "\n",
105    _ISR_Nest_level == 0 ? "task" : "interrupt",
106    _ISR_Nest_level
107  );
108  printk(
109    "  thread dispatch disable level = %" PRIu32 "\n",
110    _Thread_Dispatch_disable_level
111  );
112
113  /* Dump registers */
114
115  printk("  R0  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR0));
116  if (synch) {
117    printk(" R1  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR1));
118    printk(" R2  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR2));
119  } else {
120    printk("               ");
121    printk("               ");
122  }
123  printk(" R3  = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR3));
124  printk("  R4  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR4));
125  printk(" R5  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR5));
126  printk(" R6  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR6));
127  printk(" R7  = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR7));
128  printk("  R8  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR8));
129  printk(" R9  = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR9));
130  printk(" R10 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR10));
131  printk(" R11 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR11));
132  printk("  R12 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR12));
133  if (synch) {
134    printk(" R13 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR13));
135    printk(" R14 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR14));
136    printk(" R15 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR15));
137    printk("  R16 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR16));
138    printk(" R17 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR17));
139    printk(" R18 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR18));
140    printk(" R19 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR19));
141    printk("  R20 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR20));
142    printk(" R21 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR21));
143    printk(" R22 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR22));
144    printk(" R23 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR23));
145    printk("  R24 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR24));
146    printk(" R25 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR25));
147    printk(" R26 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR26));
148    printk(" R27 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR27));
149    printk("  R28 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR28));
150    printk(" R29 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR29));
151    printk(" R30 = 0x%08" PRIu32 "", GET_GPR(excPtr->GPR30));
152    printk(" R31 = 0x%08" PRIu32 "\n", GET_GPR(excPtr->GPR31));
153  } else {
154    printk("\n");
155  }
156  printk("  CR  = 0x%08" PRIu32 "\n", excPtr->EXC_CR);
157  printk("  CTR = 0x%08" PRIu32 "\n", excPtr->EXC_CTR);
158  printk("  XER = 0x%08" PRIu32 "\n", excPtr->EXC_XER);
159  printk("  LR  = 0x%08" PRIu32 "\n", excPtr->EXC_LR);
160
161  /* Would be great to print DAR but unfortunately,
162   * that is not portable across different CPUs.
163   * AFAIK on classic PPC DAR is SPR 19, on the
164   * 405 we have DEAR = SPR 0x3d5 and bookE says
165   * DEAR = SPR 61 :-(
166   */
167  if (ppc_exc_get_DAR != NULL) {
168    char* reg = ppc_cpu_is_60x() ? " DAR" : "DEAR";
169    printk(" %s = 0x%08" PRIu32 "\n", reg, ppc_exc_get_DAR());
170  }
171  if (ppc_cpu_is_bookE()) {
172    unsigned esr, mcsr;
173    if (ppc_cpu_is_bookE() == PPC_BOOKE_405) {
174      esr  = PPC_SPECIAL_PURPOSE_REGISTER(PPC405_ESR);
175      mcsr = PPC_SPECIAL_PURPOSE_REGISTER(PPC405_MCSR);
176    } else {
177      esr  = PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_ESR);
178      mcsr = PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_MCSR);
179    }
180    printk("  ESR = 0x%08x\n", esr);
181    printk(" MCSR = 0x%08x\n", mcsr);
182  }
183
184#ifdef PPC_MULTILIB_ALTIVEC
185  {
186    unsigned char *v = (unsigned char *) &excPtr->V0;
187    int i;
188    int j;
189
190    printk(" VSCR = 0x%08x\n", excPtr->VSCR);
191    printk("VRSAVE = 0x%08x\n", excPtr->VRSAVE);
192
193    for (i = 0; i < 32; ++i) {
194      printk("  V%02i = 0x", i);
195
196      for (j = 0; j < 16; ++j) {
197        printk("%02x", v[j]);
198      }
199
200      printk("\n");
201
202      v += 16;
203    }
204  }
205#endif
206
207#ifdef PPC_MULTILIB_FPU
208  {
209    unsigned long long *f = (unsigned long long *) &excPtr->F0;
210    int i;
211
212    printk("FPSCR = 0x%08llx\n", excPtr->FPSCR);
213
214    for (i = 0; i < 32; ++i) {
215      printk("  F%02i = 0x%016llx\n", i, f[i]);
216    }
217  }
218#endif
219
220  if (executing != NULL) {
221    const char *name = (const char *) &executing->Object.name;
222
223    printk(
224      "  executing thread ID = 0x%08" PRIx32 ", name = %c%c%c%c\n",
225      executing->Object.id,
226      name [0],
227      name [1],
228      name [2],
229      name [3]
230    );
231  } else {
232    printk("  executing thread pointer is NULL");
233  }
234
235  BSP_printStackTrace(excPtr);
236}
Note: See TracBrowser for help on using the repository browser.