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 MmLockAddressSpace(MmGetKernelAddressSpace()); 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 MmUnlockAddressSpace(MmGetKernelAddressSpace()); 125 } 126 127 CODE_SEG("INIT") 128 VOID 129 NTAPI 130 MiDbgDumpAddressSpace(VOID) 131 { 132 // 133 // Print the memory layout 134 // 135 DPRINT1(" 0x%p - 0x%p\t%s\n", 136 KSEG0_BASE, 137 (ULONG_PTR)KSEG0_BASE + MmBootImageSize, 138 "Boot Loaded Image"); 139 DPRINT1(" 0x%p - 0x%p\t%s\n", 140 MmPfnDatabase, 141 (ULONG_PTR)MmPfnDatabase + (MxPfnAllocation << PAGE_SHIFT), 142 "PFN Database"); 143 DPRINT1(" 0x%p - 0x%p\t%s\n", 144 MmNonPagedPoolStart, 145 (ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes, 146 "ARM3 Non Paged Pool"); 147 DPRINT1(" 0x%p - 0x%p\t%s\n", 148 MiSystemViewStart, 149 (ULONG_PTR)MiSystemViewStart + MmSystemViewSize, 150 "System View Space"); 151 DPRINT1(" 0x%p - 0x%p\t%s\n", 152 MmSessionBase, 153 MiSessionSpaceEnd, 154 "Session Space"); 155 DPRINT1(" 0x%p - 0x%p\t%s\n", 156 PTE_BASE, PTE_TOP, 157 "Page Tables"); 158 DPRINT1(" 0x%p - 0x%p\t%s\n", 159 PDE_BASE, PDE_TOP, 160 "Page Directories"); 161 DPRINT1(" 0x%p - 0x%p\t%s\n", 162 HYPER_SPACE, HYPER_SPACE_END, 163 "Hyperspace"); 164 DPRINT1(" 0x%p - 0x%p\t%s\n", 165 MmSystemCacheStart, MmSystemCacheEnd, 166 "System Cache"); 167 DPRINT1(" 0x%p - 0x%p\t%s\n", 168 MmPagedPoolStart, 169 (ULONG_PTR)MmPagedPoolStart + MmSizeOfPagedPoolInBytes, 170 "ARM3 Paged Pool"); 171 DPRINT1(" 0x%p - 0x%p\t%s\n", 172 MmNonPagedSystemStart, MmNonPagedPoolExpansionStart, 173 "System PTE Space"); 174 DPRINT1(" 0x%p - 0x%p\t%s\n", 175 MmNonPagedPoolExpansionStart, MmNonPagedPoolEnd, 176 "Non Paged Pool Expansion PTE Space"); 177 } 178 179 CODE_SEG("INIT") 180 NTSTATUS 181 NTAPI 182 MmInitBsmThread(VOID) 183 { 184 NTSTATUS Status; 185 OBJECT_ATTRIBUTES ObjectAttributes; 186 HANDLE ThreadHandle; 187 188 /* Create the thread */ 189 InitializeObjectAttributes(&ObjectAttributes, NULL, 0, NULL, NULL); 190 Status = PsCreateSystemThread(&ThreadHandle, 191 THREAD_ALL_ACCESS, 192 &ObjectAttributes, 193 NULL, 194 NULL, 195 KeBalanceSetManager, 196 NULL); 197 198 /* Close the handle and return status */ 199 ZwClose(ThreadHandle); 200 return Status; 201 } 202 203 CODE_SEG("INIT") 204 BOOLEAN 205 NTAPI 206 MmInitSystem(IN ULONG Phase, 207 IN PLOADER_PARAMETER_BLOCK LoaderBlock) 208 { 209 extern MMPTE ValidKernelPte; 210 PMMPTE PointerPte; 211 MMPTE TempPte = ValidKernelPte; 212 PFN_NUMBER PageFrameNumber; 213 PLIST_ENTRY ListEntry; 214 PLDR_DATA_TABLE_ENTRY DataTableEntry; 215 216 /* Initialize the kernel address space */ 217 ASSERT(Phase == 1); 218 219 #ifdef NEWCC 220 InitializeListHead(&MiSegmentList); 221 ExInitializeFastMutex(&MiGlobalPageOperation); 222 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE); 223 // Until we're fully demand paged, we can do things the old way through 224 // the balance manager 225 // CcInitView will override this... 226 MmInitializeMemoryConsumer(MC_CACHE, MiRosTrimCache); 227 #else 228 KeInitializeEvent(&MmWaitPageEvent, SynchronizationEvent, FALSE); 229 #endif 230 231 MmKernelAddressSpace = &PsIdleProcess->Vm; 232 233 /* Intialize system memory areas */ 234 MiInitSystemMemoryAreas(); 235 236 /* Dump the address space */ 237 MiDbgDumpAddressSpace(); 238 239 MmInitGlobalKernelPageDirectory(); 240 MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); 241 MmInitializeRmapList(); 242 MmInitSectionImplementation(); 243 MmInitPagingFile(); 244 245 // 246 // Create a PTE to double-map the shared data section. We allocate it 247 // from paged pool so that we can't fault when trying to touch the PTE 248 // itself (to map it), since paged pool addresses will already be mapped 249 // by the fault handler. 250 // 251 MmSharedUserDataPte = ExAllocatePoolWithTag(PagedPool, 252 sizeof(MMPTE), 253 TAG_MM); 254 if (!MmSharedUserDataPte) return FALSE; 255 256 // 257 // Now get the PTE for shared data, and read the PFN that holds it 258 // 259 PointerPte = MiAddressToPte((PVOID)KI_USER_SHARED_DATA); 260 ASSERT(PointerPte->u.Hard.Valid == 1); 261 PageFrameNumber = PFN_FROM_PTE(PointerPte); 262 263 /* Build the PTE and write it */ 264 MI_MAKE_HARDWARE_PTE_KERNEL(&TempPte, 265 PointerPte, 266 MM_READONLY, 267 PageFrameNumber); 268 *MmSharedUserDataPte = TempPte; 269 270 /* Initialize session working set support */ 271 MiInitializeSessionWsSupport(); 272 273 /* Setup session IDs */ 274 MiInitializeSessionIds(); 275 276 /* Setup the memory threshold events */ 277 if (!MiInitializeMemoryEvents()) return FALSE; 278 279 /* 280 * Unmap low memory 281 */ 282 MiInitBalancerThread(); 283 284 /* Initialize the balance set manager */ 285 MmInitBsmThread(); 286 287 /* Loop the boot loaded images (under lock) */ 288 ExAcquireResourceExclusiveLite(&PsLoadedModuleResource, TRUE); 289 for (ListEntry = PsLoadedModuleList.Flink; 290 ListEntry != &PsLoadedModuleList; 291 ListEntry = ListEntry->Flink) 292 { 293 /* Get the data table entry */ 294 DataTableEntry = CONTAINING_RECORD(ListEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderLinks); 295 296 /* Set up the image protection */ 297 MiWriteProtectSystemImage(DataTableEntry->DllBase); 298 } 299 ExReleaseResourceLite(&PsLoadedModuleResource); 300 301 return TRUE; 302 } 303 304