source: rtems/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c @ b679966d

4.104.114.95
Last change on this file since b679966d was b679966d, checked in by Joel Sherrill <joel.sherrill@…>, on 08/18/08 at 21:17:06

2008-08-18 Joel Sherrill <joel.sherrill@…>

  • mpc6xx/mmu/pte121.c, mpc6xx/mmu/pte121.h, mpc6xx/timer/timer.c, new-exceptions/e500_raw_exc_init.c, new-exceptions/bspsupport/ppc_exc_bspsupp.h, new-exceptions/bspsupport/vectors_init.c: Fix warnings.
  • Property mode set to 100644
File size: 13.7 KB
Line 
1/*
2 * vectors_init.c Exception hanlding initialisation (and generic handler).
3 *
4 *  This include file describe the data structure and the functions implemented
5 *  by rtems to handle exceptions.
6 *
7 *  Copyright (C) 1999 valette@crf.canon.fr
8 *
9 *  The license and distribution terms for this file may be
10 *  found in found in the file LICENSE in this distribution or at
11 *  http://www.rtems.com/license/LICENSE.
12 *
13 *  $Id$
14 */
15#include <rtems.h>
16#include <rtems/bspIo.h>
17#include <rtems/error.h>
18
19#include <libcpu/raw_exception.h>
20#include <libcpu/spr.h>
21#include <libcpu/cpuIdent.h>
22
23#include "vectors.h"
24#include "ppc_exc_bspsupp.h"
25
26static rtems_raw_except_global_settings exception_config;
27static rtems_raw_except_connect_data    exception_table[LAST_VALID_EXC + 1];
28
29uint32_t ppc_exc_cache_wb_check = 1;
30
31#if 0
32typedef struct ppc_exc_connect_data_ {
33        rtems_raw_except_connect_data   raw;
34        ppc_exc_handler_t                               c_hdl;                 
35} ppc_exc_connect_data;
36#endif
37
38exception_handler_t globalExceptHdl;
39
40/* T. Straumann: provide a stack trace
41 * <strauman@slac.stanford.edu>, 6/26/2001
42 */
43typedef struct LRFrameRec_ {
44        struct LRFrameRec_ *frameLink;
45        unsigned long *lr;
46} LRFrameRec, *LRFrame;
47
48#define STACK_CLAMP 50  /* in case we have a corrupted bottom */
49
50SPR_RW(SPRG1)
51SPR_RW(SPRG2)
52SPR_RO(LR)
53SPR_RO(DAR)
54#define DEAR_BOOKE 61
55#define DEAR_405   0x3d5
56SPR_RO(DEAR_BOOKE)
57SPR_RO(DEAR_405)
58
59uint32_t ppc_exc_get_DAR_dflt(void)
60{
61        if ( ppc_cpu_is_60x() )
62                return _read_DAR();
63        else switch ( ppc_cpu_is_bookE() ) {
64                default: break;
65                case PPC_BOOKE_STD:
66                case PPC_BOOKE_E500:
67                        return _read_DEAR_BOOKE();
68                case PPC_BOOKE_405:
69                        return _read_DEAR_405();
70        }
71        return 0xdeadbeef;
72}
73
74uint32_t (*ppc_exc_get_DAR)(void) = ppc_exc_get_DAR_dflt;
75
76void
77BSP_printStackTrace(BSP_Exception_frame* excPtr)
78{
79LRFrame f;
80int             i;
81LRFrame sp;
82void    *lr;
83
84        printk("Stack Trace: \n  ");
85        if (excPtr) {
86                printk("IP: 0x%08x, ",excPtr->EXC_SRR0);
87                sp=(LRFrame)excPtr->GPR1;
88                lr=(void*)excPtr->EXC_LR;
89        } else {
90                /* there's no macro for this */
91                __asm__ __volatile__("mr %0, 1":"=r"(sp));
92                lr=(LRFrame)_read_LR();
93        }
94        printk("LR: 0x%08x\n",lr);
95        for (f=(LRFrame)sp, i=0; f->frameLink && i<STACK_CLAMP; f=f->frameLink) {
96                printk("--^ 0x%08x", (long)(f->frameLink->lr));
97                if (!(++i%5))
98                        printk("\n");
99        }
100        if (i>=STACK_CLAMP) {
101                printk("Too many stack frames (stack possibly corrupted), giving up...\n");
102        } else {
103                if (i%5)
104                        printk("\n");
105        }
106}
107
108void C_exception_handler(BSP_Exception_frame* excPtr)
109{
110static int          nest        = 0;
111
112  int               recoverable = 0;
113  rtems_id          id          = 0;
114  int               synch;
115  unsigned          n;
116  rtems_status_code sc;
117
118  /* Catch recursion */
119  nest++;
120
121  if ( nest > 2 ) {
122        /* maybe printk() or dereferencing excPtr caused an exception;
123         * die silently...
124         */
125        while (1)
126                ;
127  }
128
129  synch  = (int)excPtr->_EXC_number >= 0 ;
130  n      = excPtr->_EXC_number & 0x7fff;
131
132  printk("Exception handler called for exception %d (0x%x)\n", n, n);
133  printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0);
134  printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1);
135
136  if ( nest > 1 ) {
137    printk("Recursion in the exception handler detected; I'll spin now...\n");
138        while ( 1 )
139                ;
140  }
141
142  /* Try to find out more about the context where this happened */
143  printk("\t Context: ");
144  if ( rtems_interrupt_is_in_progress() ) {
145        printk("ISR");
146  } else if ( !_Thread_Executing ) {
147        printk("Initialization (_Thread_Executing not available yet)");
148  } else {
149        if ( RTEMS_SUCCESSFUL != (sc=rtems_task_ident(RTEMS_SELF, RTEMS_LOCAL, &id)) ) {
150                printk("Unable to determine faulting task; rtems_task_ident() returned %u", sc);
151                id = 0;
152        } else {
153                printk("Task ID 0x%08x", id);
154        }
155  }
156  printk("\n");
157
158  /* Dump registers */
159
160  printk("\t R0  = %08x", excPtr->GPR0);
161  if ( synch ) {
162    printk(" R1  = %08x", excPtr->GPR1);
163    printk(" R2  = %08x", excPtr->GPR2);
164  } else {
165    printk("               ");
166    printk("               ");
167  }
168  printk(" R3  = %08x\n", excPtr->GPR3);
169  printk("\t R4  = %08x", excPtr->GPR4);
170  printk(" R5  = %08x",   excPtr->GPR5);
171  printk(" R6  = %08x",   excPtr->GPR6);
172  printk(" R7  = %08x\n", excPtr->GPR7);
173  printk("\t R8  = %08x", excPtr->GPR8);
174  printk(" R9  = %08x",   excPtr->GPR9);
175  printk(" R10 = %08x",   excPtr->GPR10);
176  printk(" R11 = %08x\n", excPtr->GPR11);
177  printk("\t R12 = %08x", excPtr->GPR12);
178  if ( synch ) {
179          printk(" R13 = %08x",   excPtr->GPR13);
180          printk(" R14 = %08x",   excPtr->GPR14);
181          printk(" R15 = %08x\n", excPtr->GPR15);
182          printk("\t R16 = %08x", excPtr->GPR16);
183          printk(" R17 = %08x",   excPtr->GPR17);
184          printk(" R18 = %08x",   excPtr->GPR18);
185          printk(" R19 = %08x\n", excPtr->GPR19);
186          printk("\t R20 = %08x", excPtr->GPR20);
187          printk(" R21 = %08x",   excPtr->GPR21);
188          printk(" R22 = %08x",   excPtr->GPR22);
189          printk(" R23 = %08x\n", excPtr->GPR23);
190          printk("\t R24 = %08x", excPtr->GPR24);
191          printk(" R25 = %08x",   excPtr->GPR25);
192          printk(" R26 = %08x",   excPtr->GPR26);
193          printk(" R27 = %08x\n", excPtr->GPR27);
194          printk("\t R28 = %08x", excPtr->GPR28);
195          printk(" R29 = %08x",   excPtr->GPR29);
196          printk(" R30 = %08x",   excPtr->GPR30);
197          printk(" R31 = %08x\n", excPtr->GPR31);
198  } else {
199      printk("\n");
200  }
201  printk("\t CR  = %08x\n", excPtr->EXC_CR);
202  printk("\t CTR = %08x\n", excPtr->EXC_CTR);
203  printk("\t XER = %08x\n", excPtr->EXC_XER);
204  printk("\t LR  = %08x\n", excPtr->EXC_LR);
205
206  /* Would be great to print DAR but unfortunately,
207   * that is not portable across different CPUs.
208   * AFAIK on classic PPC DAR is SPR 19, on the
209   * 405 we have DEAR = SPR 0x3d5 and booE says
210   * DEAR = SPR 61 :-(
211   */
212  if ( ppc_exc_get_DAR ) {
213        printk("\t DAR = %08x\n",  ppc_exc_get_DAR());
214  }
215
216  BSP_printStackTrace(excPtr);
217
218  if (excPtr->_EXC_number == ASM_DEC_VECTOR)
219       recoverable = 1;
220  if (excPtr->_EXC_number == ASM_SYS_VECTOR)
221#ifdef TEST_RAW_EXCEPTION_CODE
222    recoverable = 1;
223#else
224    recoverable = 0;
225#endif
226  if (!recoverable) {
227    if ( id ) {
228                printk("Suspending faulting task (0x%08x)\n", id);
229                /* Unnest here because rtems_task_suspend() never returns */
230                nest--;
231                rtems_task_suspend(id);
232        } else {
233        printk("unrecoverable exception!!! Push reset button\n");
234        while(1);
235        }
236  } else {
237        nest--;
238  }
239}
240
241/***********************************************************
242 * dummy functions for on/off/isOn calls
243 * these functions just do nothing fulfill the semantic
244 * requirements to enable/disable a certain exception
245 */
246void exception_nop_enable(const rtems_raw_except_connect_data* ptr)
247{
248}
249
250int exception_always_enabled(const rtems_raw_except_connect_data* ptr)
251{
252  return 1;
253}
254
255/* Raw exception framework wants to keep a pointer to
256 * the prologue so we must keep the ones we generate
257 * from templates around...
258 */
259#define NUM_PROLOG      8       /* just a reasonable limit */
260static int                  n_prolog = 0;
261static ppc_exc_min_prolog_t prologues[NUM_PROLOG];
262
263static ppc_exc_min_prolog_template_t prolog_templates[][2] = {
264        [ PPC_EXC_CLASSIC ] =
265                {
266                ppc_exc_min_prolog_sync_tmpl_std,
267                ppc_exc_min_prolog_async_tmpl_std,
268                },
269        [ PPC_EXC_405_CRITICAL ] =
270                {
271                ppc_exc_min_prolog_sync_tmpl_p405_crit,
272                ppc_exc_min_prolog_async_tmpl_p405_crit,
273                },
274        [ PPC_EXC_BOOKE_CRITICAL ] =
275                {
276                ppc_exc_min_prolog_sync_tmpl_bookE_crit,
277                ppc_exc_min_prolog_async_tmpl_bookE_crit,
278                },
279        [ PPC_EXC_E500_MACHCHK ] =
280                {
281                ppc_exc_min_prolog_sync_tmpl_e500_mchk,
282                ppc_exc_min_prolog_async_tmpl_e500_mchk,
283                },
284};
285
286static rtems_raw_except_func
287make_prologue(int vector, ppc_raw_exception_category cat)
288{
289int                           async = (cat & PPC_EXC_ASYNC) ? 1 : 0 ;
290ppc_exc_min_prolog_template_t tmpl;
291
292        cat &= ~PPC_EXC_ASYNC;
293
294        if ( n_prolog >= NUM_PROLOG ) {
295                rtems_panic("Not enough exception prologue slots; increase NUM_PROLOG (%s)\n",__FILE__);
296        }
297
298        if ( ! (tmpl = prolog_templates[cat][async]) ) {
299                rtems_panic("No exception prologue template for category 0x%02x found\n", cat);
300        }
301
302        ppc_exc_min_prolog_expand(prologues[n_prolog], tmpl, vector);
303
304        return (rtems_raw_except_func)prologues[n_prolog++];
305}
306
307void ppc_exc_table_init(
308        rtems_raw_except_connect_data    *exception_table,
309        int                               nEntries)
310{
311unsigned i,v;
312ppc_raw_exception_category cat;
313uintptr_t vaddr;
314
315        /*
316         * Initialize pointer used by low level execption handling
317         */
318        globalExceptHdl                                 = C_exception_handler;
319        /*
320         * Put  default_exception_vector_code_prolog at relevant exception
321         * code entry addresses
322         */
323        exception_config.exceptSize                     = nEntries;
324        exception_config.rawExceptHdlTbl                = exception_table;
325        exception_config.defaultRawEntry.exceptIndex    = 0;
326        exception_config.defaultRawEntry.hdl.vector     = 0;
327
328        if (ppc_cpu_has_ivpr_and_ivor()) {
329                /* Use packed version with 16-byte boundaries for CPUs with IVPR and IVOR registers */
330                exception_config.defaultRawEntry.hdl.raw_hdl = ppc_exc_min_prolog_auto_packed;
331        } else {
332                /* Note that the 'auto' handler cannot be used for everything; in particular,
333                 * it assumes classic exceptions with a vector offset aligned on a 256-byte
334                 * boundary.
335                 */
336                exception_config.defaultRawEntry.hdl.raw_hdl = ppc_exc_min_prolog_auto;
337        }
338
339        /*
340         * Note that the cast of an array address to an unsigned
341         * is not a bug as it is defined by a .set directly in asm...
342         */
343        exception_config.defaultRawEntry.hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
344
345        for (i=0; i < exception_config.exceptSize; i++) {
346
347                if ( PPC_EXC_INVALID == (cat = ppc_vector_is_valid ((v=exception_table[i].hdl.vector))) ) {
348                        continue;
349                }
350
351                exception_table[i].exceptIndex  = i;
352                exception_table[v].hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
353
354                /* special cases */
355                if ( ppc_cpu_has_shadowed_gprs()
356                                && (   ASM_60X_IMISS_VECTOR  == v
357                                        || ASM_60X_DLMISS_VECTOR == v
358                                        || ASM_60X_DSMISS_VECTOR == v ) ) {
359                        exception_table[i].hdl.raw_hdl    = ppc_exc_tgpr_clr_prolog;
360                        exception_table[i].hdl.raw_hdl_size = (unsigned)ppc_exc_tgpr_clr_prolog_size;
361                } else {
362
363                        vaddr = (uintptr_t)ppc_get_vector_addr( v );
364
365                        /*
366                         * default prolog can handle classic, synchronous exceptions
367                         * with a vector offset aligned on a 256-byte boundary.
368                         */
369                        if (cat == PPC_EXC_CLASSIC && ((vaddr & 0xff) == 0 || (ppc_cpu_has_ivpr_and_ivor() && (vaddr & 0xf) == 0))) {
370                                exception_table[i].hdl.raw_hdl_size = exception_config.defaultRawEntry.hdl.raw_hdl_size;
371                                exception_table[i].hdl.raw_hdl      = exception_config.defaultRawEntry.hdl.raw_hdl;
372                        } else {
373                                exception_table[i].hdl.raw_hdl_size = (unsigned)ppc_exc_min_prolog_size;
374                                exception_table[i].hdl.raw_hdl      = make_prologue( v, cat );
375                        }
376
377                }
378                exception_table[i].on           = exception_nop_enable;
379                exception_table[i].off          = exception_nop_enable;
380                exception_table[i].isOn         = exception_always_enabled;
381        }
382        if (!ppc_init_exceptions(&exception_config)) {
383                BSP_panic("Exception handling initialization failed\n");
384        }
385#ifdef RTEMS_DEBUG
386        else {
387                printk("Exception handling initialization done\n");
388        }
389#endif
390}
391
392
393void ppc_exc_initialize(
394        uint32_t interrupt_disable_mask,
395        uint32_t interrupt_stack_start,
396        uint32_t interrupt_stack_size
397)
398{
399        int i;
400        int n = sizeof(exception_table)/sizeof(exception_table[0]);
401
402        uint32_t interrupt_stack_end = 0;
403        uint32_t interrupt_stack_pointer = 0;
404        uint32_t *p = NULL;
405        uint32_t r13, sda_base;
406
407        /* Assembly code needs SDA_BASE in r13 (SVR4 or EABI). Make sure
408         * early init code put it there.
409         */
410        asm volatile(
411                "       lis %0,     _SDA_BASE_@h  \n"
412                "       ori %0, %0, _SDA_BASE_@l  \n"
413                "       mr  %1, 13                \n"
414        :"=r"(sda_base),"=r"(r13)
415        );
416
417        if ( sda_base != r13 ) {
418                printk("ppc_exc_initialize(): INTERNAL ERROR\n");
419                printk("  your BSP seems to not have loaded _SDA_BASE_\n");
420                printk("  into R13 as required by SVR4/EABI. Check early init code...\n");
421                printk("  _SDA_BASE_: 0x%08x, R13: 0x%08x\n", sda_base, r13);
422                while (1)
423                        ;
424        }
425
426        /* Interrupt stack end and pointer */
427        interrupt_stack_end = interrupt_stack_start + interrupt_stack_size;
428
429        interrupt_stack_pointer  = interrupt_stack_end - PPC_MINIMUM_STACK_FRAME_SIZE;
430
431        /* Ensure proper interrupt stack alignment */
432        interrupt_stack_pointer &= ~(CPU_STACK_ALIGNMENT - 1);
433
434        /* Tag interrupt stack bottom */
435        p = (uint32_t *) interrupt_stack_pointer;
436        *p = 0;
437
438        /* Move interrupt stack values to special purpose registers */
439        _write_SPRG1( interrupt_stack_pointer);
440        _write_SPRG2( interrupt_stack_start);
441
442        /* Interrupt disable mask */
443        ppc_interrupt_set_disable_mask( interrupt_disable_mask);
444
445        /* Use current MMU / RI settings when running C exception handlers */
446        ppc_exc_msr_bits = _read_MSR() & ( MSR_DR | MSR_IR | MSR_RI );
447
448        for ( i=0; i<n; i++ )
449                exception_table[i].hdl.vector = i;
450        ppc_exc_table_init(exception_table, n);
451
452        /* If we are on a classic PPC with MSR_DR enabled then
453         * assert that the mapping for at least this task's
454         * stack is write-back-caching enabled (see README/CAVEATS)
455         * Do this only if the cache is physically enabled.
456         * Since it is not easy to figure that out in a
457         * generic way we need help from the BSP: BSPs
458         * which run entirely w/o the cache may set
459         * ppc_exc_cache_wb_check to zero prior to calling
460         * this routine.
461         *
462         * We run this check only after exception handling is
463         * initialized so that we have some chance to get
464         * information printed if it fails.
465         *
466         * Note that it is unsafe to ignore this issue; if
467         * the check fails, do NOT disable it unless caches
468         * are always physically disabled.
469         */
470        if ( ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits) ) {
471                /* The size of 63 assumes cache lines are at most 32 bytes */
472                uint8_t   dummy[63];
473                uintptr_t p = (uintptr_t)dummy;
474                /* If the dcbz instruction raises an alignment exception
475                 * then the stack is mapped as write-thru or caching-disabled.
476                 * The low-level code is not capable of dealing with this
477                 * ATM.
478                 */
479                p = (p + 31) & ~31;
480                asm volatile("dcbz 0, %0"::"b"(p));
481                /* If we make it thru here then things seem to be OK */
482        }
483
484}
Note: See TracBrowser for help on using the repository browser.