[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] | 32 | void _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] | 98 | uint32_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] | 107 | void *_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] | 115 | struct Frame_ { |
---|
| 116 | struct Frame_ *up; |
---|
| 117 | uintptr_t pc; |
---|
| 118 | }; |
---|
| 119 | |
---|
[815994f] | 120 | void _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] | 176 | static void _defaultExcHandler (CPU_Exception_frame *ctx) |
---|
| 177 | { |
---|
| 178 | rtems_fatal( |
---|
| 179 | RTEMS_FATAL_SOURCE_EXCEPTION, |
---|
| 180 | (rtems_fatal_code) ctx |
---|
| 181 | ); |
---|
| 182 | } |
---|
| 183 | |
---|
[eb562f2] | 184 | cpuExcHandlerType _currentExcHandler = _defaultExcHandler; |
---|
| 185 | |
---|
[af063f6] | 186 | extern void rtems_exception_prologue_0(void); |
---|
| 187 | extern void rtems_exception_prologue_1(void); |
---|
| 188 | extern void rtems_exception_prologue_2(void); |
---|
| 189 | extern void rtems_exception_prologue_3(void); |
---|
| 190 | extern void rtems_exception_prologue_4(void); |
---|
| 191 | extern void rtems_exception_prologue_5(void); |
---|
| 192 | extern void rtems_exception_prologue_6(void); |
---|
| 193 | extern void rtems_exception_prologue_7(void); |
---|
| 194 | extern void rtems_exception_prologue_8(void); |
---|
| 195 | extern void rtems_exception_prologue_9(void); |
---|
| 196 | extern void rtems_exception_prologue_10(void); |
---|
| 197 | extern void rtems_exception_prologue_11(void); |
---|
| 198 | extern void rtems_exception_prologue_12(void); |
---|
| 199 | extern void rtems_exception_prologue_13(void); |
---|
| 200 | extern void rtems_exception_prologue_14(void); |
---|
| 201 | extern void rtems_exception_prologue_16(void); |
---|
| 202 | extern void rtems_exception_prologue_17(void); |
---|
| 203 | extern void rtems_exception_prologue_18(void); |
---|
[b02f4cc1] | 204 | #ifdef __SSE__ |
---|
| 205 | extern void rtems_exception_prologue_19(void); |
---|
| 206 | #endif |
---|
[eb562f2] | 207 | |
---|
| 208 | static 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] | 233 | void 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 (¤tIdtEntry, &limit); |
---|
| 243 | |
---|
| 244 | _CPU_ISR_Disable(level); |
---|
| 245 | for (j = 0; j < i; j++) { |
---|
| 246 | create_interrupt_gate_descriptor (¤tIdtEntry[j], tbl[j]); |
---|
| 247 | } |
---|
| 248 | _CPU_ISR_Enable(level); |
---|
| 249 | } |
---|