- Fix compile issues caused by previous patch.
[reactos.git] / reactos / ntoskrnl / mm / i386 / pfault.c
1 /* $Id$
2 *
3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS kernel
5 * FILE: ntoskrnl/mm/i386/pfault.c
6 * PURPOSE: Paging file functions
7 *
8 * PROGRAMMERS: David Welch (welch@mcmail.com)
9 */
10
11 /* INCLUDES *****************************************************************/
12
13 #include <ntoskrnl.h>
14 #define NDEBUG
15 #include <internal/debug.h>
16
17 /* EXTERNS *******************************************************************/
18
19 extern VOID MmSafeReadPtrStart(VOID);
20 extern VOID MmSafeReadPtrEnd(VOID);
21
22
23 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
24 extern ULONG KiKernelTrapHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr, PVOID Cr2);
25
26 extern BOOLEAN Ke386NoExecute;
27
28 /* FUNCTIONS *****************************************************************/
29
30 ULONG KiPageFaultHandler(PKTRAP_FRAME Tf, ULONG ExceptionNr)
31 {
32 ULONG_PTR cr2;
33 NTSTATUS Status;
34 KPROCESSOR_MODE Mode;
35
36 ASSERT(ExceptionNr == 14);
37
38 /* Store the exception number in an unused field in the trap frame. */
39 Tf->DbgArgMark = 14;
40
41 /* get the faulting address */
42 cr2 = Ke386GetCr2();
43 Tf->DbgArgPointer = cr2;
44
45 /* it's safe to enable interrupts after cr2 has been saved */
46 if (Tf->EFlags & (X86_EFLAGS_VM|X86_EFLAGS_IF))
47 {
48 Ke386EnableInterrupts();
49 }
50
51 if (cr2 >= (ULONG_PTR)MmSystemRangeStart)
52 {
53 /* check for an invalid page directory in kernel mode */
54 if (!(Tf->ErrCode & 0x5) && Mmi386MakeKernelPageTableGlobal((PVOID)cr2))
55 {
56 return 0;
57 }
58
59 /* check for non executable memory in kernel mode */
60 if (Ke386NoExecute && Tf->ErrCode & 0x10)
61 {
62 KEBUGCHECKWITHTF(ATTEMPTED_EXECUTE_OF_NOEXECUTE_MEMORY, 0, 0, 0, 0, Tf);
63 }
64 }
65
66 Mode = Tf->ErrCode & 0x4 ? UserMode : KernelMode;
67
68 /* handle the fault */
69 if (Tf->ErrCode & 0x1)
70 {
71 Status = MmAccessFault(Mode, cr2, FALSE);
72 }
73 else
74 {
75 Status = MmNotPresentFault(Mode, cr2, FALSE);
76 }
77
78 /* handle the return for v86 mode */
79 if (Tf->EFlags & X86_EFLAGS_VM)
80 {
81 if (!NT_SUCCESS(Status))
82 {
83 /* FIXME: This should use ->VdmObjects */
84 if(!KeGetCurrentProcess()->Unused)
85 {
86 *((PKV86M_TRAP_FRAME)Tf)->regs->PStatus = STATUS_NONCONTINUABLE_EXCEPTION;
87 }
88 return 1;
89 }
90 return 0;
91 }
92
93 if (Mode == KernelMode)
94 {
95 if (!NT_SUCCESS(Status))
96 {
97 if (Tf->Eip >= (ULONG_PTR)MmSafeReadPtrStart &&
98 Tf->Eip < (ULONG_PTR)MmSafeReadPtrEnd)
99 {
100 Tf->Eip = (ULONG_PTR)MmSafeReadPtrEnd;
101 Tf->Eax = 0;
102 return 0;
103 }
104 }
105 }
106 else
107 {
108 if (KeGetCurrentThread()->ApcState.UserApcPending)
109 {
110 KIRQL oldIrql;
111
112 KeRaiseIrql(APC_LEVEL, &oldIrql);
113 KiDeliverApc(UserMode, NULL, NULL);
114 KeLowerIrql(oldIrql);
115 }
116 }
117
118 if (NT_SUCCESS(Status))
119 {
120 return 0;
121 }
122
123 /*
124 * Handle user exceptions differently
125 */
126 if (Mode == KernelMode)
127 {
128 return(KiKernelTrapHandler(Tf, 14, (PVOID)cr2));
129 }
130 else
131 {
132 return(KiUserTrapHandler(Tf, 14, (PVOID)cr2));
133 }
134 }
135