Began converting minix fsd to work with new caching mechanism
[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 {
145 current = CONTAINING_RECORD(current_entry, MODULE_OBJECT, ListEntry);
146
147 if (address >= current->Base &&
148 address < (current->Base + current->Length))
149 {
150 DbgPrint("<%w: %x>\n", current->Name,
151 address - current->Base);
152 return;
153 }
154
155 current_entry = current_entry->Flink;
156 }
157 DbgPrint("<%x>\n", address);
158 }
159
160 asmlinkage void exception_handler(unsigned int edi,
161 unsigned int esi, unsigned int ebp,
162 unsigned int esp, unsigned int ebx,
163 unsigned int edx, unsigned int ecx,
164 unsigned int eax,
165 unsigned int type,
166 unsigned int ds,
167 unsigned int es,
168 unsigned int fs,
169 unsigned int gs,
170 unsigned int error_code,
171 unsigned int eip,
172 unsigned int cs, unsigned int eflags,
173 unsigned int esp0, unsigned int ss0)
174 /*
175 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
176 * message and halt the computer
177 * ARGUMENTS:
178 * Complete CPU context
179 */
180 {
181 unsigned int cr2, cr3;
182 unsigned int i;
183 // unsigned int j, sym;
184 unsigned int* stack;
185 static char *TypeStrings[] =
186 {
187 "Divide Error",
188 "Debug Trap",
189 "Unknown(2)",
190 "Breakpoint",
191 "Overflow",
192 "BOUND range exceeded",
193 "Invalid Opcode",
194 "No Math Coprocessor",
195 "Double Fault",
196 "Unknown(9)",
197 "Invalid TSS",
198 "Segment Not Present",
199 "Stack Segment Fault",
200 "General Protection",
201 "Page Fault",
202 "Math Fault",
203 "Alignment Check",
204 "Machine Check"
205 };
206
207 __asm__("cli\n\t");
208
209 if (type==14)
210 {
211 if (page_fault_handler(cs&0xffff,eip))
212 {
213 return;
214 }
215 }
216 if (type==1)
217 {
218 DbgPrint("Trap at CS:EIP %x:%x\n",cs&0xffff,eip);
219 return;
220 }
221
222 /*
223 * Activate any hook for the exception
224 */
225 if (exception_hooks[type]!=NULL)
226 {
227 exception_hooks[type](NULL,type);
228 }
229
230 /*
231 * Print out the CPU registers
232 */
233 if (type < 19)
234 {
235 DbgPrint("%s Exception: %d(%x)\n",TypeStrings[type],type,
236 error_code&0xffff);
237 }
238 else
239 {
240 DbgPrint("Exception: %d(%x)\n",type,error_code&0xffff);
241 }
242 DbgPrint("CS:EIP %x:%x\n",cs&0xffff,eip);
243 DbgPrint("CS:EIP %x");
244 print_address(eip);
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(stack[i]);
304 }
305 }
306 }
307 else
308 {
309 DbgPrint("SS:ESP %x:%x\n",ss0,esp0);
310 stack=(unsigned int *)(esp0);
311
312 DbgPrint("Stack:\n");
313 for (i=0; i<16; i++)
314 {
315 if (MmIsPagePresent(NULL,&stack[i]))
316 {
317 DbgPrint("%.8x ",stack[i]);
318 if (((i+1)%4) == 0)
319 {
320 DbgPrint("\n");
321 }
322 }
323 }
324 }
325
326 DPRINT1("Killing current task\n");
327 for(;;);
328 KeLowerIrql(PASSIVE_LEVEL);
329 if ((cs&0xffff) == USER_CS)
330 {
331 ZwTerminateProcess(NtCurrentProcess(),
332 STATUS_NONCONTINUABLE_EXCEPTION);
333 }
334
335 for(;;);
336 }
337
338 VOID KeDumpStackFrames(ULONG DummyArg, ULONG NrFrames)
339 {
340 PULONG Stack = &((&DummyArg)[-1]);
341 ULONG i;
342
343 Stack = (PVOID)(((ULONG)Stack) & (~0x3));
344
345 DbgPrint("Frames:\n");
346 for (i=0; i<NrFrames; i++)
347 {
348 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
349 if (Stack[i] > KERNEL_BASE)
350 {
351 DbgPrint("%.8x ",Stack[i]);
352 }
353 if (Stack[i] == 0xceafbeef)
354 {
355 DbgPrint("IRQ ");
356 }
357 }
358 DbgPrint("\n");
359 }
360
361 static void set_system_call_gate(unsigned int sel, unsigned int func)
362 {
363 DPRINT("sel %x %d\n",sel,sel);
364 KiIdt[sel].a = (((int)func)&0xffff) +
365 (KERNEL_CS << 16);
366 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
367 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
368 }
369
370 static void set_interrupt_gate(unsigned int sel, unsigned int func)
371 {
372 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
373 KiIdt[sel].a = (((int)func)&0xffff) +
374 (KERNEL_CS << 16);
375 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
376 }
377
378 asmlinkage unsigned int ExHookException(exception_hook fn, unsigned int exp)
379 /*
380 * FUNCTION: Hook an exception
381 */
382 {
383 if (exp>=256)
384 {
385 return(1);
386 }
387 exception_hooks[exp]=fn;
388 return(0);
389 }
390
391 asmlinkage void KeInitExceptions(void)
392 /*
393 * FUNCTION: Initalize CPU exception handling
394 */
395 {
396 int i;
397
398 DPRINT("KeInitExceptions()\n",0);
399
400 set_interrupt_gate(0,(int)exception_handler0);
401 set_interrupt_gate(1,(int)exception_handler1);
402 set_interrupt_gate(2,(int)exception_handler2);
403 set_interrupt_gate(3,(int)exception_handler3);
404 set_interrupt_gate(4,(int)exception_handler4);
405 set_interrupt_gate(5,(int)exception_handler5);
406 set_interrupt_gate(6,(int)exception_handler6);
407 set_interrupt_gate(7,(int)exception_handler7);
408 set_interrupt_gate(8,(int)exception_handler8);
409 set_interrupt_gate(9,(int)exception_handler9);
410 set_interrupt_gate(10,(int)exception_handler10);
411 set_interrupt_gate(11,(int)exception_handler11);
412 set_interrupt_gate(12,(int)exception_handler12);
413 set_interrupt_gate(13,(int)exception_handler13);
414 set_interrupt_gate(14,(int)exception_handler14);
415 set_interrupt_gate(15,(int)exception_handler15);
416 set_interrupt_gate(16,(int)exception_handler16);
417
418 for (i=17;i<256;i++)
419 {
420 set_interrupt_gate(i,(int)exception_handler_unknown);
421 }
422
423 set_system_call_gate(0x2e,(int)interrupt_handler2e);
424 }