1 /* 2 * PROJECT: ReactOS Kernel 3 * LICENSE: GPL - See COPYING in the top level directory 4 * FILE: ntoskrnl/mm/mminit.c 5 * PURPOSE: Memory Manager Initialization 6 * PROGRAMMERS: 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 "ARM3/miarm.h" 17 18 /* GLOBALS *******************************************************************/ 19 20 VOID NTAPI MiInitializeUserPfnBitmap(VOID); 21 22 BOOLEAN Mm64BitPhysicalAddress = FALSE; 23 ULONG MmReadClusterSize; 24 // 25 // 0 | 1 is on/off paging, 2 is undocumented 26 // 27 UCHAR MmDisablePagingExecutive = 1; // Forced to off 28 PMMPTE MmSharedUserDataPte; 29 PMMSUPPORT MmKernelAddressSpace; 30 31 extern KEVENT MmWaitPageEvent; 32 extern FAST_MUTEX MiGlobalPageOperation; 33 extern LIST_ENTRY MiSegmentList; 34 extern NTSTATUS MiRosTrimCache(ULONG Target, ULONG Priority, PULONG NrFreed); 35 36 /* PRIVATE FUNCTIONS *********************************************************/ 37 38 // 39 // Helper function to create initial memory areas. 40 // The created area is always read/write. 41 // 42 CODE_SEG("INIT") 43 VOID 44 NTAPI 45 MiCreateArm3StaticMemoryArea(PVOID BaseAddress, SIZE_T Size, BOOLEAN Executable) 46 { 47 const ULONG Protection = Executable ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE; 48 PVOID pBaseAddress = BaseAddress; 49 PMEMORY_AREA MArea; 50 NTSTATUS Status; 51 52 Status = MmCreateMemoryArea(MmGetKernelAddressSpace(), 53 MEMORY_AREA_OWNED_BY_ARM3 | MEMORY_AREA_STATIC, 54 &pBaseAddress, 55 Size, 56 Protection, 57 &MArea, 58 0, 59 PAGE_SIZE); 60 ASSERT(Status == STATUS_SUCCESS); 61 // TODO: Perhaps it would be prudent to bugcheck here, not only assert? 62 } 63 64 CODE_SEG("INIT") 65 VOID 66 NTAPI 67 MiInitSystemMemoryAreas(VOID) 68 { 69 // 70 // Create all the static memory areas. 71 // 72 73 #ifdef _M_AMD64 74 // Reserved range FFFF800000000000 - FFFFF68000000000 75 MiCreateArm3StaticMemoryArea((PVOID)MI_REAL_SYSTEM_RANGE_START, PTE_BASE - MI_REAL_SYSTEM_RANGE_START, FALSE); 76 #endif /* _M_AMD64 */ 77 78 // The loader mappings. The only Executable area. 79 MiCreateArm3StaticMemoryArea((PVOID)KSEG0_BASE, MmBootImageSize, TRUE); 80 81 // The PTE base 82 MiCreateArm3StaticMemoryArea((PVOID)PTE_BASE, PTE_TOP - PTE_BASE + 1, FALSE); 83 84 // Hyperspace 85 MiCreateArm3StaticMemoryArea((PVOID)HYPER_SPACE, HYPER_SPACE_END - HYPER_SPACE + 1, FALSE); 86 87 // Protect the PFN database 88 MiCreateArm3StaticMemoryArea(MmPfnDatabase, (MxPfnAllocation << PAGE_SHIFT), FALSE); 89 90 // ReactOS requires a memory area to keep the initial NP area off-bounds 91 MiCreateArm3StaticMemoryArea(MmNonPagedPoolStart, MmSizeOfNonPagedPoolInBytes, FALSE); 92 93 // System PTE space 94 MiCreateArm3StaticMemoryArea(MmNonPagedSystemStart, (MmNumberOfSystemPtes + 1) * PAGE_SIZE, FALSE); 95 96 // Nonpaged pool expansion space 97 MiCreateArm3StaticMemoryArea(MmNonPagedPoolExpansionStart, (ULONG_PTR)MmNonPagedPoolEnd - (ULONG_PTR)MmNonPagedPoolExpansionStart, FALSE); 98 99 // System view space 100 MiCreateArm3StaticMemoryArea(MiSystemViewStart, MmSystemViewSize, FALSE); 101 102 // Session space 103 MiCreateArm3StaticMemoryArea(MmSessionBase, (ULONG_PTR)MiSessionSpaceEnd - (ULONG_PTR)MmSessionBase, FALSE); 104 105 // Paged pool 106 MiCreateArm3StaticMemoryArea(MmPagedPoolStart, MmSizeOfPagedPoolInBytes, FALSE); 107 108 // Debugger mapping 109 MiCreateArm3StaticMemoryArea(MI_DEBUG_MAPPING, PAGE_SIZE, FALSE); 110 111 #if defined(_X86_) 112 // Reserved HAL area (includes KUSER_SHARED_DATA and KPCR) 113 MiCreateArm3StaticMemoryArea((PVOID)MM_HAL_VA_START, MM_HAL_VA_END - MM_HAL_VA_START + 1, FALSE); 114 #else /* _X86_ */ 115 #ifndef _M_AMD64 116 // KPCR, one page per CPU. Only for 32-bit kernel. 117 MiCreateArm3StaticMemoryArea(PCR, PAGE_SIZE * KeNumberProcessors, FALSE); 118 #endif /* _M_AMD64 */ 119 120 // KUSER_SHARED_DATA 121 MiCreateArm3StaticMemoryArea((PVOID)KI_USER_SHARED_DATA, PAGE_SIZE, FALSE); 122 #endif /* _X86_ */ 123 } 124 125 CODE_SEG("INIT") 126 VOID 127 NTAPI 128 MiDbgDumpAddressSpace(VOID) 129 { 130 // 131 // Print the memory layout 132 // 133 DPRINT1(" 0x%p - 0x%p\t%s\n", 134 KSEG0_BASE, 135 (ULONG_PTR)KSEG0_BASE + MmBootImageSize, 136 "Boot Loaded Image"); 137 DPRINT1(" 0x%p - 0x%p\t%s\n", 138 MmPfnDatabase, 139 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT), 140 "PFN Database"); 141 DPRINT1(" 0x%p - 0x%p\t%s\n", 142 MmNonPagedPoolStart, 143 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes, 144 "ARM3 Non Paged Pool"); 145 DPRINT1(" 0x%p - 0x%p\t%s\n", 146 MiSystemViewStart, 147 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize, 148 "System View Space"); 149 DPRINT1(" 0x%p - 0x%p\t%s\n", 150 MmSessionBase, 151 MiSessionSpaceEnd, 152 "Session Space"); 153 DPRINT1(" 0x%p - 0x%p\t%s\n", 154 PTE_BASE, PTE_TOP, 155 "Page Tables"); 156 DPRINT1(" 0x%p - 0x%p\t%s\n", 157 PDE_BASE, PDE_TOP, 158 "Page Directories"); 159 DPRINT1(" 0x%p - 0x%p\t%s\n", 160 HYPER_SPACE, HYPER_SPACE_END, 161 "Hyperspace"); 162 DPRINT1(" 0x%p - 0x%p\t%s\n", 163 MmSystemCacheStart, MmSystemCacheEnd, 164 "System Cache"); 165 DPRINT1(" 0x%p - 0x%p\t%s\n", 166 MmPagedPoolStart, 167 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes, 168 "ARM3 Paged Pool"); 169 DPRINT1(" 0x%p - 0x%p\t%s\n", 170 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart, 171 "System PTE Space"); 172 DPRINT1(" 0x%p - 0x%p\t%s\n", 173 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd, 174 "Non Paged Pool Expansion PTE Space"); 175 } 176 177 CODE_SEG("INIT") 178 NTSTATUS 179 NTAPI 180 MmInitBsmThread(VOID) 181 { 182 NTSTATUS Status; 183 OBJECT_ATTRIBUTES ObjectAttributes; 184 HANDLE ThreadHandle; 185 186 /* Create the thread */ 187 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 188 Status = PsCreateSystemThread(&ThreadHandle, 189 THREAD_ALL_ACCESS, 190 &ObjectAttributes, 191 NULL, 192 NULL, 193 KeBalanceSetManager, 194 NULL); 195 196 /* Close the handle and return status */ 197 ZwClose(ThreadHandle); 198 return Status; 199 } 200 201 CODE_SEG("INIT") 202 BOOLEAN 203 NTAPI 204 MmInitSystem(IN ULONG Phase, 205 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 206 { 207 extern MMPTE ValidKernelPte; 208 PMMPTE PointerPte; 209 MMPTE TempPte = ValidKernelPte; 210 PFN_NUMBER PageFrameNumber; 211 PLIST_ENTRY ListEntry; 212 PLDR_DATA_TABLE_ENTRY DataTableEntry; 213 214 /* Initialize the kernel address space */ 215 ASSERT(Phase == 1); 216 217 InitializeListHead(&MiSegmentList); 218 ExInitializeFastMutex(&MiGlobalPageOperation); 219 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE); 220 // Until we're fully demand paged, we can do things the old way through 221 // the balance manager 222 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache); 223 224 MmKernelAddressSpace = &PsIdleProcess->Vm; 225 226 /* Intialize system memory areas */ 227 MiInitSystemMemoryAreas(); 228 229 /* Dump the address space */ 230 MiDbgDumpAddressSpace(); 231 232 MmInitGlobalKernelPageDirectory(); 233 MiInitializeUserPfnBitmap(); 234 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); 235 MmInitializeRmapList(); 236 MmInitSectionImplementation(); 237 MmInitPagingFile(); 238 239 // 240 // Create a PTE to double-map the shared data section. We allocate it 241 // from paged pool so that we can't fault when trying to touch the PTE 242 // itself (to map it), since paged pool addresses will already be mapped 243 // by the fault handler. 244 // 245 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool, 246 sizeof(MMPTE), 247 TAG_MM); 248 if (!MmSharedUserDataPte) return FALSE; 249 250 // 251 // Now get the PTE for shared data, and read the PFN that holds it 252 // 253 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA); 254 ASSERT(PointerPte->u.Hard.Valid == 1); 255 PageFrameNumber = PFN_FROM_PTE(PointerPte); 256 257 /* Build the PTE and write it */ 258 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, 259 PointerPte, 260 MM_READONLY, 261 PageFrameNumber); 262 *MmSharedUserDataPte = TempPte; 263 264 /* Initialize session working set support */ 265 MiInitializeSessionWsSupport(); 266 267 /* Setup session IDs */ 268 MiInitializeSessionIds(); 269 270 /* Setup the memory threshold events */ 271 if (!MiInitializeMemoryEvents()) return FALSE; 272 273 /* 274 * Unmap low memory 275 */ 276 MiInitBalancerThread(); 277 278 /* Initialize the balance set manager */ 279 MmInitBsmThread(); 280 281 /* Loop the boot loaded images (under lock) */ 282 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE); 283 for (ListEntry = PsLoadedModuleList.Flink; 284 ListEntry != &PsLoadedModuleList; 285 ListEntry = ListEntry->Flink) 286 { 287 /* Get the data table entry */ 288 DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 289 290 /* Set up the image protection */ 291 MiWriteProtectSystemImage(DataTableEntry->DllBase); 292 } 293 ExReleaseResourceLite(&PsLoadedModuleResource); 294 295 return TRUE; 296 } 297 298