Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:23:58

0001 /**
0002  * @file
0003  *
0004  * @ingroup ppc_exc
0005  *
0006  * @brief PowerPC Exceptions implementation.
0007  */
0008 
0009 /*
0010  * Copyright (C) 1999 Eric Valette (valette@crf.canon.fr)
0011  *                    Canon Centre Recherche France.
0012  *
0013  * Derived from file "libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c".
0014  *
0015  * The license and distribution terms for this file may be
0016  * found in the file LICENSE in this distribution or at
0017  * http://www.rtems.org/license/LICENSE.
0018  */
0019 
0020 #include <bsp/vectors.h>
0021 
0022 #include <rtems/score/thread.h>
0023 #include <rtems/score/threaddispatch.h>
0024 
0025 #include <inttypes.h>
0026 
0027 #ifndef __SPE__
0028   #define GET_GPR(gpr) (gpr)
0029 #else
0030   #define GET_GPR(gpr) ((uintptr_t) ((gpr) >> 32))
0031 #endif
0032 
0033 /* T. Straumann: provide a stack trace
0034  * <strauman@slac.stanford.edu>, 6/26/2001
0035  */
0036 typedef struct LRFrameRec_ {
0037   struct LRFrameRec_ *frameLink;
0038   unsigned long *lr;
0039 } LRFrameRec, *LRFrame;
0040 
0041 #define STACK_CLAMP 50          /* in case we have a corrupted bottom */
0042 
0043 static uint32_t ppc_exc_get_DAR_dflt(void)
0044 {
0045   uint32_t val;
0046   if (ppc_cpu_is_60x()) {
0047     PPC_SPECIAL_PURPOSE_REGISTER(PPC_DAR, val);
0048     return val;
0049   } else {
0050     switch (ppc_cpu_is_bookE()) {
0051       default:
0052         break;
0053       case PPC_BOOKE_STD:
0054       case PPC_BOOKE_E500:
0055         PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_DEAR, val);
0056         return val;
0057       case PPC_BOOKE_405:
0058         PPC_SPECIAL_PURPOSE_REGISTER(PPC405_DEAR, val);
0059         return val;
0060     }
0061   }
0062   return 0xdeadbeef;
0063 }
0064 
0065 uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt;
0066 
0067 void BSP_printStackTrace(const BSP_Exception_frame *excPtr)
0068 {
0069   LRFrame f;
0070   int i;
0071   LRFrame sp;
0072   void *lr;
0073 
0074   printk("Stack Trace: \n  ");
0075   if (excPtr) {
0076     printk("IP: 0x%08" PRIxPTR ", ", excPtr->EXC_SRR0);
0077     sp = (LRFrame) GET_GPR(excPtr->GPR1);
0078     lr = (void *) excPtr->EXC_LR;
0079   } else {
0080     /* there's no macro for this */
0081     __asm__ __volatile__("mr %0, 1":"=r"(sp));
0082     lr = (LRFrame) ppc_link_register();
0083   }
0084   printk("LR: 0x%08" PRIxPTR "\n", (uintptr_t) lr);
0085   for (f = (LRFrame) sp, i = 0; f->frameLink && i < STACK_CLAMP; f = f->frameLink) {
0086     printk("--^ 0x%08" PRIxPTR "", (uintptr_t) (f->frameLink->lr));
0087     if (!(++i % 5))
0088       printk("\n");
0089   }
0090   if (i >= STACK_CLAMP) {
0091     printk("Too many stack frames (stack possibly corrupted), giving up...\n");
0092   } else {
0093     if (i % 5)
0094       printk("\n");
0095   }
0096 }
0097 
0098 void _CPU_Exception_frame_print(const CPU_Exception_frame *excPtr)
0099 {
0100   const Thread_Control *executing = _Thread_Executing;
0101   bool synch = (int) excPtr->_EXC_number >= 0;
0102   unsigned n = excPtr->_EXC_number & 0x7fff;
0103 
0104   printk("exception vector %d (0x%x)\n", n, n);
0105   printk("  next PC or address of fault = 0x%08" PRIxPTR "\n", excPtr->EXC_SRR0);
0106   printk("  saved MSR = 0x%08" PRIxPTR "\n", excPtr->EXC_SRR1);
0107 
0108   /* Try to find out more about the context where this happened */
0109   printk(
0110     "  context = %s, ISR nest level = %" PRIu32 "\n",
0111     _ISR_Nest_level == 0 ? "task" : "interrupt",
0112     _ISR_Nest_level
0113   );
0114   printk(
0115     "  thread dispatch disable level = %" PRIu32 "\n",
0116     _Thread_Dispatch_disable_level
0117   );
0118 
0119   /* Dump registers */
0120 
0121   printk("  R0  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR0));
0122   if (synch) {
0123     printk(" R1  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR1));
0124     printk(" R2  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR2));
0125   } else {
0126     printk("               ");
0127     printk("               ");
0128   }
0129   printk(" R3  = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR3));
0130   printk("  R4  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR4));
0131   printk(" R5  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR5));
0132   printk(" R6  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR6));
0133   printk(" R7  = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR7));
0134   printk("  R8  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR8));
0135   printk(" R9  = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR9));
0136   printk(" R10 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR10));
0137   printk(" R11 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR11));
0138   printk("  R12 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR12));
0139   if (synch) {
0140     printk(" R13 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR13));
0141     printk(" R14 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR14));
0142     printk(" R15 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR15));
0143     printk("  R16 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR16));
0144     printk(" R17 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR17));
0145     printk(" R18 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR18));
0146     printk(" R19 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR19));
0147     printk("  R20 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR20));
0148     printk(" R21 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR21));
0149     printk(" R22 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR22));
0150     printk(" R23 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR23));
0151     printk("  R24 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR24));
0152     printk(" R25 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR25));
0153     printk(" R26 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR26));
0154     printk(" R27 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR27));
0155     printk("  R28 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR28));
0156     printk(" R29 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR29));
0157     printk(" R30 = 0x%08" PRIxPTR "", GET_GPR(excPtr->GPR30));
0158     printk(" R31 = 0x%08" PRIxPTR "\n", GET_GPR(excPtr->GPR31));
0159   } else {
0160     printk("\n");
0161   }
0162   printk("  CR  = 0x%08" PRIx32 "\n", excPtr->EXC_CR);
0163   printk("  CTR = 0x%08" PRIxPTR "\n", excPtr->EXC_CTR);
0164   printk("  XER = 0x%08" PRIx32 "\n", excPtr->EXC_XER);
0165   printk("  LR  = 0x%08" PRIxPTR "\n", excPtr->EXC_LR);
0166 
0167   /* Would be great to print DAR but unfortunately,
0168    * that is not portable across different CPUs.
0169    * AFAIK on classic PPC DAR is SPR 19, on the
0170    * 405 we have DEAR = SPR 0x3d5 and bookE says
0171    * DEAR = SPR 61 :-(
0172    */
0173   if (ppc_exc_get_DAR != NULL) {
0174     char* reg = ppc_cpu_is_60x() ? " DAR" : "DEAR";
0175     printk(" %s = 0x%08" PRIx32 "\n", reg, ppc_exc_get_DAR());
0176   }
0177   if (ppc_cpu_is_bookE()) {
0178     uint32_t esr, mcsr;
0179     if (ppc_cpu_is_bookE() == PPC_BOOKE_405) {
0180       PPC_SPECIAL_PURPOSE_REGISTER(PPC405_ESR, esr);
0181       PPC_SPECIAL_PURPOSE_REGISTER(PPC405_MCSR, mcsr);
0182     } else {
0183       PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_ESR, esr);
0184       PPC_SPECIAL_PURPOSE_REGISTER(BOOKE_MCSR, mcsr);
0185     }
0186     printk("  ESR = 0x%08x\n", esr);
0187     printk(" MCSR = 0x%08x\n", mcsr);
0188   }
0189 
0190 #ifdef PPC_MULTILIB_ALTIVEC
0191   {
0192     unsigned char *v = (unsigned char *) &excPtr->V0;
0193     int i;
0194     int j;
0195 
0196     printk(" VSCR = 0x%08" PRIx32 "\n", excPtr->VSCR);
0197     printk("VRSAVE = 0x%08" PRIx32 "\n", excPtr->VRSAVE);
0198 
0199     for (i = 0; i < 32; ++i) {
0200       printk("  V%02i = 0x", i);
0201 
0202       for (j = 0; j < 16; ++j) {
0203         printk("%02x", v[j]);
0204       }
0205 
0206       printk("\n");
0207 
0208       v += 16;
0209     }
0210   }
0211 #endif
0212 
0213 #ifdef PPC_MULTILIB_FPU
0214   {
0215     uint64_t *f = (uint64_t *) &excPtr->F0;
0216     int i;
0217 
0218     printk("FPSCR = 0x%08" PRIu64 "\n", excPtr->FPSCR);
0219 
0220     for (i = 0; i < 32; ++i) {
0221       printk("  F%02i = 0x%016" PRIu64 "\n", i, f[i]);
0222     }
0223   }
0224 #endif
0225 
0226   if (executing != NULL) {
0227     const char *name = (const char *) &executing->Object.name;
0228 
0229     printk(
0230       "  executing thread ID = 0x%08" PRIx32 ", name = %c%c%c%c\n",
0231       executing->Object.id,
0232       name [0],
0233       name [1],
0234       name [2],
0235       name [3]
0236     );
0237   } else {
0238     printk("  executing thread pointer is NULL");
0239   }
0240 
0241   BSP_printStackTrace(excPtr);
0242 }