[NTOS:MM] Pass page fault code to MmAccessFault
[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 #include <cache/section/newmm.h>
13 #define NDEBUG
14 #include <debug.h>
15
16 #define MODULE_INVOLVED_IN_ARM3
17 #include "ARM3/miarm.h"
18
19 /* PRIVATE FUNCTIONS **********************************************************/
20
21 NTSTATUS
22 NTAPI
23 MmpAccessFault(KPROCESSOR_MODE Mode,
24 ULONG_PTR Address,
25 BOOLEAN FromMdl)
26 {
27 PMMSUPPORT AddressSpace;
28 MEMORY_AREA* MemoryArea;
29 NTSTATUS Status;
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 %u\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 break;
82
83 case MEMORY_AREA_CACHE:
84 // This code locks for itself to keep from having to break a lock
85 // passed in.
86 if (!FromMdl)
87 MmUnlockAddressSpace(AddressSpace);
88 Status = MmAccessFaultCacheSection(Mode, Address, FromMdl);
89 if (!FromMdl)
90 MmLockAddressSpace(AddressSpace);
91 break;
92
93 default:
94 Status = STATUS_ACCESS_VIOLATION;
95 break;
96 }
97 }
98 while (Status == STATUS_MM_RESTART_OPERATION);
99
100 DPRINT("Completed page fault handling\n");
101 if (!FromMdl)
102 {
103 MmUnlockAddressSpace(AddressSpace);
104 }
105 return(Status);
106 }
107
108 NTSTATUS
109 NTAPI
110 MmNotPresentFault(KPROCESSOR_MODE Mode,
111 ULONG_PTR Address,
112 BOOLEAN FromMdl)
113 {
114 PMMSUPPORT AddressSpace;
115 MEMORY_AREA* MemoryArea;
116 NTSTATUS Status;
117
118 DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
119
120 if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
121 {
122 DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address);
123 return(STATUS_UNSUCCESSFUL);
124 }
125
126 /*
127 * Find the memory area for the faulting address
128 */
129 if (Address >= (ULONG_PTR)MmSystemRangeStart)
130 {
131 /*
132 * Check permissions
133 */
134 if (Mode != KernelMode)
135 {
136 DPRINT1("Address: %x\n", Address);
137 return(STATUS_ACCESS_VIOLATION);
138 }
139 AddressSpace = MmGetKernelAddressSpace();
140 }
141 else
142 {
143 AddressSpace = &PsGetCurrentProcess()->Vm;
144 }
145
146 if (!FromMdl)
147 {
148 MmLockAddressSpace(AddressSpace);
149 }
150
151 /*
152 * Call the memory area specific fault handler
153 */
154 do
155 {
156 MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
157 if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
158 {
159 if (!FromMdl)
160 {
161 MmUnlockAddressSpace(AddressSpace);
162 }
163 return (STATUS_ACCESS_VIOLATION);
164 }
165
166 switch (MemoryArea->Type)
167 {
168 case MEMORY_AREA_SECTION_VIEW:
169 Status = MmNotPresentFaultSectionView(AddressSpace,
170 MemoryArea,
171 (PVOID)Address,
172 FromMdl);
173 break;
174
175 case MEMORY_AREA_CACHE:
176 // This code locks for itself to keep from having to break a lock
177 // passed in.
178 if (!FromMdl)
179 MmUnlockAddressSpace(AddressSpace);
180 Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl);
181 if (!FromMdl)
182 MmLockAddressSpace(AddressSpace);
183 break;
184
185 default:
186 Status = STATUS_ACCESS_VIOLATION;
187 break;
188 }
189 }
190 while (Status == STATUS_MM_RESTART_OPERATION);
191
192 DPRINT("Completed page fault handling\n");
193 if (!FromMdl)
194 {
195 MmUnlockAddressSpace(AddressSpace);
196 }
197 return(Status);
198 }
199
200 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
201
202 NTSTATUS
203 NTAPI
204 MmAccessFault(IN ULONG FaultCode,
205 IN PVOID Address,
206 IN KPROCESSOR_MODE Mode,
207 IN PVOID TrapInformation)
208 {
209 PMEMORY_AREA MemoryArea = NULL;
210 BOOLEAN StoreInstruction = !MI_IS_NOT_PRESENT_FAULT(FaultCode);
211
212 /* Cute little hack for ROS */
213 if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
214 {
215 #ifdef _M_IX86
216 /* Check for an invalid page directory in kernel mode */
217 if (Mmi386MakeKernelPageTableGlobal(Address))
218 {
219 /* All is well with the world */
220 return STATUS_SUCCESS;
221 }
222 #endif
223 }
224
225 /* Handle shared user page, which doesn't have a VAD / MemoryArea */
226 if (PAGE_ALIGN(Address) == (PVOID)MM_SHARED_USER_DATA_VA)
227 {
228 /* This is an ARM3 fault */
229 DPRINT("ARM3 fault %p\n", MemoryArea);
230 return MmArmAccessFault(StoreInstruction, Address, Mode, TrapInformation);
231 }
232
233 /* Is there a ReactOS address space yet? */
234 if (MmGetKernelAddressSpace())
235 {
236 /* Check if this is an ARM3 memory area */
237 MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address);
238 if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS))
239 {
240 /* Could this be a VAD fault from user-mode? */
241 MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address);
242 }
243 }
244
245 /* Is this an ARM3 memory area, or is there no address space yet? */
246 if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
247 (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
248 (!MmGetKernelAddressSpace()))
249 {
250 /* This is an ARM3 fault */
251 DPRINT("ARM3 fault %p\n", MemoryArea);
252 return MmArmAccessFault(StoreInstruction, Address, Mode, TrapInformation);
253 }
254
255 /* Keep same old ReactOS Behaviour */
256 if (StoreInstruction)
257 {
258 /* Call access fault */
259 return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
260 }
261 else
262 {
263 /* Call not present */
264 return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
265 }
266 }
267