scroll mode for very long start menus
[reactos.git] / reactos / apps / utils / pice / module / pgflt.c
1 /*++
2
3 Copyright (c) 1998-2001 Klaus P. Gerlicher
4
5 Module Name:
6
7 pgflt.c
8
9 Abstract:
10
11 page fault handling on x86
12
13 Environment:
14
15 Kernel mode only
16
17 Author:
18
19 Klaus P. Gerlicher
20
21 Revision History:
22
23 25-Nov-1999: created
24 15-Nov-2000: general cleanup of source files
25
26 Copyright notice:
27
28 This file may be distributed under the terms of the GNU Public License.
29
30 --*/
31
32 ////////////////////////////////////////////////////
33 // INCLUDES
34 ////
35 #include "remods.h"
36
37 #include "precomp.h"
38
39 ////////////////////////////////////////////////////
40 // GLOBALS
41 ////
42
43 char tempPageFault[1024];
44 extern void NewInt31Handler(void);
45
46 ULONG OldIntEHandler=0;
47 ULONG error_code;
48 BOOLEAN bInPageFaultHandler = FALSE;
49 static ULONG PCR_SEL = PCR_SELECTOR;
50 static ULONG OLD_PCR;
51
52 ////////////////////////////////////////////////////
53 // FUNCTIONS
54 ////
55
56 //*************************************************************************
57 // HandleInDebuggerFault()
58 //
59 //*************************************************************************
60 ULONG HandleInDebuggerFault(FRAME* ptr,ULONG address)
61 {
62 PEPROCESS tsk;
63
64 ENTER_FUNC();
65
66 DPRINT((0,"HandleInDebuggerFault(): ###### page fault @ %.8X while inside debugger, eip: %x\n",address, ptr->eip));
67
68 // fault in this page fault handler
69 if(bInPageFaultHandler)
70 {
71 DPRINT((0,"HandleInDebuggerFault(): ###### page fault @ %.8X while in page fault handler\n",address));
72
73 DPRINT((0,"!!! machine is halted !!!\n"));
74 __asm__ __volatile__ ("hlt");
75
76 LEAVE_FUNC();
77 return 0;
78 }
79
80 bInPageFaultHandler = TRUE;
81
82 // when we come here from DebuggerShell() we live on a different stack
83 // so the current task is different as well
84 tsk = IoGetCurrentProcess();
85
86 DPRINT((0,"%.8X (%.4X:%.8X %.8X %s %s %s task=%.8X )\n",
87 address,
88 ptr->cs,
89 ptr->eip,
90 ptr->eflags,
91 (ptr->error_code&1)?"PLP":"NP",
92 (ptr->error_code&2)?"WRITE":"READ",
93 (ptr->error_code&4)?"USER-MODE":"KERNEL-MODE",
94 (ULONG)tsk));
95
96 if(!bInPrintk)
97 {
98 DPRINT((0,"HandleInDebuggerFault(): unexpected pagefault in command handler!\n",address));
99 }
100 else
101 {
102 DPRINT((0,"HandleInDebuggerFault(): unexpected pagefault in command handler while in PrintkCallback()!\n",address));
103 }
104
105 if(tsk)
106 {
107 PULONG pPGD;
108 PULONG pPTE;
109
110 pPGD = ADDR_TO_PDE(address);
111
112 DPRINT((0,"PGD for %.8X @ %.8X = %.8X\n",address,(ULONG)pPGD,(ULONG)(*pPGD) ));
113
114 if(pPGD && (*pPGD)&_PAGE_PRESENT)
115 {
116 // not large page
117 if(!((*pPGD)&_PAGE_4M))
118 {
119 pPTE = ADDR_TO_PTE(address);
120 if(pPTE)
121 {
122 DPRINT((0,"PTE for %.8X @ %.8X = %.8X\n",address,(ULONG)pPTE,(ULONG)(*pPTE) ));
123 }
124 }
125 }
126 }
127
128 IntelStackWalk(ptr->eip,CurrentEBP,ulRealStackPtr);
129
130 DPRINT((0,"!!! machine is halted !!!\n"));
131 __asm__ __volatile__ ("hlt");
132
133 LEAVE_FUNC();
134
135 return 2;
136 }
137
138 //*************************************************************************
139 // HandlePageFault()
140 //
141 // returns:
142 // 0 = let the system handle it
143 // 1 = call DebuggerShell()
144 // 2 = FATAL error inside debugger
145 //*************************************************************************
146 ULONG HandlePageFault(FRAME* ptr)
147 {
148 PVOID address;
149 PEPROCESS tsk, tsk1;
150 PMADDRESS_SPACE vma;
151 PLIST_ENTRY current_entry;
152 MEMORY_AREA* current;
153 ULONG value;
154 PKTHREAD CurrentThread;
155 PETHREAD CurrentEThread;
156
157 // get linear address of page fault
158 __asm__ __volatile__("movl %%cr2,%0"
159 :"=r" (address));
160
161 DPRINT((0,"\nPageFault: bInDebShell: %d, error: %d, addr: %x\n", bInDebuggerShell, ptr->error_code, address));
162
163 // there's something terribly wrong if we get a fault in our command handler
164 if(bInDebuggerShell)
165 {
166 DPRINT((0,"return handleindebuggerfault\n"));
167 return HandleInDebuggerFault(ptr,(ULONG)address);
168 }
169
170 ASSERT(IsAddressValid((ULONG)ptr));
171 // remember error code so we can push it back on the stack
172 error_code = ptr->error_code;
173
174 //ei Check IRQL here!!!
175 /*
176 if(in_interrupt())
177 {
178 Print(OUTPUT_WINDOW,"pICE: system is currently processing an interrupt!\n");
179 return 1;
180 }
181 */
182 // current process
183 tsk = IoGetCurrentProcess();
184 DPRINT((0,"tsk: %x\t", tsk));
185 if( !tsk || !(IsAddressValid((ULONG)tsk))){
186 DPRINT((0,"tsk address not valid: tsk: %x\n", tsk));
187 return 0;
188 }
189
190 // lookup VMA for this address
191 if( (ULONG)address > KERNEL_BASE )
192 vma = my_init_mm; // use kernel mem area for kernel addresses
193 else vma = &(tsk->AddressSpace); // otherwise, use user memory area
194
195 if( !vma ){
196 DPRINT((0,"vma not valid: vma: %x\n", vma));
197 return 0;
198 }
199
200 current_entry = vma->MAreaListHead.Flink;
201 ASSERT(current_entry);
202 DPRINT((0,"vma: %x, current_entry: %x, kernel arena: %x\n", vma, current_entry, my_init_mm));
203 while(current_entry != &vma->MAreaListHead)
204 {
205 ASSERT(current_entry);
206 ASSERT(IsAddressValid((ULONG)current_entry));
207 current = CONTAINING_RECORD(current_entry,
208 MEMORY_AREA,
209 Entry);
210
211
212 if( (address >= current->BaseAddress) && (address <= current->BaseAddress + current->Length ))
213 {
214 DPRINT((0,"address: %x %x - %x Attrib: %x, Type: %x\n", address, current->BaseAddress, current->BaseAddress + current->Length, current->Attributes, current->Type));
215 //page not present
216 if( !(error_code & 1) ){
217 //check it is in pageable area
218 if( current->Type == MEMORY_AREA_SECTION_VIEW ||
219 current->Type == MEMORY_AREA_VIRTUAL_MEMORY ||
220 current->Type == MEMORY_AREA_PAGED_POOL ||
221 current->Type == MEMORY_AREA_SHARED_DATA
222 ){
223 //ei too much output Print(OUTPUT_WINDOW,"pICE: VMA Pageable Section.\n");
224 //ei DPRINT((0,"return 0 1\n"));
225 return 0; //let the system handle this
226 }
227 Print(OUTPUT_WINDOW,"pICE: VMA Page not present in non-pageable Section!\n");
228 //ei DPRINT((0,"Type: currenttype: %x return 1 2\n", current->Type));
229 return 0;
230 }
231 else{ //access violation
232
233 if( error_code & 4 )
234 { //user mode
235 if( (ULONG)address >= KERNEL_BASE )
236 {
237 Print(OUTPUT_WINDOW,"pICE: User mode program trying to access kernel memory!\n");
238 //DPRINT((0,"return 0 3\n"));
239 return 1;
240 }
241 //DPRINT((0,"return 0 4\n"));
242 return 0;
243 }
244 /*
245 if(error_code & 2)
246 {
247 //on write
248 if(!(current->Attributes & PAGE_READONLY))
249 {
250 Print(OUTPUT_WINDOW,"pICE: virtual memory arena is not writeable!\n");
251 return 1;
252 }
253 }
254 // READ ACCESS
255 else
256 {
257 // test EXT bit in error code
258 if (error_code & 1)
259 {
260 Print(OUTPUT_WINDOW,"pICE: page-level protection fault!\n");
261 return 1;
262 }
263 //
264 */
265 /*
266 if (!(current->Attributes & PAGE_EXECUTE_READ))
267 {
268 Print(OUTPUT_WINDOW,"pICE: VMA is not readable!\n");
269 return 1;
270 }
271 */
272
273 // let the system handle it
274 //DPRINT((0,"return 0 5\n"));
275 return 0;
276 }
277 }
278 current_entry = current_entry->Flink;
279 }
280
281 Print(OUTPUT_WINDOW,"pICE: no virtual memory arena at this address!\n");
282 DPRINT((0,"return 0 6\n"));
283 return 1;
284
285 // let the system handle it
286 // return 0;
287 }
288
289 //*************************************************************************
290 // NewIntEHandler()
291 //
292 //*************************************************************************
293 __asm__ ("\n\t \
294 NewIntEHandler:\n\t \
295 pushfl\n\t \
296 cli\n\t \
297 cld\n\t \
298 pushal\n\t \
299 pushl %ds\n\t \
300 \n\t \
301 // setup default data selectors\n\t \
302 movw %ss,%ax\n\t \
303 movw %ax,%ds\n\t \
304 \n\t \
305 /*\n\t \
306 * Load the PCR selector.\n\t \
307 */\n\t \
308 movl %fs, %eax\n\t \
309 movl %eax, _OLD_PCR\n\t \
310 movl _PCR_SEL, %eax\n\t \
311 movl %eax, %fs\n\t \
312 \n\t \
313 // get frame ptr\n\t \
314 lea 40(%esp),%eax\n\t \
315 pushl %eax\n\t \
316 call _HandlePageFault\n\t \
317 addl $4,%esp\n\t \
318 \n\t \
319 pushl %eax\n\t \
320 movl _OLD_PCR, %eax\n\t \
321 movl %eax, %fs\n\t \
322 popl %eax\n\t \
323 \n\t \
324 cmpl $0,%eax\n\t \
325 je call_old_inte_handler\n\t \
326 \n\t \
327 cmpl $2,%eax\n\t \
328 je call_handler_unknown_reason\n\t \
329 \n\t \
330 popl %ds\n\t \
331 popal\n\t \
332 popfl\n\t \
333 // remove error code. will be restored later when we call\n\t \
334 // original handler again.\n\t \
335 addl $4,%esp\n\t \
336 // call debugger loop\n\t \
337 pushl $" STR(REASON_PAGEFAULT) "\n\t \
338 jmp NewInt31Handler\n\t \
339 \n\t \
340 call_old_inte_handler:\n\t \
341 popl %ds\n\t \
342 popal\n\t \
343 popfl\n\t \
344 // chain to old handler\n\t \
345 .byte 0x2e\n\t \
346 jmp *_OldIntEHandler\n\t \
347 \n\t \
348 call_handler_unknown_reason:\n\t \
349 popl %ds\n\t \
350 popal\n\t \
351 popfl\n\t \
352 // remove error code. will be restored later when we call\n\t \
353 // original handler again.\n\t \
354 addl $4,%esp\n\t \
355 // call debugger loop\n\t \
356 pushl $" STR(REASON_INTERNAL_ERROR) "\n\t \
357 jmp NewInt31Handler\n\t \
358 ");
359
360
361 //*************************************************************************
362 // InstallIntEHook()
363 //
364 //*************************************************************************
365 void InstallIntEHook(void)
366 {
367 ULONG LocalIntEHandler;
368
369 ENTER_FUNC();
370
371 MaskIrqs();
372 if(!OldIntEHandler)
373 {
374 __asm__ __volatile__("mov $NewIntEHandler,%0"
375 :"=r" (LocalIntEHandler)
376 :
377 :"eax");
378 OldIntEHandler=SetGlobalInt(0x0E,(ULONG)LocalIntEHandler);
379 }
380 UnmaskIrqs();
381 DPRINT((0,"OldIntE @ %x\n", OldIntEHandler));
382 LEAVE_FUNC();
383 }
384
385 //*************************************************************************
386 // DeInstallIntEHook()
387 //
388 //*************************************************************************
389 void DeInstallIntEHook(void)
390 {
391 ENTER_FUNC();
392
393 MaskIrqs();
394 if(OldIntEHandler)
395 {
396 SetGlobalInt(0x0E,(ULONG)OldIntEHandler);
397 OldIntEHandler=0;
398 }
399 UnmaskIrqs();
400
401 LEAVE_FUNC();
402 }