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

mminit.c File Reference

#include "mi.h"

Go to the source code of this file.

Defines

#define MM_MAX_LOADER_BLOCKS   30
#define MM_SMALL_SYSTEM   ((13*1024*1024) / 4096)
#define MM_MEDIUM_SYSTEM   ((19*1024*1024) / 4096)
#define MM_MIN_INITIAL_PAGED_POOL   ((32*1024*1024) >> PAGE_SHIFT)
#define MM_DEFAULT_IO_LOCK_LIMIT   (2 * 1024 * 1024)

Functions

VOID MiMapBBTMemory (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID MiInitializeSpecialPool (VOID)
VOID MiEnablePagingTheExecutive (VOID)
VOID MiEnablePagingOfDriverAtInit (IN PMMPTE PointerPte, IN PMMPTE LastPte)
VOID MiBuildPagedPool ()
VOID MiMergeMemoryLimit (IN OUT PPHYSICAL_MEMORY_DESCRIPTOR Memory, IN PFN_NUMBER StartPage, IN PFN_NUMBER NumberOfPages)
VOID MiWriteProtectSystemImage (IN PVOID DllBase)
VOID MiInitializeSpecialPoolCriteria (IN VOID)
BOOLEAN MmInitSystem (IN ULONG Phase, IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PPHYSICAL_MEMORY_DESCRIPTOR PhysicalMemoryBlock)
VOID MmInitializeMemoryLimits (IN PLOADER_PARAMETER_BLOCK LoaderBlock, IN PBOOLEAN IncludeType, OUT PPHYSICAL_MEMORY_DESCRIPTOR Memory)
VOID MmFreeLoaderBlock (IN PLOADER_PARAMETER_BLOCK LoaderBlock)
VOID MiBuildPagedPool (VOID)
VOID MiFindInitializationCode (OUT PVOID *StartVa, OUT PVOID *EndVa)
VOID MiFreeInitializationCode (IN PVOID StartVa, IN PVOID EndVa)
MM_SYSTEMSIZE MmQuerySystemSize (VOID)
NTKERNELAPI BOOLEAN MmIsThisAnNtAsSystem (VOID)
NTKERNELAPI VOID FASTCALL MmSetPageFaultNotifyRoutine (PPAGE_FAULT_NOTIFY_ROUTINE NotifyRoutine)
NTKERNELAPI VOID FASTCALL MmSetHardFaultNotifyRoutine (PHARD_FAULT_NOTIFY_ROUTINE NotifyRoutine)

Variables

MMPTE MmSharedUserDataPte
MMINPAGE_SUPPORT_LIST MmInPageSupportList
MMEVENT_COUNT_LIST MmEventCountList
KMUTANT MmSystemLoadLock
ULONG_PTR MmSystemPtesStart [MaximumPtePoolTypes]
ULONG MiSpecialPoolPtes
ULONG MmPagedPoolCommit
PVOID BBTBuffer
ULONG BBTPagesToReserve
ULONG_PTR MmSubsectionBase
ULONG_PTR MmSubsectionTopPage
ULONG MmDataClusterSize
ULONG MmCodeClusterSize
PFN_NUMBER MmResidentAvailableAtInit
KEVENT MmImageMappingPteEvent
PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
LIST_ENTRY MmLockConflictList
LOGICAL MmPagedPoolMaximumDesired = FALSE
 PERFINFO_MMINIT_DECL
ULONG MmModifiedPageLifeInSeconds = 300
LARGE_INTEGER MiModifiedPageLife
BOOLEAN MiTimerPending = FALSE
KEVENT MiMappedPagesTooOldEvent
KDPC MiModifiedPageWriterTimerDpc
KTIMER MiModifiedPageWriterTimer
ULONG MmMaximumWorkingSetSize
ULONG MmEnforceWriteProtection
CHAR MiPteStr []
LONG MiTrimInProgressCount
PFN_NUMBER MmSystemPageDirectory
PMMPTE MmSystemPagePtes
ULONG MmTotalSystemCodePages
MM_SYSTEMSIZE MmSystemSize
ULONG MmLargeSystemCache
ULONG MmProductType
LIST_ENTRY MmLoadedUserImageList
PPAGE_FAULT_NOTIFY_ROUTINE MmPageFaultNotifyRoutine
PHARD_FAULT_NOTIFY_ROUTINE MmHardFaultNotifyRoutine


Define Documentation

#define MM_DEFAULT_IO_LOCK_LIMIT   (2 * 1024 * 1024)
 

Definition at line 149 of file mminit.c.

#define MM_MAX_LOADER_BLOCKS   30
 

Definition at line 118 of file mminit.c.

Referenced by MmFreeLoaderBlock().

#define MM_MEDIUM_SYSTEM   ((19*1024*1024) / 4096)
 

Definition at line 145 of file mminit.c.

Referenced by MmInitSystem().

#define MM_MIN_INITIAL_PAGED_POOL   ((32*1024*1024) >> PAGE_SHIFT)
 

Definition at line 147 of file mminit.c.

Referenced by MiBuildPagedPool().

#define MM_SMALL_SYSTEM   ((13*1024*1024) / 4096)
 

Definition at line 143 of file mminit.c.

Referenced by MmInitSystem().


Function Documentation

VOID MiBuildPagedPool VOID   ) 
 

Definition at line 2184 of file mminit.c.

References ActiveAndValid, ASSERT, BYTES_TO_PAGES, InitializePool(), L, LOCK_PFN, MI_GET_PAGE_COLOR_FROM_PTE, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_WRITE_VALID_PTE, MiCreateBitMap, MiFillMemoryPte, MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiInitializeSpecialPool(), MiInitializeSystemSpaceMap(), MiMapPageInHyperSpace(), MiRemoveAnyPage(), MiReserveSystemPtes(), MiUnmapPageInHyperSpace, MM_COLOR_ALIGNMENT, MM_COLOR_MASK_VIRTUAL, MM_DEMAND_ZERO_WRITE_PTE, MM_KERNEL_NOACCESS_PTE, MM_MAX_PAGED_POOL, MM_MIN_INITIAL_PAGED_POOL, MM_MINIMUM_PAGED_POOL_NTAS, MmIsThisAnNtAsSystem(), MmMaximumNonPagedPoolInBytes, MmNonPagedSystemStart, MmNumberOfPhysicalPages, MmPageAlignedPoolBase, MmPagedPoolBasePde, MmPagedPoolEnd, MmPagedPoolInfo, MmPagedPoolMaximumDesired, MmPagedPoolStart, MmSizeOfPagedPoolInBytes, MmSystemPageDirectory, MmSystemPagePtes, MmVerifyDriverBufferLength, NonPagedPool, _MMPFN::OriginalPte, PAGE_SHIFT, PAGE_SIZE, PagedPool, PDE_KTBASE, PDE_PER_PAGE, PTE_PER_PAGE, _MMPFN::PteAddress, _MMPFN::PteFrame, RtlClearAllBits(), RtlClearBits(), RtlSetAllBits(), Size, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, ValidKernelPde, and VerifierLargePagedPoolMap.

02190 : 02191 02192 This function is called to build the structures required for paged 02193 pool and initialize the pool. Once this routine is called, paged 02194 pool may be allocated. 02195 02196 Arguments: 02197 02198 None. 02199 02200 Return Value: 02201 02202 None. 02203 02204 Environment: 02205 02206 Kernel Mode Only. System initialization. 02207 02208 --*/ 02209 02210 { 02211 SIZE_T Size; 02212 PMMPTE PointerPte; 02213 PMMPTE PointerPde; 02214 PMMPTE PointerPpe; 02215 PMMPTE PointerPpeEnd; 02216 MMPTE TempPte; 02217 PMMPFN Pfn1; 02218 PFN_NUMBER PageFrameIndex; 02219 KIRQL OldIrql; 02220 ULONG i; 02221 02222 #if !defined (_WIN64) 02223 02224 // 02225 // Double map system page directory page. 02226 // 02227 02228 #if defined (_X86PAE_) 02229 02230 PointerPte = MiGetPteAddress(PDE_BASE); 02231 02232 for (i = 0 ; i < PD_PER_SYSTEM; i += 1) { 02233 MmSystemPageDirectory[i] = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02234 Pfn1 = MI_PFN_ELEMENT(MmSystemPageDirectory[i]); 02235 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02236 PointerPte += 1; 02237 } 02238 02239 // 02240 // Was not mapped physically, map it virtually in system space. 02241 // 02242 02243 PointerPte = MiReserveSystemPtes ( 02244 PD_PER_SYSTEM, 02245 SystemPteSpace, 02246 MM_COLOR_ALIGNMENT, 02247 ((ULONG_PTR)PDE_BASE & MM_COLOR_MASK_VIRTUAL), 02248 TRUE); 02249 02250 MmSystemPagePtes = (PMMPTE)MiGetVirtualAddressMappedByPte (PointerPte); 02251 02252 TempPte = ValidKernelPde; 02253 02254 for (i = 0 ; i < PD_PER_SYSTEM; i += 1) { 02255 TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory[i]; 02256 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02257 PointerPte += 1; 02258 } 02259 02260 #else 02261 02262 MmSystemPageDirectory = MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(PDE_BASE)); 02263 02264 Pfn1 = MI_PFN_ELEMENT(MmSystemPageDirectory); 02265 02266 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02267 02268 MmSystemPagePtes = (PMMPTE)MiMapPageInHyperSpace (MmSystemPageDirectory, 02269 &OldIrql); 02270 MiUnmapPageInHyperSpace (OldIrql); 02271 02272 if (!MI_IS_PHYSICAL_ADDRESS(MmSystemPagePtes)) { 02273 02274 // 02275 // Was not mapped physically, map it virtually in system space. 02276 // 02277 02278 PointerPte = MiReserveSystemPtes ( 02279 1, 02280 SystemPteSpace, 02281 MM_COLOR_ALIGNMENT, 02282 ((ULONG_PTR)PDE_BASE & MM_COLOR_MASK_VIRTUAL), 02283 TRUE); 02284 TempPte = ValidKernelPde; 02285 TempPte.u.Hard.PageFrameNumber = MmSystemPageDirectory; 02286 MI_WRITE_VALID_PTE (PointerPte, TempPte); 02287 MmSystemPagePtes = (PMMPTE)MiGetVirtualAddressMappedByPte (PointerPte); 02288 } 02289 #endif 02290 02291 #endif 02292 02293 if (MmPagedPoolMaximumDesired == TRUE) { 02294 MmSizeOfPagedPoolInBytes = 02295 ((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart); 02296 } 02297 02298 // 02299 // A size of 0 means size the pool based on physical memory. 02300 // 02301 02302 if (MmSizeOfPagedPoolInBytes == 0) { 02303 MmSizeOfPagedPoolInBytes = 2 * MmMaximumNonPagedPoolInBytes; 02304 } 02305 02306 if (MmIsThisAnNtAsSystem()) { 02307 if ((MmNumberOfPhysicalPages > ((24*1024*1024) >> PAGE_SHIFT)) && 02308 (MmSizeOfPagedPoolInBytes < MM_MINIMUM_PAGED_POOL_NTAS)) { 02309 02310 MmSizeOfPagedPoolInBytes = MM_MINIMUM_PAGED_POOL_NTAS; 02311 } 02312 } 02313 02314 if (MmSizeOfPagedPoolInBytes > 02315 (ULONG_PTR)((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart)) { 02316 MmSizeOfPagedPoolInBytes = 02317 ((PCHAR)MmNonPagedSystemStart - (PCHAR)MmPagedPoolStart); 02318 } 02319 02320 Size = BYTES_TO_PAGES(MmSizeOfPagedPoolInBytes); 02321 02322 if (Size < MM_MIN_INITIAL_PAGED_POOL) { 02323 Size = MM_MIN_INITIAL_PAGED_POOL; 02324 } 02325 02326 if (Size > (MM_MAX_PAGED_POOL >> PAGE_SHIFT)) { 02327 Size = MM_MAX_PAGED_POOL >> PAGE_SHIFT; 02328 } 02329 02330 Size = (Size + (PTE_PER_PAGE - 1)) / PTE_PER_PAGE; 02331 MmSizeOfPagedPoolInBytes = (ULONG_PTR)Size * PAGE_SIZE * PTE_PER_PAGE; 02332 02333 ASSERT ((MmSizeOfPagedPoolInBytes + (PCHAR)MmPagedPoolStart) <= 02334 (PCHAR)MmNonPagedSystemStart); 02335 02336 // 02337 // Set size to the number of pages in the pool. 02338 // 02339 02340 Size = Size * PTE_PER_PAGE; 02341 02342 MmPagedPoolEnd = (PVOID)(((PUCHAR)MmPagedPoolStart + 02343 MmSizeOfPagedPoolInBytes) - 1); 02344 02345 MmPageAlignedPoolBase[PagedPool] = MmPagedPoolStart; 02346 02347 // 02348 // Build page table page for paged pool. 02349 // 02350 02351 PointerPde = MiGetPdeAddress (MmPagedPoolStart); 02352 MmPagedPoolBasePde = PointerPde; 02353 02354 TempPte = ValidKernelPde; 02355 02356 #if defined (_WIN64) 02357 02358 // 02359 // Map in all the page directory pages to span all of paged pool. 02360 // This removes the need for a system lookup directory. 02361 // 02362 02363 PointerPpe = MiGetPpeAddress (MmPagedPoolStart); 02364 PointerPpeEnd = MiGetPpeAddress (MmPagedPoolEnd); 02365 02366 while (PointerPpe <= PointerPpeEnd) { 02367 02368 if (PointerPpe->u.Hard.Valid == 0) { 02369 PageFrameIndex = MiRemoveAnyPage( 02370 MI_GET_PAGE_COLOR_FROM_PTE (PointerPpe)); 02371 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02372 *PointerPpe = TempPte; 02373 02374 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02375 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE ( 02376 MiGetPteAddress(PDE_KTBASE)); 02377 Pfn1->PteAddress = PointerPpe; 02378 Pfn1->u2.ShareCount = 1; 02379 Pfn1->u3.e2.ReferenceCount = 1; 02380 Pfn1->u3.e1.PageLocation = ActiveAndValid; 02381 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02382 } 02383 02384 PointerPpe += 1; 02385 } 02386 02387 #endif 02388 02389 PointerPte = MiGetPteAddress (MmPagedPoolStart); 02390 MmPagedPoolInfo.FirstPteForPagedPool = PointerPte; 02391 MmPagedPoolInfo.LastPteForPagedPool = MiGetPteAddress (MmPagedPoolEnd); 02392 02393 MiFillMemoryPte (PointerPde, 02394 sizeof(MMPTE) * 02395 (1 + MiGetPdeAddress (MmPagedPoolEnd) - PointerPde), 02396 MM_KERNEL_NOACCESS_PTE); 02397 02398 LOCK_PFN (OldIrql); 02399 02400 // 02401 // Map in a page table page. 02402 // 02403 02404 PageFrameIndex = MiRemoveAnyPage( 02405 MI_GET_PAGE_COLOR_FROM_PTE (PointerPde)); 02406 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 02407 MI_WRITE_VALID_PTE (PointerPde, TempPte); 02408 02409 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 02410 #if defined (_WIN64) 02411 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE(MiGetPpeAddress (MmPagedPoolStart)); 02412 #else 02413 #if !defined (_X86PAE_) 02414 Pfn1->PteFrame = MmSystemPageDirectory; 02415 #else 02416 Pfn1->PteFrame = MmSystemPageDirectory[(PointerPde - MiGetPdeAddress(0)) / PDE_PER_PAGE]; 02417 #endif 02418 #endif 02419 Pfn1->PteAddress = PointerPde; 02420 Pfn1->u2.ShareCount = 1; 02421 Pfn1->u3.e2.ReferenceCount = 1; 02422 Pfn1->u3.e1.PageLocation = ActiveAndValid; 02423 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 02424 MiFillMemoryPte (PointerPte, PAGE_SIZE, MM_KERNEL_NOACCESS_PTE); 02425 02426 UNLOCK_PFN (OldIrql); 02427 02428 MmPagedPoolInfo.NextPdeForPagedPoolExpansion = PointerPde + 1; 02429 02430 // 02431 // Build bitmaps for paged pool. 02432 // 02433 02434 MiCreateBitMap (&MmPagedPoolInfo.PagedPoolAllocationMap, Size, NonPagedPool); 02435 RtlSetAllBits (MmPagedPoolInfo.PagedPoolAllocationMap); 02436 02437 // 02438 // Indicate first page worth of PTEs are available. 02439 // 02440 02441 RtlClearBits (MmPagedPoolInfo.PagedPoolAllocationMap, 0, PTE_PER_PAGE); 02442 02443 MiCreateBitMap (&MmPagedPoolInfo.EndOfPagedPoolBitmap, Size, NonPagedPool); 02444 RtlClearAllBits (MmPagedPoolInfo.EndOfPagedPoolBitmap); 02445 02446 // 02447 // If verifier is present then build the verifier paged pool bitmap. 02448 // 02449 02450 if (MmVerifyDriverBufferLength != (ULONG)-1) { 02451 MiCreateBitMap (&VerifierLargePagedPoolMap, Size, NonPagedPool); 02452 RtlClearAllBits (VerifierLargePagedPoolMap); 02453 } 02454 02455 // 02456 // Initialize paged pool. 02457 // 02458 02459 InitializePool (PagedPool, 0L); 02460 02461 MiInitializeSpecialPool(); 02462 02463 // 02464 // Allow mapping of views into system space. 02465 // 02466 02467 MiInitializeSystemSpaceMap ((PVOID)0); 02468 02469 return; 02470 }

VOID MiBuildPagedPool  ) 
 

Referenced by MmInitSystem().

VOID MiEnablePagingOfDriverAtInit IN PMMPTE  PointerPte,
IN PMMPTE  LastPte
 

Definition at line 2944 of file mminit.c.

References ASSERT, KeFlushSingleTb(), LOCK_PFN, LOCK_SYSTEM_WS, MI_FLUSH_ENTIRE_SESSION_TB, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_SESSION_PTE, MI_MAKE_VALID_PTE_TRANSITION, MI_PFN_ELEMENT, MI_ZERO_WSINDEX, MiDecrementShareCount(), MiGetVirtualAddressMappedByPte, MM_EXECUTE, MM_KERNEL_DEMAND_ZERO_PTE, MmResidentAvailablePages, MmTotalSystemCodePages, _MMPFN::OriginalPte, PAGE_SIZE, TRUE, _MMPTE::u, _MMPFN::u1, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, and UNLOCK_SYSTEM_WS.

Referenced by MiEnablePagingTheExecutive().

02951 : 02952 02953 This routine marks the specified range of PTEs as pagable. 02954 02955 Arguments: 02956 02957 PointerPte - Supplies the starting PTE. 02958 02959 LastPte - Supplies the ending PTE. 02960 02961 Return Value: 02962 02963 None. 02964 02965 --*/ 02966 02967 { 02968 PVOID Base; 02969 PFN_NUMBER PageFrameIndex; 02970 PMMPFN Pfn; 02971 MMPTE TempPte; 02972 KIRQL OldIrql; 02973 KIRQL OldIrqlWs; 02974 LOGICAL SessionAddress; 02975 02976 Base = MiGetVirtualAddressMappedByPte (PointerPte); 02977 SessionAddress = MI_IS_SESSION_PTE (PointerPte); 02978 02979 LOCK_SYSTEM_WS (OldIrqlWs); 02980 LOCK_PFN (OldIrql); 02981 02982 while (PointerPte <= LastPte) { 02983 02984 // 02985 // The PTE must be carefully checked as drivers may call MmPageEntire 02986 // during their DriverEntry yet faults may occur prior to this routine 02987 // running which cause pages to already be resident and in the working 02988 // set at this point. So checks for validity and wsindex must be 02989 // applied. 02990 // 02991 02992 if (PointerPte->u.Hard.Valid == 1) { 02993 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 02994 Pfn = MI_PFN_ELEMENT (PageFrameIndex); 02995 ASSERT (Pfn->u2.ShareCount == 1); 02996 02997 if (Pfn->u1.WsIndex == 0) { 02998 02999 // 03000 // Set the working set index to zero. This allows page table 03001 // pages to be brought back in with the proper WSINDEX. 03002 // 03003 03004 MI_ZERO_WSINDEX (Pfn); 03005 03006 // 03007 // Original PTE may need to be set for drivers loaded via 03008 // ntldr. 03009 // 03010 03011 if (Pfn->OriginalPte.u.Long == 0) { 03012 Pfn->OriginalPte.u.Long = MM_KERNEL_DEMAND_ZERO_PTE; 03013 #if defined(_IA64_) 03014 Pfn->OriginalPte.u.Soft.Protection |= MM_EXECUTE; 03015 #endif 03016 } 03017 03018 Pfn->u3.e1.Modified = 1; 03019 TempPte = *PointerPte; 03020 03021 MI_MAKE_VALID_PTE_TRANSITION (TempPte, 03022 Pfn->OriginalPte.u.Soft.Protection); 03023 03024 KeFlushSingleTb (Base, 03025 TRUE, 03026 TRUE, 03027 (PHARDWARE_PTE)PointerPte, 03028 TempPte.u.Flush); 03029 03030 // 03031 // Flush the translation buffer and decrement the number of valid 03032 // PTEs within the containing page table page. Note that for a 03033 // private page, the page table page is still needed because the 03034 // page is in transition. 03035 // 03036 03037 MiDecrementShareCount (PageFrameIndex); 03038 03039 MmResidentAvailablePages += 1; 03040 MmTotalSystemCodePages += 1; 03041 } 03042 else { 03043 03044 // 03045 // This would need to be taken out of the WSLEs so skip it for 03046 // now and let the normal paging algorithms remove it if we 03047 // run into memory pressure. 03048 // 03049 } 03050 03051 } 03052 Base = (PVOID)((PCHAR)Base + PAGE_SIZE); 03053 PointerPte += 1; 03054 } 03055 03056 UNLOCK_PFN (OldIrql); 03057 UNLOCK_SYSTEM_WS (OldIrqlWs); 03058 03059 if (SessionAddress == TRUE) { 03060 03061 // 03062 // Session space has no ASN - flush the entire TB. 03063 // 03064 03065 MI_FLUSH_ENTIRE_SESSION_TB (TRUE, TRUE); 03066 } 03067 03068 return; 03069 }

VOID MiEnablePagingTheExecutive VOID   ) 
 

Definition at line 2735 of file mminit.c.

References ExAcquireResourceExclusive, ExReleaseResource, FALSE, IoRemoteBootClient, KdPitchDebugger, KeEnterCriticalRegion, KeLeaveCriticalRegion, MI_IS_PHYSICAL_ADDRESS, MiEnablePagingOfDriverAtInit(), MiGetPteAddress, MiHydra, MiSpecialPoolPtes, MmDisablePagingExecutive, MmVerifyDriverBufferLength, NULL, PAGE_SIZE, PsLoadedModuleList, PsLoadedModuleResource, ROUND_TO_PAGES, RtlImageNtHeader(), SECTION_BASE_ADDRESS, and TRUE.

Referenced by MmInitSystem().

02741 : 02742 02743 This function locates the start and end of the kernel initialization 02744 code. This code resides in the "init" section of the kernel image. 02745 02746 Arguments: 02747 02748 StartVa - Returns the starting address of the init section. 02749 02750 EndVa - Returns the ending address of the init section. 02751 02752 Return Value: 02753 02754 None. 02755 02756 Environment: 02757 02758 Kernel Mode Only. End of system initialization. 02759 02760 --*/ 02761 02762 { 02763 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 02764 PVOID CurrentBase; 02765 PLIST_ENTRY Next; 02766 PIMAGE_NT_HEADERS NtHeader; 02767 PIMAGE_SECTION_HEADER SectionTableEntry; 02768 LONG i; 02769 PMMPTE PointerPte; 02770 PMMPTE LastPte; 02771 BOOLEAN PageSection; 02772 PVOID SectionBaseAddress; 02773 02774 // 02775 // Don't page kernel mode code if customer does not want it paged or if 02776 // this is a diskless remote boot client. 02777 // 02778 02779 if (MmDisablePagingExecutive 02780 #if defined(REMOTE_BOOT) 02781 || (IoRemoteBootClient && IoCscInitializationFailed) 02782 #endif 02783 ) { 02784 return; 02785 } 02786 02787 // 02788 // Walk through the loader blocks looking for the base which 02789 // contains this routine. 02790 // 02791 02792 KeEnterCriticalRegion(); 02793 ExAcquireResourceExclusive (&PsLoadedModuleResource, TRUE); 02794 Next = PsLoadedModuleList.Flink; 02795 while ( Next != &PsLoadedModuleList ) { 02796 LdrDataTableEntry = CONTAINING_RECORD( Next, 02797 LDR_DATA_TABLE_ENTRY, 02798 InLoadOrderLinks 02799 ); 02800 if (LdrDataTableEntry->SectionPointer != NULL) { 02801 02802 // 02803 // This entry was loaded by MmLoadSystemImage so it's already paged. 02804 // 02805 02806 Next = Next->Flink; 02807 continue; 02808 } 02809 02810 CurrentBase = (PVOID)LdrDataTableEntry->DllBase; 02811 NtHeader = RtlImageNtHeader(CurrentBase); 02812 02813 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 02814 sizeof(ULONG) + 02815 sizeof(IMAGE_FILE_HEADER) + 02816 NtHeader->FileHeader.SizeOfOptionalHeader); 02817 02818 // 02819 // From the image header, locate the section named 'PAGE' or 02820 // '.edata'. 02821 // 02822 02823 i = NtHeader->FileHeader.NumberOfSections; 02824 02825 PointerPte = NULL; 02826 02827 while (i > 0) { 02828 02829 if (MI_IS_PHYSICAL_ADDRESS (CurrentBase)) { 02830 02831 // 02832 // Mapped physically, can't be paged. 02833 // 02834 02835 break; 02836 } 02837 02838 SectionBaseAddress = SECTION_BASE_ADDRESS(SectionTableEntry); 02839 02840 PageSection = ((*(PULONG)SectionTableEntry->Name == 'EGAP') || 02841 (*(PULONG)SectionTableEntry->Name == 'ade.')) && 02842 (SectionBaseAddress != 02843 ((PUCHAR)CurrentBase + SectionTableEntry->VirtualAddress)); 02844 02845 if (*(PULONG)SectionTableEntry->Name == 'EGAP' && 02846 SectionTableEntry->Name[4] == 'K' && 02847 SectionTableEntry->Name[5] == 'D') { 02848 02849 // 02850 // Only pageout PAGEKD if KdPitchDebugger is TRUE. 02851 // 02852 02853 PageSection = KdPitchDebugger; 02854 } 02855 02856 if ((*(PULONG)SectionTableEntry->Name == 'EGAP') && 02857 (*(PULONG)&SectionTableEntry->Name[4] == 'RDYH')) { 02858 02859 // 02860 // Pageout PAGEHYDRA on non Hydra systems. 02861 // 02862 02863 if (MiHydra == TRUE) { 02864 PageSection = FALSE; 02865 } 02866 } 02867 02868 if ((*(PULONG)SectionTableEntry->Name == 'EGAP') && 02869 (*(PULONG)&SectionTableEntry->Name[4] == 'YFRV')) { 02870 02871 // 02872 // Pageout PAGEVRFY if no drivers are being instrumented. 02873 // 02874 02875 if (MmVerifyDriverBufferLength != (ULONG)-1) { 02876 PageSection = FALSE; 02877 } 02878 } 02879 02880 if ((*(PULONG)SectionTableEntry->Name == 'EGAP') && 02881 (*(PULONG)&SectionTableEntry->Name[4] == 'CEPS')) { 02882 02883 // 02884 // Pageout PAGESPEC special pool code if it's not enabled. 02885 // 02886 02887 if (MiSpecialPoolPtes != 0) { 02888 PageSection = FALSE; 02889 } 02890 } 02891 02892 if (PageSection) { 02893 // 02894 // This section is pagable, save away the start and end. 02895 // 02896 02897 if (PointerPte == NULL) { 02898 02899 // 02900 // Previous section was NOT pagable, get the start address. 02901 // 02902 02903 PointerPte = MiGetPteAddress (ROUND_TO_PAGES ( 02904 (ULONG_PTR)CurrentBase + 02905 SectionTableEntry->VirtualAddress)); 02906 } 02907 LastPte = MiGetPteAddress ((ULONG_PTR)CurrentBase + 02908 SectionTableEntry->VirtualAddress + 02909 (NtHeader->OptionalHeader.SectionAlignment - 1) + 02910 SectionTableEntry->SizeOfRawData - 02911 PAGE_SIZE); 02912 02913 } else { 02914 02915 // 02916 // This section is not pagable, if the previous section was 02917 // pagable, enable it. 02918 // 02919 02920 if (PointerPte != NULL) { 02921 MiEnablePagingOfDriverAtInit (PointerPte, LastPte); 02922 PointerPte = NULL; 02923 } 02924 } 02925 i -= 1; 02926 SectionTableEntry += 1; 02927 } //end while 02928 02929 if (PointerPte != NULL) { 02930 MiEnablePagingOfDriverAtInit (PointerPte, LastPte); 02931 } 02932 02933 Next = Next->Flink; 02934 } //end while 02935 02936 ExReleaseResource (&PsLoadedModuleResource); 02937 KeLeaveCriticalRegion(); 02938 02939 return; 02940 }

VOID MiFindInitializationCode OUT PVOID *  StartVa,
OUT PVOID *  EndVa
 

Definition at line 2474 of file mminit.c.

References DbgPrint, ExAcquireResourceExclusive, ExReleaseResource, KeEnterCriticalRegion, KeLeaveCriticalRegion, MiFindInitializationCode(), MiFreeInitializationCode(), NULL, PAGE_ALIGN, PAGE_SIZE, PsLoadedModuleList, PsLoadedModuleResource, ROUND_TO_PAGES, RtlImageNtHeader(), and TRUE.

Referenced by MiFindInitializationCode(), and MmZeroPageThread().

02481 : 02482 02483 This function locates the start and end of the kernel initialization 02484 code. This code resides in the "init" section of the kernel image. 02485 02486 Arguments: 02487 02488 StartVa - Returns the starting address of the init section. 02489 02490 EndVa - Returns the ending address of the init section. 02491 02492 Return Value: 02493 02494 None. 02495 02496 Environment: 02497 02498 Kernel Mode Only. End of system initialization. 02499 02500 --*/ 02501 02502 { 02503 PLDR_DATA_TABLE_ENTRY LdrDataTableEntry; 02504 PVOID CurrentBase; 02505 PVOID InitStart; 02506 PVOID InitEnd; 02507 PLIST_ENTRY Next; 02508 PIMAGE_NT_HEADERS NtHeader; 02509 PIMAGE_SECTION_HEADER SectionTableEntry; 02510 PIMAGE_SECTION_HEADER LastDiscard; 02511 LONG i; 02512 PVOID MiFindInitializationCodeAddress; 02513 02514 MiFindInitializationCodeAddress = MmGetProcedureAddress((PVOID)&MiFindInitializationCode); 02515 02516 *StartVa = NULL; 02517 02518 // 02519 // Walk through the loader blocks looking for the base which 02520 // contains this routine. 02521 // 02522 02523 KeEnterCriticalRegion(); 02524 ExAcquireResourceExclusive (&PsLoadedModuleResource, TRUE); 02525 Next = PsLoadedModuleList.Flink; 02526 02527 while ( Next != &PsLoadedModuleList ) { 02528 LdrDataTableEntry = CONTAINING_RECORD( Next, 02529 LDR_DATA_TABLE_ENTRY, 02530 InLoadOrderLinks 02531 ); 02532 if (LdrDataTableEntry->SectionPointer != NULL) { 02533 02534 // 02535 // This entry was loaded by MmLoadSystemImage so it's already 02536 // had its init section removed. 02537 // 02538 02539 Next = Next->Flink; 02540 continue; 02541 } 02542 02543 CurrentBase = (PVOID)LdrDataTableEntry->DllBase; 02544 NtHeader = RtlImageNtHeader(CurrentBase); 02545 02546 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 02547 sizeof(ULONG) + 02548 sizeof(IMAGE_FILE_HEADER) + 02549 NtHeader->FileHeader.SizeOfOptionalHeader); 02550 02551 // 02552 // From the image header, locate the section named 'INIT'. 02553 // 02554 02555 i = NtHeader->FileHeader.NumberOfSections; 02556 02557 InitStart = NULL; 02558 while (i > 0) { 02559 02560 #if DBG 02561 if ((*(PULONG)SectionTableEntry->Name == 'tini') || 02562 (*(PULONG)SectionTableEntry->Name == 'egap')) { 02563 DbgPrint("driver %wZ has lower case sections (init or pagexxx)\n", 02564 &LdrDataTableEntry->FullDllName); 02565 } 02566 #endif //DBG 02567 02568 // 02569 // Free any INIT sections (or relocation sections that haven't 02570 // been already). Note a driver may have a relocation section 02571 // but not have any INIT code. 02572 // 02573 02574 if ((*(PULONG)SectionTableEntry->Name == 'TINI') || 02575 ((SectionTableEntry->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0)) { 02576 02577 02578 InitStart = (PVOID)((PCHAR)CurrentBase + SectionTableEntry->VirtualAddress); 02579 InitEnd = (PVOID)((PCHAR)InitStart + SectionTableEntry->SizeOfRawData - 1); 02580 InitEnd = (PVOID)((PCHAR)PAGE_ALIGN ((PCHAR)InitEnd + 02581 (NtHeader->OptionalHeader.SectionAlignment - 1)) - 1); 02582 InitStart = (PVOID)ROUND_TO_PAGES (InitStart); 02583 02584 // 02585 // Check if more sections are discardable after this one so 02586 // even small INIT sections can be discarded. 02587 // 02588 02589 if (i == 1) { 02590 LastDiscard = SectionTableEntry; 02591 } 02592 else { 02593 LastDiscard = NULL; 02594 do { 02595 i -= 1; 02596 SectionTableEntry += 1; 02597 02598 if ((SectionTableEntry->Characteristics & 02599 IMAGE_SCN_MEM_DISCARDABLE) != 0) { 02600 02601 // 02602 // Discard this too. 02603 // 02604 02605 LastDiscard = SectionTableEntry; 02606 } else { 02607 break; 02608 } 02609 } while (i > 1); 02610 } 02611 02612 if (LastDiscard) { 02613 InitEnd = (PVOID)(((PCHAR)CurrentBase + 02614 LastDiscard->VirtualAddress) + 02615 (LastDiscard->SizeOfRawData - 1)); 02616 02617 // 02618 // If this isn't the last section in the driver then the 02619 // the next section is not discardable. So the last 02620 // section is not rounded down, but all others must be. 02621 // 02622 02623 if (i != 1) { 02624 InitEnd = (PVOID)((PCHAR)PAGE_ALIGN ((PCHAR)InitEnd + 02625 (NtHeader->OptionalHeader.SectionAlignment - 1)) - 1); 02626 } 02627 } 02628 02629 if (InitEnd > (PVOID)((PCHAR)CurrentBase + 02630 LdrDataTableEntry->SizeOfImage)) { 02631 InitEnd = (PVOID)(((ULONG_PTR)CurrentBase + 02632 (LdrDataTableEntry->SizeOfImage - 1)) | 02633 (PAGE_SIZE - 1)); 02634 } 02635 02636 if (InitStart <= InitEnd) { 02637 if ((MiFindInitializationCodeAddress >= InitStart) && 02638 (MiFindInitializationCodeAddress <= InitEnd)) { 02639 02640 // 02641 // This init section is in the kernel, don't free it 02642 // now as it would free this code! 02643 // 02644 02645 *StartVa = InitStart; 02646 *EndVa = InitEnd; 02647 } 02648 else { 02649 MiFreeInitializationCode (InitStart, InitEnd); 02650 } 02651 } 02652 } 02653 i -= 1; 02654 SectionTableEntry += 1; 02655 } 02656 Next = Next->Flink; 02657 } 02658 ExReleaseResource (&PsLoadedModuleResource); 02659 KeLeaveCriticalRegion(); 02660 return; 02661 }

VOID MiFreeInitializationCode IN PVOID  StartVa,
IN PVOID  EndVa
 

Definition at line 2664 of file mminit.c.

References ASSERT, FALSE, FreePageList, LOCK_PFN, MI_CONVERT_PHYSICAL_TO_PFN, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MiDeleteSystemPagableVm(), MiFreeInitializationCode(), MiGetPteAddress, MiInsertPageInList(), MmPageLocationList, MmUnlockPagableImageSection(), NULL, PAGE_SIZE, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, and ZeroKernelPte.

Referenced by MiFindInitializationCode(), MiFreeInitializationCode(), and MmZeroPageThread().

02671 : 02672 02673 This function is called to delete the initialization code. 02674 02675 Arguments: 02676 02677 StartVa - Supplies the starting address of the range to delete. 02678 02679 EndVa - Supplies the ending address of the range to delete. 02680 02681 Return Value: 02682 02683 None. 02684 02685 Environment: 02686 02687 Kernel Mode Only. Runs after system initialization. 02688 02689 --*/ 02690 02691 { 02692 PMMPFN Pfn1; 02693 PMMPTE PointerPte; 02694 PFN_NUMBER PageFrameIndex; 02695 KIRQL OldIrql; 02696 PVOID UnlockHandle; 02697 02698 UnlockHandle = MmLockPagableCodeSection((PVOID)MiFreeInitializationCode); 02699 ASSERT(UnlockHandle); 02700 02701 if (MI_IS_PHYSICAL_ADDRESS(StartVa)) { 02702 LOCK_PFN (OldIrql); 02703 while (StartVa < EndVa) { 02704 02705 // 02706 // On certain architectures (e.g., MIPS) virtual addresses 02707 // may be physical and hence have no corresponding PTE. 02708 // 02709 02710 PageFrameIndex = MI_CONVERT_PHYSICAL_TO_PFN (StartVa); 02711 02712 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 02713 Pfn1->u2.ShareCount = 0; 02714 Pfn1->u3.e2.ReferenceCount = 0; 02715 MI_SET_PFN_DELETED (Pfn1); 02716 MiInsertPageInList (MmPageLocationList[FreePageList], PageFrameIndex); 02717 StartVa = (PVOID)((PUCHAR)StartVa + PAGE_SIZE); 02718 } 02719 UNLOCK_PFN (OldIrql); 02720 } else { 02721 PointerPte = MiGetPteAddress (StartVa); 02722 MiDeleteSystemPagableVm (PointerPte, 02723 (PFN_NUMBER) (1 + MiGetPteAddress (EndVa) - 02724 PointerPte), 02725 ZeroKernelPte, 02726 FALSE, 02727 NULL); 02728 } 02729 MmUnlockPagableImageSection(UnlockHandle); 02730 return; 02731 }

VOID MiInitializeSpecialPool VOID   ) 
 

Referenced by MiBuildPagedPool().

VOID MiInitializeSpecialPoolCriteria IN  VOID  ) 
 

Referenced by MmInitSystem().

VOID MiMapBBTMemory IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 1440 of file mminit.c.

References ASSERT, _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, BBTBuffer, BBTPagesToReserve, FALSE, KeFlushEntireTb(), _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, LoaderBBTMemory, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, MI_WRITE_VALID_PTE, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiReserveSystemPtes(), MM_PTE_OWNER_MASK, MM_VA_MAPPED_BY_PDE, NULL, PAGE_SHIFT, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, PERFINFO_MMINIT_START, PTE_PER_PAGE, SystemPteSpace, TRUE, _MMPTE::u, and ValidUserPte.

Referenced by MmInitSystem().

01446 : 01447 01448 This function walks through the loader block's memory descriptor list 01449 and maps memory reserved for the BBT buffer into the system. 01450 01451 The mapped PTEs are PDE-aligned and made user accessible. 01452 01453 Arguments: 01454 01455 LoaderBlock - Supplies a pointer to the system loader block. 01456 01457 Return Value: 01458 01459 None. 01460 01461 Environment: 01462 01463 Kernel Mode Only. System initialization. 01464 01465 --*/ 01466 { 01467 PVOID Va; 01468 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 01469 PLIST_ENTRY NextMd; 01470 PFN_NUMBER NumberOfPagesMapped; 01471 PFN_NUMBER NumberOfPages; 01472 PFN_NUMBER PageFrameIndex; 01473 PMMPTE PointerPte; 01474 PMMPTE PointerPde; 01475 PMMPTE LastPde; 01476 MMPTE TempPte; 01477 01478 if (BBTPagesToReserve <= 0) { 01479 return; 01480 } 01481 01482 // 01483 // Request enough PTEs such that protection can be applied to the PDEs. 01484 // 01485 01486 NumberOfPages = (BBTPagesToReserve + (PTE_PER_PAGE - 1)) & ~(PTE_PER_PAGE - 1); 01487 01488 PointerPte = MiReserveSystemPtes((ULONG)NumberOfPages, 01489 SystemPteSpace, 01490 MM_VA_MAPPED_BY_PDE, 01491 0, 01492 FALSE); 01493 01494 if (PointerPte == NULL) { 01495 BBTPagesToReserve = 0; 01496 return; 01497 } 01498 01499 // 01500 // Allow user access to the buffer. 01501 // 01502 01503 PointerPde = MiGetPteAddress (PointerPte); 01504 LastPde = MiGetPteAddress (PointerPte + NumberOfPages); 01505 01506 ASSERT (LastPde != PointerPde); 01507 01508 do { 01509 TempPte = *PointerPde; 01510 TempPte.u.Long |= MM_PTE_OWNER_MASK; 01511 MI_WRITE_VALID_PTE (PointerPde, TempPte); 01512 PointerPde += 1; 01513 } while (PointerPde < LastPde); 01514 01515 KeFlushEntireTb (TRUE, TRUE); 01516 01517 Va = MiGetVirtualAddressMappedByPte (PointerPte); 01518 01519 TempPte = ValidUserPte; 01520 NumberOfPagesMapped = 0; 01521 01522 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 01523 01524 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 01525 01526 MemoryDescriptor = CONTAINING_RECORD(NextMd, 01527 MEMORY_ALLOCATION_DESCRIPTOR, 01528 ListEntry); 01529 01530 if (MemoryDescriptor->MemoryType == LoaderBBTMemory) { 01531 01532 PageFrameIndex = MemoryDescriptor->BasePage; 01533 NumberOfPages = MemoryDescriptor->PageCount; 01534 01535 if (NumberOfPagesMapped + NumberOfPages > BBTPagesToReserve) { 01536 NumberOfPages = BBTPagesToReserve - NumberOfPagesMapped; 01537 } 01538 01539 NumberOfPagesMapped += NumberOfPages; 01540 01541 do { 01542 01543 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 01544 MI_WRITE_VALID_PTE (PointerPte, TempPte); 01545 01546 PointerPte += 1; 01547 PageFrameIndex += 1; 01548 NumberOfPages -= 1; 01549 } while (NumberOfPages); 01550 01551 if (NumberOfPagesMapped == BBTPagesToReserve) { 01552 break; 01553 } 01554 } 01555 01556 NextMd = MemoryDescriptor->ListEntry.Flink; 01557 } 01558 01559 RtlZeroMemory(Va, BBTPagesToReserve << PAGE_SHIFT); 01560 01561 // 01562 // Tell BBT_Init how many pages were allocated. 01563 // 01564 01565 if (NumberOfPagesMapped < BBTPagesToReserve) { 01566 BBTPagesToReserve = (ULONG)NumberOfPagesMapped; 01567 } 01568 *(PULONG)Va = BBTPagesToReserve; 01569 01570 // 01571 // At this point instrumentation code will detect the existence of 01572 // buffer and initialize the structures. 01573 // 01574 01575 BBTBuffer = Va; 01576 01577 PERFINFO_MMINIT_START(); 01578 }

VOID MiMergeMemoryLimit IN OUT PPHYSICAL_MEMORY_DESCRIPTOR  Memory,
IN PFN_NUMBER  StartPage,
IN PFN_NUMBER  NumberOfPages
 

Definition at line 1899 of file mminit.c.

References MAX_PHYSICAL_MEMORY_FRAGMENTS.

Referenced by MmInitSystem().

01906 : 01907 01908 This function ensures the passed range is in the passed in Memory 01909 block adding any new data as needed. 01910 01911 The passed memory block is assumed to be at least 01912 MAX_PHYSICAL_MEMORY_FRAGMENTS large 01913 01914 Arguments: 01915 01916 Memory - Supplies the memory block to verify run is present in. 01917 01918 StartPage - Supplies the first page of the run. 01919 01920 NumberOfPages - Supplies the number of pages in the run. 01921 01922 Return Value: 01923 01924 None. 01925 01926 Environment: 01927 01928 Kernel Mode Only. System initialization. 01929 01930 --*/ 01931 { 01932 PFN_NUMBER EndPage, sp, ep, i; 01933 01934 EndPage = StartPage + NumberOfPages; 01935 01936 // 01937 // Clip range to area which is not already described 01938 // 01939 01940 for (i=0; i < Memory->NumberOfRuns; i++) { 01941 sp = Memory->Run[i].BasePage; 01942 ep = sp + Memory->Run[i].PageCount; 01943 01944 if (sp < StartPage) { 01945 if (ep > StartPage && ep < EndPage) { 01946 // bump beginning page of the target area 01947 StartPage = ep; 01948 } 01949 01950 if (ep > EndPage) { 01951 // 01952 // Target area is contained totally within this 01953 // descriptor. This range is fully accounted for. 01954 // 01955 01956 StartPage = EndPage; 01957 } 01958 01959 } else { 01960 // sp >= StartPage 01961 01962 if (sp < EndPage) { 01963 if (ep < EndPage) { 01964 // 01965 // This descriptor is totally within the target area - 01966 // check the area on either side of this descriptor 01967 // 01968 01969 MiMergeMemoryLimit (Memory, StartPage, sp - StartPage); 01970 StartPage = ep; 01971 01972 } else { 01973 // clip the ending page of the target area 01974 EndPage = sp; 01975 } 01976 } 01977 } 01978 01979 // 01980 // Anything left of target area? 01981 // 01982 01983 if (StartPage == EndPage) { 01984 return ; 01985 } 01986 } // next descriptor 01987 01988 // 01989 // The range StartPage - EndPage is a missing. Add it. 01990 // 01991 01992 if (Memory->NumberOfRuns == MAX_PHYSICAL_MEMORY_FRAGMENTS) { 01993 return ; 01994 } 01995 01996 Memory->Run[Memory->NumberOfRuns].BasePage = StartPage; 01997 Memory->Run[Memory->NumberOfRuns].PageCount = EndPage - StartPage; 01998 Memory->NumberOfPages += EndPage - StartPage; 01999 Memory->NumberOfRuns += 1; 02000 }

VOID MiWriteProtectSystemImage IN PVOID  DllBase  ) 
 

Definition at line 5633 of file sysload.c.

References ASSERT, BYTES_TO_PAGES, MI_IS_PHYSICAL_ADDRESS, MI_IS_SESSION_ADDRESS, MiGetPteAddress, MiSetSystemCodeProtection(), NULL, PAGED_CODE, and RtlImageNtHeader().

05639 : 05640 05641 This function sets the protection of a system component to read only. 05642 05643 Arguments: 05644 05645 DllBase - Supplies the base address of the system component. 05646 05647 Return Value: 05648 05649 None. 05650 05651 --*/ 05652 05653 { 05654 ULONG SectionProtection; 05655 ULONG NumberOfSubsections; 05656 ULONG SectionVirtualSize; 05657 ULONG ImageAlignment; 05658 ULONG OffsetToSectionTable; 05659 ULONG NumberOfPtes; 05660 ULONG_PTR VirtualAddress; 05661 ULONG_PTR LastVirtualAddress; 05662 PMMPTE PointerPte; 05663 PMMPTE FirstPte; 05664 PMMPTE LastPte; 05665 PMMPTE LastImagePte; 05666 PMMPTE WritablePte; 05667 PIMAGE_NT_HEADERS NtHeader; 05668 PIMAGE_FILE_HEADER FileHeader; 05669 PIMAGE_SECTION_HEADER SectionTableEntry; 05670 05671 PAGED_CODE(); 05672 05673 if (MI_IS_PHYSICAL_ADDRESS(DllBase)) { 05674 return; 05675 } 05676 05677 NtHeader = RtlImageNtHeader (DllBase); 05678 05679 ASSERT (NtHeader); 05680 05681 ImageAlignment = NtHeader->OptionalHeader.SectionAlignment; 05682 05683 // 05684 // All session drivers must be one way or the other - no mixing is allowed 05685 // within multiple copy-on-write drivers. 05686 // 05687 05688 if (MI_IS_SESSION_ADDRESS(DllBase) == 0) { 05689 05690 // 05691 // Images prior to NT5 were not protected from stepping all over 05692 // their (and others) code and readonly data. Here we somewhat 05693 // preserve that behavior, but don't allow them to step on anyone else. 05694 // 05695 05696 // 05697 // Note that drivers that are built for NT5 have presumably run on 05698 // NT5, and these get the benefits of full protection. 05699 // 05700 05701 if ((NtHeader->OptionalHeader.MajorOperatingSystemVersion < 5) || 05702 (NtHeader->OptionalHeader.MajorOperatingSystemVersion > 10)) { 05703 return; 05704 } 05705 05706 if ((NtHeader->OptionalHeader.MajorImageVersion < 5) || 05707 (NtHeader->OptionalHeader.MajorImageVersion > 10)) { 05708 return; 05709 } 05710 } 05711 05712 NumberOfPtes = BYTES_TO_PAGES (NtHeader->OptionalHeader.SizeOfImage); 05713 05714 FileHeader = &NtHeader->FileHeader; 05715 05716 NumberOfSubsections = FileHeader->NumberOfSections; 05717 05718 ASSERT (NumberOfSubsections != 0); 05719 05720 OffsetToSectionTable = sizeof(ULONG) + 05721 sizeof(IMAGE_FILE_HEADER) + 05722 FileHeader->SizeOfOptionalHeader; 05723 05724 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 05725 OffsetToSectionTable); 05726 05727 // 05728 // Verify the image contains subsections ordered by increasing virtual 05729 // address and that there are no overlaps. 05730 // 05731 05732 FirstPte = NULL; 05733 LastVirtualAddress = (ULONG_PTR)DllBase; 05734 05735 for ( ; NumberOfSubsections > 0; NumberOfSubsections -= 1, SectionTableEntry += 1) { 05736 05737 if (SectionTableEntry->Misc.VirtualSize == 0) { 05738 SectionVirtualSize = SectionTableEntry->SizeOfRawData; 05739 } 05740 else { 05741 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize; 05742 } 05743 05744 VirtualAddress = (ULONG_PTR)DllBase + SectionTableEntry->VirtualAddress; 05745 if (VirtualAddress <= LastVirtualAddress) { 05746 05747 // 05748 // Subsections are not in an increasing virtual address ordering. 05749 // No protection is provided for such a poorly linked image. 05750 // 05751 05752 KdPrint (("MM:sysload - Image at %p is badly linked\n", DllBase)); 05753 return; 05754 } 05755 LastVirtualAddress = VirtualAddress + SectionVirtualSize - 1; 05756 } 05757 05758 NumberOfSubsections = FileHeader->NumberOfSections; 05759 ASSERT (NumberOfSubsections != 0); 05760 05761 SectionTableEntry = (PIMAGE_SECTION_HEADER)((PCHAR)NtHeader + 05762 OffsetToSectionTable); 05763 05764 LastVirtualAddress = 0; 05765 05766 // 05767 // Set writable PTE here so the image headers are excluded. This is 05768 // needed so that locking down of sections can continue to edit the 05769 // image headers for counts. 05770 // 05771 05772 WritablePte = MiGetPteAddress ((ULONG_PTR)(SectionTableEntry + NumberOfSubsections) - 1); 05773 LastImagePte = MiGetPteAddress(DllBase) + NumberOfPtes; 05774 05775 for ( ; NumberOfSubsections > 0; NumberOfSubsections -= 1, SectionTableEntry += 1) { 05776 05777 if (SectionTableEntry->Misc.VirtualSize == 0) { 05778 SectionVirtualSize = SectionTableEntry->SizeOfRawData; 05779 } 05780 else { 05781 SectionVirtualSize = SectionTableEntry->Misc.VirtualSize; 05782 } 05783 05784 VirtualAddress = (ULONG_PTR)DllBase + SectionTableEntry->VirtualAddress; 05785 05786 PointerPte = MiGetPteAddress (VirtualAddress); 05787 05788 if (PointerPte >= LastImagePte) { 05789 05790 // 05791 // Skip relocation subsections (which aren't given VA space). 05792 // 05793 05794 break; 05795 } 05796 05797 SectionProtection = (SectionTableEntry->Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_EXECUTE)); 05798 05799 if (SectionProtection & IMAGE_SCN_MEM_WRITE) { 05800 05801 // 05802 // This is a writable subsection, skip it. Make sure if it's 05803 // sharing a PTE (and update the linker so this doesn't happen 05804 // for the kernel at least) that the last PTE isn't made 05805 // read only. 05806 // 05807 05808 WritablePte = MiGetPteAddress (VirtualAddress + SectionVirtualSize - 1); 05809 05810 if (LastVirtualAddress) { 05811 LastPte = MiGetPteAddress (LastVirtualAddress); 05812 05813 if (LastPte == PointerPte) { 05814 LastPte -= 1; 05815 } 05816 05817 if (FirstPte <= LastPte) { 05818 05819 ASSERT (PointerPte < LastImagePte); 05820 05821 if (LastPte >= LastImagePte) { 05822 LastPte = LastImagePte - 1; 05823 } 05824 05825 MiSetSystemCodeProtection (FirstPte, LastPte); 05826 } 05827 05828 LastVirtualAddress = 0; 05829 } 05830 continue; 05831 } 05832 05833 if (LastVirtualAddress == 0) { 05834 05835 // 05836 // There is no previous subsection or the previous 05837 // subsection was writable. Thus the current starting PTE 05838 // could be mapping both a readonly and a readwrite 05839 // subsection if the image alignment is less than PAGE_SIZE. 05840 // These cases (in either order) are handled here. 05841 // 05842 05843 if (PointerPte == WritablePte) { 05844 LastPte = MiGetPteAddress (VirtualAddress + SectionVirtualSize - 1); 05845 if (PointerPte == LastPte) { 05846 05847 // 05848 // Nothing can be protected in this subsection 05849 // due to the image alignment specified for the executable. 05850 // 05851 05852 continue; 05853 } 05854 PointerPte += 1; 05855 } 05856 FirstPte = PointerPte; 05857 } 05858 05859 LastVirtualAddress = VirtualAddress + SectionVirtualSize - 1; 05860 } 05861 05862 if (LastVirtualAddress) { 05863 LastPte = MiGetPteAddress (LastVirtualAddress); 05864 05865 if ((FirstPte <= LastPte) && (FirstPte < LastImagePte)) { 05866 05867 if (LastPte >= LastImagePte) { 05868 LastPte = LastImagePte - 1; 05869 } 05870 05871 MiSetSystemCodeProtection (FirstPte, LastPte); 05872 } 05873 } 05874 }

VOID MmFreeLoaderBlock IN PLOADER_PARAMETER_BLOCK  LoaderBlock  ) 
 

Definition at line 2005 of file mminit.c.

References _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, FreePageList, KeBugCheckEx(), KeFlushEntireTb(), KSEG0_BASE, _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, LoaderNlsData, LoaderOsloaderHeap, LoaderRegistryData, LOCK_PFN, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SET_PFN_DELETED, MI_WRITE_INVALID_PTE, MiDecrementShareCountOnly, MiGetPdeAddress, MiGetVirtualAddressMappedByPte, MiInsertPageInList(), MM_MAX_LOADER_BLOCKS, MmPageLocationList, MmVirtualBias, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, PTE_SHIFT, _MMPFN::PteAddress, TRUE, _MMPFN::u1, _MMPFN::u3, UNLOCK_PFN, ZeroKernelPte, and ZeroPte.

02011 : 02012 02013 This function is called as the last routine in phase 1 initialization. 02014 It frees memory used by the OsLoader. 02015 02016 Arguments: 02017 02018 LoadBlock - Supplies a pointer the system loader block. 02019 02020 Return Value: 02021 02022 None. 02023 02024 Environment: 02025 02026 Kernel Mode Only. System initialization. 02027 02028 --*/ 02029 02030 { 02031 02032 PLIST_ENTRY NextMd; 02033 PMMPTE Pde; 02034 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 02035 MEMORY_ALLOCATION_DESCRIPTOR SavedDescriptor[MM_MAX_LOADER_BLOCKS]; 02036 PFN_NUMBER i; 02037 PFN_NUMBER NextPhysicalPage; 02038 PMMPFN Pfn1; 02039 LONG BlockNumber = -1; 02040 KIRQL OldIrql; 02041 02042 // 02043 // 02044 // Walk through the memory descriptors and add pages to the 02045 // free list in the PFN database. 02046 // 02047 02048 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 02049 02050 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 02051 02052 MemoryDescriptor = CONTAINING_RECORD(NextMd, 02053 MEMORY_ALLOCATION_DESCRIPTOR, 02054 ListEntry); 02055 02056 02057 switch (MemoryDescriptor->MemoryType) { 02058 case LoaderOsloaderHeap: 02059 case LoaderRegistryData: 02060 case LoaderNlsData: 02061 //case LoaderMemoryData: //this has page table and other stuff. 02062 02063 // 02064 // Capture the data to temporary storage so we won't 02065 // free memory we are referencing. Coalesce it if 02066 // the blocks are adjacent and of the same type. 02067 // 02068 02069 if (BlockNumber != -1 && 02070 MemoryDescriptor->MemoryType == SavedDescriptor[BlockNumber].MemoryType && 02071 MemoryDescriptor->BasePage == SavedDescriptor[BlockNumber].BasePage + SavedDescriptor[BlockNumber].PageCount) { 02072 02073 // 02074 // these blocks are adjacent - merge them 02075 // 02076 02077 SavedDescriptor[BlockNumber].PageCount += MemoryDescriptor->PageCount; 02078 } 02079 else { 02080 BlockNumber += 1; 02081 if (BlockNumber >= MM_MAX_LOADER_BLOCKS) { 02082 KeBugCheckEx (MEMORY_MANAGEMENT, 0, 0, 0, 0); 02083 } 02084 SavedDescriptor[BlockNumber] = *MemoryDescriptor; 02085 } 02086 02087 break; 02088 02089 default: 02090 02091 break; 02092 } 02093 02094 NextMd = MemoryDescriptor->ListEntry.Flink; 02095 } 02096 02097 LOCK_PFN (OldIrql); 02098 02099 while (BlockNumber >= 0) { 02100 02101 i = SavedDescriptor[BlockNumber].PageCount; 02102 NextPhysicalPage = SavedDescriptor[BlockNumber].BasePage; 02103 02104 Pfn1 = MI_PFN_ELEMENT (NextPhysicalPage); 02105 while (i != 0) { 02106 02107 if (Pfn1->u3.e2.ReferenceCount == 0) { 02108 if (Pfn1->u1.Flink == 0) { 02109 02110 // 02111 // Set the PTE address to the physical page for 02112 // virtual address alignment checking. 02113 // 02114 02115 Pfn1->PteAddress = 02116 (PMMPTE)(NextPhysicalPage << PTE_SHIFT); 02117 MiInsertPageInList (MmPageLocationList[FreePageList], 02118 NextPhysicalPage); 02119 } 02120 } else { 02121 02122 if (NextPhysicalPage != 0) { 02123 // 02124 // Remove PTE and insert into the free list. If it is 02125 // a physical address within the PFN database, the PTE 02126 // element does not exist and therefore cannot be updated. 02127 // 02128 02129 if (!MI_IS_PHYSICAL_ADDRESS ( 02130 MiGetVirtualAddressMappedByPte (Pfn1->PteAddress))) { 02131 02132 // 02133 // Not a physical address. 02134 // 02135 02136 *(Pfn1->PteAddress) = ZeroPte; 02137 } 02138 02139 MI_SET_PFN_DELETED (Pfn1); 02140 MiDecrementShareCountOnly (NextPhysicalPage); 02141 } 02142 } 02143 02144 Pfn1++; 02145 i -= 1; 02146 NextPhysicalPage += 1; 02147 } 02148 02149 BlockNumber -= 1; 02150 } 02151 02152 // 02153 // If the kernel has been biased to allow for 3gb of user address space, 02154 // then the first 16mb of memory is doubly mapped to KSEG0_BASE and to 02155 // ALTERNATE_BASE. Therefore, the KSEG0_BASE entries must be unmapped. 02156 // 02157 02158 #if defined(_X86_) 02159 02160 if (MmVirtualBias != 0) { 02161 Pde = MiGetPdeAddress(KSEG0_BASE); 02162 MI_WRITE_INVALID_PTE (Pde, ZeroKernelPte); 02163 MI_WRITE_INVALID_PTE (Pde + 1, ZeroKernelPte); 02164 MI_WRITE_INVALID_PTE (Pde + 2, ZeroKernelPte); 02165 MI_WRITE_INVALID_PTE (Pde + 3, ZeroKernelPte); 02166 02167 #if defined(_X86PAE_) 02168 MI_WRITE_INVALID_PTE (Pde + 4, ZeroKernelPte); 02169 MI_WRITE_INVALID_PTE (Pde + 5, ZeroKernelPte); 02170 MI_WRITE_INVALID_PTE (Pde + 6, ZeroKernelPte); 02171 MI_WRITE_INVALID_PTE (Pde + 7, ZeroKernelPte); 02172 #endif 02173 02174 } 02175 02176 #endif 02177 02178 KeFlushEntireTb (TRUE, TRUE); 02179 UNLOCK_PFN (OldIrql); 02180 return; 02181 }

VOID MmInitializeMemoryLimits IN PLOADER_PARAMETER_BLOCK  LoaderBlock,
IN PBOOLEAN  IncludeType,
OUT PPHYSICAL_MEMORY_DESCRIPTOR  Memory
 

Definition at line 1582 of file mminit.c.

References ASSERT, _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, FALSE, _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, LoaderMaximum, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, TotalPages, and TRUE.

Referenced by IopInitializeResourceMap(), and MmInitSystem().

01590 : 01591 01592 This function walks through the loader block's memory 01593 descriptor list and builds a list of contiguous physical 01594 memory blocks of the desired types. 01595 01596 Arguments: 01597 01598 LoaderBlock - Supplies a pointer the system loader block. 01599 01600 IncludeType - Array of BOOLEANS of size LoaderMaximum. 01601 TRUE means include this type of memory in return. 01602 01603 Memory - Returns the physical memory blocks. 01604 01605 Return Value: 01606 01607 None. 01608 01609 Environment: 01610 01611 Kernel Mode Only. System initialization. 01612 01613 --*/ 01614 { 01615 01616 PMEMORY_ALLOCATION_DESCRIPTOR MemoryDescriptor; 01617 PLIST_ENTRY NextMd; 01618 PFN_NUMBER i; 01619 PFN_NUMBER LowestFound; 01620 PFN_NUMBER Found; 01621 PFN_NUMBER Merged; 01622 PFN_NUMBER NextPage; 01623 PFN_NUMBER TotalPages; 01624 01625 TotalPages = 0; 01626 01627 // 01628 // Walk through the memory descriptors and build the physical memory list. 01629 // 01630 01631 LowestFound = 0; 01632 Memory->Run[0].BasePage = 0xffffffff; 01633 NextPage = 0xffffffff; 01634 Memory->Run[0].PageCount = 0; 01635 i = 0; 01636 01637 do { 01638 Merged = FALSE; 01639 Found = FALSE; 01640 NextMd = LoaderBlock->MemoryDescriptorListHead.Flink; 01641 01642 while (NextMd != &LoaderBlock->MemoryDescriptorListHead) { 01643 01644 MemoryDescriptor = CONTAINING_RECORD(NextMd, 01645 MEMORY_ALLOCATION_DESCRIPTOR, 01646 ListEntry); 01647 01648 if (MemoryDescriptor->MemoryType < LoaderMaximum && 01649 IncludeType [MemoryDescriptor->MemoryType] ) { 01650 01651 // 01652 // Try to merge runs. 01653 // 01654 01655 if (MemoryDescriptor->BasePage == NextPage) { 01656 ASSERT (MemoryDescriptor->PageCount != 0); 01657 Memory->Run[i - 1].PageCount += MemoryDescriptor->PageCount; 01658 NextPage += MemoryDescriptor->PageCount; 01659 TotalPages += MemoryDescriptor->PageCount; 01660 Merged = TRUE; 01661 Found = TRUE; 01662 break; 01663 } 01664 01665 if (MemoryDescriptor->BasePage >= LowestFound) { 01666 if (Memory->Run[i].BasePage > MemoryDescriptor->BasePage) { 01667 Memory->Run[i].BasePage = MemoryDescriptor->BasePage; 01668 Memory->Run[i].PageCount = MemoryDescriptor->PageCount; 01669 } 01670 Found = TRUE; 01671 } 01672 } 01673 NextMd = MemoryDescriptor->ListEntry.Flink; 01674 } 01675 01676 if (!Merged && Found) { 01677 NextPage = Memory->Run[i].BasePage + Memory->Run[i].PageCount; 01678 TotalPages += Memory->Run[i].PageCount; 01679 i += 1; 01680 } 01681 Memory->Run[i].BasePage = 0xffffffff; 01682 LowestFound = NextPage; 01683 01684 } while (Found); 01685 ASSERT (i <= Memory->NumberOfRuns); 01686 Memory->NumberOfRuns = (ULONG)i; 01687 Memory->NumberOfPages = TotalPages; 01688 01689 return; 01690 }

BOOLEAN MmInitSystem IN ULONG  Phase,
IN PLOADER_PARAMETER_BLOCK  LoaderBlock,
IN PPHYSICAL_MEMORY_DESCRIPTOR  PhysicalMemoryBlock
 

Definition at line 184 of file mminit.c.

References ActiveAndValid, _MMPAGE_FILE_EXPANSION::ActualExpansion, ASSERT, _EPROCESS::AweLock, _PHYSICAL_MEMORY_RUN::BasePage, BBTPagesToReserve, CHAR, DbgPrint, _MMPAGE_FILE_EXPANSION::Event, ExAcquireResourceExclusive, ExAllocatePoolWithTag, ExInitializeFastMutex, ExInitializeResource, ExpMultiUserTS, ExReleaseResource, ExVerifySuite(), FALSE, _MMPAGE_FILE_EXPANSION::InProgress, KeBalanceSetManager(), KeInitializeDpc(), KeInitializeEvent, KeInitializeMutant(), KeInitializeSpinLock(), KeInitializeTimerEx(), KeSwapProcessOrStack(), KSEG0_BASE, L, _MMEVENT_COUNT_LIST::ListHead, _MMINPAGE_SUPPORT_LIST::ListHead, _MMWORKING_SET_EXPANSION_HEAD::ListHead, LoaderBad, LoaderBBTMemory, LoaderFirmwarePermanent, LoaderMaximum, LoaderSpecialMemory, LOCK_PFN, MAX_PHYSICAL_MEMORY_FRAGMENTS, MI_EXTEND_ANY_PAGEFILE, MI_GET_PAGE_COLOR_FROM_PTE, MI_GET_PAGE_FRAME_FROM_PTE, MI_MAKE_VALID_PTE, MI_PFN_ELEMENT, MI_SESSION_IMAGE_SIZE, MI_SESSION_SPACE_END, MI_SESSION_SPACE_TOTAL_SIZE, MI_WRITE_VALID_PTE, MiAddSystemPtes(), MiAdjustWorkingSetManagerParameters(), MiBuildPagedPool(), MiChargeCommitmentCantExpand(), MiDumpPfn(), MiDumpValidAddresses(), MiEnableKernelVerifier(), MiEnablePagingTheExecutive(), MiFillMemoryPte, MiFormatPte(), MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetSubsectionAddress, MiGetSubsectionAddressForPte, MiGetVirtualAddressMappedByPte, MiHighestUserPde, MiHighestUserPte, MiHydra, MiInitializeDriverVerifierList(), MiInitializeIoTrackers(), MiInitializeLoadedModuleList(), MiInitializePfn(), MiInitializeSessionIds(), MiInitializeSessionWsSupport(), MiInitializeSpecialPoolCriteria(), MiInitializeSystemCache(), MiInitMachineDependent(), MiIsPteOnPdeBoundary, MiMapBBTMemory(), MiMappedPagesTooOldEvent, MiMaximumSystemCacheSizeExtra, MiMaximumWorkingSet, MiMergeMemoryLimit(), MiModifiedPageLife, MiModifiedPageWriter(), MiModifiedPageWriterTimer, MiModifiedPageWriterTimerDispatch(), MiModifiedPageWriterTimerDpc, MiProtoAddressForPte, MiPteStr, MiPteToProto, MiReloadBootLoadedDrivers(), MiRemoveAnyPage(), MiRemoveZeroPage(), MiRequestedSystemPtes, MiSectionInitialization(), MiSessionBasePte, MiSessionLastPte, MiSessionWideInitializeAddresses(), MiSystemCacheEndExtra, MiSystemCacheStartExtra, MiSystemViewStart, MiTriageSystem(), MiTrimInProgressCount, MiWriteProtectSystemImage(), Mm64BitPhysicalAddress, MM_BOOT_IMAGE_SIZE, MM_DBG_CHECK_PFN_LOCK, MM_DBG_COMMIT_EXTRA_SYSTEM_PTES, MM_DBG_DUMP_BOOT_PTES, MM_DEFAULT_SYSTEM_PTES, MM_DEMAND_ZERO_WRITE_PTE, MM_FLUID_PHYSICAL_PAGES, MM_MAXIMUM_SYSTEM_PTES, MM_MAXIMUM_WORKING_SET, MM_MEDIUM_SYSTEM, MM_MINIMUM_SYSTEM_PTES, MM_NONPAGED_POOL_END, MM_READONLY, MM_SESSION_SPACE_DEFAULT, MM_SMALL_SYSTEM, MM_SPECIAL_POOL_PTES, MM_SYSTEM_CACHE_END, MM_SYSTEM_CACHE_START, MM_SYSTEM_CACHE_START_EXTRA, MM_SYSTEM_VIEW_SIZE, MM_SYSTEM_VIEW_SIZE_IF_HYDRA, MM_SYSTEM_VIEW_START, MM_SYSTEM_VIEW_START_IF_HYDRA, MM_TRACK_COMMIT, MmAttemptForCantExtend, MmAvailablePages, MmAvailablePagesEvent, MmAvailablePagesEventHigh, MmChargeCommitmentLock, MmCodeClusterSize, MmCollidedFlushEvent, MmCollidedLockEvent, MmCriticalSectionTimeout, MmCritsectTimeoutSeconds, MmDataClusterSize, MmDontVerifyRandomDrivers, MmDynamicMemoryMutex, MmEnforceWriteProtection, MmEventCountList, MmExpansionLock, MmHardFaultNotifyRoutine, MmHeapDeCommitFreeBlockThreshold, MmHeapDeCommitTotalFreeThreshold, MmHeapSegmentCommit, MmHeapSegmentReserve, MmHighestUserAddress, MmHighSectionBase, MmImageMappingPteEvent, MmInitializeMemoryLimits(), MmInPageSupportList, MmLargeSystem, MmLargeSystemCache, MmLoadedUserImageList, MmLockConflictList, MmLockPagesLimit, MmLockPagesPercentage, MmMappedFileIoComplete, MmMaximumDeadKernelStacks, MmMaximumNonPagedPoolInBytes, MmMaximumWorkingSetSize, MmMaxUnusedSegmentNonPagedPoolUsage, MmMaxUnusedSegmentPagedPoolUsage, MmMediumSystem, MmMinimumFreePages, MmModifiedPageLifeInSeconds, MmModifiedPageMaximum, MmModifiedPageMinimum, MmModifiedPageWriterEvent, MmMoreThanEnoughFreePages, MmNonPagedSystemStart, MmNumberOfPhysicalPages, MmNumberOfSystemPtes, MmOverCommit, MmPagedPoolEnd, MmPagedPoolStart, MmPageFaultNotifyRoutine, MmPageFileCreationLock, MmPhysicalMemoryBlock, MmProductType, MmProtectFreedNonPagedPool, MmReadClusterSize, MmResidentAvailableAtInit, MmResidentAvailablePages, MmSectionBasedMutex, MmSectionCommitMutex, MmSectionExtendResource, MmSectionExtendSetResource, MmSessionBase, MmSessionSpace, MmSharedUserDataPte, MmSizeOfPagedPoolInBytes, MmSizeOfSystemCacheInPages, MmSmallSystem, MmSnapUnloads, MmSpecialPoolTag, MmSystemCacheEnd, MmSystemCacheStart, MmSystemCacheWorkingSetList, MmSystemCacheWsMaximum, MmSystemCacheWsMinimum, MmSystemLoadLock, MmSystemRangeStart, MmSystemSize, MmSystemWsLock, MmThrottleBottom, MmThrottleTop, MmTotalCommitLimit, MmTotalCommitLimitMaximum, MmTrackLockedPages, MmTrackPtes, MmUnusedSegmentNonPagedPoolReduction, MmUnusedSegmentPagedPoolReduction, MmUnusedSegmentTrimLevel, MmUserProbeAddress, MmVerifyDriverBufferLength, MmVirtualBias, MmWorkingSetExpansionHead, MmWorkingSetManagerEvent, MmZeroingPageEvent, MmZeroingPageThreadActive, NON_PAGED_SYSTEM_END, NonPagedPoolMustSucceed, NT_SUCCESS, NULL, _PHYSICAL_MEMORY_DESCRIPTOR::NumberOfPages, _PHYSICAL_MEMORY_DESCRIPTOR::NumberOfRuns, ObjectAttributes, _MMPFN::OriginalPte, PAGE_SHIFT, PAGE_SIZE, _PHYSICAL_MEMORY_RUN::PageCount, _MMPAGE_FILE_EXPANSION::PageFileNumber, PDE_KTBASE, _EPROCESS::PhysicalVadList, PsCreateSystemThread(), PsGetCurrentProcess, PsLoadedModuleList, PsLoadedModuleResource, PTE_PER_PAGE, PTE_SHIFT, _MMPFN::PteAddress, _MMPFN::PteFrame, _MMPAGE_FILE_EXPANSION::RequestedExpansionSize, RtlImageNtHeader(), _PHYSICAL_MEMORY_DESCRIPTOR::Run, _MMPAGE_FILE_EXPANSION::Segment, SystemPteSpace, ThreadHandle, TRUE, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, ValidKernelPde, ValidKernelPte, and ZeroKernelPte.

00192 : 00193 00194 This function is called during Phase 0, phase 1 and at the end 00195 of phase 1 ("phase 2") initialization. 00196 00197 Phase 0 initializes the memory management paging functions, 00198 nonpaged and paged pool, the PFN database, etc. 00199 00200 Phase 1 initializes the section objects, the physical memory 00201 object, and starts the memory management system threads. 00202 00203 Phase 2 frees memory used by the OsLoader. 00204 00205 Arguments: 00206 00207 Phase - System initialization phase. 00208 00209 LoaderBlock - Supplies a pointer to the system loader block. 00210 00211 Return Value: 00212 00213 Returns TRUE if the initialization was successful. 00214 00215 Environment: 00216 00217 Kernel Mode Only. System initialization. 00218 00219 --*/ 00220 00221 { 00222 HANDLE ThreadHandle; 00223 OBJECT_ATTRIBUTES ObjectAttributes; 00224 PMMPTE PointerPte; 00225 PMMPTE PointerPde; 00226 PMMPTE StartPde; 00227 PMMPTE StartPpe; 00228 PMMPTE StartingPte; 00229 PMMPTE EndPde; 00230 PMMPFN Pfn1; 00231 MMPTE Pointer; 00232 PFN_NUMBER i, j; 00233 PFN_NUMBER PageFrameIndex; 00234 PFN_NUMBER DirectoryFrameIndex; 00235 MMPTE TempPte; 00236 KIRQL OldIrql; 00237 LOGICAL First; 00238 PLIST_ENTRY NextEntry; 00239 PLDR_DATA_TABLE_ENTRY DataTableEntry; 00240 ULONG MaximumSystemCacheSize; 00241 ULONG MaximumSystemCacheSizeTotal; 00242 PEPROCESS Process; 00243 PIMAGE_NT_HEADERS NtHeaders; 00244 ULONG_PTR SystemPteMultiplier; 00245 00246 BOOLEAN IncludeType[LoaderMaximum]; 00247 ULONG MemoryAlloc[(sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + 00248 sizeof(PHYSICAL_MEMORY_RUN)*MAX_PHYSICAL_MEMORY_FRAGMENTS) / 00249 sizeof(ULONG)]; 00250 00251 PPHYSICAL_MEMORY_DESCRIPTOR Memory; 00252 00253 // 00254 // Make sure structure alignment is okay. 00255 // 00256 00257 if (Phase == 0) { 00258 MmThrottleTop = 450; 00259 MmThrottleBottom = 127; 00260 00261 // 00262 // Set the highest user address, the system range start address, the 00263 // user probe address, and the virtual bias. 00264 // 00265 00266 #if defined(_AXP64_) || defined(_IA64_) 00267 00268 MmHighestUserAddress = MM_HIGHEST_USER_ADDRESS; 00269 MmUserProbeAddress = MM_USER_PROBE_ADDRESS; 00270 MmSystemRangeStart = MM_SYSTEM_RANGE_START; 00271 00272 #else 00273 00274 MmHighestUserAddress = (PVOID)(KSEG0_BASE - 0x10000 - 1); 00275 MmUserProbeAddress = KSEG0_BASE - 0x10000; 00276 MmSystemRangeStart = (PVOID)KSEG0_BASE; 00277 00278 #endif 00279 00280 MiHighestUserPte = MiGetPteAddress (MmHighestUserAddress); 00281 MiHighestUserPde = MiGetPdeAddress (MmHighestUserAddress); 00282 00283 MmVirtualBias = 0; 00284 00285 // 00286 // Set the highest section base address. 00287 // 00288 // N.B. In 32-bit systems this address must be 2gb or less even for 00289 // systems that run with 3gb enabled. Otherwise, it would not 00290 // be possible to map based sections identically in all processes. 00291 // 00292 00293 MmHighSectionBase = ((PCHAR)MmHighestUserAddress - 0x800000); 00294 00295 if (ExVerifySuite(TerminalServer) == TRUE) { 00296 MiHydra = TRUE; 00297 MiSystemViewStart = MM_SYSTEM_VIEW_START_IF_HYDRA; 00298 MmSessionBase = (ULONG_PTR)MM_SESSION_SPACE_DEFAULT; 00299 00300 } else { 00301 MiSystemViewStart = MM_SYSTEM_VIEW_START; 00302 MiHydra = FALSE; 00303 } 00304 00305 MaximumSystemCacheSize = (MM_SYSTEM_CACHE_END - MM_SYSTEM_CACHE_START) >> PAGE_SHIFT; 00306 00307 // 00308 // If the system has been biased to an alternate base address to 00309 // allow 3gb of user address space, then set the user probe address 00310 // and the maximum system cache size. 00311 // 00312 00313 #if defined(_X86_) 00314 00315 MmVirtualBias = LoaderBlock->u.I386.VirtualBias; 00316 00317 if (MmVirtualBias != 0) { 00318 MmHighestUserAddress = ((PCHAR)MmHighestUserAddress + 0x40000000); 00319 MmSystemRangeStart = ((PCHAR)MmSystemRangeStart + 0x40000000); 00320 MmUserProbeAddress += 0x40000000; 00321 MiMaximumWorkingSet += 0x40000000 >> PAGE_SHIFT; 00322 00323 MiHighestUserPte = MiGetPteAddress (MmHighestUserAddress); 00324 MiHighestUserPde = MiGetPdeAddress (MmHighestUserAddress); 00325 00326 MaximumSystemCacheSize -= MM_BOOT_IMAGE_SIZE >> PAGE_SHIFT; 00327 00328 if (MiHydra == TRUE) { 00329 00330 // 00331 // Moving to 3GB means moving session space to just above 00332 // the system cache (and lowering the system cache max size 00333 // accordingly). 00334 // 00335 00336 MaximumSystemCacheSize -= (MI_SESSION_SPACE_TOTAL_SIZE + MM_SYSTEM_VIEW_SIZE_IF_HYDRA) >> PAGE_SHIFT; 00337 00338 MiSystemViewStart = (ULONG_PTR)(MM_SYSTEM_CACHE_START + 00339 (MaximumSystemCacheSize << PAGE_SHIFT)); 00340 00341 MmSessionBase = MiSystemViewStart + MM_SYSTEM_VIEW_SIZE_IF_HYDRA + MM_BOOT_IMAGE_SIZE; 00342 00343 } else { 00344 MaximumSystemCacheSize -= MM_SYSTEM_VIEW_SIZE >> PAGE_SHIFT; 00345 MiSystemViewStart = (ULONG_PTR)(MM_SYSTEM_CACHE_START + 00346 (MaximumSystemCacheSize << PAGE_SHIFT) + 00347 MM_BOOT_IMAGE_SIZE); 00348 } 00349 } 00350 00351 #else 00352 00353 if (MiHydra == TRUE) { 00354 MaximumSystemCacheSize -= MM_SYSTEM_VIEW_SIZE_IF_HYDRA >> PAGE_SHIFT; 00355 MiSystemViewStart = MM_SYSTEM_VIEW_START_IF_HYDRA; 00356 } 00357 00358 #endif 00359 00360 if (MiHydra == TRUE) { 00361 MmSessionSpace = (PMM_SESSION_SPACE)((ULONG_PTR)MmSessionBase + MI_SESSION_IMAGE_SIZE); 00362 00363 MiSessionBasePte = MiGetPteAddress (MmSessionBase); 00364 MiSessionLastPte = MiGetPteAddress (MI_SESSION_SPACE_END); 00365 } 00366 00367 // 00368 // A few sanity checks to ensure things are as they should be. 00369 // 00370 00371 #if DBG 00372 if ((sizeof(MMWSL) % 8) != 0) { 00373 DbgPrint("working set list is not a quadword sized structure\n"); 00374 } 00375 00376 if ((sizeof(CONTROL_AREA) % 8) != 0) { 00377 DbgPrint("control area list is not a quadword sized structure\n"); 00378 } 00379 00380 if ((sizeof(SUBSECTION) % 8) != 0) { 00381 DbgPrint("subsection list is not a quadword sized structure\n"); 00382 } 00383 00384 // 00385 // Some checks to make sure prototype PTEs can be placed in 00386 // either paged or nonpaged (prototype PTEs for paged pool are here) 00387 // can be put into pte format. 00388 // 00389 00390 PointerPte = (PMMPTE)MmPagedPoolStart; 00391 Pointer.u.Long = MiProtoAddressForPte (PointerPte); 00392 TempPte = Pointer; 00393 PointerPde = MiPteToProto(&TempPte); 00394 if (PointerPte != PointerPde) { 00395 DbgPrint("unable to map start of paged pool as prototype pte %p %p\n", 00396 PointerPde, 00397 PointerPte); 00398 } 00399 00400 PointerPte = 00401 (PMMPTE)((ULONG_PTR)MM_NONPAGED_POOL_END & ~((1 << PTE_SHIFT) - 1)); 00402 00403 Pointer.u.Long = MiProtoAddressForPte (PointerPte); 00404 TempPte = Pointer; 00405 PointerPde = MiPteToProto(&TempPte); 00406 if (PointerPte != PointerPde) { 00407 DbgPrint("unable to map end of nonpaged pool as prototype pte %p %p\n", 00408 PointerPde, 00409 PointerPte); 00410 } 00411 00412 PointerPte = (PMMPTE)(((ULONG_PTR)NON_PAGED_SYSTEM_END - 00413 0x37000 + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1)); 00414 00415 for (j = 0; j < 20; j++) { 00416 Pointer.u.Long = MiProtoAddressForPte (PointerPte); 00417 TempPte = Pointer; 00418 PointerPde = MiPteToProto(&TempPte); 00419 if (PointerPte != PointerPde) { 00420 DbgPrint("unable to map end of nonpaged pool as prototype pte %p %p\n", 00421 PointerPde, 00422 PointerPte); 00423 } 00424 00425 PointerPte++; 00426 } 00427 00428 PointerPte = (PMMPTE)(((ULONG_PTR)MM_NONPAGED_POOL_END - 0x133448) & ~(ULONG_PTR)7); 00429 Pointer.u.Long = MiGetSubsectionAddressForPte (PointerPte); 00430 TempPte = Pointer; 00431 PointerPde = (PMMPTE)MiGetSubsectionAddress(&TempPte); 00432 if (PointerPte != PointerPde) { 00433 DbgPrint("unable to map end of nonpaged pool as section pte %p %p\n", 00434 PointerPde, 00435 PointerPte); 00436 00437 MiFormatPte(&TempPte); 00438 } 00439 00440 // 00441 // End of sanity checks. 00442 // 00443 00444 #endif //dbg 00445 00446 if (MmEnforceWriteProtection) { 00447 MiPteStr[0] = (CHAR)1; 00448 } 00449 00450 InitializeListHead( &MmLoadedUserImageList ); 00451 InitializeListHead( &MmLockConflictList ); 00452 00453 MmCriticalSectionTimeout.QuadPart = Int32x32To64( 00454 MmCritsectTimeoutSeconds, 00455 -10000000); 00456 00457 00458 // 00459 // Initialize PFN database mutex and System Address Space creation 00460 // mutex. 00461 // 00462 00463 ExInitializeFastMutex (&MmSectionCommitMutex); 00464 ExInitializeFastMutex (&MmSectionBasedMutex); 00465 ExInitializeFastMutex (&MmDynamicMemoryMutex); 00466 00467 KeInitializeMutant (&MmSystemLoadLock, FALSE); 00468 00469 KeInitializeEvent (&MmAvailablePagesEvent, NotificationEvent, TRUE); 00470 KeInitializeEvent (&MmAvailablePagesEventHigh, NotificationEvent, TRUE); 00471 KeInitializeEvent (&MmMappedFileIoComplete, NotificationEvent, FALSE); 00472 KeInitializeEvent (&MmImageMappingPteEvent, NotificationEvent, FALSE); 00473 KeInitializeEvent (&MmZeroingPageEvent, SynchronizationEvent, FALSE); 00474 KeInitializeEvent (&MmCollidedFlushEvent, NotificationEvent, FALSE); 00475 KeInitializeEvent (&MmCollidedLockEvent, NotificationEvent, FALSE); 00476 KeInitializeEvent (&MiMappedPagesTooOldEvent, NotificationEvent, FALSE); 00477 00478 KeInitializeDpc( &MiModifiedPageWriterTimerDpc, MiModifiedPageWriterTimerDispatch, NULL ); 00479 KeInitializeTimerEx( &MiModifiedPageWriterTimer, SynchronizationTimer ); 00480 00481 MiModifiedPageLife.QuadPart = Int32x32To64( 00482 MmModifiedPageLifeInSeconds, 00483 -10000000); 00484 00485 InitializeListHead (&MmWorkingSetExpansionHead.ListHead); 00486 InitializeListHead (&MmInPageSupportList.ListHead); 00487 InitializeListHead (&MmEventCountList.ListHead); 00488 00489 MmZeroingPageThreadActive = FALSE; 00490 00491 // 00492 // Compute physical memory blocks yet again 00493 // 00494 00495 Memory = (PPHYSICAL_MEMORY_DESCRIPTOR)&MemoryAlloc; 00496 Memory->NumberOfRuns = MAX_PHYSICAL_MEMORY_FRAGMENTS; 00497 00498 // include all memory types ... 00499 for (i=0; i < LoaderMaximum; i++) { 00500 IncludeType[i] = TRUE; 00501 } 00502 00503 // ... expect these.. 00504 IncludeType[LoaderBad] = FALSE; 00505 IncludeType[LoaderFirmwarePermanent] = FALSE; 00506 IncludeType[LoaderSpecialMemory] = FALSE; 00507 IncludeType[LoaderBBTMemory] = FALSE; 00508 00509 MmInitializeMemoryLimits(LoaderBlock, IncludeType, Memory); 00510 00511 #if defined (_X86PAE_) 00512 MiCheckPaeLicense (LoaderBlock, IncludeType, Memory); 00513 #endif 00514 00515 #if defined (_X86PAE_) || defined (_WIN64) 00516 Mm64BitPhysicalAddress = TRUE; 00517 #endif 00518 00519 // 00520 // Add all memory runs in PhysicalMemoryBlock to Memory 00521 // 00522 00523 for (i = 0; i < PhysicalMemoryBlock->NumberOfRuns; i += 1) { 00524 MiMergeMemoryLimit (Memory, 00525 PhysicalMemoryBlock->Run[i].BasePage, 00526 PhysicalMemoryBlock->Run[i].PageCount 00527 ); 00528 } 00529 00530 // 00531 // Sort and merge adjacent runs. 00532 // 00533 00534 for (i=0; i < Memory->NumberOfRuns; i++) { 00535 for (j=i+1; j < Memory->NumberOfRuns; j++) { 00536 if (Memory->Run[j].BasePage < Memory->Run[i].BasePage) { 00537 // swap runs 00538 PhysicalMemoryBlock->Run[0] = Memory->Run[j]; 00539 Memory->Run[j] = Memory->Run[i]; 00540 Memory->Run[i] = PhysicalMemoryBlock->Run[0]; 00541 } 00542 00543 if (Memory->Run[i].BasePage + Memory->Run[i].PageCount == 00544 Memory->Run[j].BasePage) { 00545 // merge runs 00546 Memory->NumberOfRuns -= 1; 00547 Memory->Run[i].PageCount += Memory->Run[j].PageCount; 00548 Memory->Run[j] = Memory->Run[Memory->NumberOfRuns]; 00549 i -= 1; 00550 break; 00551 } 00552 } 00553 } 00554 00555 // 00556 // When safebooting, don't enable special pool, the verifier or any 00557 // other options that track corruption regardless of registry settings. 00558 // 00559 00560 if (strstr(LoaderBlock->LoadOptions, SAFEBOOT_LOAD_OPTION_A)) { 00561 MmVerifyDriverBufferLength = (ULONG)-1; 00562 MmDontVerifyRandomDrivers = TRUE; 00563 MmSpecialPoolTag = (ULONG)-1; 00564 MmSnapUnloads = FALSE; 00565 MmProtectFreedNonPagedPool = FALSE; 00566 MmEnforceWriteProtection = 0; 00567 MmTrackLockedPages = FALSE; 00568 MmTrackPtes = FALSE; 00569 } 00570 else { 00571 MiTriageSystem (LoaderBlock); 00572 } 00573 00574 SystemPteMultiplier = 0; 00575 00576 if (MmNumberOfSystemPtes == 0) { 00577 #if defined (_WIN64) 00578 00579 // 00580 // 64-bit NT is not contrained by virtual address space. No 00581 // tradeoffs between nonpaged pool, paged pool and system PTEs 00582 // need to be made. So just allocate PTEs on a linear scale as 00583 // a function of the amount of RAM. 00584 // 00585 // For example on Alpha64, 4gb of RAM gets 128gb of PTEs by default. 00586 // The page table cost is the inversion of the multiplier based 00587 // on the PTE_PER_PAGE. 00588 // 00589 00590 if ((MiHydra == TRUE) && (ExpMultiUserTS == TRUE)) { 00591 SystemPteMultiplier = 128; 00592 } 00593 else { 00594 SystemPteMultiplier = 64; 00595 } 00596 if (Memory->NumberOfPages < 0x8000) { 00597 SystemPteMultiplier >>= 1; 00598 } 00599 #else 00600 if (Memory->NumberOfPages < MM_MEDIUM_SYSTEM) { 00601 MmNumberOfSystemPtes = MM_MINIMUM_SYSTEM_PTES; 00602 } else { 00603 MmNumberOfSystemPtes = MM_DEFAULT_SYSTEM_PTES; 00604 if (Memory->NumberOfPages > 8192) { 00605 MmNumberOfSystemPtes += MmNumberOfSystemPtes; 00606 00607 // 00608 // Any reasonable Hydra machine gets the maximum. 00609 // 00610 00611 if ((MiHydra == TRUE) && (ExpMultiUserTS == TRUE)) { 00612 MmNumberOfSystemPtes = MM_MAXIMUM_SYSTEM_PTES; 00613 } 00614 } 00615 } 00616 #endif 00617 } 00618 else if (MmNumberOfSystemPtes == (ULONG)-1) { 00619 00620 // 00621 // This registry setting indicates the maximum number of 00622 // system PTEs possible for this machine must be allocated. 00623 // Snap this for later reference. 00624 // 00625 00626 MiRequestedSystemPtes = MmNumberOfSystemPtes; 00627 00628 #if defined (_WIN64) 00629 SystemPteMultiplier = 256; 00630 #else 00631 MmNumberOfSystemPtes = MM_MAXIMUM_SYSTEM_PTES; 00632 #endif 00633 } 00634 00635 if (SystemPteMultiplier != 0) { 00636 if (Memory->NumberOfPages * SystemPteMultiplier > MM_MAXIMUM_SYSTEM_PTES) { 00637 MmNumberOfSystemPtes = MM_MAXIMUM_SYSTEM_PTES; 00638 } 00639 else { 00640 MmNumberOfSystemPtes = (ULONG)(Memory->NumberOfPages * SystemPteMultiplier); 00641 } 00642 } 00643 00644 if (MmNumberOfSystemPtes > MM_MAXIMUM_SYSTEM_PTES) { 00645 MmNumberOfSystemPtes = MM_MAXIMUM_SYSTEM_PTES; 00646 } 00647 00648 if (MmNumberOfSystemPtes < MM_MINIMUM_SYSTEM_PTES) { 00649 MmNumberOfSystemPtes = MM_MINIMUM_SYSTEM_PTES; 00650 } 00651 00652 if (MmHeapSegmentReserve == 0) { 00653 MmHeapSegmentReserve = 1024 * 1024; 00654 } 00655 00656 if (MmHeapSegmentCommit == 0) { 00657 MmHeapSegmentCommit = PAGE_SIZE * 2; 00658 } 00659 00660 if (MmHeapDeCommitTotalFreeThreshold == 0) { 00661 MmHeapDeCommitTotalFreeThreshold = 64 * 1024; 00662 } 00663 00664 if (MmHeapDeCommitFreeBlockThreshold == 0) { 00665 MmHeapDeCommitFreeBlockThreshold = PAGE_SIZE; 00666 } 00667 00668 #ifndef NO_POOL_CHECKS 00669 MiInitializeSpecialPoolCriteria (); 00670 #endif 00671 00672 // 00673 // If the registry indicates drivers are in the suspect list, 00674 // extra system PTEs need to be allocated to support special pool 00675 // for their allocations. 00676 // 00677 00678 if ((MmVerifyDriverBufferLength != (ULONG)-1) || 00679 ((MmSpecialPoolTag != 0) && (MmSpecialPoolTag != (ULONG)-1))) { 00680 MmNumberOfSystemPtes += MM_SPECIAL_POOL_PTES; 00681 } 00682 00683 MmNumberOfSystemPtes += BBTPagesToReserve; 00684 00685 // 00686 // Initialize the machine dependent portion of the hardware. 00687 // 00688 00689 ExInitializeResource (&MmSystemWsLock); 00690 00691 MiInitMachineDependent (LoaderBlock); 00692 00693 #if PFN_CONSISTENCY 00694 MiPfnProtectionEnabled = TRUE; 00695 #endif 00696 00697 MiReloadBootLoadedDrivers (LoaderBlock); 00698 00699 MiInitializeDriverVerifierList (LoaderBlock); 00700 00701 j = (sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + 00702 (sizeof(PHYSICAL_MEMORY_RUN) * 00703 (Memory->NumberOfRuns - 1))); 00704 00705 MmPhysicalMemoryBlock = ExAllocatePoolWithTag (NonPagedPoolMustSucceed, 00706 j, 00707 ' mM'); 00708 00709 RtlCopyMemory (MmPhysicalMemoryBlock, Memory, j); 00710 00711 // 00712 // Setup the system size as small, medium, or large depending 00713 // on memory available. 00714 // 00715 // For internal MM tuning, the following applies 00716 // 00717 // 12Mb is small 00718 // 12-19 is medium 00719 // > 19 is large 00720 // 00721 // 00722 // For all other external tuning, 00723 // < 19 is small 00724 // 19 - 31 is medium for workstation 00725 // 19 - 63 is medium for server 00726 // >= 32 is large for workstation 00727 // >= 64 is large for server 00728 // 00729 00730 MmReadClusterSize = 7; 00731 if (MmNumberOfPhysicalPages <= MM_SMALL_SYSTEM ) { 00732 MmSystemSize = MmSmallSystem; 00733 MmMaximumDeadKernelStacks = 0; 00734 MmModifiedPageMinimum = 40; 00735 MmModifiedPageMaximum = 100; 00736 MmDataClusterSize = 0; 00737 MmCodeClusterSize = 1; 00738 MmReadClusterSize = 2; 00739 00740 } else if (MmNumberOfPhysicalPages <= MM_MEDIUM_SYSTEM ) { 00741 MmSystemSize = MmSmallSystem; 00742 MmMaximumDeadKernelStacks = 2; 00743 MmModifiedPageMinimum = 80; 00744 MmModifiedPageMaximum = 150; 00745 MmSystemCacheWsMinimum += 100; 00746 MmSystemCacheWsMaximum += 150; 00747 MmDataClusterSize = 1; 00748 MmCodeClusterSize = 2; 00749 MmReadClusterSize = 4; 00750 00751 } else { 00752 MmSystemSize = MmMediumSystem; 00753 MmMaximumDeadKernelStacks = 5; 00754 MmModifiedPageMinimum = 150; 00755 MmModifiedPageMaximum = 300; 00756 MmSystemCacheWsMinimum += 400; 00757 MmSystemCacheWsMaximum += 800; 00758 MmDataClusterSize = 3; 00759 MmCodeClusterSize = 7; 00760 } 00761 00762 if (MmNumberOfPhysicalPages < ((24*1024*1024)/PAGE_SIZE)) { 00763 MmSystemCacheWsMinimum = 32; 00764 } 00765 00766 if (MmNumberOfPhysicalPages >= ((32*1024*1024)/PAGE_SIZE)) { 00767 00768 // 00769 // If we are on a workstation, 32Mb and above are considered large systems 00770 // 00771 if ( MmProductType == 0x00690057 ) { 00772 MmSystemSize = MmLargeSystem; 00773 00774 } else { 00775 00776 // 00777 // For servers, 64Mb and greater is a large system 00778 // 00779 00780 if (MmNumberOfPhysicalPages >= ((64*1024*1024)/PAGE_SIZE)) { 00781 MmSystemSize = MmLargeSystem; 00782 } 00783 } 00784 } 00785 00786 if (MmNumberOfPhysicalPages > ((33*1024*1024)/PAGE_SIZE)) { 00787 MmModifiedPageMinimum = 400; 00788 MmModifiedPageMaximum = 800; 00789 MmSystemCacheWsMinimum += 500; 00790 MmSystemCacheWsMaximum += 900; 00791 } 00792 00793 // 00794 // determine if we are on an AS system ( Winnt is not AS) 00795 // 00796 00797 if (MmProductType == 0x00690057) { 00798 SharedUserData->NtProductType = NtProductWinNt; 00799 MmProductType = 0; 00800 MmThrottleTop = 250; 00801 MmThrottleBottom = 30; 00802 00803 } else { 00804 if ( MmProductType == 0x0061004c ) { 00805 SharedUserData->NtProductType = NtProductLanManNt; 00806 00807 } else { 00808 SharedUserData->NtProductType = NtProductServer; 00809 } 00810 00811 MmProductType = 1; 00812 MmThrottleTop = 450; 00813 MmThrottleBottom = 80; 00814 MmMinimumFreePages = 81; 00815 } 00816 00817 MiAdjustWorkingSetManagerParameters((BOOLEAN)(MmProductType == 0 ? TRUE : FALSE)); 00818 00819 // 00820 // Set the ResidentAvailablePages to the number of available 00821 // pages minus the fluid value. 00822 // 00823 00824 MmResidentAvailablePages = MmAvailablePages - MM_FLUID_PHYSICAL_PAGES; 00825 00826 // 00827 // Subtract off the size of the system cache working set. 00828 // 00829 00830 MmResidentAvailablePages -= MmSystemCacheWsMinimum; 00831 MmResidentAvailableAtInit = MmResidentAvailablePages; 00832 00833 00834 if (MmResidentAvailablePages < 0) { 00835 #if DBG 00836 DbgPrint("system cache working set too big\n"); 00837 #endif 00838 return FALSE; 00839 } 00840 00841 // 00842 // Initialize spin lock for charging and releasing page file 00843 // commitment. 00844 // 00845 00846 KeInitializeSpinLock (&MmChargeCommitmentLock); 00847 00848 MiInitializeIoTrackers (); 00849 00850 // 00851 // Initialize spin lock for allowing working set expansion. 00852 // 00853 00854 KeInitializeSpinLock (&MmExpansionLock); 00855 00856 ExInitializeFastMutex (&MmPageFileCreationLock); 00857 00858 // 00859 // Initialize resource for extending sections. 00860 // 00861 00862 ExInitializeResource (&MmSectionExtendResource); 00863 ExInitializeResource (&MmSectionExtendSetResource); 00864 00865 // 00866 // Build the system cache structures. 00867 // 00868 00869 StartPde = MiGetPdeAddress (MmSystemCacheWorkingSetList); 00870 PointerPte = MiGetPteAddress (MmSystemCacheWorkingSetList); 00871 00872 #if defined (_WIN64) 00873 00874 StartPpe = MiGetPteAddress(StartPde); 00875 00876 TempPte = ValidKernelPte; 00877 00878 if (StartPpe->u.Hard.Valid == 0) { 00879 00880 // 00881 // Map in a page directory page for the system cache working set. 00882 // Note that we only populate one page table for this. 00883 // 00884 00885 DirectoryFrameIndex = MiRemoveAnyPage( 00886 MI_GET_PAGE_COLOR_FROM_PTE (StartPpe)); 00887 TempPte.u.Hard.PageFrameNumber = DirectoryFrameIndex; 00888 *StartPpe = TempPte; 00889 00890 00891 Pfn1 = MI_PFN_ELEMENT(DirectoryFrameIndex); 00892 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE ( 00893 MiGetPteAddress(PDE_KTBASE)); 00894 Pfn1->PteAddress = StartPpe; 00895 Pfn1->u2.ShareCount += 1; 00896 Pfn1->u3.e2.ReferenceCount = 1; 00897 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00898 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 00899 00900 MiFillMemoryPte (StartPde, 00901 PAGE_SIZE, 00902 ZeroKernelPte.u.Long); 00903 } 00904 00905 // 00906 // Map in a page table page. 00907 // 00908 00909 ASSERT (StartPde->u.Hard.Valid == 0); 00910 00911 PageFrameIndex = MiRemoveAnyPage( 00912 MI_GET_PAGE_COLOR_FROM_PTE (StartPde)); 00913 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 00914 MI_WRITE_VALID_PTE (StartPde, TempPte); 00915 00916 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 00917 Pfn1->PteFrame = DirectoryFrameIndex; 00918 Pfn1->PteAddress = StartPde; 00919 Pfn1->u2.ShareCount += 1; 00920 Pfn1->u3.e2.ReferenceCount = 1; 00921 Pfn1->u3.e1.PageLocation = ActiveAndValid; 00922 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 00923 00924 MiFillMemoryPte (MiGetVirtualAddressMappedByPte (StartPde), 00925 PAGE_SIZE, 00926 ZeroKernelPte.u.Long); 00927 00928 StartPpe = MiGetPpeAddress(MmSystemCacheStart); 00929 StartPde = MiGetPdeAddress(MmSystemCacheStart); 00930 PointerPte = MiGetVirtualAddressMappedByPte (StartPde); 00931 00932 #else 00933 #if !defined(_X86PAE_) 00934 ASSERT ((StartPde + 1) == MiGetPdeAddress (MmSystemCacheStart)); 00935 #endif 00936 #endif 00937 00938 MaximumSystemCacheSizeTotal = MaximumSystemCacheSize; 00939 00940 #if defined(_X86_) 00941 MaximumSystemCacheSizeTotal += MiMaximumSystemCacheSizeExtra; 00942 #endif 00943 00944 // 00945 // Size the system cache based on the amount of physical memory. 00946 // 00947 00948 i = (MmNumberOfPhysicalPages + 65) / 1024; 00949 00950 if (i >= 4) { 00951 00952 // 00953 // System has at least 4032 pages. Make the system 00954 // cache 128mb + 64mb for each additional 1024 pages. 00955 // 00956 00957 MmSizeOfSystemCacheInPages = (PFN_COUNT)( 00958 ((128*1024*1024) >> PAGE_SHIFT) + 00959 ((i - 4) * ((64*1024*1024) >> PAGE_SHIFT))); 00960 if (MmSizeOfSystemCacheInPages > MaximumSystemCacheSizeTotal) { 00961 MmSizeOfSystemCacheInPages = MaximumSystemCacheSizeTotal; 00962 } 00963 } 00964 00965 MmSystemCacheEnd = (PVOID)(((PCHAR)MmSystemCacheStart + 00966 MmSizeOfSystemCacheInPages * PAGE_SIZE) - 1); 00967 00968 #if defined(_X86_) 00969 if (MmSizeOfSystemCacheInPages > MaximumSystemCacheSize) { 00970 ASSERT (MiMaximumSystemCacheSizeExtra != 0); 00971 MmSystemCacheEnd = (PVOID)(((PCHAR)MmSystemCacheStart + 00972 MaximumSystemCacheSize * PAGE_SIZE) - 1); 00973 00974 MiSystemCacheStartExtra = (PVOID)MM_SYSTEM_CACHE_START_EXTRA; 00975 MiSystemCacheEndExtra = (PVOID)(((PCHAR)MiSystemCacheStartExtra + 00976 (MmSizeOfSystemCacheInPages - MaximumSystemCacheSize) * PAGE_SIZE) - 1); 00977 } 00978 else { 00979 MiSystemCacheStartExtra = MmSystemCacheStart; 00980 MiSystemCacheEndExtra = MmSystemCacheEnd; 00981 } 00982 #endif 00983 00984 EndPde = MiGetPdeAddress(MmSystemCacheEnd); 00985 00986 TempPte = ValidKernelPte; 00987 00988 #if defined(_WIN64) 00989 First = (StartPpe->u.Hard.Valid == 0) ? TRUE : FALSE; 00990 #endif 00991 00992 #if !defined (_WIN64) 00993 DirectoryFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (MiGetPteAddress(PDE_BASE)); 00994 #endif 00995 00996 LOCK_PFN (OldIrql); 00997 while (StartPde <= EndPde) { 00998 00999 #if defined (_WIN64) 01000 if (First == TRUE || MiIsPteOnPdeBoundary(StartPde)) { 01001 First = FALSE; 01002 StartPpe = MiGetPteAddress(StartPde); 01003 01004 // 01005 // Map in a page directory page. 01006 // 01007 01008 DirectoryFrameIndex = MiRemoveAnyPage( 01009 MI_GET_PAGE_COLOR_FROM_PTE (StartPpe)); 01010 TempPte.u.Hard.PageFrameNumber = DirectoryFrameIndex; 01011 *StartPpe = TempPte; 01012 01013 Pfn1 = MI_PFN_ELEMENT(DirectoryFrameIndex); 01014 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE ( 01015 MiGetPteAddress(PDE_KTBASE)); 01016 Pfn1->PteAddress = StartPpe; 01017 Pfn1->u2.ShareCount += 1; 01018 Pfn1->u3.e2.ReferenceCount = 1; 01019 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01020 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 01021 01022 MiFillMemoryPte (StartPde, 01023 PAGE_SIZE, 01024 ZeroKernelPte.u.Long); 01025 } 01026 #endif 01027 01028 ASSERT (StartPde->u.Hard.Valid == 0); 01029 01030 // 01031 // Map in a page table page. 01032 // 01033 01034 PageFrameIndex = MiRemoveAnyPage( 01035 MI_GET_PAGE_COLOR_FROM_PTE (StartPde)); 01036 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 01037 MI_WRITE_VALID_PTE (StartPde, TempPte); 01038 01039 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 01040 Pfn1->PteFrame = DirectoryFrameIndex; 01041 Pfn1->PteAddress = StartPde; 01042 Pfn1->u2.ShareCount += 1; 01043 Pfn1->u3.e2.ReferenceCount = 1; 01044 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01045 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 01046 01047 MiFillMemoryPte (PointerPte, 01048 PAGE_SIZE, 01049 ZeroKernelPte.u.Long); 01050 01051 StartPde += 1; 01052 PointerPte += PTE_PER_PAGE; 01053 } 01054 01055 #if defined(_X86_) 01056 if (MiSystemCacheEndExtra != MmSystemCacheEnd) { 01057 01058 StartPde = MiGetPdeAddress (MiSystemCacheStartExtra); 01059 EndPde = MiGetPdeAddress(MiSystemCacheEndExtra); 01060 01061 PointerPte = MiGetPteAddress (MiSystemCacheStartExtra); 01062 01063 while (StartPde <= EndPde) { 01064 01065 ASSERT (StartPde->u.Hard.Valid == 0); 01066 01067 // 01068 // Map in a page directory page. 01069 // 01070 01071 PageFrameIndex = MiRemoveAnyPage( 01072 MI_GET_PAGE_COLOR_FROM_PTE (StartPde)); 01073 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 01074 MI_WRITE_VALID_PTE (StartPde, TempPte); 01075 01076 Pfn1 = MI_PFN_ELEMENT(PageFrameIndex); 01077 Pfn1->PteFrame = MI_GET_PAGE_FRAME_FROM_PTE ( 01078 MiGetPdeAddress(PDE_BASE)); 01079 Pfn1->PteAddress = StartPde; 01080 Pfn1->u2.ShareCount += 1; 01081 Pfn1->u3.e2.ReferenceCount = 1; 01082 Pfn1->u3.e1.PageLocation = ActiveAndValid; 01083 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 01084 01085 MiFillMemoryPte (PointerPte, 01086 PAGE_SIZE, 01087 ZeroKernelPte.u.Long); 01088 01089 StartPde += 1; 01090 PointerPte += PTE_PER_PAGE; 01091 } 01092 } 01093 #endif 01094 01095 UNLOCK_PFN (OldIrql); 01096 01097 // 01098 // Initialize the system cache. Only set the large system cache if 01099 // we have a large amount of physical memory. 01100 // 01101 01102 if (MmLargeSystemCache != 0 && MmNumberOfPhysicalPages > 0x7FF0) { 01103 if ((MmAvailablePages > 01104 MmSystemCacheWsMaximum + ((64*1024*1024) >> PAGE_SHIFT))) { 01105 MmSystemCacheWsMaximum = 01106 MmAvailablePages - ((32*1024*1024) >> PAGE_SHIFT); 01107 ASSERT ((LONG)MmSystemCacheWsMaximum > (LONG)MmSystemCacheWsMinimum); 01108 MmMoreThanEnoughFreePages = 256; 01109 } 01110 } 01111 01112 if (MmSystemCacheWsMaximum > (MM_MAXIMUM_WORKING_SET - 5)) { 01113 MmSystemCacheWsMaximum = MM_MAXIMUM_WORKING_SET - 5; 01114 } 01115 01116 if (MmSystemCacheWsMaximum > MmSizeOfSystemCacheInPages) { 01117 MmSystemCacheWsMaximum = MmSizeOfSystemCacheInPages; 01118 if ((MmSystemCacheWsMinimum + 500) > MmSystemCacheWsMaximum) { 01119 MmSystemCacheWsMinimum = MmSystemCacheWsMaximum - 500; 01120 } 01121 } 01122 01123 MiInitializeSystemCache ((ULONG)MmSystemCacheWsMinimum, 01124 (ULONG)MmSystemCacheWsMaximum); 01125 01126 // 01127 // Set the commit page limit to four times the number of available 01128 // pages. This value is updated as paging files are created. 01129 // 01130 01131 MmTotalCommitLimit = MmAvailablePages << 2; 01132 MmTotalCommitLimitMaximum = MmTotalCommitLimit; 01133 01134 MmAttemptForCantExtend.Segment = NULL; 01135 MmAttemptForCantExtend.RequestedExpansionSize = 1; 01136 MmAttemptForCantExtend.ActualExpansion = 1; 01137 MmAttemptForCantExtend.InProgress = FALSE; 01138 MmAttemptForCantExtend.PageFileNumber = MI_EXTEND_ANY_PAGEFILE; 01139 01140 KeInitializeEvent (&MmAttemptForCantExtend.Event, 01141 NotificationEvent, 01142 FALSE); 01143 01144 if (MmOverCommit == 0) { 01145 01146 // If this value was not set via the registry, set the 01147 // over commit value to the number of available pages 01148 // minus 1024 pages (4mb with 4k pages). 01149 // 01150 01151 if (MmAvailablePages > 1024) { 01152 MmOverCommit = MmAvailablePages - 1024; 01153 } 01154 } 01155 01156 // 01157 // Set maximum working set size to 512 pages less total available 01158 // memory. 2mb on machine with 4k pages. 01159 // 01160 01161 MmMaximumWorkingSetSize = (ULONG)(MmAvailablePages - 512); 01162 01163 if (MmMaximumWorkingSetSize > (MM_MAXIMUM_WORKING_SET - 5)) { 01164 MmMaximumWorkingSetSize = MM_MAXIMUM_WORKING_SET - 5; 01165 } 01166 01167 // 01168 // Create the modified page writer event. 01169 // 01170 01171 KeInitializeEvent (&MmModifiedPageWriterEvent, NotificationEvent, FALSE); 01172 01173 // 01174 // Build paged pool. 01175 // 01176 01177 MiBuildPagedPool (); 01178 01179 // 01180 // Initialize the loaded module list. This cannot be done until 01181 // paged pool has been built. 01182 // 01183 01184 if (MiInitializeLoadedModuleList (LoaderBlock) == FALSE) { 01185 #if DBG 01186 DbgPrint("Loaded module list initialization failed\n"); 01187 #endif 01188 return FALSE; 01189 } 01190 01191 // 01192 // Initialize the unused segment thresholds. The assumption is made 01193 // that the filesystem will tack on approximately a 1024-byte paged 01194 // pool charge (regardless of file size) for each file in the cache. 01195 // 01196 01197 if (MmUnusedSegmentTrimLevel < 5) { 01198 MmUnusedSegmentTrimLevel = 5; 01199 } 01200 else if (MmUnusedSegmentTrimLevel > 40) { 01201 MmUnusedSegmentTrimLevel = 40; 01202 } 01203 01204 MmMaxUnusedSegmentPagedPoolUsage = (MmSizeOfPagedPoolInBytes / 100) * (MmUnusedSegmentTrimLevel << 1); 01205 MmUnusedSegmentPagedPoolReduction = MmMaxUnusedSegmentPagedPoolUsage >> 2; 01206 01207 MmMaxUnusedSegmentNonPagedPoolUsage = (MmMaximumNonPagedPoolInBytes / 100) * (MmUnusedSegmentTrimLevel << 1); 01208 MmUnusedSegmentNonPagedPoolReduction = MmMaxUnusedSegmentNonPagedPoolUsage >> 2; 01209 01210 // 01211 // Add more system PTEs if this is a large memory system. 01212 // Note that 64 bit systems can determine the right value at the 01213 // beginning since there is no virtual address space crunch. 01214 // 01215 01216 #if !defined (_WIN64) 01217 if (MmNumberOfPhysicalPages > ((127*1024*1024) >> PAGE_SHIFT)) { 01218 01219 PointerPde = MiGetPdeAddress ((PCHAR)MmPagedPoolEnd + 1); 01220 StartingPte = MiGetPteAddress ((PCHAR)MmPagedPoolEnd + 1); 01221 j = 0; 01222 01223 TempPte = ValidKernelPde; 01224 LOCK_PFN (OldIrql); 01225 while (PointerPde->u.Hard.Valid == 0) { 01226 01227 MiChargeCommitmentCantExpand (1, TRUE); 01228 MM_TRACK_COMMIT (MM_DBG_COMMIT_EXTRA_SYSTEM_PTES, 1); 01229 01230 PageFrameIndex = MiRemoveZeroPage ( 01231 MI_GET_PAGE_COLOR_FROM_PTE (PointerPde)); 01232 TempPte.u.Hard.PageFrameNumber = PageFrameIndex; 01233 MI_WRITE_VALID_PTE (PointerPde, TempPte); 01234 MiInitializePfn (PageFrameIndex, PointerPde, 1); 01235 PointerPde += 1; 01236 StartingPte += PAGE_SIZE / sizeof(MMPTE); 01237 j += PAGE_SIZE / sizeof(MMPTE); 01238 } 01239 01240 UNLOCK_PFN (OldIrql); 01241 01242 if (j != 0) { 01243 StartingPte = MiGetPteAddress ((PCHAR)MmPagedPoolEnd + 1); 01244 MmNonPagedSystemStart = MiGetVirtualAddressMappedByPte (StartingPte); 01245 MmNumberOfSystemPtes += j; 01246 MiAddSystemPtes (StartingPte, j, SystemPteSpace); 01247 } 01248 } 01249 #endif 01250 01251 01252 #if DBG 01253 if (MmDebug & MM_DBG_DUMP_BOOT_PTES) { 01254 MiDumpValidAddresses (); 01255 MiDumpPfn (); 01256 } 01257 #endif 01258 01259 MmPageFaultNotifyRoutine = NULL; 01260 MmHardFaultNotifyRoutine = NULL; 01261 01262 return TRUE; 01263 } 01264 01265 if (Phase == 1) { 01266 01267 #if DBG 01268 MmDebug |= MM_DBG_CHECK_PFN_LOCK; 01269 #endif 01270 01271 #ifdef _X86_ 01272 MiInitMachineDependent (LoaderBlock); 01273 #endif 01274 MiMapBBTMemory(LoaderBlock); 01275 01276 if (!MiSectionInitialization ()) { 01277 return FALSE; 01278 } 01279 01280 Process = PsGetCurrentProcess (); 01281 if (Process->PhysicalVadList.Flink == NULL) { 01282 KeInitializeSpinLock (&Process->AweLock); 01283 InitializeListHead (&Process->PhysicalVadList); 01284 } 01285 01286 #if defined(MM_SHARED_USER_DATA_VA) 01287 01288 // 01289 // Create double mapped page between kernel and user mode. 01290 // 01291 01292 PointerPte = MiGetPteAddress(KI_USER_SHARED_DATA); 01293 ASSERT (PointerPte->u.Hard.Valid == 1); 01294 PageFrameIndex = MI_GET_PAGE_FRAME_FROM_PTE (PointerPte); 01295 01296 MI_MAKE_VALID_PTE (MmSharedUserDataPte, 01297 PageFrameIndex, 01298 MM_READONLY, 01299 PointerPte); 01300 Pfn1 = MI_PFN_ELEMENT (PageFrameIndex); 01301 01302 LOCK_PFN (OldIrql); 01303 01304 Pfn1->OriginalPte.u.Long = MM_DEMAND_ZERO_WRITE_PTE; 01305 01306 UNLOCK_PFN (OldIrql); 01307 #endif 01308 01309 if (MiHydra == TRUE) { 01310 MiSessionWideInitializeAddresses (); 01311 MiInitializeSessionWsSupport (); 01312 MiInitializeSessionIds (); 01313 } 01314 01315 // 01316 // Set up system wide lock pages limit. 01317 // 01318 01319 if ((MmLockPagesPercentage < 5) || (MmLockPagesPercentage >= 100)) { 01320 01321 // 01322 // No (reasonable or max) registry override from the user 01323 // so default to allowing all available memory. 01324 // 01325 01326 MmLockPagesLimit = (PFN_NUMBER)-1; 01327 } 01328 else { 01329 01330 // 01331 // Use the registry value - note it is expressed as a percentage. 01332 // 01333 01334 MmLockPagesLimit = (PFN_NUMBER)((MmAvailablePages * MmLockPagesPercentage) / 100); 01335 } 01336 01337 // 01338 // Start the modified page writer. 01339 // 01340 01341 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 01342 01343 if (!NT_SUCCESS(PsCreateSystemThread( 01344 &ThreadHandle, 01345 THREAD_ALL_ACCESS, 01346 &ObjectAttributes, 01347 0L, 01348 NULL, 01349 MiModifiedPageWriter, 01350 NULL 01351 ))) { 01352 return FALSE; 01353 } 01354 ZwClose (ThreadHandle); 01355 01356 // 01357 // Start the balance set manager. 01358 // 01359 // The balance set manager performs stack swapping and working 01360 // set management and requires two threads. 01361 // 01362 01363 KeInitializeEvent (&MmWorkingSetManagerEvent, 01364 SynchronizationEvent, 01365 FALSE); 01366 01367 InitializeObjectAttributes( &ObjectAttributes, NULL, 0, NULL, NULL ); 01368 01369 if (!NT_SUCCESS(PsCreateSystemThread( 01370 &ThreadHandle, 01371 THREAD_ALL_ACCESS, 01372 &ObjectAttributes, 01373 0L, 01374 NULL, 01375 KeBalanceSetManager, 01376 NULL 01377 ))) { 01378 01379 return FALSE; 01380 } 01381 ZwClose (ThreadHandle); 01382 01383 if (!NT_SUCCESS(PsCreateSystemThread( 01384 &ThreadHandle, 01385 THREAD_ALL_ACCESS, 01386 &ObjectAttributes, 01387 0L, 01388 NULL, 01389 KeSwapProcessOrStack, 01390 NULL 01391 ))) { 01392 01393 return FALSE; 01394 } 01395 ZwClose (ThreadHandle); 01396 01397 #ifndef NO_POOL_CHECKS 01398 MiInitializeSpecialPoolCriteria (); 01399 #endif 01400 01401 #if defined(_X86_) 01402 MiEnableKernelVerifier (); 01403 #endif 01404 01405 ExAcquireResourceExclusive (&PsLoadedModuleResource, TRUE); 01406 01407 NextEntry = PsLoadedModuleList.Flink; 01408 01409 for ( ; NextEntry != &PsLoadedModuleList; NextEntry = NextEntry->Flink) { 01410 01411 DataTableEntry = CONTAINING_RECORD(NextEntry, 01412 LDR_DATA_TABLE_ENTRY, 01413 InLoadOrderLinks); 01414 01415 NtHeaders = RtlImageNtHeader(DataTableEntry->DllBase); 01416 01417 if ((NtHeaders->OptionalHeader.MajorOperatingSystemVersion >= 5) && 01418 (NtHeaders->OptionalHeader.MajorImageVersion >= 5)) { 01419 DataTableEntry->Flags |= LDRP_ENTRY_NATIVE; 01420 } 01421 01422 MiWriteProtectSystemImage (DataTableEntry->DllBase); 01423 } 01424 ExReleaseResource (&PsLoadedModuleResource); 01425 01426 InterlockedDecrement (&MiTrimInProgressCount); 01427 01428 return TRUE; 01429 } 01430 01431 if (Phase == 2) { 01432 MiEnablePagingTheExecutive(); 01433 return TRUE; 01434 } 01435 01436 return FALSE; 01437 }

NTKERNELAPI BOOLEAN MmIsThisAnNtAsSystem VOID   ) 
 

Definition at line 3087 of file mminit.c.

References MmProductType.

Referenced by CcInitializeCacheManager(), ExpWorkerInitialization(), ExpWorkerThread(), FsRtlInitializeTunnels(), IoInitSystem(), MiBuildPagedPool(), ObInitSystem(), and PsChangeQuantumTable().

03090 { 03091 return (BOOLEAN)MmProductType; 03092 }

MM_SYSTEMSIZE MmQuerySystemSize VOID   ) 
 

Definition at line 3073 of file mminit.c.

References MmSystemSize.

Referenced by CcAllocateInitializeBcb(), CcInitializeCacheManager(), ExInitializeRegion(), ExpWorkerInitialization(), IoInitSystem(), KeBalanceSetManager(), ObInitSystem(), PspInitPhase0(), and UdfInitializeGlobalData().

03076 { 03077 // 03078 // 12Mb is small 03079 // 12-19 is medium 03080 // > 19 is large 03081 // 03082 return MmSystemSize; 03083 }

NTKERNELAPI VOID FASTCALL MmSetHardFaultNotifyRoutine PHARD_FAULT_NOTIFY_ROUTINE  NotifyRoutine  ) 
 

Definition at line 3107 of file mminit.c.

References MmHardFaultNotifyRoutine.

03110 { 03111 MmHardFaultNotifyRoutine = NotifyRoutine; 03112 }

NTKERNELAPI VOID FASTCALL MmSetPageFaultNotifyRoutine PPAGE_FAULT_NOTIFY_ROUTINE  NotifyRoutine  ) 
 

Definition at line 3097 of file mminit.c.

References MmPageFaultNotifyRoutine.

03100 { 03101 MmPageFaultNotifyRoutine = NotifyRoutine; 03102 }


Variable Documentation

PVOID BBTBuffer
 

Definition at line 34 of file mminit.c.

Referenced by MiMapBBTMemory(), and MmCreateTeb().

ULONG BBTPagesToReserve
 

Definition at line 35 of file mminit.c.

Referenced by MiMapBBTMemory(), and MmInitSystem().

KEVENT MiMappedPagesTooOldEvent
 

Definition at line 131 of file mminit.c.

Referenced by MiModifiedPageWriterTimerDispatch(), MiModifiedPageWriterWorker(), and MmInitSystem().

LARGE_INTEGER MiModifiedPageLife
 

Definition at line 127 of file mminit.c.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

KTIMER MiModifiedPageWriterTimer
 

Definition at line 135 of file mminit.c.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

KDPC MiModifiedPageWriterTimerDpc
 

Definition at line 133 of file mminit.c.

Referenced by MiInsertPageInList(), MiModifiedPageWriterWorker(), and MmInitSystem().

CHAR MiPteStr[]
 

Definition at line 155 of file mminit.c.

Referenced by MiSetSystemCodeProtection(), and MmInitSystem().

ULONG MiSpecialPoolPtes
 

Definition at line 31 of file mminit.c.

Referenced by MiEnablePagingTheExecutive(), MiInitializeSpecialPool(), MmAllocateSpecialPool(), and MmProtectSpecialPool().

BOOLEAN MiTimerPending = FALSE
 

Definition at line 129 of file mminit.c.

Referenced by MiInsertPageInList(), MiModifiedPageWriterTimerDispatch(), and MiModifiedPageWriterWorker().

LONG MiTrimInProgressCount
 

Definition at line 157 of file mminit.c.

Referenced by MmInitSystem(), and MmTrimAllSystemPagableMemory().

ULONG MmCodeClusterSize
 

Definition at line 40 of file mminit.c.

Referenced by MiResolveMappedFileFault(), and MmInitSystem().

ULONG MmDataClusterSize
 

Definition at line 39 of file mminit.c.

Referenced by MiResolveMappedFileFault(), and MmInitSystem().

ULONG MmEnforceWriteProtection
 

Definition at line 153 of file mminit.c.

MMEVENT_COUNT_LIST MmEventCountList
 

Definition at line 28 of file mminit.c.

Referenced by MiFlushEventCounter(), MiFreeEventCounter(), MiGetEventCounter(), and MmInitSystem().

PHARD_FAULT_NOTIFY_ROUTINE MmHardFaultNotifyRoutine
 

Definition at line 180 of file mminit.c.

Referenced by MiDispatchFault(), MmInitSystem(), and MmSetHardFaultNotifyRoutine().

KEVENT MmImageMappingPteEvent
 

Definition at line 42 of file mminit.c.

Referenced by MiMapImageHeaderInHyperSpace(), and MmInitSystem().

MMINPAGE_SUPPORT_LIST MmInPageSupportList
 

Definition at line 27 of file mminit.c.

Referenced by MiFlushInPageSupportBlock(), MiFreeInPageSupportBlock(), MiGetInPageSupportBlock(), and MmInitSystem().

ULONG MmLargeSystemCache
 

Definition at line 174 of file mminit.c.

LIST_ENTRY MmLoadedUserImageList
 

Definition at line 178 of file mminit.c.

LIST_ENTRY MmLockConflictList
 

Definition at line 44 of file mminit.c.

Referenced by MiCheckForUserStackOverflow(), MiInsertConflictInList(), and MmInitSystem().

ULONG MmMaximumWorkingSetSize
 

Definition at line 151 of file mminit.c.

ULONG MmModifiedPageLifeInSeconds = 300
 

Definition at line 125 of file mminit.c.

Referenced by MmInitSystem().

ULONG MmPagedPoolCommit
 

Definition at line 32 of file mminit.c.

LOGICAL MmPagedPoolMaximumDesired = FALSE
 

Definition at line 45 of file mminit.c.

PPAGE_FAULT_NOTIFY_ROUTINE MmPageFaultNotifyRoutine
 

Definition at line 179 of file mminit.c.

Referenced by MmAccessFault(), MmInitSystem(), and MmSetPageFaultNotifyRoutine().

PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock
 

Definition at line 43 of file mminit.c.

Referenced by IopCreateSummaryDump(), IopDeleteNonExistentMemory(), IopInitializeDCB(), IopInitializeResourceMap(), IopInitializeSummaryDump(), IopReadDumpRegistry(), MiCheckForCrashDump(), MiEnsureAvailablePageOrWait(), MiFindContiguousMemory(), MmAddPhysicalMemory(), MmAllocatePagesForMdl(), MmGetPhysicalMemoryRanges(), MmInitSystem(), and MmRemovePhysicalMemory().

ULONG MmProductType
 

Definition at line 176 of file mminit.c.

PFN_NUMBER MmResidentAvailableAtInit
 

Definition at line 41 of file mminit.c.

Referenced by MmInitSystem().

MMPTE MmSharedUserDataPte
 

Definition at line 25 of file mminit.c.

Referenced by MiCheckVirtualAddress(), and MmInitSystem().

ULONG_PTR MmSubsectionBase
 

Definition at line 37 of file mminit.c.

ULONG_PTR MmSubsectionTopPage
 

Definition at line 38 of file mminit.c.

Referenced by MiAllocatePoolPages(), and MiInitMachineDependent().

KMUTANT MmSystemLoadLock
 

Definition at line 29 of file mminit.c.

PFN_NUMBER MmSystemPageDirectory
 

Definition at line 162 of file mminit.c.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), and MiFillSystemPageDirectory().

PMMPTE MmSystemPagePtes
 

Definition at line 167 of file mminit.c.

Referenced by MiAllocatePoolPages(), MiBuildPagedPool(), MiCheckPdeForPagedPool(), MiFillSystemPageDirectory(), and MiRemoveMappedPtes().

ULONG_PTR MmSystemPtesStart[MaximumPtePoolTypes]
 

Definition at line 30 of file mminit.c.

MM_SYSTEMSIZE MmSystemSize
 

Definition at line 172 of file mminit.c.

Referenced by MmInitSystem(), MmQuerySystemSize(), and MmSetMemoryPriorityProcess().

ULONG MmTotalSystemCodePages
 

Definition at line 170 of file mminit.c.

Referenced by MiEnablePagingOfDriverAtInit(), and NtQuerySystemInformation().

PERFINFO_MMINIT_DECL
 

Definition at line 47 of file mminit.c.


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