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

initmips.c File Reference

#include "mi.h"

Go to the source code of this file.

Functions

VOID MiInitMachineDependent (IN PLOADER_PARAMETER_BLOCK LoaderBlock)


Function Documentation

VOID MiInitMachineDependent IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 27 of file initmips.c.

References ActiveAndValid, ASSERT, BadPageList, _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, _MMPFNLIST::Blink, c, DISPATCH_LEVEL, ExAllocatePoolWithTag, FALSE, FIRST_MAPPING_PTE, _MMPFNLIST::Flink, _MMCOLOR_TABLES::Flink, FreePageList, HYPER_SPACE, InitializePool(), KeBugCheckEx(), KeFlushEntireTb(), KeFlushSingleTb(), KeInitializeSpinLock(), KeLowerIrql(), KeRaiseIrql(), KeSweepDcache(), KSEG0_BASE, LAST_MAPPING_PTE, _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, _MMPFNLIST::ListName, LoaderBad, LoaderFirmwareTemporary, LoaderFree, LoaderLoadedProgram, LoaderOsloaderStack, _MMSUPPORT::MaximumWorkingSetSize, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_PAGE_COLOR_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiGetPdeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializeNonPagedPool(), MiInitializeSystemPtes(), MiInsertPageInList(), _MMSUPPORT::MinimumWorkingSetSize, MiRemoveAnyPage(), MiReserveSystemPtes(), MM_COLOR_MASK, MM_EMPTY_LIST, MM_EXECUTE, MM_EXECUTE_READ, MM_EXECUTE_READWRITE, MM_EXECUTE_WRITECOPY, MM_GUARD_PAGE, MM_LOWEST_NONPAGED_SYSTEM_START, MM_MAX_ADDITIONAL_NONPAGED_POOL, MM_MAX_INITIAL_NONPAGED_POOL, MM_MAXIMUM_NUMBER_OF_COLORS, MM_PAGES_IN_KSEG0, MM_READONLY, MM_READWRITE, MM_SECONDARY_COLORS_DEFAULT, MM_SECONDARY_COLORS_MAX, MM_SECONDARY_COLORS_MIN, MM_SUBSECTION_MAP, MM_SYSTEM_SPACE_END, MM_SYSTEM_SPACE_START, MM_WRITECOPY, MMCOLOR_TABLES, MmDefaultMaximumNonPagedPool, MmFirstReservedMappingPte, MmFreePagesByColor, MmFreePagesByPrimaryColor, MmHighestPhysicalPage, MmInitializeProcessAddressSpace(), MmLastReservedMappingPte, MmLowestPhysicalPage, MmMaxAdditionNonPagedPoolPerMb, MmMaximumNonPagedPoolInBytes, MmMinAdditionNonPagedPoolPerMb, MmMinimumNonPagedPoolSize, MmNonPagedMustSucceed, MmNonPagedPoolEnd, MmNonPagedPoolExpansionStart, MmNonPagedPoolStart, MmNonPagedSystemStart, MmNumberOfPhysicalPages, MmNumberOfSystemPtes, MmPageAlignedPoolBase, MmPageLocationList, MMPFN, MmPfnDatabase, MmPfnLock, MmProtectToPteMask, MmSecondaryColorMask, MmSecondaryColors, MmSizeOfNonPagedMustSucceed, MmSizeOfNonPagedPoolInBytes, MmSubsectionBase, MmSubsectionTopPage, MmSystemProcessWorkingSetMax, MmSystemProcessWorkingSetMin, MmSystemSpaceLock, MmWorkingSetList, MmWsle, NonPagedPool, NonPagedPoolExpansion, NonPagedPoolMustSucceed, NULL, NUMBER_OF_MAPPING_PTES, PAGE_ALIGN, PAGE_DIRECTORY_MASK, PAGE_SHIFT, PAGE_SIZE, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, PsGetCurrentProcess, PTE_PER_PAGE, PTE_SHIFT, _MMPFN::PteAddress, _MMPFN::PteFrame, RtlCompareMemoryUlong(), StandbyPageList, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, ValidKernelPde, ValidKernelPte, ValidPdePde, ValidPtePte, ValidUserPte, _EPROCESS::Vm, WORKING_SET_LIST, _EPROCESS::WorkingSetPage, ZeroedPageList, ZeroKernelPte, and ZeroPte.

00033 : 00034 00035 This routine performs the necessary operations to enable virtual 00036 memory. This includes building the page directory page, building 00037 page table pages to map the code section, the data section, the' 00038 stack section and the trap handler. 00039 00040 It also initializes the PFN database and populates the free list. 00041 00042 00043 Arguments: 00044 00045 None. 00046 00047 Return Value: 00048 00049 None. 00050 00051 Environment: 00052 00053 Kernel mode. 00054 00055 --*/ 00056 00057 { 00058 00059 PMMPFN BasePfn; 00060 PMMPFN BottomPfn; 00061 PMMPFN TopPfn; 00062 BOOLEAN PfnInKseg0; 00063 ULONG i, j; 00064 ULONG HighPage; 00065 ULONG PagesLeft; 00066 ULONG PageNumber; 00067 ULONG PdePageNumber; 00068 ULONG PdePage; 00069 ULONG PageFrameIndex; 00070 ULONG NextPhysicalPage; 00071 ULONG PfnAllocation; 00072 ULONG MaxPool; 00073 KIRQL OldIrql; 00074 PEPROCESS CurrentProcess; 00075 ULONG DirBase; 00076 PVOID SpinLockPage; 00077 ULONG MostFreePage = 0; 00078 PLIST_ENTRY NextMd; 00079 PMEMORY_ALLOCATION_DESCRIPTOR FreeDescriptor; 00080 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 00081 MMPTE TempPte; 00082 PMMPTE PointerPde; 00083 PMMPTE PointerPte; 00084 PMMPTE LastPte; 00085 PMMPTE CacheStackPage; 00086 PMMPTE Pde; 00087 PMMPTE StartPde; 00088 PMMPTE EndPde; 00089 PMMPFN Pfn1; 00090 PMMPFN Pfn2; 00091 PULONG PointerLong; 00092 PVOID NonPagedPoolStartVirtual; 00093 ULONG Range; 00094 00095 // 00096 // Initialize color tables and cache policy fields of static data if R4000. 00097 // 00098 00099 ValidKernelPte.u.Hard.CachePolicy = PCR->CachePolicy; 00100 ValidUserPte.u.Hard.CachePolicy = PCR->CachePolicy; 00101 ValidPtePte.u.Hard.CachePolicy = PCR->CachePolicy; 00102 ValidPdePde.u.Hard.CachePolicy = PCR->CachePolicy; 00103 ValidKernelPde.u.Hard.CachePolicy = PCR->CachePolicy ; 00104 00105 MmProtectToPteMask[MM_READONLY] |= PCR->AlignedCachePolicy; 00106 MmProtectToPteMask[MM_EXECUTE] |= PCR->AlignedCachePolicy; 00107 MmProtectToPteMask[MM_EXECUTE_READ] |= PCR->AlignedCachePolicy; 00108 MmProtectToPteMask[MM_READWRITE] |= PCR->AlignedCachePolicy; 00109 MmProtectToPteMask[MM_WRITECOPY] |= PCR->AlignedCachePolicy; 00110 MmProtectToPteMask[MM_EXECUTE_READWRITE] |= PCR->AlignedCachePolicy; 00111 MmProtectToPteMask[MM_EXECUTE_WRITECOPY] |= PCR->AlignedCachePolicy; 00112 00113 MmProtectToPteMask[MM_GUARD_PAGE | MM_READONLY] |= PCR->AlignedCachePolicy; 00114 MmProtectToPteMask[MM_GUARD_PAGE | MM_EXECUTE] |= PCR->AlignedCachePolicy; 00115 MmProtectToPteMask[MM_GUARD_PAGE | MM_EXECUTE_READ] |= PCR->AlignedCachePolicy; 00116 MmProtectToPteMask[MM_GUARD_PAGE | MM_READWRITE] |= PCR->AlignedCachePolicy; 00117 MmProtectToPteMask[MM_GUARD_PAGE | MM_WRITECOPY] |= PCR->AlignedCachePolicy; 00118 MmProtectToPteMask[MM_GUARD_PAGE | MM_EXECUTE_READWRITE] |= PCR->AlignedCachePolicy; 00119 MmProtectToPteMask[MM_GUARD_PAGE | MM_EXECUTE_WRITECOPY] |= PCR->AlignedCachePolicy; 00120 00121 PointerPte = MiGetPdeAddress (PDE_BASE); 00122 00123 PointerPte->u.Hard.Dirty = 1; 00124 PointerPte->u.Hard.Valid = 1; 00125 PointerPte->u.Hard.Global = 1; 00126 PointerPte->u.Hard.Write = 0; 00127 00128 PdePageNumber = PointerPte->u.Hard.PageFrameNumber; 00129 00130 PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PointerPte->u.Long; 00131 00132 KeSweepDcache (FALSE); 00133 00134 // 00135 // Get the lower bound of the free physical memory and the 00136 // number of physical pages by walking the memory descriptor lists. 00137 // 00138 00139 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00140 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00141 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00142 MEMORY_ALLOCATION_DESCRIPTOR, 00143 ListEntry); 00144 00145 MmNumberOfPhysicalPages += MemoryDescriptor->PageCount; 00146 if (MemoryDescriptor->BasePage < MmLowestPhysicalPage) { 00147 MmLowestPhysicalPage = MemoryDescriptor->BasePage; 00148 } 00149 00150 // 00151 // If the memory range described by the descriptor is larger 00152 // than the previous largest range and the descriptor describes 00153 // memory that is in KSEG0, then record the address of the 00154 // descriptor. 00155 // 00156 00157 HighPage = MemoryDescriptor->BasePage + MemoryDescriptor->PageCount - 1; 00158 if (MemoryDescriptor->MemoryType == LoaderFree) { 00159 if ((MemoryDescriptor->PageCount > MostFreePage) && 00160 (HighPage < MM_PAGES_IN_KSEG0)) { 00161 MostFreePage = MemoryDescriptor->PageCount; 00162 FreeDescriptor = MemoryDescriptor; 00163 } 00164 } 00165 00166 if (HighPage > MmHighestPhysicalPage) { 00167 MmHighestPhysicalPage = HighPage; 00168 } 00169 00170 NextMd = MemoryDescriptor->ListEntry.Flink; 00171 } 00172 00173 // 00174 // If the number of physical pages is less than 1024, then bug check. 00175 // 00176 00177 if (MmNumberOfPhysicalPages < 1024) { 00178 KeBugCheckEx (INSTALL_MORE_MEMORY, 00179 MmNumberOfPhysicalPages, 00180 MmLowestPhysicalPage, 00181 MmHighestPhysicalPage, 00182 0); 00183 } 00184 00185 // 00186 // Build non-paged pool using the physical pages following the 00187 // data page in which to build the pool from. Non-page pool grows 00188 // from the high range of the virtual address space and expands 00189 // downward. 00190 // 00191 // At this time non-paged pool is constructed so virtual addresses 00192 // are also physically contiguous. 00193 // 00194 00195 if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) > 00196 (7 * (MmNumberOfPhysicalPages << 3))) { 00197 00198 // 00199 // More than 7/8 of memory allocated to nonpagedpool, reset to 0. 00200 // 00201 00202 MmSizeOfNonPagedPoolInBytes = 0; 00203 } 00204 00205 if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize) { 00206 00207 // 00208 // Calculate the size of nonpaged pool. 00209 // Use the minimum size, then for every MB about 4mb add extra 00210 // pages. 00211 // 00212 00213 MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize; 00214 00215 MmSizeOfNonPagedPoolInBytes += 00216 ((MmNumberOfPhysicalPages - 1024)/256) * 00217 MmMinAdditionNonPagedPoolPerMb; 00218 } 00219 00220 if (MmSizeOfNonPagedPoolInBytes > MM_MAX_INITIAL_NONPAGED_POOL) { 00221 MmSizeOfNonPagedPoolInBytes = MM_MAX_INITIAL_NONPAGED_POOL; 00222 } 00223 00224 // 00225 // Align to page size boundary. 00226 // 00227 00228 MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1); 00229 00230 // 00231 // Calculate the maximum size of pool. 00232 // 00233 00234 if (MmMaximumNonPagedPoolInBytes == 0) { 00235 00236 // 00237 // Calculate the size of nonpaged pool. If 4mb of less use 00238 // the minimum size, then for every MB about 4mb add extra 00239 // pages. 00240 // 00241 00242 MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool; 00243 00244 // 00245 // Make sure enough expansion for pfn database exists. 00246 // 00247 00248 MmMaximumNonPagedPoolInBytes += (ULONG)PAGE_ALIGN ( 00249 MmHighestPhysicalPage * sizeof(MMPFN)); 00250 00251 MmMaximumNonPagedPoolInBytes += 00252 ((MmNumberOfPhysicalPages - 1024)/256) * 00253 MmMaxAdditionNonPagedPoolPerMb; 00254 } 00255 00256 MaxPool = MmSizeOfNonPagedPoolInBytes + PAGE_SIZE * 16 + 00257 (ULONG)PAGE_ALIGN ( 00258 MmHighestPhysicalPage * sizeof(MMPFN)); 00259 00260 if (MmMaximumNonPagedPoolInBytes < MaxPool) { 00261 MmMaximumNonPagedPoolInBytes = MaxPool; 00262 } 00263 00264 if (MmMaximumNonPagedPoolInBytes > MM_MAX_ADDITIONAL_NONPAGED_POOL) { 00265 MmMaximumNonPagedPoolInBytes = MM_MAX_ADDITIONAL_NONPAGED_POOL; 00266 } 00267 00268 MmNonPagedPoolStart = (PVOID)((ULONG)MmNonPagedPoolEnd 00269 - (MmMaximumNonPagedPoolInBytes - 1)); 00270 00271 MmNonPagedPoolStart = (PVOID)PAGE_ALIGN(MmNonPagedPoolStart); 00272 NonPagedPoolStartVirtual = MmNonPagedPoolStart; 00273 00274 00275 // 00276 // Calculate the starting PDE for the system PTE pool which is 00277 // right below the nonpaged pool. 00278 // 00279 00280 MmNonPagedSystemStart = (PVOID)(((ULONG)MmNonPagedPoolStart - 00281 ((MmNumberOfSystemPtes + 1) * PAGE_SIZE)) & 00282 (~PAGE_DIRECTORY_MASK)); 00283 00284 if (MmNonPagedSystemStart < MM_LOWEST_NONPAGED_SYSTEM_START) { 00285 MmNonPagedSystemStart = MM_LOWEST_NONPAGED_SYSTEM_START; 00286 MmNumberOfSystemPtes = (((ULONG)MmNonPagedPoolStart - 00287 (ULONG)MmNonPagedSystemStart) >> PAGE_SHIFT)-1; 00288 ASSERT (MmNumberOfSystemPtes > 1000); 00289 } 00290 00291 // 00292 // Set the global bit in all PDE's for system space. 00293 // 00294 00295 StartPde = MiGetPdeAddress (MM_SYSTEM_SPACE_START); 00296 EndPde = MiGetPdeAddress (MM_SYSTEM_SPACE_END); 00297 00298 while (StartPde <= EndPde) { 00299 if (StartPde->u.Hard.Global == 0) { 00300 00301 // 00302 // Set the Global bit. 00303 // 00304 00305 TempPte = *StartPde; 00306 TempPte.u.Hard.Global = 1; 00307 *StartPde = TempPte; 00308 } 00309 StartPde += 1; 00310 } 00311 00312 StartPde = MiGetPdeAddress (MmNonPagedSystemStart); 00313 00314 EndPde = MiGetPdeAddress((PVOID)((PCHAR)MmNonPagedPoolEnd - 1)); 00315 00316 ASSERT ((EndPde - StartPde) < (LONG)FreeDescriptor->PageCount); 00317 00318 NextPhysicalPage = FreeDescriptor->BasePage; 00319 TempPte = ValidKernelPte; 00320 00321 while (StartPde <= EndPde) { 00322 if (StartPde->u.Hard.Valid == 0) { 00323 00324 // 00325 // Map in a page directory page. 00326 // 00327 00328 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00329 NextPhysicalPage += 1; 00330 *StartPde = TempPte; 00331 00332 } 00333 StartPde += 1; 00334 } 00335 00336 // 00337 // Zero the PTEs before nonpaged pool. 00338 // 00339 00340 StartPde = MiGetPteAddress (MmNonPagedSystemStart); 00341 PointerPte = MiGetPteAddress(MmNonPagedPoolStart); 00342 00343 RtlZeroMemory (StartPde, ((ULONG)PointerPte - (ULONG)StartPde)); 00344 00345 // 00346 // Fill in the PTEs for non-paged pool. 00347 // 00348 00349 LastPte = MiGetPteAddress((ULONG)MmNonPagedPoolStart + 00350 MmSizeOfNonPagedPoolInBytes - 1); 00351 while (PointerPte <= LastPte) { 00352 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00353 NextPhysicalPage += 1; 00354 *PointerPte = TempPte; 00355 PointerPte++; 00356 } 00357 00358 ASSERT (NextPhysicalPage < 00359 (FreeDescriptor->BasePage + FreeDescriptor->PageCount)); 00360 00361 // 00362 // Zero the remaining PTEs (if any). 00363 // 00364 00365 StartPde = (PMMPTE)((ULONG)MiGetPteAddress (MmNonPagedPoolEnd) | (PAGE_SIZE - sizeof(MMPTE))); 00366 while (PointerPte <= StartPde) { 00367 *PointerPte = ZeroKernelPte; 00368 PointerPte++; 00369 } 00370 00371 PointerPte = MiGetPteAddress (MmNonPagedPoolStart); 00372 MmNonPagedPoolStart = 00373 (PVOID)(KSEG0_BASE | (PointerPte->u.Hard.PageFrameNumber << PAGE_SHIFT)); 00374 00375 MmPageAlignedPoolBase[NonPagedPool] = MmNonPagedPoolStart; 00376 00377 MmSubsectionBase = (ULONG)MmNonPagedPoolStart; 00378 if (NextPhysicalPage < (MM_SUBSECTION_MAP >> PAGE_SHIFT)) { 00379 MmSubsectionBase = KSEG0_BASE; 00380 MmSubsectionTopPage = MM_SUBSECTION_MAP >> PAGE_SHIFT; 00381 } 00382 00383 // 00384 // Non-paged pages now exist, build the pool structures. 00385 // 00386 00387 MmNonPagedPoolExpansionStart = (PVOID)((PCHAR)NonPagedPoolStartVirtual + 00388 MmSizeOfNonPagedPoolInBytes); 00389 MiInitializeNonPagedPool (NonPagedPoolStartVirtual); 00390 00391 // 00392 // Before Non-paged pool can be used, the PFN database must 00393 // be built. This is due to the fact that the start and end of 00394 // allocation bits for nonpaged pool are maintained in the 00395 // PFN elements for the corresponding pages. 00396 // 00397 00398 // 00399 // Calculate the number of pages required from page zero to 00400 // the highest page. 00401 // 00402 00403 // 00404 // Get the number of secondary colors and add the arrary for tracking 00405 // secondary colors to the end of the PFN database. 00406 // 00407 // Get secondary color value from registry. 00408 // 00409 00410 if (MmSecondaryColors == 0) { 00411 MmSecondaryColors = PCR->SecondLevelDcacheSize; 00412 } 00413 00414 MmSecondaryColors = MmSecondaryColors >> PAGE_SHIFT; 00415 00416 // 00417 // Make sure value is power of two and within limits. 00418 // 00419 00420 if (((MmSecondaryColors & (MmSecondaryColors -1)) != 0) || 00421 (MmSecondaryColors < MM_SECONDARY_COLORS_MIN) || 00422 (MmSecondaryColors > MM_SECONDARY_COLORS_MAX)) { 00423 MmSecondaryColors = MM_SECONDARY_COLORS_DEFAULT; 00424 } 00425 00426 MmSecondaryColorMask = (MmSecondaryColors - 1) & ~MM_COLOR_MASK; 00427 00428 PfnAllocation = 1 + ((((MmHighestPhysicalPage + 1) * sizeof(MMPFN)) + 00429 (MmSecondaryColors * sizeof(MMCOLOR_TABLES)*2)) 00430 >> PAGE_SHIFT); 00431 00432 // 00433 // If the number of pages remaining in the current descriptor is 00434 // greater than the number of pages needed for the PFN database, 00435 // then allocate the PFN database from the current free descriptor. 00436 // 00437 00438 HighPage = FreeDescriptor->BasePage + FreeDescriptor->PageCount; 00439 PagesLeft = HighPage - NextPhysicalPage; 00440 if (PagesLeft >= PfnAllocation) { 00441 00442 // 00443 // Allocate the PFN database in kseg0. 00444 // 00445 // Compute the address of the PFN by allocating the appropriate 00446 // number of pages from the end of the free descriptor. 00447 // 00448 00449 PfnInKseg0 = TRUE; 00450 MmPfnDatabase = (PMMPFN)(KSEG0_BASE | 00451 ((HighPage - PfnAllocation) << PAGE_SHIFT)); 00452 00453 RtlZeroMemory(MmPfnDatabase, PfnAllocation * PAGE_SIZE); 00454 FreeDescriptor->PageCount -= PfnAllocation; 00455 00456 } else { 00457 00458 // 00459 // Allocate the PFN database in virtual memory. 00460 // 00461 // Calculate the start of the Pfn Database (it starts a physical 00462 // page zero, even if the Lowest physical page is not zero). 00463 // 00464 00465 PfnInKseg0 = FALSE; 00466 PointerPte = MiReserveSystemPtes (PfnAllocation, 00467 NonPagedPoolExpansion, 00468 0, 00469 0, 00470 TRUE); 00471 00472 MmPfnDatabase = (PMMPFN)(MiGetVirtualAddressMappedByPte (PointerPte)); 00473 00474 // 00475 // Go through the memory descriptors and for each physical page 00476 // make the PFN database has a valid PTE to map it. This allows 00477 // machines with sparse physical memory to have a minimal PFN 00478 // database. 00479 // 00480 00481 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00482 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00483 00484 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00485 MEMORY_ALLOCATION_DESCRIPTOR, 00486 ListEntry); 00487 00488 PointerPte = MiGetPteAddress (MI_PFN_ELEMENT( 00489 MemoryDescriptor->BasePage)); 00490 00491 LastPte = MiGetPteAddress (((PCHAR)(MI_PFN_ELEMENT( 00492 MemoryDescriptor->BasePage + 00493 MemoryDescriptor->PageCount))) - 1); 00494 00495 while (PointerPte <= LastPte) { 00496 if (PointerPte->u.Hard.Valid == 0) { 00497 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00498 NextPhysicalPage += 1; 00499 *PointerPte = TempPte; 00500 RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte), 00501 PAGE_SIZE); 00502 } 00503 PointerPte++; 00504 } 00505 00506 NextMd = MemoryDescriptor->ListEntry.Flink; 00507 } 00508 } 00509 00510 // 00511 // Initialize support for colored pages. 00512 // 00513 00514 MmFreePagesByColor[0] = (PMMCOLOR_TABLES) 00515 &MmPfnDatabase[MmHighestPhysicalPage + 1]; 00516 00517 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 00518 00519 // 00520 // Make sure the PTEs are mapped. 00521 // 00522 00523 if (!MI_IS_PHYSICAL_ADDRESS(MmFreePagesByColor[0])) { 00524 PointerPte = MiGetPteAddress (&MmFreePagesByColor[0][0]); 00525 00526 LastPte = MiGetPteAddress ( 00527 (PVOID)((PCHAR)&MmFreePagesByColor[1][MmSecondaryColors] - 1)); 00528 00529 while (PointerPte <= LastPte) { 00530 if (PointerPte->u.Hard.Valid == 0) { 00531 TempPte.u.Hard.PageFrameNumber = NextPhysicalPage; 00532 NextPhysicalPage += 1; 00533 *PointerPte = TempPte; 00534 RtlZeroMemory (MiGetVirtualAddressMappedByPte (PointerPte), 00535 PAGE_SIZE); 00536 } 00537 PointerPte++; 00538 } 00539 } 00540 00541 for (i = 0; i < MmSecondaryColors; i++) { 00542 MmFreePagesByColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST; 00543 MmFreePagesByColor[FreePageList][i].Flink = MM_EMPTY_LIST; 00544 } 00545 00546 for (i = 0; i < MM_MAXIMUM_NUMBER_OF_COLORS; i++) { 00547 MmFreePagesByPrimaryColor[ZeroedPageList][i].ListName = ZeroedPageList; 00548 MmFreePagesByPrimaryColor[FreePageList][i].ListName = FreePageList; 00549 MmFreePagesByPrimaryColor[ZeroedPageList][i].Flink = MM_EMPTY_LIST; 00550 MmFreePagesByPrimaryColor[FreePageList][i].Flink = MM_EMPTY_LIST; 00551 MmFreePagesByPrimaryColor[ZeroedPageList][i].Blink = MM_EMPTY_LIST; 00552 MmFreePagesByPrimaryColor[FreePageList][i].Blink = MM_EMPTY_LIST; 00553 } 00554 00555 // 00556 // Go through the page table entries and for any page which is 00557 // valid, update the corresponding PFN database element. 00558 // 00559 00560 PointerPde = MiGetPdeAddress (PTE_BASE); 00561 00562 PdePage = PointerPde->u.Hard.PageFrameNumber; 00563 Pfn1 = MI_PFN_ELEMENT(PdePage); 00564 Pfn1->PteFrame = PdePage; 00565 Pfn1->PteAddress = PointerPde; 00566 Pfn1->u2.ShareCount += 1; 00567 Pfn1->u3.e2.ReferenceCount = 1; 00568 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00569 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE (PointerPde); 00570 00571 // 00572 // Add the pages which were used to construct nonpaged pool to 00573 // the pfn database. 00574 // 00575 00576 Pde = MiGetPdeAddress ((ULONG)NonPagedPoolStartVirtual - 00577 ((MmNumberOfSystemPtes + 1) * PAGE_SIZE)); 00578 00579 EndPde = MiGetPdeAddress(MmNonPagedPoolEnd); 00580 00581 while (Pde <= EndPde) { 00582 if (Pde->u.Hard.Valid == 1) { 00583 PdePage = Pde->u.Hard.PageFrameNumber; 00584 Pfn1 = MI_PFN_ELEMENT(PdePage); 00585 Pfn1->PteFrame = PointerPde->u.Hard.PageFrameNumber; 00586 Pfn1->PteAddress = Pde; 00587 Pfn1->u2.ShareCount += 1; 00588 Pfn1->u3.e2.ReferenceCount = 1; 00589 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00590 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE (Pde); 00591 00592 PointerPte = MiGetVirtualAddressMappedByPte (Pde); 00593 for (j = 0 ; j < PTE_PER_PAGE; j++) { 00594 if (PointerPte->u.Hard.Valid == 1) { 00595 00596 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 00597 Pfn2 = MI_PFN_ELEMENT(PageFrameIndex); 00598 Pfn2->PteFrame = PdePage; 00599 Pfn2->u2.ShareCount += 1; 00600 Pfn2->u3.e2.ReferenceCount = 1; 00601 Pfn2->u3.e1.PageLocation = ActiveAndValid; 00602 Pfn2->PteAddress = 00603 (PMMPTE)(KSEG0_BASE | (PageFrameIndex << PTE_SHIFT)); 00604 00605 Pfn2->u3.e1.PageColor = 00606 MI_GET_PAGE_COLOR_FROM_PTE (Pfn2->PteAddress); 00607 } 00608 PointerPte++; 00609 } 00610 } 00611 Pde++; 00612 } 00613 00614 // 00615 // If page zero is still unused, mark it as in use. This is 00616 // temporary as we want to find bugs where a physical page 00617 // is specified as zero. 00618 // 00619 00620 Pfn1 = &MmPfnDatabase[MmLowestPhysicalPage]; 00621 if (Pfn1->u3.e2.ReferenceCount == 0) { 00622 00623 // 00624 // Make the reference count non-zero and point it into a 00625 // page directory. 00626 // 00627 00628 Pde = MiGetPdeAddress (0xb0000000); 00629 PdePage = Pde->u.Hard.PageFrameNumber; 00630 Pfn1->PteFrame = PdePageNumber; 00631 Pfn1->PteAddress = Pde; 00632 Pfn1->u2.ShareCount += 1; 00633 Pfn1->u3.e2.ReferenceCount = 1; 00634 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00635 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE (Pde); 00636 } 00637 00638 // end of temporary set to physical page zero. 00639 00640 00641 // 00642 // 00643 // Walk through the memory descriptors and add pages to the 00644 // free list in the PFN database. 00645 // 00646 00647 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 00648 00649 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 00650 00651 MemoryDescriptor = CONTAINING_RECORD(NextMd, 00652 MEMORY_ALLOCATION_DESCRIPTOR, 00653 ListEntry); 00654 00655 i = MemoryDescriptor->PageCount; 00656 NextPhysicalPage = MemoryDescriptor->BasePage; 00657 00658 switch (MemoryDescriptor->MemoryType) { 00659 case LoaderBad: 00660 while (i != 0) { 00661 MiInsertPageInList (MmPageLocationList[BadPageList], 00662 NextPhysicalPage); 00663 i -= 1; 00664 NextPhysicalPage += 1; 00665 } 00666 break; 00667 00668 case LoaderFree: 00669 case LoaderLoadedProgram: 00670 case LoaderFirmwareTemporary: 00671 case LoaderOsloaderStack: 00672 00673 Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage); 00674 while (i != 0) { 00675 if (Pfn1->u3.e2.ReferenceCount == 0) { 00676 00677 // 00678 // Set the PTE address to the phyiscal page for 00679 // virtual address alignment checking. 00680 // 00681 00682 Pfn1->PteAddress = (PMMPTE)(NextPhysicalPage << PTE_SHIFT); 00683 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE ( 00684 Pfn1->PteAddress); 00685 00686 MiInsertPageInList (MmPageLocationList[FreePageList], 00687 NextPhysicalPage); 00688 } 00689 Pfn1++; 00690 i -= 1; 00691 NextPhysicalPage += 1; 00692 } 00693 break; 00694 00695 default: 00696 PointerPte = MiGetPteAddress(KSEG0_BASE | 00697 (NextPhysicalPage << PAGE_SHIFT)); 00698 00699 Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage); 00700 while (i != 0) { 00701 00702 // 00703 // Set page as in use. 00704 // 00705 00706 Pfn1->PteFrame = PdePageNumber; 00707 Pfn1->PteAddress = PointerPte; 00708 Pfn1->u2.ShareCount += 1; 00709 Pfn1->u3.e2.ReferenceCount = 1; 00710 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00711 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE ( 00712 PointerPte); 00713 00714 Pfn1++; 00715 i -= 1; 00716 NextPhysicalPage += 1; 00717 PointerPte += 1; 00718 } 00719 00720 break; 00721 } 00722 00723 NextMd = MemoryDescriptor->ListEntry.Flink; 00724 } 00725 00726 // 00727 // If the PFN database is allocated in virtual memory, then indicate that 00728 // the PFN database is allocated in NonPaged pool. Otherwise, scan the PFN 00729 // database for holes and insert the respective pages in the free page list. 00730 // 00731 00732 if (PfnInKseg0 == FALSE) { 00733 00734 // 00735 // The PFN database is allocated in virtual memory. 00736 // 00737 // Set the start and end of allocation. 00738 // 00739 00740 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmLowestPhysicalPage])->u.Hard.PageFrameNumber); 00741 Pfn1->u3.e1.StartOfAllocation = 1; 00742 Pfn1 = MI_PFN_ELEMENT(MiGetPteAddress(&MmPfnDatabase[MmHighestPhysicalPage])->u.Hard.PageFrameNumber); 00743 Pfn1->u3.e1.EndOfAllocation = 1; 00744 00745 } else { 00746 00747 // 00748 // The PFN database is allocated in KSEG0. 00749 // 00750 // Mark all pfn entries for the pfn pages in use. 00751 // 00752 00753 PageNumber = ((ULONG)MmPfnDatabase - KSEG0_BASE) >> PAGE_SHIFT; 00754 Pfn1 = MI_PFN_ELEMENT(PageNumber); 00755 do { 00756 Pfn1->PteAddress = (PMMPTE)(PageNumber << PTE_SHIFT); 00757 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE(Pfn1->PteAddress); 00758 Pfn1 += 1; 00759 PfnAllocation -= 1; 00760 } while (PfnAllocation != 0); 00761 00762 // Scan the PFN database backward for pages that are completely zero. 00763 // These pages are unused and can be added to the free list 00764 // 00765 00766 BottomPfn = MI_PFN_ELEMENT(MmHighestPhysicalPage); 00767 do { 00768 00769 // 00770 // Compute the address of the start of the page that is next 00771 // lower in memory and scan backwards until that page address 00772 // is reached or just crossed. 00773 // 00774 00775 if (((ULONG)BottomPfn & (PAGE_SIZE - 1)) != 0) { 00776 BasePfn = (PMMPFN)((ULONG)BottomPfn & ~(PAGE_SIZE - 1)); 00777 TopPfn = BottomPfn + 1; 00778 00779 } else { 00780 BasePfn = (PMMPFN)((ULONG)BottomPfn - PAGE_SIZE); 00781 TopPfn = BottomPfn; 00782 } 00783 00784 while (BottomPfn > BasePfn) { 00785 BottomPfn -= 1; 00786 } 00787 00788 // 00789 // If the entire range over which the PFN entries span is 00790 // completely zero and the PFN entry that maps the page is 00791 // not in the range, then add the page to the appropriate 00792 // free list. 00793 // 00794 00795 Range = (ULONG)TopPfn - (ULONG)BottomPfn; 00796 if (RtlCompareMemoryUlong((PVOID)BottomPfn, Range, 0) == Range) { 00797 00798 // 00799 // Set the PTE address to the physical page for virtual 00800 // address alignment checking. 00801 // 00802 00803 PageNumber = ((ULONG)BasePfn - KSEG0_BASE) >> PAGE_SHIFT; 00804 Pfn1 = MI_PFN_ELEMENT(PageNumber); 00805 00806 ASSERT(Pfn1->u3.e2.ReferenceCount == 0); 00807 00808 PfnAllocation += 1; 00809 00810 Pfn1->PteAddress = (PMMPTE)(PageNumber << PTE_SHIFT); 00811 Pfn1->u3.e1.PageColor = MI_GET_PAGE_COLOR_FROM_PTE(Pfn1->PteAddress); 00812 MiInsertPageInList(MmPageLocationList[FreePageList], 00813 PageNumber); 00814 } 00815 00816 } while (BottomPfn > MmPfnDatabase); 00817 } 00818 00819 // 00820 // Indicate that nonpaged pool must succeed is allocated in 00821 // nonpaged pool. 00822 // 00823 00824 i = MmSizeOfNonPagedMustSucceed; 00825 Pfn1 = MI_PFN_ELEMENT(MI_CONVERT_PHYSICAL_TO_PFN (MmNonPagedMustSucceed)); 00826 while ((LONG)i > 0) { 00827 Pfn1->u3.e1.StartOfAllocation = 1; 00828 Pfn1->u3.e1.EndOfAllocation = 1; 00829 i -= PAGE_SIZE; 00830 Pfn1 += 1; 00831 } 00832 00833 KeInitializeSpinLock (&MmSystemSpaceLock); 00834 KeInitializeSpinLock (&MmPfnLock); 00835 00836 // 00837 // Initialize the nonpaged available PTEs for mapping I/O space 00838 // and kernel stacks. 00839 // 00840 00841 PointerPte = MiGetPteAddress ((ULONG)NonPagedPoolStartVirtual - 00842 ((MmNumberOfSystemPtes + 1) * PAGE_SIZE)); 00843 00844 PointerPte = (PMMPTE)PAGE_ALIGN (PointerPte); 00845 if (PfnInKseg0) { 00846 MmNumberOfSystemPtes = MiGetPteAddress(MmNonPagedPoolExpansionStart) - PointerPte - 1; 00847 } else { 00848 MmNumberOfSystemPtes = MiGetPteAddress(NonPagedPoolStartVirtual) - PointerPte - 1; 00849 } 00850 00851 MiInitializeSystemPtes (PointerPte, MmNumberOfSystemPtes, SystemPteSpace); 00852 00853 // 00854 // Initialize the nonpaged pool. 00855 // 00856 00857 InitializePool(NonPagedPool,0); 00858 00859 // 00860 // Initialize memory management structures for this process. 00861 // 00862 00863 // 00864 // Build working set list. System initialization has created 00865 // a PTE for hyperspace. 00866 // 00867 // Note, we can't remove a zeroed page as hyper space does not 00868 // exist and we map non-zeroed pages into hyper space to zero. 00869 // 00870 00871 PointerPte = MiGetPdeAddress(HYPER_SPACE); 00872 00873 ASSERT (PointerPte->u.Hard.Valid == 1); 00874 PointerPte->u.Hard.Global = 0; 00875 PointerPte->u.Hard.Write = 1; 00876 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 00877 00878 // 00879 // Point to the page table page we just created and zero it. 00880 // 00881 00882 00883 // KeFillEntryTb ((PHARDWARE_PTE)PointerPte, 00884 // MiGetPteAddress(HYPER_SPACE), 00885 // TRUE); 00886 00887 PointerPte = MiGetPteAddress(HYPER_SPACE); 00888 RtlZeroMemory ((PVOID)PointerPte, PAGE_SIZE); 00889 00890 // 00891 // Hyper space now exists, set the necessary variables. 00892 // 00893 00894 MmFirstReservedMappingPte = MiGetPteAddress (FIRST_MAPPING_PTE); 00895 MmLastReservedMappingPte = MiGetPteAddress (LAST_MAPPING_PTE); 00896 00897 MmWorkingSetList = WORKING_SET_LIST; 00898 MmWsle = (PMMWSLE)((PUCHAR)WORKING_SET_LIST + sizeof(MMWSL)); 00899 00900 // 00901 // Initialize this process's memory management structures including 00902 // the working set list. 00903 // 00904 00905 // 00906 // The pfn element for the page directory has already been initialized, 00907 // zero the reference count and the share count so they won't be 00908 // wrong. 00909 // 00910 00911 Pfn1 = MI_PFN_ELEMENT (PdePageNumber); 00912 Pfn1->u2.ShareCount = 0; 00913 Pfn1->u3.e2.ReferenceCount = 0; 00914 Pfn1->u3.e1.PageColor = 0; 00915 00916 // 00917 // The pfn element for the PDE which maps hyperspace has already 00918 // been initialized, zero the reference count and the share count 00919 // so they won't be wrong. 00920 // 00921 00922 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 00923 Pfn1->u2.ShareCount = 0; 00924 Pfn1->u3.e2.ReferenceCount = 0; 00925 Pfn1->u3.e1.PageColor = 1; 00926 00927 00928 CurrentProcess = PsGetCurrentProcess (); 00929 00930 // 00931 // Get a page for the working set list and map it into the Page 00932 // directory at the page after hyperspace. 00933 // 00934 00935 PointerPte = MiGetPteAddress (HYPER_SPACE); 00936 PageFrameIndex = MiRemoveAnyPage (MI_GET_PAGE_COLOR_FROM_PTE(PointerPte)); 00937 CurrentProcess->WorkingSetPage = PageFrameIndex; 00938 00939 TempPte.u.Hard.Global = 0; 00940 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00941 PointerPde = MiGetPdeAddress (HYPER_SPACE) + 1; 00942 00943 // 00944 // Assert that the double mapped pages have the same alignment. 00945 // 00946 00947 ASSERT ((PointerPte->u.Long & (0xF << PTE_SHIFT)) == 00948 (PointerPde->u.Long & (0xF << PTE_SHIFT))); 00949 00950 *PointerPde = TempPte; 00951 00952 PointerPte = MiGetVirtualAddressMappedByPte (PointerPde); 00953 00954 KeFillEntryTb ((PHARDWARE_PTE)PointerPde, 00955 PointerPte, 00956 TRUE); 00957 00958 RtlZeroMemory ((PVOID)PointerPte, PAGE_SIZE); 00959 00960 TempPte = *PointerPde; 00961 TempPte.u.Hard.Valid = 0; 00962 TempPte.u.Hard.Global = 0; 00963 00964 KeRaiseIrql(DISPATCH_LEVEL, &OldIrql); 00965 KeFlushSingleTb (PointerPte, 00966 TRUE, 00967 FALSE, 00968 (PHARDWARE_PTE)PointerPde, 00969 TempPte.u.Hard); 00970 00971 KeLowerIrql(OldIrql); 00972 00973 #ifdef R4000 00974 00975 // 00976 // Initialize hyperspace for this process. 00977 // 00978 00979 i = NUMBER_OF_MAPPING_PTES - MM_COLOR_MASK; 00980 PointerPte = MmFirstReservedMappingPte; 00981 while (PointerPte <= (MmFirstReservedMappingPte + MM_COLOR_MASK)) { 00982 PointerPte->u.Hard.PageFrameNumber = i; 00983 PointerPte += 1; 00984 } 00985 00986 #endif 00987 00988 CurrentProcess->Vm.MaximumWorkingSetSize = MmSystemProcessWorkingSetMax; 00989 CurrentProcess->Vm.MinimumWorkingSetSize = MmSystemProcessWorkingSetMin; 00990 00991 MmInitializeProcessAddressSpace (CurrentProcess, 00992 (PEPROCESS)NULL, 00993 (PVOID)NULL); 00994 00995 *PointerPde = ZeroPte; 00996 KeFlushEntireTb(TRUE, TRUE); 00997 00998 // 00999 // Check to see if moving the secondary page structures to the end 01000 // of the PFN database is a waste of memory. And if so, copy it 01001 // to paged pool. 01002 // 01003 // If the PFN datbase ends on a page aligned boundary and the 01004 // size of the two arrays is less than a page, free the page 01005 // and allocate nonpagedpool for this. 01006 // 01007 01008 if ((((ULONG)MmFreePagesByColor[0] & (PAGE_SIZE - 1)) == 0) && 01009 ((MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)) < PAGE_SIZE)) { 01010 01011 PMMCOLOR_TABLES c; 01012 01013 c = MmFreePagesByColor[0]; 01014 01015 MmFreePagesByColor[0] = ExAllocatePoolWithTag (NonPagedPoolMustSucceed, 01016 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES), 01017 ' mM'); 01018 01019 MmFreePagesByColor[1] = &MmFreePagesByColor[0][MmSecondaryColors]; 01020 01021 RtlMoveMemory (MmFreePagesByColor[0], 01022 c, 01023 MmSecondaryColors * 2 * sizeof(MMCOLOR_TABLES)); 01024 01025 // 01026 // Free the page. 01027 // 01028 01029 if (!MI_IS_PHYSICAL_ADDRESS(c)) { 01030 PointerPte = MiGetPteAddress(c); 01031 PageFrameIndex = PointerPte->u.Hard.PageFrameNumber; 01032 *PointerPte = ZeroKernelPte; 01033 } else { 01034 PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (c); 01035 } 01036 01037 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01038 ASSERT ((Pfn1->u3.e2.ReferenceCount <= 1) && (Pfn1->u2.ShareCount <= 1)); 01039 Pfn1->u2.ShareCount = 0; 01040 Pfn1->u3.e2.ReferenceCount = 0; 01041 MI_SET_PFN_DELETED (Pfn1); 01042 #if DBG 01043 Pfn1->u3.e1.PageLocation = StandbyPageList; 01044 #endif //DBG 01045 MiInsertPageInList (MmPageLocationList[FreePageList], PageFrameIndex); 01046 } 01047 return; 01048 } }


Generated on Sat May 15 19:44:12 2004 for test by doxygen 1.3.7