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