Fixed reference counting of page tables
[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 #include <internal/ps.h>
21 #include <internal/trap.h>
22
23 #define NDEBUG
24 #include <internal/debug.h>
25
26 /* GLOBALS *****************************************************************/
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 void exception_handler0(void);
35 extern void exception_handler1(void);
36 extern void exception_handler2(void);
37 extern void exception_handler3(void);
38 extern void exception_handler4(void);
39 extern void exception_handler5(void);
40 extern void exception_handler6(void);
41 extern void exception_handler7(void);
42 extern void exception_handler8(void);
43 extern void exception_handler9(void);
44 extern void exception_handler10(void);
45 extern void exception_handler11(void);
46 extern void exception_handler12(void);
47 extern void exception_handler13(void);
48 extern void exception_handler14(void);
49 extern void exception_handler15(void);
50 extern void exception_handler16(void);
51 extern void exception_handler_unknown(void);
52
53 extern ULONG init_stack;
54 extern ULONG init_stack_top;
55
56 /* FUNCTIONS ****************************************************************/
57
58 extern unsigned int _text_start__, _text_end__;
59
60 STATIC BOOLEAN
61 print_address(PVOID address)
62 {
63 PLIST_ENTRY current_entry;
64 PMODULE_OBJECT current;
65 extern LIST_ENTRY ModuleListHead;
66
67 current_entry = ModuleListHead.Flink;
68
69 while (current_entry != &ModuleListHead &&
70 current_entry != NULL)
71 {
72 current = CONTAINING_RECORD(current_entry, MODULE_OBJECT, ListEntry);
73
74 if (address >= current->Base &&
75 address < (current->Base + current->Length))
76 {
77 DbgPrint("<%wZ: %x>", &current->Name,
78 address - current->Base);
79 return(TRUE);
80 }
81
82 current_entry = current_entry->Flink;
83 }
84 #if 0
85 DbgPrint("<%x>", address);
86 #endif
87 return(FALSE);
88 }
89
90 ULONG
91 exception_handler(struct trap_frame* tf)
92 /*
93 * FUNCTION: Called by the lowlevel execption handlers to print an amusing
94 * message and halt the computer
95 * ARGUMENTS:
96 * Complete CPU context
97 */
98 {
99 unsigned int cr2, cr3;
100 unsigned int i;
101 // unsigned int j, sym;
102 PULONG stack;
103 NTSTATUS Status;
104 static char *TypeStrings[] =
105 {
106 "Divide Error",
107 "Debug Trap",
108 "NMI",
109 "Breakpoint",
110 "Overflow",
111 "BOUND range exceeded",
112 "Invalid Opcode",
113 "No Math Coprocessor",
114 "Double Fault",
115 "Unknown(9)",
116 "Invalid TSS",
117 "Segment Not Present",
118 "Stack Segment Fault",
119 "General Protection",
120 "Page Fault",
121 "Math Fault",
122 "Alignment Check",
123 "Machine Check"
124 };
125
126 __asm__("movl %%cr2,%0\n\t"
127 : "=d" (cr2));
128
129 if (tf->eflags & (1 << 17))
130 {
131 return(KeV86Exception(tf, cr2));
132 }
133
134 if (PsGetCurrentThread() != NULL &&
135 tf->esp < (ULONG)PsGetCurrentThread()->Tcb.StackLimit)
136 {
137 DbgPrint("Stack underflow (tf->esp %x Limit %x)\n",
138 tf->esp, (ULONG)PsGetCurrentThread()->Tcb.StackLimit);
139 tf->type = 12;
140 }
141
142 if (tf->type == 14)
143 {
144 __asm__("sti\n\t");
145 Status = MmPageFault(tf->cs&0xffff,
146 &tf->eip,
147 &tf->eax,
148 cr2,
149 tf->error_code);
150 if (NT_SUCCESS(Status))
151 {
152 return(0);
153 }
154 }
155
156 /*
157 * FIXME: Something better
158 */
159 if (tf->type==1)
160 {
161 DbgPrint("Trap at CS:EIP %x:%x\n",tf->cs&0xffff,tf->eip);
162 return(0);
163 }
164
165 /*
166 * Print out the CPU registers
167 */
168 if (tf->type < 19)
169 {
170 DbgPrint("%s Exception: %d(%x)\n",TypeStrings[tf->type],tf->type,
171 tf->error_code&0xffff);
172 }
173 else
174 {
175 DbgPrint("Exception: %d(%x)\n",tf->type,tf->error_code&0xffff);
176 }
177 DbgPrint("CS:EIP %x:%x ",tf->cs&0xffff,tf->eip);
178 print_address((PVOID)tf->eip);
179 DbgPrint("\n");
180 __asm__("movl %%cr3,%0\n\t"
181 : "=d" (cr3));
182 DbgPrint("cr2 %x cr3 %x ",cr2,cr3);
183 // for(;;);
184 DbgPrint("Proc: %x ",PsGetCurrentProcess());
185 if (PsGetCurrentProcess() != NULL)
186 {
187 DbgPrint("Pid: %x <", PsGetCurrentProcess()->UniqueProcessId);
188 DbgPrint("%.8s> ", PsGetCurrentProcess()->ImageFileName);
189 }
190 if (PsGetCurrentThread() != NULL)
191 {
192 DbgPrint("Thrd: %x Tid: %x",
193 PsGetCurrentThread(),
194 PsGetCurrentThread()->Cid.UniqueThread);
195 }
196 DbgPrint("\n");
197 DbgPrint("DS %x ES %x FS %x GS %x\n", tf->ds&0xffff, tf->es&0xffff,
198 tf->fs&0xffff, tf->gs&0xfff);
199 DbgPrint("EAX: %.8x EBX: %.8x ECX: %.8x\n", tf->eax, tf->ebx, tf->ecx);
200 DbgPrint("EDX: %.8x EBP: %.8x ESI: %.8x\n", tf->edx, tf->ebp, tf->esi);
201 DbgPrint("EDI: %.8x EFLAGS: %.8x ", tf->edi, tf->eflags);
202 if ((tf->cs&0xffff) == KERNEL_CS)
203 {
204 DbgPrint("kESP %.8x ", tf->esp);
205 if (PsGetCurrentThread() != NULL)
206 {
207 DbgPrint("kernel stack base %x\n",
208 PsGetCurrentThread()->Tcb.StackLimit);
209
210 }
211 }
212 else
213 {
214 DbgPrint("kernel ESP %.8x\n", tf->esp);
215 }
216 if ((tf->cs & 0xffff) == KERNEL_CS)
217 {
218 DbgPrint("ESP %x\n", tf->esp);
219 stack = (PULONG) (tf->esp + 24);
220 stack = (PULONG)(((ULONG)stack) & (~0x3));
221
222 DbgPrint("stack<%p>: ", stack);
223
224 for (i = 0; i < 18; i = i + 6)
225 {
226 DbgPrint("%.8x %.8x %.8x %.8x\n",
227 stack[i], stack[i+1],
228 stack[i+2], stack[i+3],
229 stack[i+4], stack[i+5]);
230 }
231 DbgPrint("Frames:\n");
232 for (i = 0; i < 32; i++)
233 {
234 if (stack[i] > ((unsigned int) &_text_start__) &&
235 !(stack[i] >= ((ULONG)&init_stack) &&
236 stack[i] <= ((ULONG)&init_stack_top)))
237 {
238 // DbgPrint(" %.8x", stack[i]);
239 print_address((PVOID)stack[i]);
240 DbgPrint(" ");
241 }
242 }
243 }
244 else
245 {
246 #if 1
247 DbgPrint("SS:ESP %x:%x\n", tf->ss0, tf->esp0);
248 stack=(PULONG)(tf->esp0);
249
250 DbgPrint("Stack:\n");
251 for (i=0; i<64; i++)
252 {
253 if (MmIsPagePresent(NULL,&stack[i]))
254 {
255 DbgPrint("%.8x ",stack[i]);
256 if (((i+1)%8) == 0)
257 {
258 DbgPrint("\n");
259 }
260 }
261 }
262
263 if (MmIsPagePresent(NULL, (PVOID)tf->eip))
264 {
265 unsigned char instrs[512];
266
267 memcpy(instrs, (PVOID)tf->eip, 512);
268
269 DbgPrint("Instrs: ");
270
271 for (i=0; i<10; i++)
272 {
273 DbgPrint("%x ", instrs[i]);
274 }
275 }
276 #endif
277 }
278
279 DbgPrint("\n");
280 if ((tf->cs&0xffff) == USER_CS &&
281 tf->eip < KERNEL_BASE)
282 {
283 DbgPrint("Killing current task\n");
284 // for(;;);
285 KeLowerIrql(PASSIVE_LEVEL);
286 if ((tf->cs&0xffff) == USER_CS)
287 {
288 ZwTerminateProcess(NtCurrentProcess(),
289 STATUS_NONCONTINUABLE_EXCEPTION);
290 }
291 }
292 for(;;);
293 }
294
295 VOID KeDumpStackFrames(PVOID _Stack, ULONG NrFrames)
296 {
297 PULONG Stack = (PULONG)_Stack;
298 ULONG i;
299
300 Stack = (PVOID)(((ULONG)Stack) & (~0x3));
301 DbgPrint("Stack: %x\n", Stack);
302 if (PsGetCurrentThread() != NULL)
303 {
304 DbgPrint("kernel stack base %x\n",
305 PsGetCurrentThread()->Tcb.StackLimit);
306 }
307
308 DbgPrint("Frames:\n");
309 for (i=0; i<NrFrames; i++)
310 {
311 // if (Stack[i] > KERNEL_BASE && Stack[i] < ((ULONG)&etext))
312 if (Stack[i] > KERNEL_BASE)
313 {
314 // DbgPrint("%.8x ",Stack[i]);
315 print_address((PVOID)Stack[i]);
316 DbgPrint(" ");
317 }
318 if (Stack[i] == 0xceafbeef)
319 {
320 DbgPrint("IRQ ");
321 }
322 }
323 DbgPrint("\n");
324 }
325
326 static void set_system_call_gate(unsigned int sel, unsigned int func)
327 {
328 DPRINT("sel %x %d\n",sel,sel);
329 KiIdt[sel].a = (((int)func)&0xffff) +
330 (KERNEL_CS << 16);
331 KiIdt[sel].b = 0xef00 + (((int)func)&0xffff0000);
332 DPRINT("idt[sel].b %x\n",KiIdt[sel].b);
333 }
334
335 static void set_interrupt_gate(unsigned int sel, unsigned int func)
336 {
337 DPRINT("set_interrupt_gate(sel %d, func %x)\n",sel,func);
338 KiIdt[sel].a = (((int)func)&0xffff) +
339 (KERNEL_CS << 16);
340 KiIdt[sel].b = 0x8f00 + (((int)func)&0xffff0000);
341 }
342
343 void KeInitExceptions(void)
344 /*
345 * FUNCTION: Initalize CPU exception handling
346 */
347 {
348 int i;
349
350 DPRINT("KeInitExceptions()\n",0);
351
352 set_interrupt_gate(0,(int)exception_handler0);
353 set_interrupt_gate(1,(int)exception_handler1);
354 set_interrupt_gate(2,(int)exception_handler2);
355 set_interrupt_gate(3,(int)exception_handler3);
356 set_interrupt_gate(4,(int)exception_handler4);
357 set_interrupt_gate(5,(int)exception_handler5);
358 set_interrupt_gate(6,(int)exception_handler6);
359 set_interrupt_gate(7,(int)exception_handler7);
360 set_interrupt_gate(8,(int)exception_handler8);
361 set_interrupt_gate(9,(int)exception_handler9);
362 set_interrupt_gate(10,(int)exception_handler10);
363 set_interrupt_gate(11,(int)exception_handler11);
364 set_interrupt_gate(12,(int)exception_handler12);
365 set_interrupt_gate(13,(int)exception_handler13);
366 set_interrupt_gate(14,(int)exception_handler14);
367 set_interrupt_gate(15,(int)exception_handler15);
368 set_interrupt_gate(16,(int)exception_handler16);
369
370 for (i=17;i<256;i++)
371 {
372 set_interrupt_gate(i,(int)exception_handler_unknown);
373 }
374
375 set_system_call_gate(0x2d,(int)interrupt_handler2d);
376 set_system_call_gate(0x2e,(int)interrupt_handler2e);
377 }