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 NTSTATUS 264 NTAPI 265 MmCreateMirror(VOID) 266 { 267 UNIMPLEMENTED; 268 return STATUS_NOT_IMPLEMENTED; 269 } 270 271 /* EOF */ 272