test: initmips.c Source File

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

# initmips.c

Go to the documentation of this file.

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