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