xref: /reactos/ntoskrnl/mm/ARM3/mmsup.c (revision 34593d93)
1 /*
2  * PROJECT:         ReactOS Kernel
3  * LICENSE:         BSD - See COPYING.ARM in the top level directory
4  * FILE:            ntoskrnl/mm/ARM3/mmsup.c
5  * PURPOSE:         ARM Memory Manager Support Routines
6  * PROGRAMMERS:     ReactOS Portable Systems Group
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <ntoskrnl.h>
12 #define NDEBUG
13 #include <debug.h>
14 
15 #define MODULE_INVOLVED_IN_ARM3
16 #include <mm/ARM3/miarm.h>
17 
18 /* GLOBALS ********************************************************************/
19 
20 SIZE_T MmMinimumWorkingSetSize;
21 SIZE_T MmMaximumWorkingSetSize;
22 SIZE_T MmPagesAboveWsMinimum;
23 
24 /* PUBLIC FUNCTIONS ***********************************************************/
25 
26 /*
27  * @unimplemented
28  */
29 NTSTATUS
30 NTAPI
MmMapUserAddressesToPage(IN PVOID BaseAddress,IN SIZE_T NumberOfBytes,IN PVOID PageAddress)31 MmMapUserAddressesToPage(IN PVOID BaseAddress,
32                          IN SIZE_T NumberOfBytes,
33                          IN PVOID PageAddress)
34 {
35     UNIMPLEMENTED;
36     return STATUS_NOT_IMPLEMENTED;
37 }
38 
39 /*
40  * @unimplemented
41  */
42 NTSTATUS
43 NTAPI
MmAdjustWorkingSetSize(IN SIZE_T WorkingSetMinimumInBytes,IN SIZE_T WorkingSetMaximumInBytes,IN ULONG SystemCache,IN BOOLEAN IncreaseOkay)44 MmAdjustWorkingSetSize(IN SIZE_T WorkingSetMinimumInBytes,
45                        IN SIZE_T WorkingSetMaximumInBytes,
46                        IN ULONG SystemCache,
47                        IN BOOLEAN IncreaseOkay)
48 {
49     SIZE_T MinimumWorkingSetSize, MaximumWorkingSetSize;
50     SSIZE_T Delta;
51     PMMSUPPORT Ws;
52     NTSTATUS Status;
53 
54     /* Check for special case: empty the working set */
55     if ((WorkingSetMinimumInBytes == -1) &&
56         (WorkingSetMaximumInBytes == -1))
57     {
58         UNIMPLEMENTED;
59         return STATUS_NOT_IMPLEMENTED;
60     }
61 
62     /* Assume success */
63     Status = STATUS_SUCCESS;
64 
65     /* Get the working set and lock it */
66     Ws = &PsGetCurrentProcess()->Vm;
67     MiLockWorkingSet(PsGetCurrentThread(), Ws);
68 
69     /* Calculate the actual minimum and maximum working set size to set */
70     MinimumWorkingSetSize = (WorkingSetMinimumInBytes != 0) ?
71         (WorkingSetMinimumInBytes / PAGE_SIZE) : Ws->MinimumWorkingSetSize;
72     MaximumWorkingSetSize = (WorkingSetMaximumInBytes != 0) ?
73         (WorkingSetMaximumInBytes / PAGE_SIZE) : Ws->MaximumWorkingSetSize;
74 
75     /* Check if the new maximum exceeds the global maximum */
76     if (MaximumWorkingSetSize > MmMaximumWorkingSetSize)
77     {
78         MaximumWorkingSetSize = MmMaximumWorkingSetSize;
79         Status = STATUS_WORKING_SET_LIMIT_RANGE;
80     }
81 
82     /* Check if the new minimum is below the global minimum */
83     if (MinimumWorkingSetSize < MmMinimumWorkingSetSize)
84     {
85         MinimumWorkingSetSize = MmMinimumWorkingSetSize;
86         Status = STATUS_WORKING_SET_LIMIT_RANGE;
87     }
88 
89     /* Check if the new minimum exceeds the new maximum */
90     if (MinimumWorkingSetSize > MaximumWorkingSetSize)
91     {
92         DPRINT1("MinimumWorkingSetSize (%lu) > MaximumWorkingSetSize (%lu)\n",
93                 MinimumWorkingSetSize, MaximumWorkingSetSize);
94         Status = STATUS_BAD_WORKING_SET_LIMIT;
95         goto Cleanup;
96     }
97 
98     /* Calculate the minimum WS size adjustment and check if we increase */
99     Delta = MinimumWorkingSetSize - Ws->MinimumWorkingSetSize;
100     if (Delta > 0)
101     {
102         /* Is increasing ok? */
103         if (!IncreaseOkay)
104         {
105             DPRINT1("Privilege for WS size increase not held\n");
106             Status = STATUS_PRIVILEGE_NOT_HELD;
107             goto Cleanup;
108         }
109 
110         /* Check if the number of available pages is large enough */
111         if (((SIZE_T)Delta / 1024) > (MmAvailablePages - 128))
112         {
113             DPRINT1("Not enough available pages\n");
114             Status = STATUS_INSUFFICIENT_RESOURCES;
115             goto Cleanup;
116         }
117 
118         /* Check if there are enough resident available pages */
119         if ((SIZE_T)Delta >
120             (MmResidentAvailablePages - MmSystemLockPagesCount - 256))
121         {
122             DPRINT1("Not enough resident pages\n");
123             Status = STATUS_INSUFFICIENT_RESOURCES;
124             goto Cleanup;
125         }
126     }
127 
128     /* Update resident available pages */
129     if (Delta != 0)
130     {
131         InterlockedExchangeAddSizeT(&MmResidentAvailablePages, -Delta);
132     }
133 
134     /* Calculate new pages above minimum WS size */
135     Delta += max((SSIZE_T)Ws->WorkingSetSize - MinimumWorkingSetSize, 0);
136 
137     /* Subtract old pages above minimum WS size */
138     Delta -= max((SSIZE_T)Ws->WorkingSetSize - Ws->MinimumWorkingSetSize, 0);
139 
140     /* If it changed, add it to the global variable */
141     if (Delta != 0)
142     {
143         InterlockedExchangeAddSizeT(&MmPagesAboveWsMinimum, Delta);
144     }
145 
146     /* Set the new working set size */
147     Ws->MinimumWorkingSetSize = MinimumWorkingSetSize;
148     Ws->MaximumWorkingSetSize = MaximumWorkingSetSize;
149 
150 Cleanup:
151 
152     /* Unlock the working set and return the status */
153     MiUnlockWorkingSet(PsGetCurrentThread(), Ws);
154     return Status;
155 }
156 
157 /*
158  * @unimplemented
159  */
160 BOOLEAN
161 NTAPI
MmSetAddressRangeModified(IN PVOID Address,IN SIZE_T Length)162 MmSetAddressRangeModified(IN PVOID Address,
163                           IN SIZE_T Length)
164 {
165    UNIMPLEMENTED;
166    return FALSE;
167 }
168 
169 /*
170  * @implemented
171  */
172 BOOLEAN
173 NTAPI
MmIsAddressValid(IN PVOID VirtualAddress)174 MmIsAddressValid(IN PVOID VirtualAddress)
175 {
176 #if _MI_PAGING_LEVELS >= 4
177     /* Check if the PXE is valid */
178     if (MiAddressToPxe(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
179 #endif
180 
181 #if _MI_PAGING_LEVELS >= 3
182     /* Check if the PPE is valid */
183     if (MiAddressToPpe(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
184 #endif
185 
186 #if _MI_PAGING_LEVELS >= 2
187     /* Check if the PDE is valid */
188     if (MiAddressToPde(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
189 #endif
190 
191     /* Check if the PTE is valid */
192     if (MiAddressToPte(VirtualAddress)->u.Hard.Valid == 0) return FALSE;
193 
194     /* This address is valid now, but it will only stay so if the caller holds
195      * the PFN lock */
196     return TRUE;
197 }
198 
199 /*
200  * @unimplemented
201  */
202 BOOLEAN
203 NTAPI
MmIsNonPagedSystemAddressValid(IN PVOID VirtualAddress)204 MmIsNonPagedSystemAddressValid(IN PVOID VirtualAddress)
205 {
206     DPRINT1("WARNING: %s returns bogus result\n", __FUNCTION__);
207     return MmIsAddressValid(VirtualAddress);
208 }
209 
210 /*
211  * @unimplemented
212  */
213 NTSTATUS
214 NTAPI
MmSetBankedSection(IN HANDLE ProcessHandle,IN PVOID VirtualAddress,IN ULONG BankLength,IN BOOLEAN ReadWriteBank,IN PVOID BankRoutine,IN PVOID Context)215 MmSetBankedSection(IN HANDLE ProcessHandle,
216                    IN PVOID VirtualAddress,
217                    IN ULONG BankLength,
218                    IN BOOLEAN ReadWriteBank,
219                    IN PVOID BankRoutine,
220                    IN PVOID Context)
221 {
222     UNIMPLEMENTED;
223     return STATUS_NOT_IMPLEMENTED;
224 }
225 
226 /*
227  * @implemented
228  */
229 BOOLEAN
230 NTAPI
MmIsRecursiveIoFault(VOID)231 MmIsRecursiveIoFault(VOID)
232 {
233     PETHREAD Thread = PsGetCurrentThread();
234 
235     //
236     // If any of these is true, this is a recursive fault
237     //
238     return ((Thread->DisablePageFaultClustering) | (Thread->ForwardClusterOnly));
239 }
240 
241 /*
242  * @implemented
243  */
244 BOOLEAN
245 NTAPI
MmIsThisAnNtAsSystem(VOID)246 MmIsThisAnNtAsSystem(VOID)
247 {
248     /* Return if this is a server system */
249     return MmProductType & 0xFF;
250 }
251 
252 /*
253  * @implemented
254  */
255 MM_SYSTEMSIZE
256 NTAPI
MmQuerySystemSize(VOID)257 MmQuerySystemSize(VOID)
258 {
259     /* Return the low, medium or high memory system type */
260     return MmSystemSize;
261 }
262 
263 NTSTATUS
264 NTAPI
MmCreateMirror(VOID)265 MmCreateMirror(VOID)
266 {
267     UNIMPLEMENTED;
268     return STATUS_NOT_IMPLEMENTED;
269 }
270 
271 /* EOF */
272