ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

init.c
Go to the documentation of this file.
00001 /*
00002  * COPYRIGHT:       GPL, See COPYING in the top level directory
00003  * PROJECT:         ReactOS kernel
00004  * FILE:            ntoskrnl/mm/amd64/init.c
00005  * PURPOSE:         Memory Manager Initialization for amd64
00006  *
00007  * PROGRAMMERS:     Timo kreuzer (timo.kreuzer@reactos.org)
00008  *                  ReactOS Portable Systems Group
00009  */
00010 
00011 /* INCLUDES ***************************************************************/
00012 
00013 #include <ntoskrnl.h>
00014 //#define NDEBUG
00015 #include <debug.h>
00016 
00017 #include "../ARM3/miarm.h"
00018 
00019 #ifdef _WINKD_
00020 extern PMMPTE MmDebugPte;
00021 #endif
00022 
00023 /* GLOBALS *****************************************************************/
00024 
00025 /* Template PTE and PDE for a kernel page */
00026 MMPTE ValidKernelPde = {{PTE_VALID|PTE_READWRITE|PTE_DIRTY|PTE_ACCESSED}};
00027 MMPTE ValidKernelPte = {{PTE_VALID|PTE_READWRITE|PTE_DIRTY|PTE_ACCESSED}};
00028 
00029 /* Template PDE for a demand-zero page */
00030 MMPDE DemandZeroPde  = {{MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS}};
00031 MMPTE DemandZeroPte  = {{MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS}};
00032 
00033 /* Template PTE for prototype page */
00034 MMPTE PrototypePte = {{(MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) |
00035                       PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << 32)}};
00036 
00037 /* Template PTE for decommited page */
00038 MMPTE MmDecommittedPte = {{MM_DECOMMIT << MM_PTE_SOFTWARE_PROTECTION_BITS}};
00039 
00040 /* Address ranges */
00041 PVOID MiSessionViewEnd;
00042 PVOID MiSystemPteSpaceStart;
00043 PVOID MiSystemPteSpaceEnd;
00044 
00045 ULONG64 MxPfnSizeInBytes;
00046 BOOLEAN MiIncludeType[LoaderMaximum];
00047 PFN_NUMBER MxFreePageBase;
00048 ULONG64 MxFreePageCount = 0;
00049 
00050 BOOLEAN MiPfnsInitialized = FALSE;
00051 
00052 /* FUNCTIONS *****************************************************************/
00053 
00054 VOID
00055 NTAPI
00056 INIT_FUNCTION
00057 MiInitializeSessionSpaceLayout()
00058 {
00059     MmSessionSize = MI_SESSION_SIZE;
00060     MmSessionViewSize = MI_SESSION_VIEW_SIZE;
00061     MmSessionPoolSize = MI_SESSION_POOL_SIZE;
00062     MmSessionImageSize = MI_SESSION_IMAGE_SIZE;
00063     MmSystemViewSize = MI_SYSTEM_VIEW_SIZE;
00064 
00065     /* Set up session space */
00066     MiSessionSpaceEnd = (PVOID)MI_SESSION_SPACE_END;
00067 
00068     /* This is where we will load Win32k.sys and the video driver */
00069     MiSessionImageEnd = MiSessionSpaceEnd;
00070     MiSessionImageStart = (PCHAR)MiSessionImageEnd - MmSessionImageSize;
00071 
00072     /* The view starts right below the session working set (itself below
00073      * the image area) */
00074     MiSessionViewEnd = (PVOID)MI_SESSION_VIEW_END;
00075     MiSessionViewStart = (PCHAR)MiSessionViewEnd - MmSessionViewSize;
00076     ASSERT(IS_PAGE_ALIGNED(MiSessionViewStart));
00077 
00078     /* Session pool follows */
00079     MiSessionPoolEnd = MiSessionViewStart;
00080     MiSessionPoolStart = (PCHAR)MiSessionPoolEnd - MmSessionPoolSize;
00081     ASSERT(IS_PAGE_ALIGNED(MiSessionPoolStart));
00082 
00083     /* And it all begins here */
00084     MmSessionBase = MiSessionPoolStart;
00085 
00086     /* System view space ends at session space, so now that we know where
00087      * this is, we can compute the base address of system view space itself. */
00088     MiSystemViewStart = (PCHAR)MmSessionBase - MmSystemViewSize;
00089     ASSERT(IS_PAGE_ALIGNED(MiSystemViewStart));
00090 
00091     /* Sanity checks */
00092     ASSERT(MiSessionViewEnd <= MiSessionImageStart);
00093     ASSERT(MmSessionBase <= MiSessionPoolStart);
00094 }
00095 
00096 VOID
00097 NTAPI
00098 MiMapPPEs(
00099     PVOID StartAddress,
00100     PVOID EndAddress)
00101 {
00102     PMMPDE PointerPpe;
00103     MMPDE TmplPde = ValidKernelPde;
00104 
00105     /* Loop the PPEs */
00106     for (PointerPpe = MiAddressToPpe(StartAddress);
00107          PointerPpe <= MiAddressToPpe(EndAddress);
00108          PointerPpe++)
00109     {
00110         /* Check if its already mapped */
00111         if (!PointerPpe->u.Hard.Valid)
00112         {
00113             /* No, map it! */
00114             TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
00115             MI_WRITE_VALID_PTE(PointerPpe, TmplPde);
00116 
00117             /* Zero out the page table */
00118             RtlZeroMemory(MiPteToAddress(PointerPpe), PAGE_SIZE);
00119         }
00120     }
00121 }
00122 
00123 VOID
00124 NTAPI
00125 MiMapPDEs(
00126     PVOID StartAddress,
00127     PVOID EndAddress)
00128 {
00129     PMMPDE PointerPde;
00130     MMPDE TmplPde = ValidKernelPde;
00131 
00132     /* Loop the PDEs */
00133     for (PointerPde = MiAddressToPde(StartAddress);
00134          PointerPde <= MiAddressToPde(EndAddress);
00135          PointerPde++)
00136     {
00137         /* Check if its already mapped */
00138         if (!PointerPde->u.Hard.Valid)
00139         {
00140             /* No, map it! */
00141             TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
00142             MI_WRITE_VALID_PTE(PointerPde, TmplPde);
00143 
00144             /* Zero out the page table */
00145             RtlZeroMemory(MiPteToAddress(PointerPde), PAGE_SIZE);
00146         }
00147     }
00148 }
00149 
00150 VOID
00151 NTAPI
00152 MiMapPTEs(
00153     PVOID StartAddress,
00154     PVOID EndAddress)
00155 {
00156     PMMPTE PointerPte;
00157     MMPTE TmplPte = ValidKernelPte;
00158 
00159     /* Loop the PTEs */
00160     for (PointerPte = MiAddressToPte(StartAddress);
00161          PointerPte <= MiAddressToPte(EndAddress);
00162          PointerPte++)
00163     {
00164         /* Check if its already mapped */
00165         if (!PointerPte->u.Hard.Valid)
00166         {
00167             /* No, map it! */
00168             TmplPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
00169             MI_WRITE_VALID_PTE(PointerPte, TmplPte);
00170 
00171             /* Zero out the page (FIXME: not always neccessary) */
00172             RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
00173         }
00174     }
00175 }
00176 
00177 VOID
00178 NTAPI
00179 INIT_FUNCTION
00180 MiInitializePageTable()
00181 {
00182     ULONG64 PxePhysicalAddress;
00183     MMPTE TmplPte, *PointerPxe;
00184     PFN_NUMBER PxePfn;
00185 
00186     /* Get current directory base */
00187     PxePfn = ((PMMPTE)PXE_SELFMAP)->u.Hard.PageFrameNumber;
00188     PxePhysicalAddress = PxePfn << PAGE_SHIFT;
00189     ASSERT(PxePhysicalAddress == __readcr3());
00190 
00191     /* Set directory base for the system process */
00192     PsGetCurrentProcess()->Pcb.DirectoryTableBase[0] = PxePhysicalAddress;
00193 
00194     /* Enable global pages */
00195     __writecr4(__readcr4() | CR4_PGE);
00196     ASSERT(__readcr4() & CR4_PGE);
00197 
00198     /* Enable no execute */
00199     __writemsr(X86_MSR_EFER, __readmsr(X86_MSR_EFER) | EFER_NXE);
00200 
00201     /* Loop the user mode PXEs */
00202     for (PointerPxe = MiAddressToPxe(0);
00203          PointerPxe <= MiAddressToPxe(MmHighestUserAddress);
00204          PointerPxe++)
00205     {
00206         /* Zero the PXE, clear all mappings */
00207         PointerPxe->u.Long = 0;
00208     }
00209 
00210     /* Flush the TLB */
00211     KeFlushCurrentTb();
00212 
00213     /* Set up a template PTE */
00214     TmplPte.u.Long = 0;
00215     TmplPte.u.Flush.Valid = 1;
00216     TmplPte.u.Flush.Write = 1;
00217     HyperTemplatePte = TmplPte;
00218 
00219     /* Create PDPTs (72 KB) for shared system address space,
00220      * skip page tables TODO: use global pages. */
00221 
00222     /* Loop the PXEs */
00223     for (PointerPxe = MiAddressToPxe((PVOID)HYPER_SPACE);
00224          PointerPxe <= MiAddressToPxe(MI_HIGHEST_SYSTEM_ADDRESS);
00225          PointerPxe++)
00226     {
00227         /* Is the PXE already valid? */
00228         if (!PointerPxe->u.Hard.Valid)
00229         {
00230             /* It's not Initialize it */
00231             TmplPte.u.Flush.PageFrameNumber = MxGetNextPage(1);
00232             *PointerPxe = TmplPte;
00233 
00234             /* Zero the page. The PXE is the PTE for the PDPT. */
00235             RtlZeroMemory(MiPteToAddress(PointerPxe), PAGE_SIZE);
00236         }
00237     }
00238 
00239     /* Map PPEs for paged pool */
00240     MiMapPPEs(MmPagedPoolStart, MmPagedPoolEnd);
00241 
00242     /* Setup 1 PPE for hyper space */
00243     MiMapPPEs((PVOID)HYPER_SPACE, (PVOID)HYPER_SPACE_END);
00244 
00245     /* Setup PPEs for system space view */
00246     MiMapPPEs(MiSystemViewStart, (PCHAR)MiSystemViewStart + MmSystemViewSize);
00247 
00248     /* Setup the mapping PDEs */
00249     MiMapPDEs((PVOID)MI_MAPPING_RANGE_START, (PVOID)MI_MAPPING_RANGE_END);
00250 
00251     /* Setup the mapping PTEs */
00252     MmFirstReservedMappingPte = MiAddressToPte((PVOID)MI_MAPPING_RANGE_START);
00253     MmLastReservedMappingPte = MiAddressToPte((PVOID)MI_MAPPING_RANGE_END);
00254     MmFirstReservedMappingPte->u.Hard.PageFrameNumber = MI_HYPERSPACE_PTES;
00255 
00256 #ifdef _WINKD_
00257     /* Setup debug mapping PTE */
00258     MiMapPPEs((PVOID)MI_DEBUG_MAPPING, (PVOID)MI_DEBUG_MAPPING);
00259     MiMapPDEs((PVOID)MI_DEBUG_MAPPING, (PVOID)MI_DEBUG_MAPPING);
00260     MmDebugPte = MiAddressToPte((PVOID)MI_DEBUG_MAPPING);
00261 #endif
00262 
00263     /* Setup PDE and PTEs for VAD bitmap and working set list */
00264     MiMapPDEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 1));
00265     MiMapPTEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 1));
00266 }
00267 
00268 VOID
00269 NTAPI
00270 INIT_FUNCTION
00271 MiBuildNonPagedPool(VOID)
00272 {
00273     /* Check if this is a machine with less than 256MB of RAM, and no overide */
00274     if ((MmNumberOfPhysicalPages <= MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING) &&
00275         !(MmSizeOfNonPagedPoolInBytes))
00276     {
00277         /* Force the non paged pool to be 2MB so we can reduce RAM usage */
00278         MmSizeOfNonPagedPoolInBytes = 2 * 1024 * 1024;
00279     }
00280 
00281     /* Check if the user gave a ridicuously large nonpaged pool RAM size */
00282     if ((MmSizeOfNonPagedPoolInBytes >> PAGE_SHIFT) >
00283         (MmNumberOfPhysicalPages * 7 / 8))
00284     {
00285         /* More than 7/8ths of RAM was dedicated to nonpaged pool, ignore! */
00286         MmSizeOfNonPagedPoolInBytes = 0;
00287     }
00288 
00289     /* Check if no registry setting was set, or if the setting was too low */
00290     if (MmSizeOfNonPagedPoolInBytes < MmMinimumNonPagedPoolSize)
00291     {
00292         /* Start with the minimum (256 KB) and add 32 KB for each MB above 4 */
00293         MmSizeOfNonPagedPoolInBytes = MmMinimumNonPagedPoolSize;
00294         MmSizeOfNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
00295                                        256 * MmMinAdditionNonPagedPoolPerMb;
00296     }
00297 
00298     /* Check if the registy setting or our dynamic calculation was too high */
00299     if (MmSizeOfNonPagedPoolInBytes > MI_MAX_INIT_NONPAGED_POOL_SIZE)
00300     {
00301         /* Set it to the maximum */
00302         MmSizeOfNonPagedPoolInBytes = MI_MAX_INIT_NONPAGED_POOL_SIZE;
00303     }
00304 
00305     /* Check if a percentage cap was set through the registry */
00306     if (MmMaximumNonPagedPoolPercent)
00307     {
00308         /* Don't feel like supporting this right now */
00309         UNIMPLEMENTED;
00310     }
00311 
00312     /* Page-align the nonpaged pool size */
00313     MmSizeOfNonPagedPoolInBytes &= ~(PAGE_SIZE - 1);
00314 
00315     /* Now, check if there was a registry size for the maximum size */
00316     if (!MmMaximumNonPagedPoolInBytes)
00317     {
00318         /* Start with the default (1MB) and add 400 KB for each MB above 4 */
00319         MmMaximumNonPagedPoolInBytes = MmDefaultMaximumNonPagedPool;
00320         MmMaximumNonPagedPoolInBytes += (MmNumberOfPhysicalPages - 1024) /
00321                                          256 * MmMaxAdditionNonPagedPoolPerMb;
00322     }
00323 
00324     /* Don't let the maximum go too high */
00325     if (MmMaximumNonPagedPoolInBytes > MI_MAX_NONPAGED_POOL_SIZE)
00326     {
00327         /* Set it to the upper limit */
00328         MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
00329     }
00330 
00331     /* Convert nonpaged pool size from bytes to pages */
00332     MmMaximumNonPagedPoolInPages = MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT;
00333 
00334     /* Non paged pool starts after the PFN database */
00335     MmNonPagedPoolStart = MmPfnDatabase + MxPfnAllocation * PAGE_SIZE;
00336 
00337     /* Calculate the nonpaged pool expansion start region */
00338     MmNonPagedPoolExpansionStart = (PCHAR)MmNonPagedPoolStart +
00339                                           MmSizeOfNonPagedPoolInBytes;
00340     ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolExpansionStart));
00341 
00342     /* And this is where the none paged pool ends */
00343     MmNonPagedPoolEnd = (PCHAR)MmNonPagedPoolStart + MmMaximumNonPagedPoolInBytes;
00344     ASSERT(MmNonPagedPoolEnd < (PVOID)MM_HAL_VA_START);
00345 
00346     /* Map PPEs and PDEs for non paged pool (including expansion) */
00347     MiMapPPEs(MmNonPagedPoolStart, MmNonPagedPoolEnd);
00348     MiMapPDEs(MmNonPagedPoolStart, MmNonPagedPoolEnd);
00349 
00350     /* Map the nonpaged pool PTEs (without expansion) */
00351     MiMapPTEs(MmNonPagedPoolStart, (PCHAR)MmNonPagedPoolExpansionStart - 1);
00352 
00353     /* Initialize the ARM3 nonpaged pool */
00354     MiInitializeNonPagedPool();
00355     MiInitializeNonPagedPoolThresholds();
00356 
00357 }
00358 
00359 VOID
00360 NTAPI
00361 INIT_FUNCTION
00362 MiBuildSystemPteSpace()
00363 {
00364     PMMPTE PointerPte;
00365 
00366     /* Use the default numer of system PTEs */
00367     MmNumberOfSystemPtes = MI_NUMBER_SYSTEM_PTES;
00368     MiNonPagedSystemSize = (MmNumberOfSystemPtes + 1) * PAGE_SIZE;
00369 
00370     /* Put system PTEs at the start of the system VA space */
00371     MiSystemPteSpaceStart = MmNonPagedSystemStart;
00372     MiSystemPteSpaceEnd = (PUCHAR)MiSystemPteSpaceStart + MiNonPagedSystemSize;
00373 
00374     /* Map the PPEs and PDEs for the system PTEs */
00375     MiMapPPEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
00376     MiMapPDEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
00377 
00378     /* Initialize the system PTE space */
00379     PointerPte = MiAddressToPte(MiSystemPteSpaceStart);
00380     MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace);
00381 
00382     /* Reserve system PTEs for zeroing PTEs and clear them */
00383     MiFirstReservedZeroingPte = MiReserveSystemPtes(MI_ZERO_PTES, SystemPteSpace);
00384     RtlZeroMemory(MiFirstReservedZeroingPte, MI_ZERO_PTES * sizeof(MMPTE));
00385 
00386     /* Set the counter to maximum */
00387     MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
00388 }
00389 
00390 static
00391 VOID
00392 MiSetupPfnForPageTable(
00393     PFN_NUMBER PageFrameIndex,
00394     PMMPTE PointerPte)
00395 {
00396     PMMPFN Pfn;
00397     PMMPDE PointerPde;
00398 
00399     /* Get the pfn entry for this page */
00400     Pfn = MiGetPfnEntry(PageFrameIndex);
00401 
00402     /* Check if it's valid memory */
00403     if ((PageFrameIndex <= MmHighestPhysicalPage) &&
00404         (MmIsAddressValid(Pfn)) &&
00405         (Pfn->u3.e1.PageLocation == ActiveAndValid))
00406     {
00407         /* Setup the PFN entry */
00408         Pfn->u1.WsIndex = 0;
00409         Pfn->u2.ShareCount++;
00410         Pfn->PteAddress = PointerPte;
00411         Pfn->OriginalPte = *PointerPte;
00412         Pfn->u3.e1.PageLocation = ActiveAndValid;
00413         Pfn->u3.e1.CacheAttribute = MiNonCached;
00414         Pfn->u3.e2.ReferenceCount = 1;
00415         Pfn->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte));
00416     }
00417 
00418     /* Increase the shared count of the PFN entry for the PDE */
00419     PointerPde = MiAddressToPde(MiPteToAddress(PointerPte));
00420     Pfn = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
00421     Pfn->u2.ShareCount++;
00422 }
00423 
00424 VOID
00425 NTAPI
00426 MiBuildPfnDatabaseFromPageTables(VOID)
00427 {
00428     PVOID Address = NULL;
00429     PFN_NUMBER PageFrameIndex;
00430     PMMPDE PointerPde;
00431     PMMPTE PointerPte;
00432     ULONG k, l;
00433     PMMPFN Pfn;
00434 #if (_MI_PAGING_LEVELS >= 3)
00435     PMMPDE PointerPpe;
00436     ULONG j;
00437 #endif
00438 #if (_MI_PAGING_LEVELS == 4)
00439     PMMPDE PointerPxe;
00440     ULONG i;
00441 #endif
00442 
00443     /* Manual setup of the top level page directory */
00444 #if (_MI_PAGING_LEVELS == 4)
00445     PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PXE_BASE));
00446 #elif (_MI_PAGING_LEVELS == 3)
00447     PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PPE_BASE));
00448 #else
00449     PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PDE_BASE));
00450 #endif
00451     Pfn = MiGetPfnEntry(PageFrameIndex);
00452     ASSERT(Pfn->u3.e1.PageLocation == ActiveAndValid);
00453     Pfn->u1.WsIndex = 0;
00454     Pfn->u2.ShareCount = 1;
00455     Pfn->PteAddress = NULL;
00456     Pfn->u3.e1.CacheAttribute = MiNonCached;
00457     Pfn->u3.e2.ReferenceCount = 1;
00458     Pfn->u4.PteFrame = 0;
00459 
00460 #if (_MI_PAGING_LEVELS == 4)
00461     /* Loop all PXEs in the PML4 */
00462     PointerPxe = MiAddressToPxe(Address);
00463     for (i = 0; i < PXE_PER_PAGE; i++, PointerPxe++)
00464     {
00465         /* Skip invalid PXEs */
00466         if (!PointerPxe->u.Hard.Valid) continue;
00467 
00468         /* Handle the PFN */
00469         PageFrameIndex = PFN_FROM_PXE(PointerPxe);
00470         MiSetupPfnForPageTable(PageFrameIndex, PointerPxe);
00471 
00472         /* Get starting VA for this PXE */
00473         Address = MiPxeToAddress(PointerPxe);
00474 #endif
00475 #if (_MI_PAGING_LEVELS >= 3)
00476         /* Loop all PPEs in this PDP */
00477         PointerPpe = MiAddressToPpe(Address);
00478         for (j = 0; j < PPE_PER_PAGE; j++, PointerPpe++)
00479         {
00480             /* Skip invalid PPEs */
00481             if (!PointerPpe->u.Hard.Valid) continue;
00482 
00483             /* Handle the PFN */
00484             PageFrameIndex = PFN_FROM_PPE(PointerPpe);
00485             MiSetupPfnForPageTable(PageFrameIndex, PointerPpe);
00486 
00487             /* Get starting VA for this PPE */
00488             Address = MiPpeToAddress(PointerPpe);
00489 #endif
00490             /* Loop all PDEs in this PD */
00491             PointerPde = MiAddressToPde(Address);
00492             for (k = 0; k < PDE_PER_PAGE; k++, PointerPde++)
00493             {
00494                 /* Skip invalid PDEs */
00495                 if (!PointerPde->u.Hard.Valid) continue;
00496 
00497                 /* Handle the PFN */
00498                 PageFrameIndex = PFN_FROM_PDE(PointerPde);
00499                 MiSetupPfnForPageTable(PageFrameIndex, PointerPde);
00500 
00501                 /* Get starting VA for this PDE */
00502                 Address = MiPdeToAddress(PointerPde);
00503 
00504                 /* Loop all PTEs in this PT */
00505                 PointerPte = MiAddressToPte(Address);
00506                 for (l = 0; l < PTE_PER_PAGE; l++, PointerPte++)
00507                 {
00508                     /* Skip invalid PTEs */
00509                     if (!PointerPte->u.Hard.Valid) continue;
00510 
00511                     /* Handle the PFN */
00512                     PageFrameIndex = PFN_FROM_PTE(PointerPte);
00513                     MiSetupPfnForPageTable(PageFrameIndex, PointerPte);
00514                 }
00515             }
00516 #if (_MI_PAGING_LEVELS >= 3)
00517         }
00518 #endif
00519 #if (_MI_PAGING_LEVELS == 4)
00520     }
00521 #endif
00522 }
00523 
00524 VOID
00525 NTAPI
00526 INIT_FUNCTION
00527 MiAddDescriptorToDatabase(
00528     PFN_NUMBER BasePage,
00529     PFN_NUMBER PageCount,
00530     TYPE_OF_MEMORY MemoryType)
00531 {
00532     PMMPFN Pfn;
00533 
00534     ASSERT(!MiIsMemoryTypeInvisible(MemoryType));
00535 
00536     /* Check if the memory is free */
00537     if (MiIsMemoryTypeFree(MemoryType))
00538     {
00539         /* Get the last pfn of this descriptor. Note we loop backwards */
00540         Pfn = &MmPfnDatabase[BasePage + PageCount - 1];
00541 
00542         /* Loop all pages */
00543         while (PageCount--)
00544         {
00545             /* Add it to the free list */
00546             Pfn->u3.e1.CacheAttribute = MiNonCached;
00547             MiInsertPageInFreeList(BasePage + PageCount);
00548 
00549             /* Go to the previous page */
00550             Pfn--;
00551         }
00552     }
00553     else if (MemoryType == LoaderXIPRom)
00554     {
00555         Pfn = &MmPfnDatabase[BasePage];
00556         while (PageCount--)
00557         {
00558             /* Make it a pseudo-I/O ROM mapping */
00559             Pfn->PteAddress = 0;
00560             Pfn->u1.Flink = 0;
00561             Pfn->u2.ShareCount = 0;
00562             Pfn->u3.e1.PageLocation = 0;
00563             Pfn->u3.e1.CacheAttribute = MiNonCached;
00564             Pfn->u3.e1.Rom = 1;
00565             Pfn->u3.e1.PrototypePte = 1;
00566             Pfn->u3.e2.ReferenceCount = 0;
00567             Pfn->u4.InPageError = 0;
00568             Pfn->u4.PteFrame = 0;
00569 
00570             /* Advance one */
00571             Pfn++;
00572         }
00573     }
00574     else if (MemoryType == LoaderBad)
00575     {
00576         // FIXME: later
00577         ASSERT(FALSE);
00578     }
00579     else
00580     {
00581         /* For now skip it */
00582         DbgPrint("Skipping BasePage=0x%lx, PageCount=0x%lx, MemoryType=%lx\n",
00583                  BasePage, PageCount, MemoryType);
00584         Pfn = &MmPfnDatabase[BasePage];
00585         while (PageCount--)
00586         {
00587             /* Make an active PFN */
00588             Pfn->u3.e1.PageLocation = ActiveAndValid;
00589 
00590             /* Advance one */
00591             Pfn++;
00592         }
00593     }
00594 }
00595 
00596 VOID
00597 NTAPI
00598 INIT_FUNCTION
00599 MiBuildPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
00600 {
00601     PLIST_ENTRY ListEntry;
00602     PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
00603     PFN_NUMBER BasePage, PageCount;
00604 
00605     /* Map the PDEs and PPEs for the pfn database (ignore holes) */
00606 #if (_MI_PAGING_LEVELS >= 3)
00607     MiMapPPEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1);
00608 #endif
00609     MiMapPDEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1);
00610 
00611     /* First initialize the color tables */
00612     MiInitializeColorTables();
00613 
00614     /* Loop the memory descriptors */
00615     for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
00616          ListEntry != &LoaderBlock->MemoryDescriptorListHead;
00617          ListEntry = ListEntry->Flink)
00618     {
00619         /* Get the descriptor */
00620         Descriptor = CONTAINING_RECORD(ListEntry,
00621                                        MEMORY_ALLOCATION_DESCRIPTOR,
00622                                        ListEntry);
00623 
00624         /* Skip invisible memory */
00625         if (MiIsMemoryTypeInvisible(Descriptor->MemoryType)) continue;
00626 
00627         /* If this is the free descriptor, use the copy instead */
00628         if (Descriptor == MxFreeDescriptor) Descriptor = &MxOldFreeDescriptor;
00629 
00630         /* Get the range for this descriptor */
00631         BasePage = Descriptor->BasePage;
00632         PageCount = Descriptor->PageCount;
00633 
00634         /* Map the pages for the database */
00635         MiMapPTEs(&MmPfnDatabase[BasePage],
00636                   (PUCHAR)(&MmPfnDatabase[BasePage + PageCount]) - 1);
00637 
00638         /* If this was the free descriptor, skip the next step */
00639         if (Descriptor == &MxOldFreeDescriptor) continue;
00640 
00641         /* Add this descriptor to the database */
00642         MiAddDescriptorToDatabase(BasePage, PageCount, Descriptor->MemoryType);
00643     }
00644 
00645     /* At this point the whole pfn database is mapped. We are about to add the
00646        pages from the free descriptor to the database, so from now on we cannot
00647        use it anymore. */
00648 
00649     /* Now add the free descriptor */
00650     BasePage = MxFreeDescriptor->BasePage;
00651     PageCount = MxFreeDescriptor->PageCount;
00652     MiAddDescriptorToDatabase(BasePage, PageCount, LoaderFree);
00653 
00654     /* And finally the memory we used */
00655     BasePage = MxOldFreeDescriptor.BasePage;
00656     PageCount = MxFreeDescriptor->BasePage - BasePage;
00657     MiAddDescriptorToDatabase(BasePage, PageCount, LoaderMemoryData);
00658 
00659     /* Reset the descriptor back so we can create the correct memory blocks */
00660     *MxFreeDescriptor = MxOldFreeDescriptor;
00661 }
00662 
00663 NTSTATUS
00664 NTAPI
00665 INIT_FUNCTION
00666 MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
00667 {
00668     KIRQL OldIrql;
00669 
00670     ASSERT(MxPfnAllocation != 0);
00671 
00672     /* Set some hardcoded addresses */
00673     MmHyperSpaceEnd = (PVOID)HYPER_SPACE_END;
00674     MmNonPagedSystemStart = (PVOID)MM_SYSTEM_SPACE_START;
00675     MmPfnDatabase = (PVOID)MI_PFN_DATABASE;
00676     MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST;
00677 
00678 
00679 //    PrototypePte.u.Proto.Valid = 1
00680 //    PrototypePte.u.ReadOnly
00681 //    PrototypePte.u.Prototype
00682 //    PrototypePte.u.Protection = MM_READWRITE;
00683 //    PrototypePte.u.ProtoAddress
00684     PrototypePte.u.Soft.PageFileHigh = MI_PTE_LOOKUP_NEEDED;
00685 
00686 
00687     MiInitializePageTable();
00688 
00689     MiBuildNonPagedPool();
00690 
00691     MiBuildSystemPteSpace();
00692 
00693     /* Need to be at DISPATCH_LEVEL for MiInsertPageInFreeList */
00694     KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00695 
00696     /* Map the PFN database pages */
00697     MiBuildPfnDatabase(LoaderBlock);
00698 
00699     /* Now process the page tables */
00700     MiBuildPfnDatabaseFromPageTables();
00701 
00702     /* PFNs are initialized now! */
00703     MiPfnsInitialized = TRUE;
00704 
00705     //KeLowerIrql(OldIrql);
00706 
00707     /* Need to be at DISPATCH_LEVEL for InitializePool */
00708     //KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
00709 
00710     /* Initialize the nonpaged pool */
00711     InitializePool(NonPagedPool, 0);
00712 
00713     KeLowerIrql(OldIrql);
00714 
00715     /* Initialize the balancer */
00716     MmInitializeBalancer((ULONG)MmAvailablePages, 0);
00717 
00718     /* Make sure we have everything we need */
00719     ASSERT(MmPfnDatabase);
00720     ASSERT(MmNonPagedSystemStart);
00721     ASSERT(MmNonPagedPoolStart);
00722     ASSERT(MmSizeOfNonPagedPoolInBytes);
00723     ASSERT(MmMaximumNonPagedPoolInBytes);
00724     ASSERT(MmNonPagedPoolExpansionStart);
00725     ASSERT(MmHyperSpaceEnd);
00726     ASSERT(MmNumberOfSystemPtes);
00727     ASSERT(MiAddressToPde(MmNonPagedPoolStart)->u.Hard.Valid);
00728     ASSERT(MiAddressToPte(MmNonPagedPoolStart)->u.Hard.Valid);
00729 
00730     return STATUS_SUCCESS;
00731 }

Generated on Sat May 26 2012 04:22:07 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.