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