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

5
Last change on this file since fd05a05 was fd05a05, checked in by Gedare Bloom <gedare@…>, on 01/08/16 at 17:15:46

i386: move idle thread into BSP layer

  • Property mode set to 100644
File size: 7.0 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
123struct Frame_ {
124        struct Frame_  *up;
125        uintptr_t               pc;
126};
127
128void _CPU_Exception_frame_print (const CPU_Exception_frame *ctx)
129{
130  unsigned int faultAddr = 0;
131  printk("----------------------------------------------------------\n");
132  printk("Exception %d caught at PC %x by thread %d\n",
133         ctx->idtIndex,
134         ctx->eip,
135         _Thread_Executing->Object.id);
136  printk("----------------------------------------------------------\n");
137  printk("Processor execution context at time of the fault was  :\n");
138  printk("----------------------------------------------------------\n");
139  printk(" EAX = %x     EBX = %x        ECX = %x        EDX = %x\n",
140         ctx->eax, ctx->ebx, ctx->ecx, ctx->edx);
141  printk(" ESI = %x     EDI = %x        EBP = %x        ESP = %x\n",
142         ctx->esi, ctx->edi, ctx->ebp, ctx->esp0);
143  printk("----------------------------------------------------------\n");
144  printk("Error code pushed by processor itself (if not 0) = %x\n",
145         ctx->faultCode);
146  printk("----------------------------------------------------------\n");
147  if (ctx->idtIndex == I386_EXCEPTION_PAGE_FAULT){
148    faultAddr = i386_get_cr2();
149    printk("Page fault linear address (CR2) = %x\n", faultAddr);
150    printk("----------------------------------------------------------\n\n");
151  }
152 if (_ISR_Nest_level > 0) {
153    /*
154     * In this case we shall not delete the task interrupted as
155     * it has nothing to do with the fault. We cannot return either
156     * because the eip points to the faulty instruction so...
157     */
158    printk("Exception while executing ISR!!!. System locked\n");
159  }
160  else {
161        struct Frame_ *fp = (struct Frame_*)ctx->ebp;
162        int           i;
163
164        printk("Call Stack Trace of EIP:\n");
165        if ( fp ) {
166                for ( i=1; fp->up; fp=fp->up, i++ ) {
167                        printk("0x%08x ",fp->pc);
168                        if ( ! (i&3) )
169                                printk("\n");
170                }
171        }
172        printk("\n");
173    /*
174     * OK I could probably use a simplified version but at least this
175     * should work.
176     */
177#if 0
178    printk(" ************ FAULTY THREAD WILL BE SUSPENDED **************\n");
179    rtems_task_suspend(_Thread_Executing->Object.id);
180#endif
181  }
182}
183
184static void _defaultExcHandler (CPU_Exception_frame *ctx)
185{
186  rtems_fatal(
187    RTEMS_FATAL_SOURCE_EXCEPTION,
188    (rtems_fatal_code) ctx
189  );
190}
191
192cpuExcHandlerType _currentExcHandler = _defaultExcHandler;
193
194extern void rtems_exception_prologue_0(void);
195extern void rtems_exception_prologue_1(void);
196extern void rtems_exception_prologue_2(void);
197extern void rtems_exception_prologue_3(void);
198extern void rtems_exception_prologue_4(void);
199extern void rtems_exception_prologue_5(void);
200extern void rtems_exception_prologue_6(void);
201extern void rtems_exception_prologue_7(void);
202extern void rtems_exception_prologue_8(void);
203extern void rtems_exception_prologue_9(void);
204extern void rtems_exception_prologue_10(void);
205extern void rtems_exception_prologue_11(void);
206extern void rtems_exception_prologue_12(void);
207extern void rtems_exception_prologue_13(void);
208extern void rtems_exception_prologue_14(void);
209extern void rtems_exception_prologue_16(void);
210extern void rtems_exception_prologue_17(void);
211extern void rtems_exception_prologue_18(void);
212#ifdef __SSE__
213extern void rtems_exception_prologue_19(void);
214#endif
215
216static rtems_raw_irq_hdl tbl[] = {
217         rtems_exception_prologue_0,
218         rtems_exception_prologue_1,
219         rtems_exception_prologue_2,
220         rtems_exception_prologue_3,
221         rtems_exception_prologue_4,
222         rtems_exception_prologue_5,
223         rtems_exception_prologue_6,
224         rtems_exception_prologue_7,
225         rtems_exception_prologue_8,
226         rtems_exception_prologue_9,
227         rtems_exception_prologue_10,
228         rtems_exception_prologue_11,
229         rtems_exception_prologue_12,
230         rtems_exception_prologue_13,
231         rtems_exception_prologue_14,
232     0,
233         rtems_exception_prologue_16,
234         rtems_exception_prologue_17,
235         rtems_exception_prologue_18,
236#ifdef __SSE__
237         rtems_exception_prologue_19,
238#endif
239};
240
241void rtems_exception_init_mngt(void)
242{
243      size_t                     i,j;
244      interrupt_gate_descriptor  *currentIdtEntry;
245      unsigned                   limit;
246      unsigned                   level;
247
248      i = sizeof(tbl) / sizeof (rtems_raw_irq_hdl);
249
250      i386_get_info_from_IDTR (&currentIdtEntry, &limit);
251
252      _CPU_ISR_Disable(level);
253      for (j = 0; j < i; j++) {
254        create_interrupt_gate_descriptor (&currentIdtEntry[j], tbl[j]);
255      }
256      _CPU_ISR_Enable(level);
257}
Note: See TracBrowser for help on using the repository browser.