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

4.11
Last change on this file since 3e2647a7 was 3e2647a7, checked in by Sebastian Huber <sebastian.huber@…>, on Dec 23, 2014 at 1:18:06 PM

powerpc: AltiVec? and FPU context support

Add AltiVec? and FPU support to the Context_Control in case we use the
e6500 multilib.

Add PPC_MULTILIB_ALTIVEC and PPC_MULTILIB_FPU multilib defines. Add
non-volatile AltiVec? and FPU context to Context_Control. Add save/restore of
non-volatile AltiVec? and FPU to _CPU_Context_switch(). Add save/restore
of volatile AltiVec? and FPU context to the exception code. Adjust data
cache optimizations for the new context and cache line size.

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