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