Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

iniaxp64.c

Go to the documentation of this file.
00001 /*++ 00002 00003 Copyright (c) 1990 Microsoft Corporation 00004 Copyright (c) 1992 Digital Equipment Corporation 00005 00006 Module Name: 00007 00008 initalpha.c 00009 00010 Abstract: 00011 00012 This module contains the machine dependent initialization for the 00013 memory management component. It is specifically tailored to the 00014 ALPHA architecture. 00015 00016 Author: 00017 00018 Lou Perazzoli (loup) 3-Apr-1990 00019 Joe Notarangelo 23-Apr-1992 ALPHA version 00020 00021 Revision History: 00022 00023 Landy Wang (landyw) 02-June-1998 : Modifications for full 3-level 64-bit NT. 00024 00025 --*/ 00026 00027 #include "mi.h" 00028 #include <inbv.h> 00029 00030 // 00031 // Local definitions. 00032 // 00033 00034 #define _1mbInPages (0x100000 >> PAGE_SHIFT) 00035 #define _4gbInPages (0x100000000 >> PAGE_SHIFT) 00036 00037 // 00038 // Local data. 00039 // 00040 00041 PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor; 00042 PFN_NUMBER MxNextPhysicalPage; 00043 PFN_NUMBER MxNumberOfPages; 00044 00045 PFN_NUMBER 00046 MxGetNextPage ( 00047 VOID 00048 ) 00049 00050 /*++ 00051 00052 Routine Description: 00053 00054 This function returns the next physical page number from either the 00055 largest low memory descritor or the largest free descriptor. If there 00056 are no physical pages left, then a bugcheck is executed since the 00057 system cannot be initialized. 00058 00059 Arguments: 00060 00061 LoaderBlock - Supplies the address of the loader block. 00062 00063 Return Value: 00064 00065 None. 00066 00067 Environment: 00068 00069 Kernel mode. 00070 00071 --*/ 00072 00073 { 00074 00075 // 00076 // If there are free pages left in the current descriptor, then 00077 // return the next physical page. Otherwise, attempt to switch 00078 // descriptors. 00079 // 00080 00081 if (MxNumberOfPages != 0) { 00082 MxNumberOfPages -= 1; 00083 return MxNextPhysicalPage++; 00084 00085 } else { 00086 00087 // 00088 // If the current descriptor is not the largest free descriptor, 00089 // then switch to the largest free descriptor. Otherwise, bugcheck. 00090 // 00091 00092 if (MxNextPhysicalPage == 00093 (MxFreeDescriptor->BasePage + MxFreeDescriptor->PageCount)) { 00094 KeBugCheckEx(INSTALL_MORE_MEMORY, 00095 MmNumberOfPhysicalPages, 00096 MmLowestPhysicalPage, 00097 MmHighestPhysicalPage, 00098 0); 00099 00100 return 0; 00101 00102 } else { 00103 MxNumberOfPages = MxFreeDescriptor->PageCount - 1; 00104 MxNextPhysicalPage = MxFreeDescriptor->BasePage; 00105 return MxNextPhysicalPage++; 00106 } 00107 } 00108 } 00109 00110 VOID 00111 MiInitMachineDependent ( 00112 IN PLOADER_PARAMETER_BLOCK LoaderBlock 00113 ) 00114 00115 /*++ 00116 00117 Routine Description: 00118 00119 This routine performs the necessary operations to enable virtual 00120 memory. This includes building the page directory parent pages and 00121 the page directories for the system, building page table pages to map 00122 the code section, the data section, the stack section and the trap handler. 00123 It also initializes the PFN database and populates the free list. 00124 00125 Arguments: 00126 00127 LoaderBlock - Supplies the address of the loader block. 00128 00129 Return Value: 00130 00131 None. 00132 00133 Environment: 00134 00135 Kernel mode. 00136 00137 --*/ 00138 00139 { 00140 LOGICAL First; 00141 CHAR Buffer[256]; 00142 PMMPFN BasePfn; 00143 PMMPFN BottomPfn; 00144 PMMPFN TopPfn; 00145 PFN_NUMBER i; 00146 ULONG j; 00147 PFN_NUMBER HighPage; 00148 PFN_NUMBER PagesLeft; 00149 PFN_NUMBER PageNumber; 00150 PFN_NUMBER PtePage; 00151 PFN_NUMBER PdePage; 00152 PFN_NUMBER PpePage; 00153 PFN_NUMBER FrameNumber; 00154 PFN_NUMBER PfnAllocation; 00155 PEPROCESS CurrentProcess; 00156 PVOID SpinLockPage; 00157 PFN_NUMBER MostFreePage; 00158 PFN_NUMBER MostFreeLowMem; 00159 PLIST_ENTRY NextMd; 00160 SIZE_T MaxPool; 00161 PFN_NUMBER NextPhysicalPage; 00162 KIRQL OldIrql; 00163 PMEMORY_ALLOCATION_DESCRIPTOR FreeDescriptorLowMem; 00164 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 00165 MMPTE TempPte; 00166 PMMPTE PointerPde; 00167 PMMPTE PointerPte; 00168 PMMPTE LastPte; 00169 PMMPTE CacheStackPage; 00170 PMMPTE Pde; 00171 PMMPTE StartPpe; 00172 PMMPTE StartPde; 00173 PMMPTE StartPte; 00174 PMMPTE EndPpe; 00175 PMMPTE EndPde; 00176 PMMPTE EndPte; 00177 PMMPFN Pfn1; 00178 PMMPFN Pfn2; 00179 PULONG PointerLong; 00180 PMMFREE_POOL_ENTRY Entry; 00181 PVOID NonPagedPoolStartVirtual; 00182 ULONG Range; 00183 00184 MostFreePage = 0; 00185 MostFreeLowMem = 0; 00186 FreeDescriptorLowMem = NULL; 00187 00188 // 00189 // Get the lower bound of the free physical memory and the number of 00190 // physical pages by walking the memory descriptor lists. In addition, 00191 // find the memory descriptor with the most free pages that is within 00192 // the first 4gb of physical memory. This memory can be used to allocate 00193 // common buffers for use by PCI devices that cannot address more than 00194 // 32 bits. Also find the largest free memory descriptor. 00195 // 00196 00197 // 00198 // When restoring a hibernation image, OS Loader needs to use "a few" extra 00199 // pages of LoaderFree memory. 00200 // This is not accounted for when reserving memory for hibernation below. 00201 // Start with a safety margin to allow for this plus modest future increase. 00202 // 00203 00204 MmHiberPages = 96; 00205 00206 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00207 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00208 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00209 MEMORY_ALLOCATION_DESCRIPTOR, 00210 ListEntry); 00211 00212 HighPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount - 1; 00213 00214 // 00215 // This check results in /BURNMEMORY chunks not being counted. 00216 // 00217 00218 if (MemoryDescriptor->MemoryType != LoaderBad) { 00219 MmNumberOfPhysicalPages += (PFN_COUNT)MemoryDescriptor->PageCount; 00220 } 00221 00222 // 00223 // If the lowest page is lower than the lowest page encountered 00224 // so far, then set the new low page number. 00225 // 00226 00227 if (MemoryDescriptor->BasePage < MmLowestPhysicalPage) { 00228 MmLowestPhysicalPage = MemoryDescriptor->BasePage; 00229 } 00230 00231 // 00232 // If the highest page is greater than the highest page encountered 00233 // so far, then set the new high page number. 00234 // 00235 00236 if (HighPage > MmHighestPhysicalPage) { 00237 MmHighestPhysicalPage = HighPage; 00238 } 00239 00240 // 00241 // Locate the largest free block starting below 4GB and the largest 00242 // free block. 00243 // 00244 00245 if ((MemoryDescriptor->MemoryType == LoaderFree) || 00246 (MemoryDescriptor->MemoryType == LoaderLoadedProgram) || 00247 (MemoryDescriptor->MemoryType == LoaderFirmwareTemporary) || 00248 (MemoryDescriptor->MemoryType == LoaderOsloaderStack)) { 00249 00250 // 00251 // Every page that will be used as free memory that is not already 00252 // marked as LoaderFree must be counted so a hibernate can reserve 00253 // the proper amount. 00254 // 00255 00256 if (MemoryDescriptor->MemoryType != LoaderFree) { 00257 MmHiberPages += MemoryDescriptor->PageCount; 00258 } 00259 00260 if ((MemoryDescriptor->PageCount > MostFreeLowMem) && 00261 (MemoryDescriptor->BasePage < _4gbInPages) && 00262 (HighPage < _4gbInPages)) { 00263 MostFreeLowMem = MemoryDescriptor->PageCount; 00264 FreeDescriptorLowMem = MemoryDescriptor; 00265 00266 } else if (MemoryDescriptor->PageCount > MostFreePage) { 00267 MostFreePage = MemoryDescriptor->PageCount; 00268 MxFreeDescriptor = MemoryDescriptor; 00269 } 00270 } else if (MemoryDescriptor->MemoryType == LoaderOsloaderHeap) { 00271 // 00272 // We do not want to use this memory yet as it still has important 00273 // data structures in it. But we still want to account for this in 00274 // the hibernation pages 00275 // 00276 MmHiberPages += MemoryDescriptor->PageCount; 00277 } 00278 00279 NextMd = MemoryDescriptor->ListEntry.Flink; 00280 } 00281 00282 MmHighestPossiblePhysicalPage = MmHighestPhysicalPage; 00283 00284 // 00285 // Perform sanity checks on the results of walking the memory 00286 // descriptors. 00287 // 00288 // If the number of physical pages is less that 1024 (i.e., 8mb), then 00289 // bugcheck. There is not enough memory to run the system. 00290 // 00291 00292 if (MmNumberOfPhysicalPages < 1024) { 00293 KeBugCheckEx(INSTALL_MORE_MEMORY, 00294 MmNumberOfPhysicalPages, 00295 MmLowestPhysicalPage, 00296 MmHighestPhysicalPage, 00297 0); 00298 } 00299 00300 // 00301 // If there is no free descriptor below 4gb, then it is not possible to 00302 // run devices that only support 32 address bits. It is also highly 00303 // unlikely that the configuration data is correct so bugcheck. 00304 // 00305 00306 if (FreeDescriptorLowMem == NULL) { 00307 InbvDisplayString("MmInit *** FATAL ERROR *** no free memory below 4gb\n"); 00308 KeBugCheck(MEMORY_MANAGEMENT); 00309 } 00310 00311 // 00312 // Set the initial nonpaged frame allocation parameters. 00313 // 00314 00315 MxNextPhysicalPage = FreeDescriptorLowMem->BasePage; 00316 MxNumberOfPages = FreeDescriptorLowMem->PageCount; 00317 00318 // 00319 // Compute the initial and maximum size of nonpaged pool. The initial 00320 // allocation of nonpaged pool is such that it is both virtually and 00321 // physically contiguous. 00322 // 00323 // If the size of the initial nonpaged pool was initialized from the 00324 // registry and is greater than 7/8 of physical memory, then force the 00325 // size of the initial nonpaged pool to be computed. 00326 // 00327 00328 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > 00329 (7 * (MmNumberOfPhysicalPages >> 3))) { 00330 MmSizeOfNonPagedPoolInBytes = 0; 00331 } 00332 00333 // 00334 // If the size of the initial nonpaged pool is less than the minimum 00335 // amount, then compute the size of initial nonpaged pool as the minimum 00336 // size up to 8mb and a computed amount for every 1mb thereafter. 00337 // 00338 00339 if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) { 00340 MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; 00341 if (MmNumberOfPhysicalPages > 1024) { 00342 MmSizeOfNonPagedPoolInBytes += 00343 ((MmNumberOfPhysicalPages - 1024) / _1mbInPages) * 00344 MmMinAdditionNonPagedPoolPerMb; 00345 } 00346 } 00347 00348 // 00349 // Align the size of the initial nonpaged pool to page size boundary. 00350 // 00351 00352 MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); 00353 00354 // 00355 // Limit initial nonpaged pool size to the maximum allowable size. 00356 // 00357 00358 if (MmSizeOfNonPagedPoolInBytes > MM_MAX_INITIAL_NONPAGED_POOL) { 00359 MmSizeOfNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL; 00360 } 00361 00362 // 00363 // If the computed size of the initial nonpaged pool will not fit in the 00364 // largest low memory descriptor, then recompute the size of nonpaged pool 00365 // to be the size of the largest low memory descriptor. If the largest 00366 // low memory descriptor does not contain the minimum initial nonpaged 00367 // pool size, then the system cannot be booted. 00368 // 00369 00370 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > MxNumberOfPages) { 00371 00372 // 00373 // Reserve all of low memory for nonpaged pool. 00374 // 00375 00376 MmSizeOfNonPagedPoolInBytes = MxNumberOfPages << PAGE_SHIFT; 00377 if(MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) { 00378 InbvDisplayString("MmInit *** FATAL ERROR *** cannot allocate nonpaged pool\n"); 00379 sprintf(Buffer, 00380 "Largest description = %d pages, require %d pages\n", 00381 MxNumberOfPages, 00382 MmMinimumNonPagedPoolSize >> PAGE_SHIFT); 00383 00384 InbvDisplayString(Buffer); 00385 KeBugCheck(MEMORY_MANAGEMENT); 00386 } 00387 } 00388 00389 // 00390 // Reserve the physically and virtually contiguous memory that maps 00391 // the initial nonpaged pool and set page frame allocation parameters. 00392 // 00393 00394 MxNextPhysicalPage += (PFN_NUMBER)(MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT); 00395 MxNumberOfPages -= (PFN_NUMBER)(MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT); 00396 00397 // 00398 // Calculate the maximum size of nonpaged pool. 00399 // 00400 00401 if (MmMaximumNonPagedPoolInBytes == 0) { 00402 00403 // 00404 // Calculate the size of nonpaged pool. If 8mb or less use the 00405 // minimum size, then for every MB above 8mb add extra pages. 00406 // 00407 00408 MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; 00409 00410 // 00411 // Make sure enough expansion for PFN database exists. 00412 // 00413 00414 MmMaximumNonPagedPoolInBytes += 00415 ((ULONG_PTR)PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN))); 00416 00417 // 00418 // If the number of physical pages is greater than 8mb, then compute 00419 // an additional amount for every 1mb thereafter. 00420 // 00421 00422 if (MmNumberOfPhysicalPages > 1024) { 00423 MmMaximumNonPagedPoolInBytes += 00424 ((MmNumberOfPhysicalPages - 1024) / _1mbInPages) * 00425 MmMaxAdditionNonPagedPoolPerMb; 00426 } 00427 00428 // 00429 // If the maximum size of nonpaged pool is greater than the maximum 00430 // default size of nonpaged pool, then limit the maximum size of 00431 // onopaged pool to the maximum default size. 00432 // 00433 00434 if (MmMaximumNonPagedPoolInBytes > MM_MAX_DEFAULT_NONPAGED_POOL) { 00435 MmMaximumNonPagedPoolInBytes = MM_MAX_DEFAULT_NONPAGED_POOL; 00436 } 00437 } 00438 00439 // 00440 // Align the maximum size of nonpaged pool to page size boundary. 00441 // 00442 00443 MmMaximumNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); 00444 00445 // 00446 // Compute the maximum size of nonpaged pool to include 16 additional 00447 // pages and enough space to map the PFN database. 00448 // 00449 00450 MaxPool = MmSizeOfNonPagedPoolInBytes + (PAGE_SIZE * 16) + 00451 ((ULONG_PTR)PAGE_ALIGN((MmHighestPhysicalPage + 1) * sizeof(MMPFN))); 00452 00453 // 00454 // If the maximum size of nonpaged pool is less than the computed 00455 // maximum size of nonpaged pool, then set the maximum size of nonpaged 00456 // pool to the computed maximum size. 00457 // 00458 00459 if (MmMaximumNonPagedPoolInBytes < MaxPool) { 00460 MmMaximumNonPagedPoolInBytes = MaxPool; 00461 } 00462 00463 // 00464 // Limit maximum nonpaged pool to MM_MAX_ADDITIONAL_NONPAGED_POOL. 00465 // 00466 00467 if (MmMaximumNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00468 MmMaximumNonPagedPoolInBytes = MM_MAX_ADDITIONAL_NONPAGED_POOL; 00469 } 00470 00471 // 00472 // Compute the starting address of nonpaged pool. 00473 // 00474 00475 MmNonPagedPoolStart = (PCHAR)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes; 00476 NonPagedPoolStartVirtual = MmNonPagedPoolStart; 00477 00478 // 00479 // Calculate the starting address for nonpaged system space rounded 00480 // down to a second level PDE mapping boundary. 00481 // 00482 00483 MmNonPagedSystemStart = (PVOID)(((ULONG_PTR)MmNonPagedPoolStart - 00484 (((ULONG_PTR)MmNumberOfSystemPtes + 1) * PAGE_SIZE)) & 00485 (~PAGE_DIRECTORY2_MASK)); 00486 00487 // 00488 // Limit the starting address of system space to the lowest allowable 00489 // address for nonpaged system space. 00490 // 00491 00492 if (MmNonPagedSystemStart < MM_LOWEST_NONPAGED_SYSTEM_START) { 00493 MmNonPagedSystemStart = MM_LOWEST_NONPAGED_SYSTEM_START; 00494 } 00495 00496 // 00497 // Recompute the actual number of system PTEs. 00498 // 00499 00500 MmNumberOfSystemPtes = (ULONG)(((ULONG_PTR)MmNonPagedPoolStart - 00501 (ULONG_PTR)MmNonPagedSystemStart) >> PAGE_SHIFT) - 1; 00502 00503 ASSERT(MmNumberOfSystemPtes > 1000); 00504 00505 // 00506 // Set the global bit for all PPEs and PDEs in system space. 00507 // 00508 00509 StartPde = MiGetPdeAddress(MM_SYSTEM_SPACE_START); 00510 EndPde = MiGetPdeAddress(MM_SYSTEM_SPACE_END); 00511 First = TRUE; 00512 00513 while (StartPde <= EndPde) { 00514 00515 if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) { 00516 First = FALSE; 00517 StartPpe = MiGetPteAddress(StartPde); 00518 if (StartPpe->u.Hard.Valid == 0) { 00519 StartPpe += 1; 00520 StartPde = MiGetVirtualAddressMappedByPte (StartPpe); 00521 continue; 00522 } 00523 TempPte = *StartPpe; 00524 TempPte.u.Hard.Global = 1; 00525 *StartPpe = TempPte; 00526 } 00527 00528 TempPte = *StartPde; 00529 TempPte.u.Hard.Global = 1; 00530 *StartPde = TempPte; 00531 StartPde += 1; 00532 } 00533 00534 // 00535 // If HYDRA, then reset the global bit for all PPE & PDEs in session space. 00536 // 00537 00538 if (MiHydra == TRUE) { 00539 00540 StartPde = MiGetPdeAddress(MmSessionBase); 00541 EndPde = MiGetPdeAddress(MI_SESSION_SPACE_END); 00542 First = TRUE; 00543 00544 while (StartPde < EndPde) { 00545 00546 if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) { 00547 First = FALSE; 00548 StartPpe = MiGetPteAddress(StartPde); 00549 if (StartPpe->u.Hard.Valid == 0) { 00550 StartPpe += 1; 00551 StartPde = MiGetVirtualAddressMappedByPte (StartPpe); 00552 continue; 00553 } 00554 TempPte = *StartPpe; 00555 TempPte.u.Hard.Global = 0; 00556 *StartPpe = TempPte; 00557 } 00558 00559 TempPte = *StartPde; 00560 TempPte.u.Hard.Global = 0; 00561 *StartPde = TempPte; 00562 00563 ASSERT(StartPde->u.Long == 0); 00564 00565 StartPde += 1; 00566 } 00567 } 00568 00569 // 00570 // Allocate a page directory and a pair of page table pages. 00571 // Map the hyper space page directory page into the top level parent 00572 // directory & the hyper space page table page into the page directory 00573 // and map an additional page that will eventually be used for the 00574 // working set list. Page tables after the first two are set up later 00575 // on during individual process working set initialization. 00576 // 00577 // The working set list page will eventually be a part of hyper space. 00578 // It is mapped into the second level page directory page so it can be 00579 // zeroed and so it will be accounted for in the PFN database. Later 00580 // the page will be unmapped, and its page frame number captured in the 00581 // system process object. 00582 // 00583 00584 TempPte = ValidKernelPte; 00585 TempPte.u.Hard.Global = 0; 00586 00587 StartPde = MiGetPdeAddress(HYPER_SPACE); 00588 StartPpe = MiGetPteAddress(StartPde); 00589 00590 if (StartPpe->u.Hard.Valid == 0) { 00591 ASSERT (StartPpe->u.Long == 0); 00592 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00593 *StartPpe = TempPte; 00594 RtlZeroMemory (MiGetVirtualAddressMappedByPte (StartPpe), 00595 PAGE_SIZE); 00596 } 00597 00598 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00599 *StartPde = TempPte; 00600 00601 // 00602 // Zero the hyper space page table page. 00603 // 00604 00605 StartPte = MiGetPteAddress(HYPER_SPACE); 00606 RtlZeroMemory(StartPte, PAGE_SIZE); 00607 00608 // 00609 // Allocate page directory and page table pages for 00610 // system PTEs and nonpaged pool. 00611 // 00612 00613 TempPte = ValidKernelPte; 00614 StartPde = MiGetPdeAddress(MmNonPagedSystemStart); 00615 EndPde = MiGetPdeAddress(MmNonPagedPoolEnd); 00616 First = TRUE; 00617 00618 while (StartPde <= EndPde) { 00619 00620 if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) { 00621 First = FALSE; 00622 StartPpe = MiGetPteAddress(StartPde); 00623 if (StartPpe->u.Hard.Valid == 0) { 00624 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00625 *StartPpe = TempPte; 00626 RtlZeroMemory (MiGetVirtualAddressMappedByPte (StartPpe), 00627 PAGE_SIZE); 00628 } 00629 } 00630 00631 if (StartPde->u.Hard.Valid == 0) { 00632 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00633 *StartPde = TempPte; 00634 } 00635 StartPde += 1; 00636 } 00637 00638 // 00639 // Zero the PTEs that map the nonpaged region just before nonpaged pool. 00640 // 00641 00642 StartPte = MiGetPteAddress(MmNonPagedSystemStart); 00643 EndPte = MiGetPteAddress(MmNonPagedPoolEnd); 00644 00645 if (!MiIsPteOnPdeBoundary (EndPte)) { 00646 EndPte = (PMMPTE)((ULONG_PTR)PAGE_ALIGN (EndPte) + PAGE_SIZE); 00647 } 00648 00649 RtlZeroMemory(StartPte, (ULONG_PTR)EndPte - (ULONG_PTR)StartPte); 00650 00651 // 00652 // Fill in the PTEs to cover the initial nonpaged pool. The physical 00653 // page frames to cover this range were reserved earlier from the 00654 // largest low memory free descriptor. The initial allocation is both 00655 // physically and virtually contiguous. 00656 // 00657 00658 StartPte = MiGetPteAddress(MmNonPagedPoolStart); 00659 EndPte = MiGetPteAddress((PCHAR)MmNonPagedPoolStart + 00660 MmSizeOfNonPagedPoolInBytes); 00661 00662 PageNumber = FreeDescriptorLowMem->BasePage; 00663 00664 #if 0 00665 ASSERT (MxFreeDescriptor == FreeDescriptorLowMem); 00666 MxNumberOfPages -= (EndPte - StartPte); 00667 MxNextPhysicalPage += (EndPte - StartPte); 00668 #endif 00669 00670 while (StartPte < EndPte) { 00671 TempPte.u.Hard.PageFrameNumber = PageNumber; 00672 PageNumber += 1; 00673 *StartPte = TempPte; 00674 StartPte += 1; 00675 } 00676 00677 // 00678 // Zero the remaining PTEs (if any) for the initial nonpaged pool up to 00679 // the end of the current page table page. 00680 // 00681 00682 while (!MiIsPteOnPdeBoundary (StartPte)) { 00683 *StartPte = ZeroKernelPte; 00684 StartPte += 1; 00685 } 00686 00687 // 00688 // Convert the starting nonpaged pool address to a 43-bit superpage 00689 // address and set the address of the initial nonpaged pool allocation. 00690 // 00691 00692 PointerPte = MiGetPteAddress(MmNonPagedPoolStart); 00693 MmNonPagedPoolStart = KSEG_ADDRESS(PointerPte->u.Hard.PageFrameNumber); 00694 MmPageAlignedPoolBase[NonPagedPool] = MmNonPagedPoolStart; 00695 00696 // 00697 // Set subsection base to the address to zero (the PTE format allows the 00698 // complete address space to be spanned) and the top subsection page. 00699 // 00700 00701 MmSubsectionBase = 0; 00702 MmSubsectionTopPage = (KSEG2_BASE - KSEG0_BASE) >> PAGE_SHIFT; 00703 00704 // 00705 // Initialize the pool structures in the nonpaged memory just mapped. 00706 // 00707 00708 MmNonPagedPoolExpansionStart = 00709 (PCHAR)NonPagedPoolStartVirtual + MmSizeOfNonPagedPoolInBytes; 00710 00711 MiInitializeNonPagedPool (); 00712 00713 // 00714 // Before Nonpaged pool can be used, the PFN database must be built. 00715 // This is due to the fact that the start and ending allocation bits 00716 // for nonpaged pool are stored in the PFN elements for the corresponding 00717 // pages. 00718 // 00719 // Calculate the number of pages required from page zero to the highest 00720 // page. 00721 // 00722 // Get the number of secondary colors and add the array for tracking 00723 // secondary colors to the end of the PFN database. 00724 // 00725 00726 if (MmSecondaryColors == 0) { 00727 MmSecondaryColors = PCR->SecondLevelCacheSize; 00728 } 00729 00730 MmSecondaryColors = MmSecondaryColors >> PAGE_SHIFT; 00731 00732 // 00733 // Make sure value is power of two and within limits. 00734 // 00735 00736 if (((MmSecondaryColors & (MmSecondaryColors - 1)) != 0) || 00737 (MmSecondaryColors < MM_SECONDARY_COLORS_MIN) || 00738 (MmSecondaryColors > MM_SECONDARY_COLORS_MAX)) { 00739 MmSecondaryColors = MM_SECONDARY_COLORS_DEFAULT; 00740 } 00741 00742 MmSecondaryColorMask = MmSecondaryColors - 1; 00743 PfnAllocation = 00744 1 + ((((MmHighestPhysicalPage + 1) * sizeof(MMPFN)) + 00745 ((PFN_NUMBER)MmSecondaryColors * sizeof(MMCOLOR_TABLES) * 2)) >> PAGE_SHIFT); 00746 00747 // 00748 // If the number of pages remaining in the current descriptor is 00749 // greater than the number of pages needed for the PFN database, 00750 // then allocate the PFN database from the current free descriptor. 00751 // Otherwise, allocate the PFN database virtually. 00752 // 00753 00754 #ifndef PFN_CONSISTENCY 00755 00756 if (MxNumberOfPages >= PfnAllocation) { 00757 00758 // 00759 // Allocate the PFN database in the 43-bit superpage. 00760 // 00761 // Compute the address of the PFN by allocating the appropriate 00762 // number of pages from the end of the free descriptor. 00763 // 00764 00765 HighPage = MxNextPhysicalPage + MxNumberOfPages; 00766 MmPfnDatabase = KSEG_ADDRESS(HighPage - PfnAllocation); 00767 RtlZeroMemory(MmPfnDatabase, PfnAllocation * PAGE_SIZE); 00768 00769 // 00770 // Mark off the chunk of memory used for the PFN database from 00771 // either the largest low free memory descriptor or the largest 00772 // free memory descriptor. 00773 // 00774 // N.B. The PFN database size is subtracted from the appropriate 00775 // memory descriptor so it will not appear to be free when 00776 // the memory descriptors are scanned to initialize the PFN 00777 // database. 00778 // 00779 00780 MxNumberOfPages -= PfnAllocation; 00781 if ((MxNextPhysicalPage >= FreeDescriptorLowMem->BasePage) && 00782 (MxNextPhysicalPage < (FreeDescriptorLowMem->BasePage + 00783 FreeDescriptorLowMem->PageCount))) { 00784 FreeDescriptorLowMem->PageCount -= (PFN_COUNT)PfnAllocation; 00785 00786 } else { 00787 MxFreeDescriptor->PageCount -= (PFN_COUNT)PfnAllocation; 00788 } 00789 00790 // 00791 // Allocate one PTE at the very top of nonpaged pool. This provides 00792 // protection against the caller of the first real nonpaged expansion allocation in case he accidentally overruns his 00793 // pool block. (We'll trap instead of corrupting the PFN database). 00794 // This also allows us to freely increment in MiFreePoolPages without 00795 // having to worry about a valid PTE after the end of the highest 00796 // nonpaged pool allocation. 00797 // 00798 00799 MiReserveSystemPtes(1, NonPagedPoolExpansion, 0, 0, TRUE); 00800 00801 } else { 00802 00803 #endif // PFN_CONSISTENCY 00804 00805 // 00806 // Calculate the start of the PFN database (it starts at physical 00807 // page zero, even if the lowest physical page is not zero). 00808 // 00809 00810 PointerPte = MiReserveSystemPtes((ULONG)PfnAllocation, 00811 NonPagedPoolExpansion, 00812 0, 00813 0, 00814 TRUE); 00815 00816 #if PFN_CONSISTENCY 00817 00818 MiPfnStartPte = PointerPte; 00819 MiPfnPtes = PfnAllocation; 00820 00821 #endif 00822 00823 MmPfnDatabase = (PMMPFN)(MiGetVirtualAddressMappedByPte(PointerPte)); 00824 00825 // 00826 // Allocate one more PTE just below the PFN database. This provides 00827 // protection against the caller of the first real nonpaged 00828 // expansion allocation in case he accidentally overruns his pool 00829 // block. (We'll trap instead of corrupting the PFN database). 00830 // This also allows us to freely increment in MiFreePoolPages 00831 // without having to worry about a valid PTE just after the end of 00832 // the highest nonpaged pool allocation. 00833 // 00834 00835 MiReserveSystemPtes(1, NonPagedPoolExpansion, 0, 0, TRUE); 00836 00837 // 00838 // Go through the memory descriptors and for each physical page 00839 // make the PFN database have a valid PTE to map it. This allows 00840 // machines with sparse physical memory to have a minimal PFN 00841 // database. 00842 // 00843 00844 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00845 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00846 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00847 MEMORY_ALLOCATION_DESCRIPTOR, 00848 ListEntry); 00849 00850 PointerPte = MiGetPteAddress(MI_PFN_ELEMENT( 00851 MemoryDescriptor->BasePage)); 00852 00853 HighPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount; 00854 LastPte = MiGetPteAddress((PCHAR)MI_PFN_ELEMENT(HighPage) - 1); 00855 while (PointerPte <= LastPte) { 00856 if (PointerPte->u.Hard.Valid == 0) { 00857 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00858 *PointerPte = TempPte; 00859 RtlZeroMemory(MiGetVirtualAddressMappedByPte(PointerPte), 00860 PAGE_SIZE); 00861 } 00862 00863 PointerPte += 1; 00864 } 00865 00866 NextMd = MemoryDescriptor->ListEntry.Flink; 00867 } 00868 00869 #ifndef PFN_CONSISTENCY 00870 00871 } 00872 00873 #endif // PFN_CONSISTENCY 00874 00875 // 00876 // Initialize support for colored pages. 00877 // 00878 00879 MmFreePagesByColor[0] = 00880 (PMMCOLOR_TABLES)&MmPfnDatabase[MmHighestPhysicalPage + 1]; 00881 00882 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 00883 00884 // 00885 // Make sure the color table are mapped if they are not physically 00886 // allocated. 00887 // 00888 00889 if (MI_IS_PHYSICAL_ADDRESS(MmFreePagesByColor[0]) == FALSE) { 00890 PointerPte = MiGetPteAddress(&MmFreePagesByColor[0][0]); 00891 LastPte = 00892 MiGetPteAddress((PCHAR)&MmFreePagesByColor[1][MmSecondaryColors] - 1); 00893 00894 while (PointerPte <= LastPte) { 00895 if (PointerPte->u.Hard.Valid == 0) { 00896 TempPte.u.Hard.PageFrameNumber = MxGetNextPage(); 00897 *PointerPte = TempPte; 00898 RtlZeroMemory(MiGetVirtualAddressMappedByPte(PointerPte), 00899 PAGE_SIZE); 00900 } 00901 00902 PointerPte += 1; 00903 } 00904 } 00905 00906 // 00907 // Initialize the secondary color free page listheads. 00908 // 00909 00910 for (i = 0; i < MmSecondaryColors; i += 1) { 00911 MmFreePagesByColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST; 00912 MmFreePagesByColor[FreePageList][i].Flink = MM_EMPTY_LIST; 00913 } 00914 00915 // 00916 // Go through the page table entries and for any page which is valid, 00917 // update the corresponding PFN database element. 00918 // 00919 // Add the level one page directory parent page to the PFN database. 00920 // 00921 00922 PointerPde = (PMMPTE)PDE_SELFMAP; 00923 PpePage = MI_GET_PAGE_FRAME_FROM_PTE(PointerPde); 00924 Pfn1 = MI_PFN_ELEMENT(PpePage); 00925 Pfn1->PteFrame = PpePage; 00926 Pfn1->PteAddress = PointerPde; 00927 Pfn1->u2.ShareCount += 1; 00928 Pfn1->u3.e2.ReferenceCount = 1; 00929 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00930 Pfn1->u3.e1.PageColor = 00931 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(PointerPde)); 00932 00933 // 00934 // Add the pages which were used to construct the nonpaged part of the 00935 // system, hyper space, and the system process working set list to the 00936 // PFN database. 00937 // 00938 // The scan begins at the start of hyper space so the hyper space page 00939 // table page and the working set list page will be accounted for in 00940 // the PFN database. 00941 // 00942 00943 StartPde = MiGetPdeAddress(HYPER_SPACE); 00944 EndPde = MiGetPdeAddress(NON_PAGED_SYSTEM_END); 00945 First = TRUE; 00946 00947 while (StartPde <= EndPde) { 00948 00949 if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) { 00950 First = FALSE; 00951 StartPpe = MiGetPteAddress(StartPde); 00952 if (StartPpe->u.Hard.Valid == 0) { 00953 StartPpe += 1; 00954 StartPde = MiGetVirtualAddressMappedByPte (StartPpe); 00955 continue; 00956 } 00957 00958 PdePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPpe); 00959 00960 Pfn1 = MI_PFN_ELEMENT(PdePage); 00961 Pfn1->PteFrame = PpePage; 00962 Pfn1->PteAddress = StartPde; 00963 Pfn1->u2.ShareCount += 1; 00964 Pfn1->u3.e2.ReferenceCount = 1; 00965 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00966 Pfn1->u3.e1.PageColor = 00967 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(StartPpe)); 00968 } 00969 00970 // 00971 // If the second level PDE entry is valid, then add the page to the 00972 // PFN database. 00973 // 00974 00975 if (StartPde->u.Hard.Valid == 1) { 00976 00977 PtePage = MI_GET_PAGE_FRAME_FROM_PTE(StartPde); 00978 Pfn1 = MI_PFN_ELEMENT(PtePage); 00979 Pfn1->PteFrame = PdePage; 00980 Pfn1->PteAddress = StartPde; 00981 Pfn1->u2.ShareCount += 1; 00982 Pfn1->u3.e2.ReferenceCount = 1; 00983 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00984 Pfn1->u3.e1.PageColor = 00985 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(StartPde)); 00986 00987 // 00988 // Scan the page table page for valid PTEs. 00989 // 00990 00991 PointerPte = MiGetVirtualAddressMappedByPte(StartPde); 00992 00993 if ((PointerPte < MiGetPteAddress (KSEG0_BASE)) || 00994 (PointerPte >= MiGetPteAddress (KSEG2_BASE))) { 00995 00996 for (j = 0 ; j < PTE_PER_PAGE; j += 1) { 00997 00998 // 00999 // If the page table page is valid, then add the page 01000 // to the PFN database. 01001 // 01002 01003 if (PointerPte->u.Hard.Valid == 1) { 01004 FrameNumber = MI_GET_PAGE_FRAME_FROM_PTE(PointerPte); 01005 Pfn2 = MI_PFN_ELEMENT(FrameNumber); 01006 Pfn2->PteFrame = PtePage; 01007 Pfn2->PteAddress = (PMMPTE)KSEG_ADDRESS(PtePage) + j; 01008 Pfn2->u2.ShareCount += 1; 01009 Pfn2->u3.e2.ReferenceCount = 1; 01010 Pfn2->u3.e1.PageLocation = ActiveAndValid; 01011 Pfn2->u3.e1.PageColor = 01012 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(Pfn2->PteAddress)); 01013 } 01014 01015 PointerPte += 1; 01016 } 01017 } 01018 } 01019 01020 StartPde += 1; 01021 } 01022 01023 // 01024 // If the lowest physical page is still unused add it to the PFN 01025 // database by making its reference count nonzero and pointing 01026 // it to a second level page directory entry. 01027 // 01028 01029 Pfn1 = &MmPfnDatabase[MmLowestPhysicalPage]; 01030 if (Pfn1->u3.e2.ReferenceCount == 0) { 01031 Pde = MiGetPdeAddress(0xFFFFFFFFB0000000); 01032 PdePage = MI_GET_PAGE_FRAME_FROM_PTE(Pde); 01033 Pfn1->PteFrame = PdePage; 01034 Pfn1->PteAddress = Pde; 01035 Pfn1->u2.ShareCount += 1; 01036 Pfn1->u3.e2.ReferenceCount = 1; 01037 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01038 Pfn1->u3.e1.PageColor = 01039 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(Pde)); 01040 } 01041 01042 // 01043 // Walk through the memory descriptors and add pages to the free list 01044 // in the PFN database as appropriate. 01045 // 01046 01047 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 01048 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 01049 MemoryDescriptor = CONTAINING_RECORD(NextMd, 01050 MEMORY_ALLOCATION_DESCRIPTOR, 01051 ListEntry); 01052 01053 // 01054 // Set the base page number and the number of pages and switch 01055 // on the memory type. 01056 // 01057 01058 i = MemoryDescriptor->PageCount; 01059 NextPhysicalPage = MemoryDescriptor->BasePage; 01060 switch (MemoryDescriptor->MemoryType) { 01061 01062 // 01063 // Bad pages are not usable and are placed on the bad 01064 // page list. 01065 // 01066 01067 case LoaderBad: 01068 while (i != 0) { 01069 MiInsertPageInList(MmPageLocationList[BadPageList], 01070 NextPhysicalPage); 01071 01072 i -= 1; 01073 NextPhysicalPage += 1; 01074 } 01075 01076 break; 01077 01078 // 01079 // Pages from descriptor types free, loaded program, firmware 01080 // temporary, and OS Loader stack are potentially free. 01081 // 01082 01083 case LoaderFree: 01084 case LoaderLoadedProgram: 01085 case LoaderFirmwareTemporary: 01086 case LoaderOsloaderStack: 01087 Pfn1 = MI_PFN_ELEMENT(NextPhysicalPage); 01088 while (i != 0) { 01089 01090 // 01091 // If the PFN database entry for the respective page 01092 // is not referenced, then insert the page in the free 01093 // page list. 01094 // 01095 01096 if (Pfn1->u3.e2.ReferenceCount == 0) { 01097 Pfn1->PteAddress = KSEG_ADDRESS(NextPhysicalPage); 01098 Pfn1->u3.e1.PageColor = 01099 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(Pfn1->PteAddress)); 01100 01101 MiInsertPageInList(MmPageLocationList[FreePageList], 01102 NextPhysicalPage); 01103 } 01104 01105 Pfn1 += 1; 01106 i -= 1; 01107 NextPhysicalPage += 1; 01108 } 01109 01110 break; 01111 01112 // 01113 // All the remaining memory descriptor types represent memory 01114 // that has been already allocated and is not available. 01115 // 01116 01117 default: 01118 PointerPte = KSEG_ADDRESS(NextPhysicalPage); 01119 Pfn1 = MI_PFN_ELEMENT(NextPhysicalPage); 01120 while (i != 0) { 01121 01122 // 01123 // Set the page in use. 01124 // 01125 01126 Pfn1->PteFrame = PpePage; 01127 Pfn1->PteAddress = PointerPte; 01128 Pfn1->u2.ShareCount += 1; 01129 Pfn1->u3.e2.ReferenceCount = 1; 01130 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01131 Pfn1->u3.e1.PageColor = 01132 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(PointerPte)); 01133 01134 Pfn1 += 1; 01135 i -= 1; 01136 NextPhysicalPage += 1; 01137 PointerPte += 1; 01138 } 01139 01140 break; 01141 } 01142 01143 NextMd = MemoryDescriptor->ListEntry.Flink; 01144 } 01145 01146 // 01147 // Everything has been accounted for except the PFN database. 01148 // 01149 01150 if (MI_IS_PHYSICAL_ADDRESS(MmPfnDatabase) == FALSE) { 01151 01152 // 01153 // The PFN database is allocated in virtual memory. 01154 // 01155 // Set the start and end of allocation in the PFN database. 01156 // 01157 01158 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmLowestPhysicalPage])->u.Hard.PageFrameNumber); 01159 Pfn1->u3.e1.StartOfAllocation = 1; 01160 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmHighestPhysicalPage])->u.Hard.PageFrameNumber); 01161 Pfn1->u3.e1.EndOfAllocation = 1; 01162 01163 } else { 01164 01165 // 01166 // The PFN database is allocated in KSEG43. 01167 // 01168 // Mark all PFN entries for the PFN pages in use. 01169 // 01170 01171 PageNumber = MI_CONVERT_PHYSICAL_TO_PFN(MmPfnDatabase); 01172 Pfn1 = MI_PFN_ELEMENT(PageNumber); 01173 do { 01174 Pfn1->PteAddress = KSEG_ADDRESS(PageNumber); 01175 Pfn1->u3.e1.PageColor = 01176 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(Pfn1->PteAddress)); 01177 01178 Pfn1->u3.e2.ReferenceCount += 1; 01179 PageNumber += 1; 01180 Pfn1 += 1; 01181 PfnAllocation -= 1; 01182 } while (PfnAllocation != 0); 01183 01184 // 01185 // Scan the PFN database backward for pages that are completely zero. 01186 // These pages are unused and can be added to the free list. 01187 // 01188 01189 BottomPfn = MI_PFN_ELEMENT(MmHighestPhysicalPage); 01190 do { 01191 01192 // 01193 // Compute the address of the start of the page that is next 01194 // lower in memory and scan backwards until that page address 01195 // is reached or just crossed. 01196 // 01197 01198 if (((ULONG_PTR)BottomPfn & (PAGE_SIZE - 1)) != 0) { 01199 BasePfn = (PMMPFN)((ULONG_PTR)BottomPfn & ~(PAGE_SIZE - 1)); 01200 TopPfn = BottomPfn + 1; 01201 01202 } else { 01203 BasePfn = (PMMPFN)((ULONG_PTR)BottomPfn - PAGE_SIZE); 01204 TopPfn = BottomPfn; 01205 } 01206 01207 while (BottomPfn > BasePfn) { 01208 BottomPfn -= 1; 01209 } 01210 01211 // 01212 // If the entire range over which the PFN entries span is 01213 // completely zero and the PFN entry that maps the page is 01214 // not in the range, then add the page to the appropriate 01215 // free list. 01216 // 01217 01218 Range = (ULONG)((ULONG_PTR)TopPfn - (ULONG_PTR)BottomPfn); 01219 if (RtlCompareMemoryUlong((PVOID)BottomPfn, Range, 0) == Range) { 01220 01221 // 01222 // Set the PTE address to the physical page for virtual 01223 // address alignment checking. 01224 // 01225 01226 PageNumber = (PFN_NUMBER)(((ULONG_PTR)BasePfn - KSEG43_BASE) >> PAGE_SHIFT); 01227 Pfn1 = MI_PFN_ELEMENT(PageNumber); 01228 01229 ASSERT(Pfn1->u3.e2.ReferenceCount == 1); 01230 01231 Pfn1->u3.e2.ReferenceCount = 0; 01232 PfnAllocation += 1; 01233 Pfn1->PteAddress = KSEG_ADDRESS(PageNumber); 01234 Pfn1->u3.e1.PageColor = 01235 MI_GET_COLOR_FROM_SECONDARY(GET_PAGE_COLOR_FROM_PTE(Pfn1->PteAddress)); 01236 01237 MiInsertPageInList(MmPageLocationList[FreePageList], 01238 PageNumber); 01239 } 01240 01241 } while (BottomPfn > MmPfnDatabase); 01242 } 01243 01244 // 01245 // Indicate that nonpaged pool must succeed is allocated in nonpaged pool. 01246 // 01247 01248 i = MmSizeOfNonPagedMustSucceed; 01249 Pfn1 = MI_PFN_ELEMENT(MI_CONVERT_PHYSICAL_TO_PFN(MmNonPagedMustSucceed)); 01250 while (i != 0) { 01251 Pfn1->u3.e1.StartOfAllocation = 1; 01252 Pfn1->u3.e1.EndOfAllocation = 1; 01253 i -= PAGE_SIZE; 01254 Pfn1 += 1; 01255 } 01256 01257 // 01258 // Recompute the number of system PTEs to include the virtual space 01259 // occupied by the initialize nonpaged pool allocation in KSEG43, and 01260 // initialize the nonpaged available PTEs for mapping I/O space and 01261 // kernel stacks. 01262 // 01263 01264 PointerPte = MiGetPteAddress(MmNonPagedSystemStart); 01265 MmNumberOfSystemPtes = (ULONG)(MiGetPteAddress(MmNonPagedPoolExpansionStart) - PointerPte - 1); 01266 KeInitializeSpinLock(&MmSystemSpaceLock); 01267 KeInitializeSpinLock(&MmPfnLock); 01268 MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace); 01269 01270 // 01271 // Initialize the nonpaged pool. 01272 // 01273 01274 InitializePool(NonPagedPool, 0); 01275 01276 // 01277 // Initialize memory management structures for the system process. 01278 // 01279 // Set the address of the first and last reserved PTE in hyper space. 01280 // 01281 01282 MmFirstReservedMappingPte = MiGetPteAddress(FIRST_MAPPING_PTE); 01283 MmLastReservedMappingPte = MiGetPteAddress(LAST_MAPPING_PTE); 01284 01285 // 01286 // Set the address of the start of the working set list and header. 01287 // 01288 01289 MmWorkingSetList = WORKING_SET_LIST; 01290 MmWsle = (PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)); 01291 01292 // 01293 // The PFN element for the page directory parent will be initialized 01294 // a second time when the process address space is initialized. Therefore, 01295 // the share count and the reference count must be set to zero. 01296 // 01297 01298 Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE((PMMPTE)PDE_SELFMAP)); 01299 Pfn1->u2.ShareCount = 0; 01300 Pfn1->u3.e2.ReferenceCount = 0; 01301 01302 // 01303 // The PFN element for the hyper space page directory page will be 01304 // initialized a second time when the process address space is initialized. 01305 // Therefore, the share count and the reference count must be set to zero. 01306 // 01307 01308 PointerPte = MiGetPpeAddress(HYPER_SPACE); 01309 Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE(PointerPte)); 01310 Pfn1->u2.ShareCount = 0; 01311 Pfn1->u3.e2.ReferenceCount = 0; 01312 01313 // 01314 // The PFN elements for the hyper space page table page and working set list 01315 // page will be initialized a second time when the process address space 01316 // is initialized. Therefore, the share count and the reference must be 01317 // set to zero. 01318 // 01319 01320 StartPde = MiGetPdeAddress(HYPER_SPACE); 01321 01322 Pfn1 = MI_PFN_ELEMENT(MI_GET_PAGE_FRAME_FROM_PTE(StartPde)); 01323 Pfn1->u2.ShareCount = 0; 01324 Pfn1->u3.e2.ReferenceCount = 0; 01325 01326 // 01327 // Save the page frame number of the working set page in the system 01328 // process object and unmap the working set page from the second level 01329 // page directory page. 01330 // 01331 01332 LOCK_PFN(OldIrql); 01333 01334 FrameNumber = MiRemoveZeroPageIfAny (0); 01335 if (FrameNumber == 0) { 01336 FrameNumber = MiRemoveAnyPage (0); 01337 UNLOCK_PFN (OldIrql); 01338 MiZeroPhysicalPage (FrameNumber, 0); 01339 LOCK_PFN (OldIrql); 01340 01341 Pfn1 = MI_PFN_ELEMENT(FrameNumber); 01342 Pfn1->u2.ShareCount = 0; 01343 Pfn1->u3.e2.ReferenceCount = 0; 01344 } 01345 01346 CurrentProcess = PsGetCurrentProcess(); 01347 CurrentProcess->WorkingSetPage = FrameNumber; 01348 PointerPte = MiGetVirtualAddressMappedByPte(EndPde); 01349 01350 UNLOCK_PFN(OldIrql); 01351 01352 // 01353 // Initialize the system process memory management structures including 01354 // the working set list. 01355 // 01356 01357 PointerPte = MmFirstReservedMappingPte; 01358 PointerPte->u.Hard.PageFrameNumber = NUMBER_OF_MAPPING_PTES; 01359 CurrentProcess->Vm.MaximumWorkingSetSize = (ULONG)MmSystemProcessWorkingSetMax; 01360 CurrentProcess->Vm.MinimumWorkingSetSize = (ULONG)MmSystemProcessWorkingSetMin; 01361 01362 MmInitializeProcessAddressSpace(CurrentProcess, NULL, NULL, NULL); 01363 01364 // 01365 // Check to see if moving the secondary page structures to the end 01366 // of the PFN database is a waste of memory. And if so, copy it 01367 // to paged pool. 01368 // 01369 // If the PFN database ends on a page aligned boundary and the 01370 // size of the two arrays is less than a page, free the page 01371 // and allocate nonpagedpool for this. 01372 // 01373 01374 if ((((ULONG_PTR)MmFreePagesByColor[0] & (PAGE_SIZE - 1)) == 0) && 01375 ((MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)) < PAGE_SIZE)) { 01376 01377 PMMCOLOR_TABLES c; 01378 01379 c = MmFreePagesByColor[0]; 01380 MmFreePagesByColor[0] = 01381 ExAllocatePoolWithTag(NonPagedPoolMustSucceed, 01382 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES), 01383 ' mM'); 01384 01385 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 01386 01387 RtlMoveMemory (MmFreePagesByColor[0], 01388 c, 01389 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)); 01390 01391 // 01392 // Free the page. 01393 // 01394 01395 if (!MI_IS_PHYSICAL_ADDRESS(c)) { 01396 PointerPte = MiGetPteAddress(c); 01397 FrameNumber = MI_GET_PAGE_FRAME_FROM_PTE(PointerPte); 01398 *PointerPte = ZeroKernelPte; 01399 01400 } else { 01401 FrameNumber = MI_CONVERT_PHYSICAL_TO_PFN(c); 01402 } 01403 01404 LOCK_PFN (OldIrql); 01405 01406 Pfn1 = MI_PFN_ELEMENT (FrameNumber); 01407 01408 ASSERT ((Pfn1->u3.e2.ReferenceCount <= 1) && (Pfn1->u2.ShareCount <= 1)); 01409 01410 Pfn1->u2.ShareCount = 0; 01411 Pfn1->u3.e2.ReferenceCount = 0; 01412 MI_SET_PFN_DELETED(Pfn1); 01413 01414 #if DBG 01415 01416 Pfn1->u3.e1.PageLocation = StandbyPageList; 01417 01418 #endif //DBG 01419 01420 MiInsertPageInList (MmPageLocationList[FreePageList], FrameNumber); 01421 01422 UNLOCK_PFN (OldIrql); 01423 } 01424 01425 return; 01426 }

Generated on Sat May 15 19:40:21 2004 for test by doxygen 1.3.7