source: rtems/cpukit/score/cpu/i386/cpu.c @ deaf716

5
Last change on this file since deaf716 was deaf716, checked in by Sebastian Huber <sebastian.huber@…>, on 02/03/16 at 10:13:53

i386: Avoid SCORE_EXTERN

Update #2559.

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