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