[FREELDR]
[reactos.git] / ntoskrnl / mm / mmfault.c
1 /*
2 * COPYRIGHT: See COPYING in the top directory
3 * PROJECT: ReactOS kernel
4 * FILE: ntoskrnl/mm/mmfault.c
5 * PURPOSE: Kernel memory managment functions
6 * PROGRAMMERS: David Welch (welch@cwcom.net)
7 */
8
9 /* INCLUDES *******************************************************************/
10
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14
15 #define MODULE_INVOLVED_IN_ARM3
16 #include "ARM3/miarm.h"
17
18 /* PRIVATE FUNCTIONS **********************************************************/
19
20 NTSTATUS
21 NTAPI
22 MmpAccessFault(KPROCESSOR_MODE Mode,
23 ULONG_PTR Address,
24 BOOLEAN FromMdl)
25 {
26 PMMSUPPORT AddressSpace;
27 MEMORY_AREA* MemoryArea;
28 NTSTATUS Status;
29 BOOLEAN Locked = FromMdl;
30
31 DPRINT("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
32
33 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
34 {
35 DPRINT1("Page fault at high IRQL was %d\n", KeGetCurrentIrql());
36 return(STATUS_UNSUCCESSFUL);
37 }
38
39 /*
40 * Find the memory area for the faulting address
41 */
42 if (Address >= (ULONG_PTR)MmSystemRangeStart)
43 {
44 /*
45 * Check permissions
46 */
47 if (Mode != KernelMode)
48 {
49 DPRINT1("MmAccessFault(Mode %d, Address %x)\n", Mode, Address);
50 return(STATUS_ACCESS_VIOLATION);
51 }
52 AddressSpace = MmGetKernelAddressSpace();
53 }
54 else
55 {
56 AddressSpace = &PsGetCurrentProcess()->Vm;
57 }
58
59 if (!FromMdl)
60 {
61 MmLockAddressSpace(AddressSpace);
62 }
63 do
64 {
65 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
66 if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
67 {
68 if (!FromMdl)
69 {
70 MmUnlockAddressSpace(AddressSpace);
71 }
72 return (STATUS_ACCESS_VIOLATION);
73 }
74
75 switch (MemoryArea->Type)
76 {
77 case MEMORY_AREA_SECTION_VIEW:
78 Status = MmAccessFaultSectionView(AddressSpace,
79 MemoryArea,
80 (PVOID)Address,
81 Locked);
82 break;
83
84 case MEMORY_AREA_VIRTUAL_MEMORY:
85 Status = STATUS_ACCESS_VIOLATION;
86 break;
87
88 default:
89 Status = STATUS_ACCESS_VIOLATION;
90 break;
91 }
92 }
93 while (Status == STATUS_MM_RESTART_OPERATION);
94
95 DPRINT("Completed page fault handling\n");
96 if (!FromMdl)
97 {
98 MmUnlockAddressSpace(AddressSpace);
99 }
100 return(Status);
101 }
102
103 NTSTATUS
104 NTAPI
105 MmNotPresentFault(KPROCESSOR_MODE Mode,
106 ULONG_PTR Address,
107 BOOLEAN FromMdl)
108 {
109 PMMSUPPORT AddressSpace;
110 MEMORY_AREA* MemoryArea;
111 NTSTATUS Status;
112 BOOLEAN Locked = FromMdl;
113
114 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
115
116 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
117 {
118 DPRINT1("Page fault at high IRQL was %d, address %x\n", KeGetCurrentIrql(), Address);
119 return(STATUS_UNSUCCESSFUL);
120 }
121
122 /*
123 * Find the memory area for the faulting address
124 */
125 if (Address >= (ULONG_PTR)MmSystemRangeStart)
126 {
127 /*
128 * Check permissions
129 */
130 if (Mode != KernelMode)
131 {
132 DPRINT1("Address: %x\n", Address);
133 return(STATUS_ACCESS_VIOLATION);
134 }
135 AddressSpace = MmGetKernelAddressSpace();
136 }
137 else
138 {
139 AddressSpace = &PsGetCurrentProcess()->Vm;
140 }
141
142 if (!FromMdl)
143 {
144 MmLockAddressSpace(AddressSpace);
145 }
146
147 /*
148 * Call the memory area specific fault handler
149 */
150 do
151 {
152 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
153 if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
154 {
155 if (!FromMdl)
156 {
157 MmUnlockAddressSpace(AddressSpace);
158 }
159 return (STATUS_ACCESS_VIOLATION);
160 }
161
162 switch (MemoryArea->Type)
163 {
164 case MEMORY_AREA_SECTION_VIEW:
165 Status = MmNotPresentFaultSectionView(AddressSpace,
166 MemoryArea,
167 (PVOID)Address,
168 Locked);
169 break;
170
171 case MEMORY_AREA_VIRTUAL_MEMORY:
172 Status = MmNotPresentFaultVirtualMemory(AddressSpace,
173 MemoryArea,
174 (PVOID)Address,
175 Locked);
176 break;
177
178 default:
179 Status = STATUS_ACCESS_VIOLATION;
180 break;
181 }
182 }
183 while (Status == STATUS_MM_RESTART_OPERATION);
184
185 DPRINT("Completed page fault handling\n");
186 if (!FromMdl)
187 {
188 MmUnlockAddressSpace(AddressSpace);
189 }
190 return(Status);
191 }
192
193 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
194
195 NTSTATUS
196 NTAPI
197 MmAccessFault(IN BOOLEAN StoreInstruction,
198 IN PVOID Address,
199 IN KPROCESSOR_MODE Mode,
200 IN PVOID TrapInformation)
201 {
202 PMEMORY_AREA MemoryArea = NULL;
203
204 /* Cute little hack for ROS */
205 if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
206 {
207 #ifdef _M_IX86
208 /* Check for an invalid page directory in kernel mode */
209 if (Mmi386MakeKernelPageTableGlobal(Address))
210 {
211 /* All is well with the world */
212 return STATUS_SUCCESS;
213 }
214 #endif
215 }
216
217 /* Is there a ReactOS address space yet? */
218 if (MmGetKernelAddressSpace())
219 {
220 /* Check if this is an ARM3 memory area */
221 MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address);
222 if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS))
223 {
224 /* Could this be a VAD fault from user-mode? */
225 MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address);
226 }
227 }
228
229 /* Is this an ARM3 memory area, or is there no address space yet? */
230 if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
231 (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
232 (!MmGetKernelAddressSpace()))
233 {
234 /* This is an ARM3 fault */
235 DPRINT("ARM3 fault %p\n", MemoryArea);
236 return MmArmAccessFault(StoreInstruction, Address, Mode, TrapInformation);
237 }
238
239 /* Keep same old ReactOS Behaviour */
240 if (StoreInstruction)
241 {
242 /* Call access fault */
243 return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
244 }
245 else
246 {
247 /* Call not present */
248 return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
249 }
250 }
251