Fixed problem with handles not being released
[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 #include <internal/mm.h>
21
22 #define NDEBUG
23 #include <internal/debug.h>
24
25 /* GLOBALS *****************************************************************/
26
27 static exception_hook* exception_hooks[256]={NULL,};
28
29 #define _STR(x) #x
30 #define STR(x) _STR(x)
31
32 extern void interrupt_handler2e(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("<%w: %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 unsigned int* stack;
184 static char *TypeStrings[] =
185 {
186 "Divide Error",
187 "Debug Trap",
188 "Unknown(2)",
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\n", PsGetCurrentProcess()->UniqueProcessId);
255 }
256 if (PsGetCurrentThread() != NULL)
257 {
258 DbgPrint("Thread: %x Thread id: %x\n",
259 PsGetCurrentThread(),
260 PsGetCurrentThread()->Cid.UniqueThread);
261 }
262 DbgPrint("DS %x ES %x FS %x GS %x\n",ds&0xffff,es&0xffff,fs&0xffff,
263 gs&0xfff);
264 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n",eax,ebx,ecx);
265 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n",edx,ebp,esi);
266 DbgPrint("EDI: %.8x EFLAGS: %.8x ",edi,eflags);
267 if ((cs&0xffff) == KERNEL_CS)
268 {
269 DbgPrint("kESP %.8x\n",esp);
270 if (PsGetCurrentThread() != NULL)
271 {
272 DbgPrint("kernel stack base %x\n",
273 PsGetCurrentThread()->Tcb.Context.KernelStackBase);
274
275 }
276 }
277 else
278 {
279 DbgPrint("kernel ESP %.8x\n",esp);
280 }
281 if ((cs & 0xffff) == KERNEL_CS)
282 {
283 DbgPrint("ESP %x\n",esp);
284 stack = (unsigned int *) (esp + 24);
285
286 DbgPrint("Stack:\n");
287 for (i = 0; i < 16; i = i + 4)
288 {
289 DbgPrint("%.8x %.8x %.8x %.8x\n",
290 stack[i],
291 stack[i+1],
292 stack[i+2],
293 stack[i+3]);
294 }
295 DbgPrint("Frames:\n");
296 for (i = 0; i < 32; i++)
297 {
298 if (stack[i] > ((unsigned int) &stext) &&
299 !(stack[i] >= ((ULONG)&init_stack) &&
300 stack[i] <= ((ULONG)&init_stack_top)))
301 {
302 // DbgPrint(" %.8x", stack[i]);
303 print_address((PVOID)stack[i]);
304 DbgPrint(" ");
305 }
306 }
307 }
308 else
309 {
310 DbgPrint("SS:ESP %x:%x\n",ss0,esp0);
311 stack=(unsigned int *)(esp0);
312
313 DbgPrint("Stack:\n");
314 for (i=0; i<16; i++)
315 {
316 if (MmIsPagePresent(NULL,&stack[i]))
317 {
318 DbgPrint("%.8x ",stack[i]);
319 if (((i+1)%4) == 0)
320 {
321 DbgPrint("\n");
322 }
323 }
324 }
325 }
326
327 DbgPrint("\n");
328 DbgPrint("Killing current task\n");
329 // for(;;);
330 KeLowerIrql(PASSIVE_LEVEL);
331 if ((cs&0xffff) == USER_CS)
332 {
333 ZwTerminateProcess(NtCurrentProcess(),
334 STATUS_NONCONTINUABLE_EXCEPTION);
335 }
336
337 for(;;);
338 }
339
340 VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames)
341 {
342 PULONG Stack = (PULONG)_Stack;
343 ULONG i;
344
345 Stack = (PVOID)(((ULONG)Stack) & (~0x3));
346 DbgPrint("Stack: %x\n", Stack);
347
348 DbgPrint("Frames:\n");
349 for (i=0; i<NrFrames; i++)
350 {
351 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
352 if (Stack[i] > KERNEL_BASE)
353 {
354 // DbgPrint("%.8x ",Stack[i]);
355 print_address((PVOID)Stack[i]);
356 DbgPrint(" ");
357 }
358 if (Stack[i] == 0xceafbeef)
359 {
360 DbgPrint("IRQ ");
361 }
362 }
363 DbgPrint("\n");
364 }
365
366 static void set_system_call_gate(unsigned int sel, unsigned int func)
367 {
368 DPRINT("sel %x %d\n",sel,sel);
369 KiIdt[sel].a = (((int)func)&0xffff) +
370 (KERNEL_CS << 16);
371 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
372 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
373 }
374
375 static void set_interrupt_gate(unsigned int sel, unsigned int func)
376 {
377 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
378 KiIdt[sel].a = (((int)func)&0xffff) +
379 (KERNEL_CS << 16);
380 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
381 }
382
383 asmlinkage unsigned int ExHookException(exception_hook fn, unsigned int exp)
384 /*
385 * FUNCTION: Hook an exception
386 */
387 {
388 if (exp>=256)
389 {
390 return(1);
391 }
392 exception_hooks[exp]=fn;
393 return(0);
394 }
395
396 asmlinkage void KeInitExceptions(void)
397 /*
398 * FUNCTION: Initalize CPU exception handling
399 */
400 {
401 int i;
402
403 DPRINT("KeInitExceptions()\n",0);
404
405 set_interrupt_gate(0,(int)exception_handler0);
406 set_interrupt_gate(1,(int)exception_handler1);
407 set_interrupt_gate(2,(int)exception_handler2);
408 set_interrupt_gate(3,(int)exception_handler3);
409 set_interrupt_gate(4,(int)exception_handler4);
410 set_interrupt_gate(5,(int)exception_handler5);
411 set_interrupt_gate(6,(int)exception_handler6);
412 set_interrupt_gate(7,(int)exception_handler7);
413 set_interrupt_gate(8,(int)exception_handler8);
414 set_interrupt_gate(9,(int)exception_handler9);
415 set_interrupt_gate(10,(int)exception_handler10);
416 set_interrupt_gate(11,(int)exception_handler11);
417 set_interrupt_gate(12,(int)exception_handler12);
418 set_interrupt_gate(13,(int)exception_handler13);
419 set_interrupt_gate(14,(int)exception_handler14);
420 set_interrupt_gate(15,(int)exception_handler15);
421 set_interrupt_gate(16,(int)exception_handler16);
422
423 for (i=17;i<256;i++)
424 {
425 set_interrupt_gate(i,(int)exception_handler_unknown);
426 }
427
428 set_system_call_gate(0x2e,(int)interrupt_handler2e);
429 }