xref: /reactos/ntoskrnl/mm/mmfault.c (revision 1734f297)
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                                               !FromMdl);
82             break;
83 #ifdef NEWCC
84         case MEMORY_AREA_CACHE:
85             // This code locks for itself to keep from having to break a lock
86             // passed in.
87             if (!FromMdl)
88                 MmUnlockAddressSpace(AddressSpace);
89             Status = MmAccessFaultCacheSection(Mode, Address, FromMdl);
90             if (!FromMdl)
91                 MmLockAddressSpace(AddressSpace);
92             break;
93 #endif
94         default:
95             Status = STATUS_ACCESS_VIOLATION;
96             break;
97         }
98     }
99     while (Status == STATUS_MM_RESTART_OPERATION);
100 
101     DPRINT("Completed page fault handling\n");
102     if (!FromMdl)
103     {
104         MmUnlockAddressSpace(AddressSpace);
105     }
106     return(Status);
107 }
108 
109 NTSTATUS
110 NTAPI
111 MmNotPresentFault(KPROCESSOR_MODE Mode,
112                   ULONG_PTR Address,
113                   BOOLEAN FromMdl)
114 {
115     PMMSUPPORT AddressSpace;
116     MEMORY_AREA* MemoryArea;
117     NTSTATUS Status;
118 
119     DPRINT("MmNotPresentFault(Mode %d, Address %x)\n", Mode, Address);
120 
121     if (KeGetCurrentIrql() >= DISPATCH_LEVEL)
122     {
123         DPRINT1("Page fault at high IRQL was %u, address %x\n", KeGetCurrentIrql(), Address);
124         return(STATUS_UNSUCCESSFUL);
125     }
126 
127     /*
128      * Find the memory area for the faulting address
129      */
130     if (Address >= (ULONG_PTR)MmSystemRangeStart)
131     {
132         /*
133          * Check permissions
134          */
135         if (Mode != KernelMode)
136         {
137             DPRINT1("Address: %x\n", Address);
138             return(STATUS_ACCESS_VIOLATION);
139         }
140         AddressSpace = MmGetKernelAddressSpace();
141     }
142     else
143     {
144         AddressSpace = &PsGetCurrentProcess()->Vm;
145     }
146 
147     if (!FromMdl)
148     {
149         MmLockAddressSpace(AddressSpace);
150     }
151 
152     /*
153      * Call the memory area specific fault handler
154      */
155     do
156     {
157         MemoryArea = MmLocateMemoryAreaByAddress(AddressSpace, (PVOID)Address);
158         if (MemoryArea == NULL || MemoryArea->DeleteInProgress)
159         {
160             if (!FromMdl)
161             {
162                 MmUnlockAddressSpace(AddressSpace);
163             }
164             return (STATUS_ACCESS_VIOLATION);
165         }
166 
167         switch (MemoryArea->Type)
168         {
169         case MEMORY_AREA_SECTION_VIEW:
170             Status = MmNotPresentFaultSectionView(AddressSpace,
171                                                   MemoryArea,
172                                                   (PVOID)Address,
173                                                   !FromMdl);
174             break;
175 #ifdef NEWCC
176         case MEMORY_AREA_CACHE:
177             // This code locks for itself to keep from having to break a lock
178             // passed in.
179             if (!FromMdl)
180                 MmUnlockAddressSpace(AddressSpace);
181             Status = MmNotPresentFaultCacheSection(Mode, Address, FromMdl);
182             if (!FromMdl)
183                 MmLockAddressSpace(AddressSpace);
184             break;
185 #endif
186         default:
187             Status = STATUS_ACCESS_VIOLATION;
188             break;
189         }
190     }
191     while (Status == STATUS_MM_RESTART_OPERATION);
192 
193     DPRINT("Completed page fault handling\n");
194     if (!FromMdl)
195     {
196         MmUnlockAddressSpace(AddressSpace);
197     }
198     return(Status);
199 }
200 
201 extern BOOLEAN Mmi386MakeKernelPageTableGlobal(PVOID Address);
202 
203 NTSTATUS
204 NTAPI
205 MmAccessFault(IN ULONG FaultCode,
206               IN PVOID Address,
207               IN KPROCESSOR_MODE Mode,
208               IN PVOID TrapInformation)
209 {
210     PMEMORY_AREA MemoryArea = NULL;
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(FaultCode, 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(FaultCode, Address, Mode, TrapInformation);
253     }
254 
255     /* Keep same old ReactOS Behaviour */
256     if (!MI_IS_NOT_PRESENT_FAULT(FaultCode))
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 
268