* Sync up to trunk head (r65394).
[reactos.git] / ntoskrnl / mm / ARM3 / mmsup.c
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
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
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
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
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
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
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
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
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
257 MmQuerySystemSize(VOID)
258 {
259 /* Return the low, medium or high memory system type */
260 return MmSystemSize;
261 }
262
263 /* EOF */