[RSHELL]
[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 BOOLEAN StoreInstruction,
205 IN PVOID Address,
206 IN KPROCESSOR_MODE Mode,
207 IN PVOID TrapInformation)
208 {
209 PMEMORY_AREA MemoryArea = NULL;
210
211 /* Cute little hack for ROS */
212 if ((ULONG_PTR)Address >= (ULONG_PTR)MmSystemRangeStart)
213 {
214 #ifdef _M_IX86
215 /* Check for an invalid page directory in kernel mode */
216 if (Mmi386MakeKernelPageTableGlobal(Address))
217 {
218 /* All is well with the world */
219 return STATUS_SUCCESS;
220 }
221 #endif
222 }
223
224 /* Is there a ReactOS address space yet? */
225 if (MmGetKernelAddressSpace())
226 {
227 /* Check if this is an ARM3 memory area */
228 MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address);
229 if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS))
230 {
231 /* Could this be a VAD fault from user-mode? */
232 MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address);
233 }
234 }
235
236 /* Is this an ARM3 memory area, or is there no address space yet? */
237 if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
238 (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
239 (!MmGetKernelAddressSpace()))
240 {
241 /* This is an ARM3 fault */
242 DPRINT("ARM3 fault %p\n", MemoryArea);
243 return MmArmAccessFault(StoreInstruction, Address, Mode, TrapInformation);
244 }
245
246 /* Keep same old ReactOS Behaviour */
247 if (StoreInstruction)
248 {
249 /* Call access fault */
250 return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
251 }
252 else
253 {
254 /* Call not present */
255 return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
256 }
257 }
258