Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninit.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: GPL, See COPYING in the top level directory 00003 * PROJECT: ReactOS kernel 00004 * FILE: ntoskrnl/mm/amd64/init.c 00005 * PURPOSE: Memory Manager Initialization for amd64 00006 * 00007 * PROGRAMMERS: Timo kreuzer (timo.kreuzer@reactos.org) 00008 * ReactOS Portable Systems Group 00009 */ 00010 00011 /* INCLUDES ***************************************************************/ 00012 00013 #include <ntoskrnl.h> 00014 //#define NDEBUG 00015 #include <debug.h> 00016 00017 #include "../ARM3/miarm.h" 00018 00019 #ifdef _WINKD_ 00020 extern PMMPTE MmDebugPte; 00021 #endif 00022 00023 /* GLOBALS *****************************************************************/ 00024 00025 /* Template PTE and PDE for a kernel page */ 00026 MMPTE ValidKernelPde = {{PTE_VALID|PTE_READWRITE|PTE_DIRTY|PTE_ACCESSED}}; 00027 MMPTE ValidKernelPte = {{PTE_VALID|PTE_READWRITE|PTE_DIRTY|PTE_ACCESSED}}; 00028 00029 /* Template PDE for a demand-zero page */ 00030 MMPDE DemandZeroPde = {{MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS}}; 00031 MMPTE DemandZeroPte = {{MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS}}; 00032 00033 /* Template PTE for prototype page */ 00034 MMPTE PrototypePte = {{(MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) | 00035 PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << 32)}}; 00036 00037 /* Template PTE for decommited page */ 00038 MMPTE MmDecommittedPte = {{MM_DECOMMIT << MM_PTE_SOFTWARE_PROTECTION_BITS}}; 00039 00040 /* Address ranges */ 00041 PVOID MiSessionViewEnd; 00042 PVOID MiSystemPteSpaceStart; 00043 PVOID MiSystemPteSpaceEnd; 00044 00045 ULONG64 MxPfnSizeInBytes; 00046 BOOLEAN MiIncludeType[LoaderMaximum]; 00047 PFN_NUMBER MxFreePageBase; 00048 ULONG64 MxFreePageCount = 0; 00049 00050 BOOLEAN MiPfnsInitialized = FALSE; 00051 00052 /* FUNCTIONS *****************************************************************/ 00053 00054 VOID 00055 NTAPI 00056 INIT_FUNCTION 00057 MiInitializeSessionSpaceLayout() 00058 { 00059 MmSessionSize = MI_SESSION_SIZE; 00060 MmSessionViewSize = MI_SESSION_VIEW_SIZE; 00061 MmSessionPoolSize = MI_SESSION_POOL_SIZE; 00062 MmSessionImageSize = MI_SESSION_IMAGE_SIZE; 00063 MmSystemViewSize = MI_SYSTEM_VIEW_SIZE; 00064 00065 /* Set up session space */ 00066 MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END; 00067 00068 /* This is where we will load Win32k.sys and the video driver */ 00069 MiSessionImageEnd = MiSessionSpaceEnd; 00070 MiSessionImageStart = (PCHAR)MiSessionImageEnd - MmSessionImageSize; 00071 00072 /* The view starts right below the session working set (itself below 00073 * the image area) */ 00074 MiSessionViewEnd = (PVOID)MI_SESSION_VIEW_END; 00075 MiSessionViewStart = (PCHAR)MiSessionViewEnd - MmSessionViewSize; 00076 ASSERT(IS_PAGE_ALIGNED(MiSessionViewStart)); 00077 00078 /* Session pool follows */ 00079 MiSessionPoolEnd = MiSessionViewStart; 00080 MiSessionPoolStart = (PCHAR)MiSessionPoolEnd - MmSessionPoolSize; 00081 ASSERT(IS_PAGE_ALIGNED(MiSessionPoolStart)); 00082 00083 /* And it all begins here */ 00084 MmSessionBase = MiSessionPoolStart; 00085 00086 /* System view space ends at session space, so now that we know where 00087 * this is, we can compute the base address of system view space itself. */ 00088 MiSystemViewStart = (PCHAR)MmSessionBase - MmSystemViewSize; 00089 ASSERT(IS_PAGE_ALIGNED(MiSystemViewStart)); 00090 00091 /* Sanity checks */ 00092 ASSERT(MiSessionViewEnd <= MiSessionImageStart); 00093 ASSERT(MmSessionBase <= MiSessionPoolStart); 00094 } 00095 00096 VOID 00097 NTAPI 00098 MiMapPPEs( 00099 PVOID StartAddress, 00100 PVOID EndAddress) 00101 { 00102 PMMPDE PointerPpe; 00103 MMPDE TmplPde = ValidKernelPde; 00104 00105 /* Loop the PPEs */ 00106 for (PointerPpe = MiAddressToPpe(StartAddress); 00107 PointerPpe <= MiAddressToPpe(EndAddress); 00108 PointerPpe++) 00109 { 00110 /* Check if its already mapped */ 00111 if (!PointerPpe->u.Hard.Valid) 00112 { 00113 /* No, map it! */ 00114 TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1); 00115 MI_WRITE_VALID_PTE(PointerPpe, TmplPde); 00116 00117 /* Zero out the page table */ 00118 RtlZeroMemory(MiPteToAddress(PointerPpe), PAGE_SIZE); 00119 } 00120 } 00121 } 00122 00123 VOID 00124 NTAPI 00125 MiMapPDEs( 00126 PVOID StartAddress, 00127 PVOID EndAddress) 00128 { 00129 PMMPDE PointerPde; 00130 MMPDE TmplPde = ValidKernelPde; 00131 00132 /* Loop the PDEs */ 00133 for (PointerPde = MiAddressToPde(StartAddress); 00134 PointerPde <= MiAddressToPde(EndAddress); 00135 PointerPde++) 00136 { 00137 /* Check if its already mapped */ 00138 if (!PointerPde->u.Hard.Valid) 00139 { 00140 /* No, map it! */ 00141 TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1); 00142 MI_WRITE_VALID_PTE(PointerPde, TmplPde); 00143 00144 /* Zero out the page table */ 00145 RtlZeroMemory(MiPteToAddress(PointerPde), PAGE_SIZE); 00146 } 00147 } 00148 } 00149 00150 VOID 00151 NTAPI 00152 MiMapPTEs( 00153 PVOID StartAddress, 00154 PVOID EndAddress) 00155 { 00156 PMMPTE PointerPte; 00157 MMPTE TmplPte = ValidKernelPte; 00158 00159 /* Loop the PTEs */ 00160 for (PointerPte = MiAddressToPte(StartAddress); 00161 PointerPte <= MiAddressToPte(EndAddress); 00162 PointerPte++) 00163 { 00164 /* Check if its already mapped */ 00165 if (!PointerPte->u.Hard.Valid) 00166 { 00167 /* No, map it! */ 00168 TmplPte.u.Hard.PageFrameNumber = MxGetNextPage(1); 00169 MI_WRITE_VALID_PTE(PointerPte, TmplPte); 00170 00171 /* Zero out the page (FIXME: not always neccessary) */ 00172 RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE); 00173 } 00174 } 00175 } 00176 00177 VOID 00178 NTAPI 00179 INIT_FUNCTION 00180 MiInitializePageTable() 00181 { 00182 ULONG64 PxePhysicalAddress; 00183 MMPTE TmplPte, *PointerPxe; 00184 PFN_NUMBER PxePfn; 00185 00186 /* Get current directory base */ 00187 PxePfn = ((PMMPTE)PXE_SELFMAP)->u.Hard.PageFrameNumber; 00188 PxePhysicalAddress = PxePfn << PAGE_SHIFT; 00189 ASSERT(PxePhysicalAddress == __readcr3()); 00190 00191 /* Set directory base for the system process */ 00192 PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PxePhysicalAddress; 00193 00194 /* Enable global pages */ 00195 __writecr4(__readcr4() | CR4_PGE); 00196 ASSERT(__readcr4() & CR4_PGE); 00197 00198 /* Enable no execute */ 00199 __writemsr(X86_MSR_EFER, __readmsr(X86_MSR_EFER) | EFER_NXE); 00200 00201 /* Loop the user mode PXEs */ 00202 for (PointerPxe = MiAddressToPxe(0); 00203 PointerPxe <= MiAddressToPxe(MmHighestUserAddress); 00204 PointerPxe++) 00205 { 00206 /* Zero the PXE, clear all mappings */ 00207 PointerPxe->u.Long = 0; 00208 } 00209 00210 /* Flush the TLB */ 00211 KeFlushCurrentTb(); 00212 00213 /* Set up a template PTE */ 00214 TmplPte.u.Long = 0; 00215 TmplPte.u.Flush.Valid = 1; 00216 TmplPte.u.Flush.Write = 1; 00217 HyperTemplatePte = TmplPte; 00218 00219 /* Create PDPTs (72 KB) for shared system address space, 00220 * skip page tables TODO: use global pages. */ 00221 00222 /* Loop the PXEs */ 00223 for (PointerPxe = MiAddressToPxe((PVOID)HYPER_SPACE); 00224 PointerPxe <= MiAddressToPxe(MI_HIGHEST_SYSTEM_ADDRESS); 00225 PointerPxe++) 00226 { 00227 /* Is the PXE already valid? */ 00228 if (!PointerPxe->u.Hard.Valid) 00229 { 00230 /* It's not Initialize it */ 00231 TmplPte.u.Flush.PageFrameNumber = MxGetNextPage(1); 00232 *PointerPxe = TmplPte; 00233 00234 /* Zero the page. The PXE is the PTE for the PDPT. */ 00235 RtlZeroMemory(MiPteToAddress(PointerPxe), PAGE_SIZE); 00236 } 00237 } 00238 00239 /* Map PPEs for paged pool */ 00240 MiMapPPEs(MmPagedPoolStart, MmPagedPoolEnd); 00241 00242 /* Setup 1 PPE for hyper space */ 00243 MiMapPPEs((PVOID)HYPER_SPACE, (PVOID)HYPER_SPACE_END); 00244 00245 /* Setup PPEs for system space view */ 00246 MiMapPPEs(MiSystemViewStart, (PCHAR)MiSystemViewStart + MmSystemViewSize); 00247 00248 /* Setup the mapping PDEs */ 00249 MiMapPDEs((PVOID)MI_MAPPING_RANGE_START, (PVOID)MI_MAPPING_RANGE_END); 00250 00251 /* Setup the mapping PTEs */ 00252 MmFirstReservedMappingPte = MiAddressToPte((PVOID)MI_MAPPING_RANGE_START); 00253 MmLastReservedMappingPte = MiAddressToPte((PVOID)MI_MAPPING_RANGE_END); 00254 MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES; 00255 00256 #ifdef _WINKD_ 00257 /* Setup debug mapping PTE */ 00258 MiMapPPEs((PVOID)MI_DEBUG_MAPPING, (PVOID)MI_DEBUG_MAPPING); 00259 MiMapPDEs((PVOID)MI_DEBUG_MAPPING, (PVOID)MI_DEBUG_MAPPING); 00260 MmDebugPte = MiAddressToPte((PVOID)MI_DEBUG_MAPPING); 00261 #endif 00262 00263 /* Setup PDE and PTEs for VAD bitmap and working set list */ 00264 MiMapPDEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 1)); 00265 MiMapPTEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 1)); 00266 } 00267 00268 VOID 00269 NTAPI 00270 INIT_FUNCTION 00271 MiBuildNonPagedPool(VOID) 00272 { 00273 /* Check if this is a machine with less than 256MB of RAM, and no overide */ 00274 if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) && 00275 !(MmSizeOfNonPagedPoolInBytes)) 00276 { 00277 /* Force the non paged pool to be 2MB so we can reduce RAM usage */ 00278 MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024; 00279 } 00280 00281 /* Check if the user gave a ridicuously large nonpaged pool RAM size */ 00282 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > 00283 (MmNumberOfPhysicalPages * 7 / 8)) 00284 { 00285 /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */ 00286 MmSizeOfNonPagedPoolInBytes = 0; 00287 } 00288 00289 /* Check if no registry setting was set, or if the setting was too low */ 00290 if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) 00291 { 00292 /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */ 00293 MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; 00294 MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) / 00295 256 * MmMinAdditionNonPagedPoolPerMb; 00296 } 00297 00298 /* Check if the registy setting or our dynamic calculation was too high */ 00299 if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE) 00300 { 00301 /* Set it to the maximum */ 00302 MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE; 00303 } 00304 00305 /* Check if a percentage cap was set through the registry */ 00306 if (MmMaximumNonPagedPoolPercent) 00307 { 00308 /* Don't feel like supporting this right now */ 00309 UNIMPLEMENTED; 00310 } 00311 00312 /* Page-align the nonpaged pool size */ 00313 MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); 00314 00315 /* Now, check if there was a registry size for the maximum size */ 00316 if (!MmMaximumNonPagedPoolInBytes) 00317 { 00318 /* Start with the default (1MB) and add 400 KB for each MB above 4 */ 00319 MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; 00320 MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) / 00321 256 * MmMaxAdditionNonPagedPoolPerMb; 00322 } 00323 00324 /* Don't let the maximum go too high */ 00325 if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE) 00326 { 00327 /* Set it to the upper limit */ 00328 MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE; 00329 } 00330 00331 /* Convert nonpaged pool size from bytes to pages */ 00332 MmMaximumNonPagedPoolInPages = MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT; 00333 00334 /* Non paged pool starts after the PFN database */ 00335 MmNonPagedPoolStart = MmPfnDatabase + MxPfnAllocation * PAGE_SIZE; 00336 00337 /* Calculate the nonpaged pool expansion start region */ 00338 MmNonPagedPoolExpansionStart = (PCHAR)MmNonPagedPoolStart + 00339 MmSizeOfNonPagedPoolInBytes; 00340 ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolExpansionStart)); 00341 00342 /* And this is where the none paged pool ends */ 00343 MmNonPagedPoolEnd = (PCHAR)MmNonPagedPoolStart + MmMaximumNonPagedPoolInBytes; 00344 ASSERT(MmNonPagedPoolEnd < (PVOID)MM_HAL_VA_START); 00345 00346 /* Map PPEs and PDEs for non paged pool (including expansion) */ 00347 MiMapPPEs(MmNonPagedPoolStart, MmNonPagedPoolEnd); 00348 MiMapPDEs(MmNonPagedPoolStart, MmNonPagedPoolEnd); 00349 00350 /* Map the nonpaged pool PTEs (without expansion) */ 00351 MiMapPTEs(MmNonPagedPoolStart, (PCHAR)MmNonPagedPoolExpansionStart - 1); 00352 00353 /* Initialize the ARM3 nonpaged pool */ 00354 MiInitializeNonPagedPool(); 00355 MiInitializeNonPagedPoolThresholds(); 00356 00357 } 00358 00359 VOID 00360 NTAPI 00361 INIT_FUNCTION 00362 MiBuildSystemPteSpace() 00363 { 00364 PMMPTE PointerPte; 00365 00366 /* Use the default numer of system PTEs */ 00367 MmNumberOfSystemPtes = MI_NUMBER_SYSTEM_PTES; 00368 MiNonPagedSystemSize = (MmNumberOfSystemPtes + 1) * PAGE_SIZE; 00369 00370 /* Put system PTEs at the start of the system VA space */ 00371 MiSystemPteSpaceStart = MmNonPagedSystemStart; 00372 MiSystemPteSpaceEnd = (PUCHAR)MiSystemPteSpaceStart + MiNonPagedSystemSize; 00373 00374 /* Map the PPEs and PDEs for the system PTEs */ 00375 MiMapPPEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd); 00376 MiMapPDEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd); 00377 00378 /* Initialize the system PTE space */ 00379 PointerPte = MiAddressToPte(MiSystemPteSpaceStart); 00380 MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace); 00381 00382 /* Reserve system PTEs for zeroing PTEs and clear them */ 00383 MiFirstReservedZeroingPte = MiReserveSystemPtes(MI_ZERO_PTES, SystemPteSpace); 00384 RtlZeroMemory(MiFirstReservedZeroingPte, MI_ZERO_PTES * sizeof(MMPTE)); 00385 00386 /* Set the counter to maximum */ 00387 MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1; 00388 } 00389 00390 static 00391 VOID 00392 MiSetupPfnForPageTable( 00393 PFN_NUMBER PageFrameIndex, 00394 PMMPTE PointerPte) 00395 { 00396 PMMPFN Pfn; 00397 PMMPDE PointerPde; 00398 00399 /* Get the pfn entry for this page */ 00400 Pfn = MiGetPfnEntry(PageFrameIndex); 00401 00402 /* Check if it's valid memory */ 00403 if ((PageFrameIndex <= MmHighestPhysicalPage) && 00404 (MmIsAddressValid(Pfn)) && 00405 (Pfn->u3.e1.PageLocation == ActiveAndValid)) 00406 { 00407 /* Setup the PFN entry */ 00408 Pfn->u1.WsIndex = 0; 00409 Pfn->u2.ShareCount++; 00410 Pfn->PteAddress = PointerPte; 00411 Pfn->OriginalPte = *PointerPte; 00412 Pfn->u3.e1.PageLocation = ActiveAndValid; 00413 Pfn->u3.e1.CacheAttribute = MiNonCached; 00414 Pfn->u3.e2.ReferenceCount = 1; 00415 Pfn->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte)); 00416 } 00417 00418 /* Increase the shared count of the PFN entry for the PDE */ 00419 PointerPde = MiAddressToPde(MiPteToAddress(PointerPte)); 00420 Pfn = MiGetPfnEntry(PFN_FROM_PTE(PointerPde)); 00421 Pfn->u2.ShareCount++; 00422 } 00423 00424 VOID 00425 NTAPI 00426 MiBuildPfnDatabaseFromPageTables(VOID) 00427 { 00428 PVOID Address = NULL; 00429 PFN_NUMBER PageFrameIndex; 00430 PMMPDE PointerPde; 00431 PMMPTE PointerPte; 00432 ULONG k, l; 00433 PMMPFN Pfn; 00434 #if (_MI_PAGING_LEVELS >= 3) 00435 PMMPDE PointerPpe; 00436 ULONG j; 00437 #endif 00438 #if (_MI_PAGING_LEVELS == 4) 00439 PMMPDE PointerPxe; 00440 ULONG i; 00441 #endif 00442 00443 /* Manual setup of the top level page directory */ 00444 #if (_MI_PAGING_LEVELS == 4) 00445 PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PXE_BASE)); 00446 #elif (_MI_PAGING_LEVELS == 3) 00447 PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PPE_BASE)); 00448 #else 00449 PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PDE_BASE)); 00450 #endif 00451 Pfn = MiGetPfnEntry(PageFrameIndex); 00452 ASSERT(Pfn->u3.e1.PageLocation == ActiveAndValid); 00453 Pfn->u1.WsIndex = 0; 00454 Pfn->u2.ShareCount = 1; 00455 Pfn->PteAddress = NULL; 00456 Pfn->u3.e1.CacheAttribute = MiNonCached; 00457 Pfn->u3.e2.ReferenceCount = 1; 00458 Pfn->u4.PteFrame = 0; 00459 00460 #if (_MI_PAGING_LEVELS == 4) 00461 /* Loop all PXEs in the PML4 */ 00462 PointerPxe = MiAddressToPxe(Address); 00463 for (i = 0; i < PXE_PER_PAGE; i++, PointerPxe++) 00464 { 00465 /* Skip invalid PXEs */ 00466 if (!PointerPxe->u.Hard.Valid) continue; 00467 00468 /* Handle the PFN */ 00469 PageFrameIndex = PFN_FROM_PXE(PointerPxe); 00470 MiSetupPfnForPageTable(PageFrameIndex, PointerPxe); 00471 00472 /* Get starting VA for this PXE */ 00473 Address = MiPxeToAddress(PointerPxe); 00474 #endif 00475 #if (_MI_PAGING_LEVELS >= 3) 00476 /* Loop all PPEs in this PDP */ 00477 PointerPpe = MiAddressToPpe(Address); 00478 for (j = 0; j < PPE_PER_PAGE; j++, PointerPpe++) 00479 { 00480 /* Skip invalid PPEs */ 00481 if (!PointerPpe->u.Hard.Valid) continue; 00482 00483 /* Handle the PFN */ 00484 PageFrameIndex = PFN_FROM_PPE(PointerPpe); 00485 MiSetupPfnForPageTable(PageFrameIndex, PointerPpe); 00486 00487 /* Get starting VA for this PPE */ 00488 Address = MiPpeToAddress(PointerPpe); 00489 #endif 00490 /* Loop all PDEs in this PD */ 00491 PointerPde = MiAddressToPde(Address); 00492 for (k = 0; k < PDE_PER_PAGE; k++, PointerPde++) 00493 { 00494 /* Skip invalid PDEs */ 00495 if (!PointerPde->u.Hard.Valid) continue; 00496 00497 /* Handle the PFN */ 00498 PageFrameIndex = PFN_FROM_PDE(PointerPde); 00499 MiSetupPfnForPageTable(PageFrameIndex, PointerPde); 00500 00501 /* Get starting VA for this PDE */ 00502 Address = MiPdeToAddress(PointerPde); 00503 00504 /* Loop all PTEs in this PT */ 00505 PointerPte = MiAddressToPte(Address); 00506 for (l = 0; l < PTE_PER_PAGE; l++, PointerPte++) 00507 { 00508 /* Skip invalid PTEs */ 00509 if (!PointerPte->u.Hard.Valid) continue; 00510 00511 /* Handle the PFN */ 00512 PageFrameIndex = PFN_FROM_PTE(PointerPte); 00513 MiSetupPfnForPageTable(PageFrameIndex, PointerPte); 00514 } 00515 } 00516 #if (_MI_PAGING_LEVELS >= 3) 00517 } 00518 #endif 00519 #if (_MI_PAGING_LEVELS == 4) 00520 } 00521 #endif 00522 } 00523 00524 VOID 00525 NTAPI 00526 INIT_FUNCTION 00527 MiAddDescriptorToDatabase( 00528 PFN_NUMBER BasePage, 00529 PFN_NUMBER PageCount, 00530 TYPE_OF_MEMORY MemoryType) 00531 { 00532 PMMPFN Pfn; 00533 00534 ASSERT(!MiIsMemoryTypeInvisible(MemoryType)); 00535 00536 /* Check if the memory is free */ 00537 if (MiIsMemoryTypeFree(MemoryType)) 00538 { 00539 /* Get the last pfn of this descriptor. Note we loop backwards */ 00540 Pfn = &MmPfnDatabase[BasePage + PageCount - 1]; 00541 00542 /* Loop all pages */ 00543 while (PageCount--) 00544 { 00545 /* Add it to the free list */ 00546 Pfn->u3.e1.CacheAttribute = MiNonCached; 00547 MiInsertPageInFreeList(BasePage + PageCount); 00548 00549 /* Go to the previous page */ 00550 Pfn--; 00551 } 00552 } 00553 else if (MemoryType == LoaderXIPRom) 00554 { 00555 Pfn = &MmPfnDatabase[BasePage]; 00556 while (PageCount--) 00557 { 00558 /* Make it a pseudo-I/O ROM mapping */ 00559 Pfn->PteAddress = 0; 00560 Pfn->u1.Flink = 0; 00561 Pfn->u2.ShareCount = 0; 00562 Pfn->u3.e1.PageLocation = 0; 00563 Pfn->u3.e1.CacheAttribute = MiNonCached; 00564 Pfn->u3.e1.Rom = 1; 00565 Pfn->u3.e1.PrototypePte = 1; 00566 Pfn->u3.e2.ReferenceCount = 0; 00567 Pfn->u4.InPageError = 0; 00568 Pfn->u4.PteFrame = 0; 00569 00570 /* Advance one */ 00571 Pfn++; 00572 } 00573 } 00574 else if (MemoryType == LoaderBad) 00575 { 00576 // FIXME: later 00577 ASSERT(FALSE); 00578 } 00579 else 00580 { 00581 /* For now skip it */ 00582 DbgPrint("Skipping BasePage=0x%lx, PageCount=0x%lx, MemoryType=%lx\n", 00583 BasePage, PageCount, MemoryType); 00584 Pfn = &MmPfnDatabase[BasePage]; 00585 while (PageCount--) 00586 { 00587 /* Make an active PFN */ 00588 Pfn->u3.e1.PageLocation = ActiveAndValid; 00589 00590 /* Advance one */ 00591 Pfn++; 00592 } 00593 } 00594 } 00595 00596 VOID 00597 NTAPI 00598 INIT_FUNCTION 00599 MiBuildPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00600 { 00601 PLIST_ENTRY ListEntry; 00602 PMEMORY_ALLOCATION_DESCRIPTOR Descriptor; 00603 PFN_NUMBER BasePage, PageCount; 00604 00605 /* Map the PDEs and PPEs for the pfn database (ignore holes) */ 00606 #if (_MI_PAGING_LEVELS >= 3) 00607 MiMapPPEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1); 00608 #endif 00609 MiMapPDEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1); 00610 00611 /* First initialize the color tables */ 00612 MiInitializeColorTables(); 00613 00614 /* Loop the memory descriptors */ 00615 for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink; 00616 ListEntry != &LoaderBlock->MemoryDescriptorListHead; 00617 ListEntry = ListEntry->Flink) 00618 { 00619 /* Get the descriptor */ 00620 Descriptor = CONTAINING_RECORD(ListEntry, 00621 MEMORY_ALLOCATION_DESCRIPTOR, 00622 ListEntry); 00623 00624 /* Skip invisible memory */ 00625 if (MiIsMemoryTypeInvisible(Descriptor->MemoryType)) continue; 00626 00627 /* If this is the free descriptor, use the copy instead */ 00628 if (Descriptor == MxFreeDescriptor) Descriptor = &MxOldFreeDescriptor; 00629 00630 /* Get the range for this descriptor */ 00631 BasePage = Descriptor->BasePage; 00632 PageCount = Descriptor->PageCount; 00633 00634 /* Map the pages for the database */ 00635 MiMapPTEs(&MmPfnDatabase[BasePage], 00636 (PUCHAR)(&MmPfnDatabase[BasePage + PageCount]) - 1); 00637 00638 /* If this was the free descriptor, skip the next step */ 00639 if (Descriptor == &MxOldFreeDescriptor) continue; 00640 00641 /* Add this descriptor to the database */ 00642 MiAddDescriptorToDatabase(BasePage, PageCount, Descriptor->MemoryType); 00643 } 00644 00645 /* At this point the whole pfn database is mapped. We are about to add the 00646 pages from the free descriptor to the database, so from now on we cannot 00647 use it anymore. */ 00648 00649 /* Now add the free descriptor */ 00650 BasePage = MxFreeDescriptor->BasePage; 00651 PageCount = MxFreeDescriptor->PageCount; 00652 MiAddDescriptorToDatabase(BasePage, PageCount, LoaderFree); 00653 00654 /* And finally the memory we used */ 00655 BasePage = MxOldFreeDescriptor.BasePage; 00656 PageCount = MxFreeDescriptor->BasePage - BasePage; 00657 MiAddDescriptorToDatabase(BasePage, PageCount, LoaderMemoryData); 00658 00659 /* Reset the descriptor back so we can create the correct memory blocks */ 00660 *MxFreeDescriptor = MxOldFreeDescriptor; 00661 } 00662 00663 NTSTATUS 00664 NTAPI 00665 INIT_FUNCTION 00666 MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock) 00667 { 00668 KIRQL OldIrql; 00669 00670 ASSERT(MxPfnAllocation != 0); 00671 00672 /* Set some hardcoded addresses */ 00673 MmHyperSpaceEnd = (PVOID)HYPER_SPACE_END; 00674 MmNonPagedSystemStart = (PVOID)MM_SYSTEM_SPACE_START; 00675 MmPfnDatabase = (PVOID)MI_PFN_DATABASE; 00676 MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST; 00677 00678 00679 // PrototypePte.u.Proto.Valid = 1 00680 // PrototypePte.u.ReadOnly 00681 // PrototypePte.u.Prototype 00682 // PrototypePte.u.Protection = MM_READWRITE; 00683 // PrototypePte.u.ProtoAddress 00684 PrototypePte.u.Soft.PageFileHigh = MI_PTE_LOOKUP_NEEDED; 00685 00686 00687 MiInitializePageTable(); 00688 00689 MiBuildNonPagedPool(); 00690 00691 MiBuildSystemPteSpace(); 00692 00693 /* Need to be at DISPATCH_LEVEL for MiInsertPageInFreeList */ 00694 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00695 00696 /* Map the PFN database pages */ 00697 MiBuildPfnDatabase(LoaderBlock); 00698 00699 /* Now process the page tables */ 00700 MiBuildPfnDatabaseFromPageTables(); 00701 00702 /* PFNs are initialized now! */ 00703 MiPfnsInitialized = TRUE; 00704 00705 //KeLowerIrql(OldIrql); 00706 00707 /* Need to be at DISPATCH_LEVEL for InitializePool */ 00708 //KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00709 00710 /* Initialize the nonpaged pool */ 00711 InitializePool(NonPagedPool, 0); 00712 00713 KeLowerIrql(OldIrql); 00714 00715 /* Initialize the balancer */ 00716 MmInitializeBalancer((ULONG)MmAvailablePages, 0); 00717 00718 /* Make sure we have everything we need */ 00719 ASSERT(MmPfnDatabase); 00720 ASSERT(MmNonPagedSystemStart); 00721 ASSERT(MmNonPagedPoolStart); 00722 ASSERT(MmSizeOfNonPagedPoolInBytes); 00723 ASSERT(MmMaximumNonPagedPoolInBytes); 00724 ASSERT(MmNonPagedPoolExpansionStart); 00725 ASSERT(MmHyperSpaceEnd); 00726 ASSERT(MmNumberOfSystemPtes); 00727 ASSERT(MiAddressToPde(MmNonPagedPoolStart)->u.Hard.Valid); 00728 ASSERT(MiAddressToPte(MmNonPagedPoolStart)->u.Hard.Valid); 00729 00730 return STATUS_SUCCESS; 00731 } Generated on Sat May 26 2012 04:22:07 for ReactOS by
1.7.6.1
|