xref: /reactos/ntoskrnl/mm/mmfault.c (revision 3476cdae)
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 #ifdef NEWCC
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 #endif
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 #ifdef NEWCC
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 #endif
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 
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     /* Handle shared user page, which doesn't have a VAD / MemoryArea */
225     if (PAGE_ALIGN(Address) == (PVOID)MM_SHARED_USER_DATA_VA)
226     {
227         /* This is an ARM3 fault */
228         DPRINT("ARM3 fault %p\n", MemoryArea);
229         return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation);
230     }
231 
232     /* Is there a ReactOS address space yet? */
233     if (MmGetKernelAddressSpace())
234     {
235         /* Check if this is an ARM3 memory area */
236         MemoryArea = MmLocateMemoryAreaByAddress(MmGetKernelAddressSpace(), Address);
237         if (!(MemoryArea) && (Address <= MM_HIGHEST_USER_ADDRESS))
238         {
239             /* Could this be a VAD fault from user-mode? */
240             MemoryArea = MmLocateMemoryAreaByAddress(MmGetCurrentAddressSpace(), Address);
241         }
242     }
243 
244     /* Is this an ARM3 memory area, or is there no address space yet? */
245     if (((MemoryArea) && (MemoryArea->Type == MEMORY_AREA_OWNED_BY_ARM3)) ||
246             (!(MemoryArea) && ((ULONG_PTR)Address >= (ULONG_PTR)MmPagedPoolStart)) ||
247             (!MmGetKernelAddressSpace()))
248     {
249         /* This is an ARM3 fault */
250         DPRINT("ARM3 fault %p\n", MemoryArea);
251         return MmArmAccessFault(FaultCode, Address, Mode, TrapInformation);
252     }
253 
254     /* Keep same old ReactOS Behaviour */
255     if (!MI_IS_NOT_PRESENT_FAULT(FaultCode))
256     {
257         /* Call access fault */
258         return MmpAccessFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
259     }
260     else
261     {
262         /* Call not present */
263         return MmNotPresentFault(Mode, (ULONG_PTR)Address, TrapInformation ? FALSE : TRUE);
264     }
265 }
266 
267