Reworked APC and waiting code, seems more stable now
[reactos.git] / reactos / ntoskrnl / ke / i386 / exp.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/hal/x86/exp.c
5 * PURPOSE: Handling exceptions
6 * PROGRAMMER: David Welch (welch@cwcom.net)
7 * REVISION HISTORY:
8 * ??/??/??: Created
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ddk/ntddk.h>
14 #include <internal/ntoskrnl.h>
15 #include <internal/ke.h>
16 #include <internal/symbol.h>
17 #include <internal/i386/segment.h>
18 #include <internal/mmhal.h>
19 #include <internal/module.h>
20
21 #define NDEBUG
22 #include <internal/debug.h>
23
24 /* GLOBALS *****************************************************************/
25
26 asmlinkage int page_fault_handler(unsigned int cs,
27 unsigned int eip);
28
29 static exception_hook* exception_hooks[256]={NULL,};
30
31 #define _STR(x) #x
32 #define STR(x) _STR(x)
33
34 extern void interrupt_handler2e(void);
35
36 extern ULONG init_stack;
37 extern ULONG init_stack_top;
38
39 /* FUNCTIONS ****************************************************************/
40
41 #define EXCEPTION_HANDLER_WITH_ERROR(x,y) \
42 void exception_handler##y (void); \
43 void tmp_exception_handler##y (void) { \
44 __asm__("\n\t_exception_handler"##x":\n\t" \
45 "pushl %gs\n\t" \
46 "pushl %fs\n\t" \
47 "pushl %es\n\t" \
48 "pushl %ds\n\t" \
49 "pushl $"##x"\n\t" \
50 "pusha\n\t" \
51 "movw $"STR(KERNEL_DS)",%ax\n\t" \
52 "movw %ax,%ds\n\t" \
53 "movw %ax,%es\n\t" \
54 "movw %ax,%fs\n\t" \
55 "movw %ax,%gs\n\t" \
56 "call _exception_handler\n\t" \
57 "popa\n\t" \
58 "addl $4,%esp\n\t" \
59 "popl %ds\n\t" \
60 "popl %es\n\t" \
61 "popl %fs\n\t" \
62 "popl %gs\n\t" \
63 "addl $4,%esp\n\t" \
64 "iret\n\t"); }
65
66 #define EXCEPTION_HANDLER_WITHOUT_ERROR(x,y) \
67 asmlinkage void exception_handler##y (void); \
68 void tmp_exception_handler##y (void) { \
69 __asm__("\n\t_exception_handler"##x":\n\t" \
70 "pushl $0\n\t" \
71 "pushl %gs\n\t" \
72 "pushl %fs\n\t" \
73 "pushl %es\n\t" \
74 "pushl %ds\n\t" \
75 "pushl $"##x"\n\t" \
76 "pusha\n\t" \
77 "movw $"STR(KERNEL_DS)",%ax\n\t" \
78 "movw %ax,%ds\n\t" \
79 "movw %ax,%es\n\t" \
80 "movw %ax,%fs\n\t" \
81 "movw %ax,%gs\n\t" \
82 "call _exception_handler\n\t" \
83 "popa\n\t" \
84 "addl $4,%esp\n\t" \
85 "popl %ds\n\t" \
86 "popl %es\n\t" \
87 "popl %fs\n\t" \
88 "popl %gs\n\t" \
89 "addl $4,%esp\n\t" \
90 "iret\n\t"); }
91
92 asmlinkage void exception_handler_unknown(void);
93 asmlinkage void tmp_exception_handler_unknown(void)
94 {
95 __asm__("\n\t_exception_handler_unknown:\n\t"
96 "pushl $0\n\t"
97 "pushl %gs\n\t"
98 "pushl %fs\n\t"
99 "pushl %es\n\t"
100 "pushl %ds\n\t"
101 "pushl %ds\n\t"
102 "pushl $0xff\n\t"
103 "pusha\n\t"
104 "movw $"STR(KERNEL_DS)",%ax\n\t"
105 "movw %ax,%ds\n\t"
106 "movw %ax,%es\n\t"
107 "movw %ax,%fs\n\t"
108 "movw %ax,%gs\n\t"
109 "call _exception_handler\n\t"
110 "popa\n\t"
111 "addl $8,%esp\n\t"
112 "iret\n\t");
113 }
114
115 EXCEPTION_HANDLER_WITHOUT_ERROR("0",0);
116 EXCEPTION_HANDLER_WITHOUT_ERROR("1",1);
117 EXCEPTION_HANDLER_WITHOUT_ERROR("2",2);
118 EXCEPTION_HANDLER_WITHOUT_ERROR("3",3);
119 EXCEPTION_HANDLER_WITHOUT_ERROR("4",4);
120 EXCEPTION_HANDLER_WITHOUT_ERROR("5",5);
121 EXCEPTION_HANDLER_WITHOUT_ERROR("6",6);
122 EXCEPTION_HANDLER_WITHOUT_ERROR("7",7);
123 EXCEPTION_HANDLER_WITH_ERROR("8",8);
124 EXCEPTION_HANDLER_WITHOUT_ERROR("9",9);
125 EXCEPTION_HANDLER_WITH_ERROR("10",10);
126 EXCEPTION_HANDLER_WITH_ERROR("11",11);
127 EXCEPTION_HANDLER_WITH_ERROR("12",12);
128 EXCEPTION_HANDLER_WITH_ERROR("13",13);
129 EXCEPTION_HANDLER_WITH_ERROR("14",14);
130 EXCEPTION_HANDLER_WITH_ERROR("15",15);
131 EXCEPTION_HANDLER_WITHOUT_ERROR("16",16);
132
133 extern unsigned int stext, etext;
134
135 static void print_address(PVOID address)
136 {
137 PLIST_ENTRY current_entry;
138 PMODULE_OBJECT current;
139 extern LIST_ENTRY ModuleListHead;
140
141 current_entry = ModuleListHead.Flink;
142
143 while (current_entry != &ModuleListHead &&
144 current_entry != NULL)
145 {
146 current = CONTAINING_RECORD(current_entry, MODULE_OBJECT, ListEntry);
147
148 if (address >= current->Base &&
149 address < (current->Base + current->Length))
150 {
151 DbgPrint("<%w: %x>", current->Name,
152 address - current->Base);
153 return;
154 }
155
156 current_entry = current_entry->Flink;
157 }
158 DbgPrint("<%x>", address);
159 }
160
161 asmlinkage void exception_handler(unsigned int edi,
162 unsigned int esi, unsigned int ebp,
163 unsigned int esp, unsigned int ebx,
164 unsigned int edx, unsigned int ecx,
165 unsigned int eax,
166 unsigned int type,
167 unsigned int ds,
168 unsigned int es,
169 unsigned int fs,
170 unsigned int gs,
171 unsigned int error_code,
172 unsigned int eip,
173 unsigned int cs, unsigned int eflags,
174 unsigned int esp0, unsigned int ss0)
175 /*
176 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
177 * message and halt the computer
178 * ARGUMENTS:
179 * Complete CPU context
180 */
181 {
182 unsigned int cr2, cr3;
183 unsigned int i;
184 // unsigned int j, sym;
185 unsigned int* stack;
186 static char *TypeStrings[] =
187 {
188 "Divide Error",
189 "Debug Trap",
190 "Unknown(2)",
191 "Breakpoint",
192 "Overflow",
193 "BOUND range exceeded",
194 "Invalid Opcode",
195 "No Math Coprocessor",
196 "Double Fault",
197 "Unknown(9)",
198 "Invalid TSS",
199 "Segment Not Present",
200 "Stack Segment Fault",
201 "General Protection",
202 "Page Fault",
203 "Math Fault",
204 "Alignment Check",
205 "Machine Check"
206 };
207
208 __asm__("cli\n\t");
209
210 if (type==14)
211 {
212 if (page_fault_handler(cs&0xffff,eip))
213 {
214 return;
215 }
216 }
217 if (type==1)
218 {
219 DbgPrint("Trap at CS:EIP %x:%x\n",cs&0xffff,eip);
220 return;
221 }
222
223 /*
224 * Activate any hook for the exception
225 */
226 if (exception_hooks[type]!=NULL)
227 {
228 exception_hooks[type](NULL,type);
229 }
230
231 /*
232 * Print out the CPU registers
233 */
234 if (type < 19)
235 {
236 DbgPrint("%s Exception: %d(%x)\n",TypeStrings[type],type,
237 error_code&0xffff);
238 }
239 else
240 {
241 DbgPrint("Exception: %d(%x)\n",type,error_code&0xffff);
242 }
243 DbgPrint("CS:EIP %x:%x\n",cs&0xffff,eip);
244 DbgPrint("CS:EIP %x:", cs&0xffff);
245 print_address((PVOID)eip);
246 DbgPrint("\n");
247 __asm__("movl %%cr2,%0\n\t"
248 : "=d" (cr2));
249 __asm__("movl %%cr3,%0\n\t"
250 : "=d" (cr3));
251 DbgPrint("cr2 %x cr3 %x\n",cr2,cr3);
252 // for(;;);
253 DbgPrint("Process: %x\n",PsGetCurrentProcess());
254 if (PsGetCurrentProcess() != NULL)
255 {
256 DbgPrint("Process id: %x\n", PsGetCurrentProcess()->UniqueProcessId);
257 }
258 if (PsGetCurrentThread() != NULL)
259 {
260 DbgPrint("Thread: %x Thread id: %x\n",
261 PsGetCurrentThread(),
262 PsGetCurrentThread()->Cid.UniqueThread);
263 }
264 DbgPrint("DS %x ES %x FS %x GS %x\n",ds&0xffff,es&0xffff,fs&0xffff,
265 gs&0xfff);
266 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n",eax,ebx,ecx);
267 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n",edx,ebp,esi);
268 DbgPrint("EDI: %.8x EFLAGS: %.8x ",edi,eflags);
269 if ((cs&0xffff) == KERNEL_CS)
270 {
271 DbgPrint("kESP %.8x\n",esp);
272 if (PsGetCurrentThread() != NULL)
273 {
274 DbgPrint("kernel stack base %x\n",
275 PsGetCurrentThread()->Tcb.Context.KernelStackBase);
276
277 }
278 }
279 else
280 {
281 DbgPrint("kernel ESP %.8x\n",esp);
282 }
283 if ((cs & 0xffff) == KERNEL_CS)
284 {
285 DbgPrint("ESP %x\n",esp);
286 stack = (unsigned int *) (esp + 24);
287
288 DbgPrint("Stack:\n");
289 for (i = 0; i < 16; i = i + 4)
290 {
291 DbgPrint("%.8x %.8x %.8x %.8x\n",
292 stack[i],
293 stack[i+1],
294 stack[i+2],
295 stack[i+3]);
296 }
297 DbgPrint("Frames:\n");
298 for (i = 0; i < 32; i++)
299 {
300 if (stack[i] > ((unsigned int) &stext) &&
301 !(stack[i] >= ((ULONG)&init_stack) &&
302 stack[i] <= ((ULONG)&init_stack_top)))
303 {
304 // DbgPrint(" %.8x", stack[i]);
305 print_address((PVOID)stack[i]);
306 DbgPrint(" ");
307 }
308 }
309 }
310 else
311 {
312 DbgPrint("SS:ESP %x:%x\n",ss0,esp0);
313 stack=(unsigned int *)(esp0);
314
315 DbgPrint("Stack:\n");
316 for (i=0; i<16; i++)
317 {
318 if (MmIsPagePresent(NULL,&stack[i]))
319 {
320 DbgPrint("%.8x ",stack[i]);
321 if (((i+1)%4) == 0)
322 {
323 DbgPrint("\n");
324 }
325 }
326 }
327 }
328
329 DbgPrint("\n");
330 DbgPrint("Killing current task\n");
331 // for(;;);
332 KeLowerIrql(PASSIVE_LEVEL);
333 if ((cs&0xffff) == USER_CS)
334 {
335 ZwTerminateProcess(NtCurrentProcess(),
336 STATUS_NONCONTINUABLE_EXCEPTION);
337 }
338
339 for(;;);
340 }
341
342 VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames)
343 {
344 PULONG Stack = (PULONG)_Stack;
345 ULONG i;
346
347 Stack = (PVOID)(((ULONG)Stack) & (~0x3));
348 DbgPrint("Stack: %x\n", Stack);
349
350 DbgPrint("Frames:\n");
351 for (i=0; i<NrFrames; i++)
352 {
353 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
354 if (Stack[i] > KERNEL_BASE)
355 {
356 // DbgPrint("%.8x ",Stack[i]);
357 print_address((PVOID)Stack[i]);
358 DbgPrint(" ");
359 }
360 if (Stack[i] == 0xceafbeef)
361 {
362 DbgPrint("IRQ ");
363 }
364 }
365 DbgPrint("\n");
366 }
367
368 static void set_system_call_gate(unsigned int sel, unsigned int func)
369 {
370 DPRINT("sel %x %d\n",sel,sel);
371 KiIdt[sel].a = (((int)func)&0xffff) +
372 (KERNEL_CS << 16);
373 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
374 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
375 }
376
377 static void set_interrupt_gate(unsigned int sel, unsigned int func)
378 {
379 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
380 KiIdt[sel].a = (((int)func)&0xffff) +
381 (KERNEL_CS << 16);
382 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
383 }
384
385 asmlinkage unsigned int ExHookException(exception_hook fn, unsigned int exp)
386 /*
387 * FUNCTION: Hook an exception
388 */
389 {
390 if (exp>=256)
391 {
392 return(1);
393 }
394 exception_hooks[exp]=fn;
395 return(0);
396 }
397
398 asmlinkage void KeInitExceptions(void)
399 /*
400 * FUNCTION: Initalize CPU exception handling
401 */
402 {
403 int i;
404
405 DPRINT("KeInitExceptions()\n",0);
406
407 set_interrupt_gate(0,(int)exception_handler0);
408 set_interrupt_gate(1,(int)exception_handler1);
409 set_interrupt_gate(2,(int)exception_handler2);
410 set_interrupt_gate(3,(int)exception_handler3);
411 set_interrupt_gate(4,(int)exception_handler4);
412 set_interrupt_gate(5,(int)exception_handler5);
413 set_interrupt_gate(6,(int)exception_handler6);
414 set_interrupt_gate(7,(int)exception_handler7);
415 set_interrupt_gate(8,(int)exception_handler8);
416 set_interrupt_gate(9,(int)exception_handler9);
417 set_interrupt_gate(10,(int)exception_handler10);
418 set_interrupt_gate(11,(int)exception_handler11);
419 set_interrupt_gate(12,(int)exception_handler12);
420 set_interrupt_gate(13,(int)exception_handler13);
421 set_interrupt_gate(14,(int)exception_handler14);
422 set_interrupt_gate(15,(int)exception_handler15);
423 set_interrupt_gate(16,(int)exception_handler16);
424
425 for (i=17;i<256;i++)
426 {
427 set_interrupt_gate(i,(int)exception_handler_unknown);
428 }
429
430 set_system_call_gate(0x2e,(int)interrupt_handler2e);
431 }