test: iniaxp64.c File Reference

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

# iniaxp64.c File Reference

`#include "mi.h"`
`#include <inbv.h>`

Go to the source code of this file.

## Defines

#define | _1mbInPages (0x100000 >> PAGE_SHIFT)
#define | _4gbInPages (0x100000000 >> PAGE_SHIFT)

## Functions

PFN_NUMBER | MxGetNextPage (VOID)
VOID | MiInitMachineDependent (IN PLOADER_PARAMETER_BLOCK LoaderBlock)

## Variables

PMEMORY_ALLOCATION_DESCRIPTOR | MxFreeDescriptor
PFN_NUMBER | MxNextPhysicalPage
PFN_NUMBER | MxNumberOfPages

## Define Documentation

#define _1mbInPages (0x100000 >> PAGE_SHIFT)

| Definition at line 34 of file iniaxp64.c. Referenced by MiInitMachineDependent().

#define _4gbInPages (0x100000000 >> PAGE_SHIFT)

| Definition at line 35 of file iniaxp64.c. Referenced by MiInitMachineDependent().

## Function Documentation

VOID MiInitMachineDependent | ( | IN PLOADER_PARAMETER_BLOCK | LoaderBlock | ) |

Definition at line 111 of file iniaxp64.c.

References _1mbInPages, _4gbInPages, ActiveAndValid, ASSERT, BadPageList, _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, Buffer, c, CHAR, ExAllocatePoolWithTag, FALSE, FIRST_MAPPING_PTE, _MMCOLOR_TABLES::Flink, FreePageList, HYPER_SPACE, InbvDisplayString(), InitializePool(), KeBugCheck(), KeBugCheckEx(), KeInitializeSpinLock(), KSEG0_BASE, KSEG2_BASE, LAST_MAPPING_PTE, _MEMORY_ALLOCATION_DESCRIPTOR::ListEntry, LoaderBad, LoaderFirmwareTemporary, LoaderFree, LoaderLoadedProgram, LoaderOsloaderHeap, LoaderOsloaderStack, LOCK_PFN, _MMSUPPORT::MaximumWorkingSetSize, _MEMORY_ALLOCATION_DESCRIPTOR::MemoryType, MI_CONVERT_PHYSICAL_TO_PFN, MI_GET_COLOR_FROM_SECONDARY, MI_GET_PAGE_FRAME_FROM_PTE, MI_IS_PHYSICAL_ADDRESS, MI_PFN_ELEMENT, MI_SESSION_SPACE_END, MI_SET_PFN_DELETED, MiGetPdeAddress, MiGetPpeAddress, MiGetPteAddress, MiGetVirtualAddressMappedByPte, MiHydra, MiInitializeNonPagedPool(), MiInitializeSystemPtes(), MiInsertPageInList(), MiIsPteOnPdeBoundary, _MMSUPPORT::MinimumWorkingSetSize, MiRemoveAnyPage(), MiRemoveZeroPageIfAny, MiReserveSystemPtes(), MiZeroPhysicalPage(), MM_EMPTY_LIST, MM_LOWEST_NONPAGED_SYSTEM_START, MM_MAX_ADDITIONAL_NONPAGED_POOL, MM_MAX_DEFAULT_NONPAGED_POOL, MM_MAX_INITIAL_NONPAGED_POOL, MM_SECONDARY_COLORS_DEFAULT, MM_SECONDARY_COLORS_MAX, MM_SECONDARY_COLORS_MIN, MM_SYSTEM_SPACE_END, MM_SYSTEM_SPACE_START, MMCOLOR_TABLES, MmDefaultMaximumNonPagedPool, MmFirstReservedMappingPte, MmFreePagesByColor, MmHiberPages, MmHighestPhysicalPage, MmHighestPossiblePhysicalPage, MmInitializeProcessAddressSpace(), MmLastReservedMappingPte, MmLowestPhysicalPage, MmMaxAdditionNonPagedPoolPerMb, MmMaximumNonPagedPoolInBytes, MmMinAdditionNonPagedPoolPerMb, MmMinimumNonPagedPoolSize, MmNonPagedMustSucceed, MmNonPagedPoolEnd, MmNonPagedPoolExpansionStart, MmNonPagedPoolStart, MmNonPagedSystemStart, MmNumberOfPhysicalPages, MmNumberOfSystemPtes, MmPageAlignedPoolBase, MmPageLocationList, MMPFN, MmPfnDatabase, MmPfnLock, MmSecondaryColorMask, MmSecondaryColors, MmSessionBase, MmSizeOfNonPagedMustSucceed, MmSizeOfNonPagedPoolInBytes, MmSubsectionBase, MmSubsectionTopPage, MmSystemProcessWorkingSetMax, MmSystemProcessWorkingSetMin, MmSystemSpaceLock, MmWorkingSetList, MmWsle, MxFreeDescriptor, MxGetNextPage(), MxNextPhysicalPage, MxNumberOfPages, NON_PAGED_SYSTEM_END, NonPagedPool, NonPagedPoolExpansion, NonPagedPoolMustSucceed, NULL, NUMBER_OF_MAPPING_PTES, PAGE_ALIGN, PAGE_DIRECTORY2_MASK, PAGE_SHIFT, PAGE_SIZE, _MEMORY_ALLOCATION_DESCRIPTOR::PageCount, PsGetCurrentProcess, PTE_PER_PAGE, _MMPFN::PteAddress, _MMPFN::PteFrame, RtlCompareMemoryUlong(), sprintf(), StandbyPageList, SystemPteSpace, TRUE, _MMPTE::u, _MMPFN::u2, _MMPFN::u3, UNLOCK_PFN, ValidKernelPte, _EPROCESS::Vm, WORKING_SET_LIST, _EPROCESS::WorkingSetPage, ZeroedPageList, and ZeroKernelPte.

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

PFN_NUMBER MxGetNextPage | ( | VOID |  | ) |

Definition at line 46 of file iniaxp64.c.

References _MEMORY_ALLOCATION_DESCRIPTOR::BasePage, KeBugCheckEx(), MmHighestPhysicalPage, MmLowestPhysicalPage, MmNumberOfPhysicalPages, MxFreeDescriptor, MxNextPhysicalPage, MxNumberOfPages, and _MEMORY_ALLOCATION_DESCRIPTOR::PageCount.

Referenced by MiInitMachineDependent().

    00052                    :
    00053
    00054     This function returns the next physical page number from either the
    00055     largest low memory descritor or the largest free descriptor. If there
    00056     are no physical pages left, then a bugcheck is executed since the
    00057     system cannot be initialized.
    00058
    00059 Arguments:
    00060
    00061     LoaderBlock - Supplies the address of the loader block.
    00062
    00063 Return Value:
    00064
    00065     None.
    00066
    00067 Environment:
    00068
    00069     Kernel mode.
    00070
    00071 --*/
    00072
    00073 {
    00074
    00075     //
    00076     // If there are free pages left in the current descriptor, then
    00077     // return the next physical page. Otherwise, attempt to switch
    00078     // descriptors.
    00079     //
    00080
    00081     if (MxNumberOfPages != 0) {
    00082         MxNumberOfPages -= 1;
    00083         return MxNextPhysicalPage++;
    00084
    00085     } else {
    00086
    00087         //
    00088         // If the current descriptor is not the largest free descriptor,
    00089         // then switch to the largest free descriptor. Otherwise, bugcheck.
    00090         //
    00091
    00092         if (MxNextPhysicalPage ==
    00093                 (MxFreeDescriptor->BasePage + MxFreeDescriptor->PageCount)) {
    00094             KeBugCheckEx(INSTALL_MORE_MEMORY,
    00095                          MmNumberOfPhysicalPages,
    00096                          MmLowestPhysicalPage,
    00097                          MmHighestPhysicalPage,
    00098                          0);
    00099
    00100             return 0;
    00101
    00102         } else {
    00103             MxNumberOfPages = MxFreeDescriptor->PageCount - 1;
    00104             MxNextPhysicalPage = MxFreeDescriptor->BasePage;
    00105             return MxNextPhysicalPage++;
    00106         }
    00107     }
    00108 }

## Variable Documentation

PMEMORY_ALLOCATION_DESCRIPTOR MxFreeDescriptor

| Definition at line 41 of file iniaxp64.c. Referenced by MiInitMachineDependent(), and MxGetNextPage().

PFN_NUMBER MxNextPhysicalPage

| Definition at line 42 of file iniaxp64.c. Referenced by MiInitMachineDependent(), and MxGetNextPage().

PFN_NUMBER MxNumberOfPages

| Definition at line 43 of file iniaxp64.c. Referenced by MiInitMachineDependent(), and MxGetNextPage().