source: rtems/cpukit/score/cpu/i386/cpu.c @ 815994f

4.115
Last change on this file since 815994f was 815994f, checked in by Sebastian Huber <sebastian.huber@…>, on 11/25/12 at 16:48:11

score: Add CPU_Exception_frame

Add CPU port type CPU_Exception_frame and function
_CPU_Exception_frame_print().

The CPU ports of avr, bfin, h8300, lm32, m32c, m32r, m68k, nios2, sh,
sparc64, and v850 use an empty default implementation of
_CPU_Exception_frame_print().

Add rtems_exception_frame and rtems_exception_frame_print().

Add RTEMS_FATAL_SOURCE_EXCEPTION for CPU exceptions. Use rtems_fatal()
with source RTEMS_FATAL_SOURCE_EXCEPTION in CPU ports of i386, powerpc,
and sparc for unexpected exceptions.

Add third parameter to RTEMS_BSP_CLEANUP_OPTIONS() which controls the
BSP_PRINT_EXCEPTION_CONTEXT define used in the default
bsp_fatal_extension().

Add test sptests/spfatal26.

  • Property mode set to 100644
File size: 6.6 KB
RevLine 
[ac7d5ef0]1/*
2 *  Intel i386 Dependent Source
3 *
[08311cc3]4 *  COPYRIGHT (c) 1989-1999.
[ac7d5ef0]5 *  On-Line Applications Research Corporation (OAR).
6 *
[98e4ebf5]7 *  The license and distribution terms for this file may be
8 *  found in the file LICENSE in this distribution or at
[51fa11c]9 *  http://www.rtems.com/license/LICENSE.
[ac7d5ef0]10 */
11
[199041aa]12#ifdef HAVE_CONFIG_H
13#include "config.h"
14#endif
15
[a324355]16#include <rtems.h>
[ac7d5ef0]17#include <rtems/system.h>
[a324355]18#include <rtems/score/types.h>
[5e9b32b]19#include <rtems/score/isr.h>
[a324355]20#include <rtems/score/idtr.h>
21
[d56918c9]22#include <rtems/bspIo.h>
[eb562f2]23#include <rtems/score/thread.h>
[ac7d5ef0]24
25/*  _CPU_Initialize
26 *
27 *  This routine performs processor dependent initialization.
28 *
[c03e2bc]29 *  INPUT PARAMETERS: NONE
[ac7d5ef0]30 */
31
[c03e2bc]32void _CPU_Initialize(void)
[ac7d5ef0]33{
[752badac]34#if CPU_HARDWARE_FP
[c05f6238]35  register uint16_t             fp_status __asm__ ("ax");
[14865ec7]36  register Context_Control_fp  *fp_context;
[752badac]37#endif
[ac7d5ef0]38
39  /*
40   *  The following code saves a NULL i387 context which is given
41   *  to each task at start and restart time.  The following code
42   *  is based upon that provided in the i386 Programmer's
43   *  Manual and should work on any coprocessor greater than
44   *  the i80287.
45   *
[6805640e]46   *  NOTE: The NO WAIT form of the coprocessor instructions
[ac7d5ef0]47   *        MUST be used in case there is not a coprocessor
48   *        to wait for.
49   */
50
[6805640e]51#if CPU_HARDWARE_FP
[ac7d5ef0]52  fp_status = 0xa5a5;
[c05f6238]53  __asm__ volatile( "fninit" );
54  __asm__ volatile( "fnstsw %0" : "=a" (fp_status) : "0" (fp_status) );
[ac7d5ef0]55
56  if ( fp_status ==  0 ) {
57
[3652ad35]58    fp_context = &_CPU_Null_fp_context;
[ac7d5ef0]59
[b02f4cc1]60#ifdef __SSE__
61        asm volatile( "fstcw %0":"=m"(fp_context->fpucw) );
62#else
[c05f6238]63    __asm__ volatile( "fsave (%0)" : "=r" (fp_context)
[ac7d5ef0]64                               : "0"  (fp_context)
65                );
[b02f4cc1]66#endif
67  }
68#endif
69
70#ifdef __SSE__
71
[c05f6238]72  __asm__ volatile("stmxcsr %0":"=m"(fp_context->mxcsr));
[b02f4cc1]73
74  /* The BSP must enable the SSE extensions (early).
75   * If any SSE instruction was already attempted
76   * then that crashed the system.
77   * As a courtesy, we double-check here but it
78   * may be too late (which is also why we don't
79   * enable SSE here).
[42e243e]80   */
[b02f4cc1]81  {
82  uint32_t cr4;
83    __asm__ __volatile__("mov %%cr4, %0":"=r"(cr4));
84    if ( 0x600 != (cr4 & 0x600) ) {
85      printk("PANIC: RTEMS was compiled for SSE but BSP did not enable it (CR4: 0x%08x)\n", cr4);
86      while ( 1 ) {
87        __asm__ __volatile__("hlt");
88          }
89        }
[ac7d5ef0]90  }
[6805640e]91#endif
[ac7d5ef0]92}
93
[3dc9afb6]94/*
[3a4ae6c]95 *  _CPU_ISR_Get_level
96 */
[84c53452]97
[e6aeabd]98uint32_t   _CPU_ISR_Get_level( void )
[3a4ae6c]99{
[e6aeabd]100  uint32_t   level;
[84c53452]101
[3a4ae6c]102  i386_get_interrupt_level( level );
[84c53452]103
[3a4ae6c]104  return level;
105}
[8b2ee37c]106
[cca8379]107void *_CPU_Thread_Idle_body( uintptr_t ignored )
[8b2ee37c]108{
109  while(1){
[c05f6238]110    __asm__ volatile ("hlt");
[8b2ee37c]111  }
[3c87adba]112  return NULL;
[8b2ee37c]113}
[eb562f2]114
[020363d]115struct Frame_ {
116        struct Frame_  *up;
117        uintptr_t               pc;
118};
119
[815994f]120void _CPU_Exception_frame_print (const CPU_Exception_frame *ctx)
[eb562f2]121{
[1dfc188e]122  unsigned int faultAddr = 0;
[eb562f2]123  printk("----------------------------------------------------------\n");
124  printk("Exception %d caught at PC %x by thread %d\n",
125         ctx->idtIndex,
126         ctx->eip,
127         _Thread_Executing->Object.id);
128  printk("----------------------------------------------------------\n");
129  printk("Processor execution context at time of the fault was  :\n");
130  printk("----------------------------------------------------------\n");
131  printk(" EAX = %x     EBX = %x        ECX = %x        EDX = %x\n",
132         ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
133  printk(" ESI = %x     EDI = %x        EBP = %x        ESP = %x\n",
134         ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
135  printk("----------------------------------------------------------\n");
136  printk("Error code pushed by processor itself (if not 0) = %x\n",
137         ctx->faultCode);
[e029467]138  printk("----------------------------------------------------------\n");
[6dfebd9]139  if (ctx->idtIndex == I386_EXCEPTION_PAGE_FAULT){
[e029467]140    faultAddr = i386_get_cr2();
[1dfc188e]141    printk("Page fault linear address (CR2) = %x\n", faultAddr);
142    printk("----------------------------------------------------------\n\n");
[e029467]143  }
144 if (_ISR_Nest_level > 0) {
[b285860]145    /*
146     * In this case we shall not delete the task interrupted as
147     * it has nothing to do with the fault. We cannot return either
148     * because the eip points to the faulty instruction so...
149     */
150    printk("Exception while executing ISR!!!. System locked\n");
151  }
152  else {
[020363d]153        struct Frame_ *fp = (struct Frame_*)ctx->ebp;
154        int           i;
155
156        printk("Call Stack Trace of EIP:\n");
157        if ( fp ) {
158                for ( i=1; fp->up; fp=fp->up, i++ ) {
159                        printk("0x%08x ",fp->pc);
160                        if ( ! (i&3) )
161                                printk("\n");
162                }
163        }
164        printk("\n");
[b285860]165    /*
166     * OK I could probably use a simplified version but at least this
167     * should work.
168     */
[e58f80cb]169#if 0
[020363d]170    printk(" ************ FAULTY THREAD WILL BE SUSPENDED **************\n");
171    rtems_task_suspend(_Thread_Executing->Object.id);
[e58f80cb]172#endif
[b285860]173  }
[eb562f2]174}
175
[815994f]176static void _defaultExcHandler (CPU_Exception_frame *ctx)
177{
178  rtems_fatal(
179    RTEMS_FATAL_SOURCE_EXCEPTION,
180    (rtems_fatal_code) ctx
181  );
182}
183
[eb562f2]184cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
185
[af063f6]186extern void rtems_exception_prologue_0(void);
187extern void rtems_exception_prologue_1(void);
188extern void rtems_exception_prologue_2(void);
189extern void rtems_exception_prologue_3(void);
190extern void rtems_exception_prologue_4(void);
191extern void rtems_exception_prologue_5(void);
192extern void rtems_exception_prologue_6(void);
193extern void rtems_exception_prologue_7(void);
194extern void rtems_exception_prologue_8(void);
195extern void rtems_exception_prologue_9(void);
196extern void rtems_exception_prologue_10(void);
197extern void rtems_exception_prologue_11(void);
198extern void rtems_exception_prologue_12(void);
199extern void rtems_exception_prologue_13(void);
200extern void rtems_exception_prologue_14(void);
201extern void rtems_exception_prologue_16(void);
202extern void rtems_exception_prologue_17(void);
203extern void rtems_exception_prologue_18(void);
[b02f4cc1]204#ifdef __SSE__
205extern void rtems_exception_prologue_19(void);
206#endif
[eb562f2]207
208static rtems_raw_irq_hdl tbl[] = {
209         rtems_exception_prologue_0,
210         rtems_exception_prologue_1,
211         rtems_exception_prologue_2,
212         rtems_exception_prologue_3,
213         rtems_exception_prologue_4,
214         rtems_exception_prologue_5,
215         rtems_exception_prologue_6,
216         rtems_exception_prologue_7,
217         rtems_exception_prologue_8,
218         rtems_exception_prologue_9,
219         rtems_exception_prologue_10,
220         rtems_exception_prologue_11,
221         rtems_exception_prologue_12,
222         rtems_exception_prologue_13,
223         rtems_exception_prologue_14,
[70f6ff7]224     0,
[eb562f2]225         rtems_exception_prologue_16,
226         rtems_exception_prologue_17,
227         rtems_exception_prologue_18,
[b02f4cc1]228#ifdef __SSE__
229         rtems_exception_prologue_19,
230#endif
[eb562f2]231};
232
[917f816]233void rtems_exception_init_mngt(void)
[eb562f2]234{
[917f816]235      size_t                     i,j;
[eb562f2]236      interrupt_gate_descriptor  *currentIdtEntry;
237      unsigned                   limit;
238      unsigned                   level;
[84c53452]239
[eb562f2]240      i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
241
242      i386_get_info_from_IDTR (&currentIdtEntry, &limit);
243
244      _CPU_ISR_Disable(level);
245      for (j = 0; j < i; j++) {
246        create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
247      }
248      _CPU_ISR_Enable(level);
249}
Note: See TracBrowser for help on using the repository browser.