Author: tkreuzer
Date: Sat Feb  4 10:40:27 2012
New Revision: 55403

URL: http://svn.reactos.org/svn/reactos?rev=55403&view=rev
Log:
[NTOSKRNL/MM/AMD64]
- Add MI_REAL_SYSTEM_RANGE_START, which is the canonical system space base 
address, while MmSystemRangeStart variable contains a broken value, like on 
Windows.
- Define MmSystemRangeStart to MI_REAL_SYSTEM_RANGE_START, since on amd64 there 
is no dynamic system space start address and we don't want to use the broken 
address anywhere
- Add some more address layout definitions
- Add MiIsPteOnP*eBoundary() macro
- Add MMPPE, MI_WRITE_VALID_PPE and ValidKernelPpe definitions
- Fix initialization of PrototypePte
- Add mappings for VAD bitmap and working set list to MiInitializePageTable
- Fix calculations in MiBuildNonPagedPool
- Improve MiBuildSystemPteSpace
- Implement MiBuildPfnDatabase, MiAddDescriptorToDatabase, 
MiBuildPfnDatabaseFromPageTables, MiSetupPfnForPageTable all of these are 
written to be portable, yet they are untested on anything else than amd64 builds
- Mostly finish MiInitMachineDependent

Modified:
    trunk/reactos/ntoskrnl/include/internal/amd64/mm.h
    trunk/reactos/ntoskrnl/mm/amd64/init.c

Modified: trunk/reactos/ntoskrnl/include/internal/amd64/mm.h
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/amd64/mm.h?rev=55403&r1=55402&r2=55403&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1] Sat Feb  4 
10:40:27 2012
@@ -8,29 +8,39 @@
 #define MI_HIGHEST_USER_ADDRESS         (PVOID)0x000007FFFFFEFFFFULL
 #define MI_USER_PROBE_ADDRESS           (PVOID)0x000007FFFFFF0000ULL
 #define MI_DEFAULT_SYSTEM_RANGE_START   (PVOID)0xFFFF080000000000ULL
+#define MI_REAL_SYSTEM_RANGE_START             0xFFFF800000000000ULL
+#define MI_PAGE_TABLE_BASE                     0xFFFFF68000000000ULL
 #define HYPER_SPACE                            0xFFFFF70000000000ULL
 #define HYPER_SPACE_END                        0xFFFFF77FFFFFFFFFULL
-#define MI_SESSION_SPACE_MINIMUM        (PVOID)0xFFFFF90000000000ULL
-#define MI_SESSION_VIEW_END             (PVOID)0xFFFFF97FFF000000ULL
-#define MI_SESSION_SPACE_END            (PVOID)0xFFFFF98000000000ULL
-#define MI_SYSTEM_PTE_START             (PVOID)0xFFFFFAA000000000ULL
-#define MI_PAGED_POOL_START             (PVOID)0xFFFFFA8000000000ULL
-#define MI_NON_PAGED_SYSTEM_START_MIN          0xFFFFFAA000000000ULL
-#define MI_PFN_DATABASE                 (PVOID)0xFFFFFAC000000000ULL
-#define MI_NONPAGED_POOL_END            (PVOID)0xFFFFFAE000000000ULL
-#define MI_DEBUG_MAPPING                (PVOID)0xFFFFFFFF80000000ULL // FIXME
+#define MI_SHARED_SYSTEM_PAGE                  0xFFFFF78000000000ULL
+#define MI_SYSTEM_CACHE_WS_START               0xFFFFF78000001000ULL
+#define MI_LOADER_MAPPINGS                     0xFFFFF80000000000ULL
+#define MI_PAGED_SYSTEM_START                  0xFFFFF88000000000ULL
+#define MI_PAGED_POOL_START             (PVOID)0xFFFFF8A000000000ULL
+#define MI_PAGED_POOL_END                      0xFFFFF8BFFFFFFFFFULL
+#define MI_SESSION_SPACE_START                 0xFFFFF90000000000ULL
+#define MI_SESSION_VIEW_END                    0xFFFFF97FFF000000ULL
+#define MI_SESSION_SPACE_END                   0xFFFFF97FFFFFFFFFULL
+#define MM_SYSTEM_SPACE_START                  0xFFFFF98000000000ULL
+#define MI_PFN_DATABASE                        0xFFFFFA8000000000ULL
 #define MI_HIGHEST_SYSTEM_ADDRESS       (PVOID)0xFFFFFFFFFFFFFFFFULL
-#define MI_SYSTEM_CACHE_WS_START        (PVOID)0xFFFFF78000001000ULL // CHECKME
-
+
+/* WOW64 address definitions */
 #define MM_HIGHEST_USER_ADDRESS_WOW64   0x7FFEFFFF
 #define MM_SYSTEM_RANGE_START_WOW64     0x80000000
 
-
-#define MI_SYSTEM_PTE_END               (PVOID)((ULONG64)MI_SYSTEM_PTE_START + 
MI_NUMBER_SYSTEM_PTES * PAGE_SIZE - 1)
+#define MI_DEBUG_MAPPING                (PVOID)0xFFFFFFFF80000000ULL // FIXME
+#define MI_NON_PAGED_SYSTEM_START_MIN   MM_SYSTEM_SPACE_START // FIXME
+#define MI_SYSTEM_PTE_START             MM_SYSTEM_SPACE_START
+#define MI_SYSTEM_PTE_END               (MI_SYSTEM_PTE_START + 
MI_NUMBER_SYSTEM_PTES * PAGE_SIZE - 1)
 #define MI_SYSTEM_PTE_BASE              (PVOID)MiAddressToPte(KSEG0_BASE)
 #define MM_HIGHEST_VAD_ADDRESS          
(PVOID)((ULONG_PTR)MM_HIGHEST_USER_ADDRESS - (16 * PAGE_SIZE))
-#define MI_MAPPING_RANGE_START          (ULONG64)HYPER_SPACE
+#define MI_MAPPING_RANGE_START          HYPER_SPACE
 #define MI_MAPPING_RANGE_END            (MI_MAPPING_RANGE_START + 
MI_HYPERSPACE_PTES * PAGE_SIZE)
+#define MI_DUMMY_PTE                        (MI_MAPPING_RANGE_END + PAGE_SIZE)
+#define MI_VAD_BITMAP                       (MI_DUMMY_PTE + PAGE_SIZE)
+#define MI_WORKING_SET_LIST                 (MI_VAD_BITMAP + PAGE_SIZE)
+#define MI_NONPAGED_POOL_END 0
 
 /* Memory sizes */
 #define MI_MIN_PAGES_FOR_NONPAGED_POOL_TUNING ((255*1024*1024) >> PAGE_SHIFT)
@@ -55,6 +65,8 @@
                                                MI_SESSION_IMAGE_SIZE + \
                                                MI_SESSION_WORKING_SET_SIZE)
 
+#define MmSystemRangeStart ((PVOID)MI_REAL_SYSTEM_RANGE_START)
+
 /* Misc constants */
 #define _MI_PAGING_LEVELS                   4
 #define MI_NUMBER_SYSTEM_PTES               22000
@@ -63,9 +75,6 @@
 #define NR_SECTION_PAGE_ENTRIES             1024
 #define MI_HYPERSPACE_PTES                  (256 - 1)
 #define MI_ZERO_PTES                        (32)
-#define MI_DUMMY_PTE                        (PMMPTE)(MI_MAPPING_RANGE_END + 
PAGE_SIZE)
-#define MI_VAD_BITMAP                       (PMMPTE)(MI_DUMMY_PTE + PAGE_SIZE)
-#define MI_WORKING_SET_LIST                 (PMMPTE)(MI_VAD_BITMAP + PAGE_SIZE)
 /* FIXME - different architectures have different cache line sizes... */
 #define MM_CACHE_LINE_SIZE                  32
 
@@ -74,6 +83,13 @@
 #define PAE_PAGE_MASK(x)       ((x)&(~0xfffLL))
 #define IS_ALIGNED(addr, align) (((ULONG64)(addr) & (align - 1)) == 0)
 #define IS_PAGE_ALIGNED(addr) IS_ALIGNED(addr, PAGE_SIZE)
+
+#define MiIsPteOnPdeBoundary(PointerPte) \
+    ((((ULONG_PTR)PointerPte) & (PAGE_SIZE - 1)) == 0)
+#define MiIsPteOnPpeBoundary(PointerPte) \
+    ((((ULONG_PTR)PointerPte) & (PDE_PER_PAGE * PAGE_SIZE - 1)) == 0)
+#define MiIsPteOnPxeBoundary(PointerPte) \
+    ((((ULONG_PTR)PointerPte) & (PPE_PER_PAGE * PDE_PER_PAGE * PAGE_SIZE - 1)) 
== 0)
 
 /* MMPTE related defines */
 #define MM_EMPTY_PTE_LIST  ((ULONG64)0xFFFFFFFF)
@@ -129,6 +145,11 @@
 /* On x86, these two are the same */
 #define MMPDE MMPTE
 #define PMMPDE PMMPTE
+#define MMPPE MMPTE
+#define PMMPPE PMMPTE
+#define MI_WRITE_VALID_PPE MI_WRITE_VALID_PTE
+
+#define ValidKernelPpe ValidKernelPde
 
 PULONG64
 FORCEINLINE

Modified: trunk/reactos/ntoskrnl/mm/amd64/init.c
URL: 
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/amd64/init.c?rev=55403&r1=55402&r2=55403&view=diff
==============================================================================
--- trunk/reactos/ntoskrnl/mm/amd64/init.c [iso-8859-1] (original)
+++ trunk/reactos/ntoskrnl/mm/amd64/init.c [iso-8859-1] Sat Feb  4 10:40:27 2012
@@ -32,13 +32,12 @@
 
 /* Template PTE for prototype page */
 MMPTE PrototypePte = {{(MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS) |
-                      PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << PAGE_SHIFT)}};
-
-/* Sizes */
-SIZE_T MiNonPagedSystemSize;
+                      PTE_PROTOTYPE | (MI_PTE_LOOKUP_NEEDED << 32)}};
 
 /* Address ranges */
 PVOID MiSessionViewEnd;
+PVOID MiSystemPteSpaceStart;
+PVOID MiSystemPteSpaceEnd;
 
 ULONG64 MxPfnSizeInBytes;
 BOOLEAN MiIncludeType[LoaderMaximum];
@@ -69,7 +68,7 @@
 
     /* The view starts right below the session working set (itself below
      * the image area) */
-    MiSessionViewEnd = MI_SESSION_VIEW_END;
+    MiSessionViewEnd = (PVOID)MI_SESSION_VIEW_END;
     MiSessionViewStart = (PCHAR)MiSessionViewEnd - MmSessionViewSize;
     ASSERT(IS_PAGE_ALIGNED(MiSessionViewStart));
 
@@ -110,7 +109,7 @@
         {
             /* No, map it! */
             TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
-            *PointerPpe = TmplPde;
+            MI_WRITE_VALID_PTE(PointerPpe, TmplPde);
 
             /* Zero out the page table */
             RtlZeroMemory(MiPteToAddress(PointerPpe), PAGE_SIZE);
@@ -137,7 +136,7 @@
         {
             /* No, map it! */
             TmplPde.u.Hard.PageFrameNumber = MxGetNextPage(1);
-            *PointerPde = TmplPde;
+            MI_WRITE_VALID_PTE(PointerPde, TmplPde);
 
             /* Zero out the page table */
             RtlZeroMemory(MiPteToAddress(PointerPde), PAGE_SIZE);
@@ -164,7 +163,10 @@
         {
             /* No, map it! */
             TmplPte.u.Hard.PageFrameNumber = MxGetNextPage(1);
-            *PointerPte = TmplPte;
+            MI_WRITE_VALID_PTE(PointerPte, TmplPte);
+
+            /* Zero out the page (FIXME: not always neccessary) */
+            RtlZeroMemory(MiPteToAddress(PointerPte), PAGE_SIZE);
         }
     }
 }
@@ -212,10 +214,10 @@
     HyperTemplatePte = TmplPte;
 
     /* Create PDPTs (72 KB) for shared system address space,
-     * skip page tables and hyperspace */
+     * skip page tables TODO: use global pages. */
 
     /* Loop the PXEs */
-    for (PointerPxe = MiAddressToPxe((PVOID)(HYPER_SPACE_END + 1));
+    for (PointerPxe = MiAddressToPxe((PVOID)HYPER_SPACE);
          PointerPxe <= MiAddressToPxe(MI_HIGHEST_SYSTEM_ADDRESS);
          PointerPxe++)
     {
@@ -231,8 +233,13 @@
         }
     }
 
-    /* Setup the mapping PPEs and PDEs */
-    MiMapPPEs((PVOID)MI_MAPPING_RANGE_START, (PVOID)MI_MAPPING_RANGE_END);
+    /* Map PPEs for paged pool */
+    MiMapPPEs(MmPagedPoolStart, MmPagedPoolEnd);
+
+    /* Setup 1 PPE for hyper space */
+    MiMapPPEs((PVOID)HYPER_SPACE, (PVOID)HYPER_SPACE_END);
+
+    /* Setup the mapping PDEs */
     MiMapPDEs((PVOID)MI_MAPPING_RANGE_START, (PVOID)MI_MAPPING_RANGE_END);
 
     /* Setup the mapping PTEs */
@@ -246,6 +253,10 @@
     MiMapPDEs((PVOID)MI_DEBUG_MAPPING, (PVOID)MI_DEBUG_MAPPING);
     MmDebugPte = MiAddressToPte((PVOID)MI_DEBUG_MAPPING);
 #endif
+
+    /* Setup PDE and PTEs for VAD bitmap and working set list */
+    MiMapPDEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 
1));
+    MiMapPTEs((PVOID)MI_VAD_BITMAP, (PVOID)(MI_WORKING_SET_LIST + PAGE_SIZE - 
1));
 }
 
 VOID
@@ -311,34 +322,31 @@
         MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
     }
 
-    /* Put non paged pool to the end of the region */
-    MmNonPagedPoolStart = (PCHAR)MmNonPagedPoolEnd - 
MmMaximumNonPagedPoolInBytes;
-
-    /* Make sure it doesn't collide with the PFN database */
-    if ((PCHAR)MmNonPagedPoolStart < (PCHAR)MmPfnDatabase + MxPfnSizeInBytes)
-    {
-        /* Put non paged pool after the PFN database */
-        MmNonPagedPoolStart = (PCHAR)MmPfnDatabase + MxPfnSizeInBytes;
-        MmMaximumNonPagedPoolInBytes = (ULONG64)MmNonPagedPoolEnd -
-                                       (ULONG64)MmNonPagedPoolStart;
-    }
-
-    ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolStart));
+    /* Convert nonpaged pool size from bytes to pages */
+    MmMaximumNonPagedPoolInPages = MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT;
+
+    /* Non paged pool starts after the PFN database */
+    MmNonPagedPoolStart = MmPfnDatabase + MxPfnAllocation * PAGE_SIZE;
 
     /* Calculate the nonpaged pool expansion start region */
     MmNonPagedPoolExpansionStart = (PCHAR)MmNonPagedPoolStart +
                                           MmSizeOfNonPagedPoolInBytes;
     ASSERT(IS_PAGE_ALIGNED(MmNonPagedPoolExpansionStart));
 
+    /* And this is where the none paged pool ends */
+    MmNonPagedPoolEnd = (PCHAR)MmNonPagedPoolStart + 
MmMaximumNonPagedPoolInBytes;
+    ASSERT(MmNonPagedPoolEnd < (PVOID)MM_HAL_VA_START);
+
     /* Map PPEs and PDEs for non paged pool (including expansion) */
     MiMapPPEs(MmNonPagedPoolStart, MmNonPagedPoolEnd);
     MiMapPDEs(MmNonPagedPoolStart, MmNonPagedPoolEnd);
 
     /* Map the nonpaged pool PTEs (without expansion) */
-    MiMapPTEs(MmNonPagedPoolStart, (PUCHAR)MmNonPagedPoolExpansionStart - 1);
+    MiMapPTEs(MmNonPagedPoolStart, (PCHAR)MmNonPagedPoolExpansionStart - 1);
 
     /* Initialize the ARM3 nonpaged pool */
     MiInitializeNonPagedPool();
+    MiInitializeNonPagedPoolThresholds();
 
     /* Initialize the nonpaged pool */
     InitializePool(NonPagedPool, 0);
@@ -353,32 +361,18 @@
 
     /* Use the default numer of system PTEs */
     MmNumberOfSystemPtes = MI_NUMBER_SYSTEM_PTES;
-
-    /* System PTE pool is below the PFN database */
     MiNonPagedSystemSize = (MmNumberOfSystemPtes + 1) * PAGE_SIZE;
-    MmNonPagedSystemStart = (PCHAR)MmPfnDatabase - MiNonPagedSystemSize;
-    MmNonPagedSystemStart = MM_ROUND_DOWN(MmNonPagedSystemStart, 512 * 
PAGE_SIZE);
-
-    /* Don't let it go below the minimum */
-    if (MmNonPagedSystemStart < (PVOID)MI_NON_PAGED_SYSTEM_START_MIN)
-    {
-        /* This is a hard-coded limit in the Windows NT address space */
-        MmNonPagedSystemStart = (PVOID)MI_NON_PAGED_SYSTEM_START_MIN;
-
-        /* Reduce the amount of system PTEs to reach this point */
-        MmNumberOfSystemPtes = (ULONG)(((ULONG64)MmPfnDatabase -
-                                (ULONG64)MmNonPagedSystemStart) >>
-                                PAGE_SHIFT);
-        MmNumberOfSystemPtes--;
-        ASSERT(MmNumberOfSystemPtes > 1000);
-    }
-
-    /* Map the PDEs and PPEs for the system PTEs */
-    MiMapPPEs(MI_SYSTEM_PTE_START, MI_SYSTEM_PTE_END);
-    MiMapPDEs(MI_SYSTEM_PTE_START, MI_SYSTEM_PTE_END);
-
-    /* Create the system PTE space */
-    PointerPte = MiAddressToPte(MI_SYSTEM_PTE_START);
+
+    /* Put system PTEs at the start of the system VA space */
+    MiSystemPteSpaceStart = MmNonPagedSystemStart;
+    MiSystemPteSpaceEnd = (PUCHAR)MiSystemPteSpaceStart + MiNonPagedSystemSize;
+
+    /* Map the PPEs and PDEs for the system PTEs */
+    MiMapPPEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
+    MiMapPDEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
+
+    /* Initialize the system PTE space */
+    PointerPte = MiAddressToPte(MiSystemPteSpaceStart);
     MiInitializeSystemPtes(PointerPte, MmNumberOfSystemPtes, SystemPteSpace);
 
     /* Reserve system PTEs for zeroing PTEs and clear them */
@@ -389,13 +383,302 @@
     MiFirstReservedZeroingPte->u.Hard.PageFrameNumber = MI_ZERO_PTES - 1;
 }
 
+static
+VOID
+MiSetupPfnForPageTable(
+    PFN_NUMBER PageFrameIndex,
+    PMMPTE PointerPte)
+{
+    PMMPFN Pfn;
+    PMMPDE PointerPde;
+
+    /* Get the pfn entry for this page */
+    Pfn = MiGetPfnEntry(PageFrameIndex);
+
+    /* Check if it's valid memory */
+    if ((PageFrameIndex <= MmHighestPhysicalPage) &&
+        (MmIsAddressValid(Pfn)) &&
+        (Pfn->u3.e1.PageLocation == ActiveAndValid))
+    {
+        /* Setup the PFN entry */
+        Pfn->u1.WsIndex = 0;
+        Pfn->u2.ShareCount++;
+        Pfn->PteAddress = PointerPte;
+        Pfn->OriginalPte = *PointerPte;
+        Pfn->u3.e1.PageLocation = ActiveAndValid;
+        Pfn->u3.e1.CacheAttribute = MiNonCached;
+        Pfn->u3.e2.ReferenceCount = 1;
+        Pfn->u4.PteFrame = PFN_FROM_PTE(MiAddressToPte(PointerPte));
+    }
+
+    /* Increase the shared count of the PFN entry for the PDE */
+    PointerPde = MiAddressToPde(MiPteToAddress(PointerPte));
+    Pfn = MiGetPfnEntry(PFN_FROM_PTE(PointerPde));
+    Pfn->u2.ShareCount++;
+}
+
+VOID
+NTAPI
+MiBuildPfnDatabaseFromPageTables(VOID)
+{
+    PVOID Address = NULL;
+    PFN_NUMBER PageFrameIndex;
+    PMMPDE PointerPde;
+    PMMPTE PointerPte;
+    ULONG k, l;
+    PMMPFN Pfn;
+#if (_MI_PAGING_LEVELS >= 3)
+    PMMPDE PointerPpe;
+    ULONG j;
+#endif
+#if (_MI_PAGING_LEVELS == 4)
+    PMMPDE PointerPxe;
+    ULONG i;
+#endif
+
+    /* Manual setup of the top level page directory */
+#if (_MI_PAGING_LEVELS == 4)
+    PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PXE_BASE));
+#elif (_MI_PAGING_LEVELS == 3)
+    PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PPE_BASE));
+#else
+    PageFrameIndex = PFN_FROM_PTE(MiAddressToPte(PDE_BASE));
+#endif
+    Pfn = MiGetPfnEntry(PageFrameIndex);
+    ASSERT(Pfn->u3.e1.PageLocation == ActiveAndValid);
+    Pfn->u1.WsIndex = 0;
+    Pfn->u2.ShareCount = 1;
+    Pfn->PteAddress = NULL;
+    Pfn->u3.e1.CacheAttribute = MiNonCached;
+    Pfn->u3.e2.ReferenceCount = 1;
+    Pfn->u4.PteFrame = 0;
+
+#if (_MI_PAGING_LEVELS == 4)
+    /* Loop all PXEs in the PML4 */
+    PointerPxe = MiAddressToPxe(Address);
+    for (i = 0; i < PXE_PER_PAGE; i++, PointerPxe++)
+    {
+        /* Skip invalid PXEs */
+        if (!PointerPxe->u.Hard.Valid) continue;
+
+        /* Handle the PFN */
+        PageFrameIndex = PFN_FROM_PXE(PointerPxe);
+        MiSetupPfnForPageTable(PageFrameIndex, PointerPxe);
+
+        /* Get starting VA for this PXE */
+        Address = MiPxeToAddress(PointerPxe);
+#endif
+#if (_MI_PAGING_LEVELS >= 3)
+        /* Loop all PPEs in this PDP */
+        PointerPpe = MiAddressToPpe(Address);
+        for (j = 0; j < PPE_PER_PAGE; j++, PointerPpe++)
+        {
+            /* Skip invalid PPEs */
+            if (!PointerPpe->u.Hard.Valid) continue;
+
+            /* Handle the PFN */
+            PageFrameIndex = PFN_FROM_PPE(PointerPpe);
+            MiSetupPfnForPageTable(PageFrameIndex, PointerPpe);
+
+            /* Get starting VA for this PPE */
+            Address = MiPpeToAddress(PointerPpe);
+#endif
+            /* Loop all PDEs in this PD */
+            PointerPde = MiAddressToPde(Address);
+            for (k = 0; k < PDE_PER_PAGE; k++, PointerPde++)
+            {
+                /* Skip invalid PDEs */
+                if (!PointerPde->u.Hard.Valid) continue;
+
+                /* Handle the PFN */
+                PageFrameIndex = PFN_FROM_PDE(PointerPde);
+                MiSetupPfnForPageTable(PageFrameIndex, PointerPde);
+
+                /* Get starting VA for this PDE */
+                Address = MiPdeToAddress(PointerPde);
+
+                /* Loop all PTEs in this PT */
+                PointerPte = MiAddressToPte(Address);
+                for (l = 0; l < PTE_PER_PAGE; l++, PointerPte++)
+                {
+                    /* Skip invalid PTEs */
+                    if (!PointerPte->u.Hard.Valid) continue;
+
+                    /* Handle the PFN */
+                    PageFrameIndex = PFN_FROM_PTE(PointerPte);
+                    MiSetupPfnForPageTable(PageFrameIndex, PointerPte);
+                }
+            }
+#if (_MI_PAGING_LEVELS >= 3)
+        }
+#endif
+#if (_MI_PAGING_LEVELS == 4)
+    }
+#endif
+}
+
+VOID
+NTAPI
+INIT_FUNCTION
+MiAddDescriptorToDatabase(
+    PFN_NUMBER BasePage,
+    PFN_NUMBER PageCount,
+    TYPE_OF_MEMORY MemoryType)
+{
+    PMMPFN Pfn;
+
+    ASSERT(!MiIsMemoryTypeInvisible(MemoryType));
+
+    /* Check if the memory is free */
+    if (MiIsMemoryTypeFree(MemoryType))
+    {
+        /* Get the last pfn of this descriptor. Note we loop backwards */
+        Pfn = &MmPfnDatabase[BasePage + PageCount - 1];
+
+        /* Loop all pages */
+        while (PageCount--)
+        {
+            /* Add it to the free list */
+            Pfn->u3.e1.CacheAttribute = MiNonCached;
+            MiInsertPageInFreeList(BasePage + PageCount);
+
+            /* Go to the previous page */
+            Pfn--;
+        }
+    }
+    else if (MemoryType == LoaderXIPRom)
+    {
+        Pfn = &MmPfnDatabase[BasePage];
+        while (PageCount--)
+        {
+            /* Make it a pseudo-I/O ROM mapping */
+            Pfn->PteAddress = 0;
+            Pfn->u1.Flink = 0;
+            Pfn->u2.ShareCount = 0;
+            Pfn->u3.e1.PageLocation = 0;
+            Pfn->u3.e1.CacheAttribute = MiNonCached;
+            Pfn->u3.e1.Rom = 1;
+            Pfn->u3.e1.PrototypePte = 1;
+            Pfn->u3.e2.ReferenceCount = 0;
+            Pfn->u4.InPageError = 0;
+            Pfn->u4.PteFrame = 0;
+
+            /* Advance one */
+            Pfn++;
+        }
+    }
+    else if (MemoryType == LoaderBad)
+    {
+        // FIXME: later
+        ASSERT(FALSE);
+    }
+    else
+    {
+        /* For now skip it */
+        DbgPrint("Skipping BasePage=0x%lx, PageCount=0x%lx, MemoryType=%lx\n",
+                 BasePage, PageCount, MemoryType);
+        Pfn = &MmPfnDatabase[BasePage];
+        while (PageCount--)
+        {
+            /* Make an active PFN */
+            Pfn->u3.e1.PageLocation = ActiveAndValid;
+
+            /* Advance one */
+            Pfn++;
+        }
+    }
+}
+
+VOID
+NTAPI
+INIT_FUNCTION
+MiBuildPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
+{
+    PLIST_ENTRY ListEntry;
+    PMEMORY_ALLOCATION_DESCRIPTOR Descriptor;
+    PFN_NUMBER BasePage, PageCount;
+
+    /* Map the PDEs and PPEs for the pfn database (ignore holes) */
+#if (_MI_PAGING_LEVELS >= 3)
+    MiMapPPEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1);
+#endif
+    MiMapPDEs(MmPfnDatabase, (PUCHAR)MmPfnDatabase + MxPfnAllocation - 1);
+
+    /* First initialize the color tables */
+    MiInitializeColorTables();
+
+    /* Loop the memory descriptors */
+    for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+         ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+         ListEntry = ListEntry->Flink)
+    {
+        /* Get the descriptor */
+        Descriptor = CONTAINING_RECORD(ListEntry,
+                                       MEMORY_ALLOCATION_DESCRIPTOR,
+                                       ListEntry);
+
+        /* Skip invisible memory */
+        if (MiIsMemoryTypeInvisible(Descriptor->MemoryType)) continue;
+
+        /* If this is the free descriptor, use the copy instead */
+        if (Descriptor == MxFreeDescriptor) Descriptor = &MxOldFreeDescriptor;
+
+        /* Get the range for this descriptor */
+        BasePage = Descriptor->BasePage;
+        PageCount = Descriptor->PageCount;
+
+        /* Map the pages for the database */
+        MiMapPTEs(&MmPfnDatabase[BasePage],
+                  (PUCHAR)(&MmPfnDatabase[BasePage + PageCount]) - 1);
+
+        /* If this was the free descriptor, skip the next step */
+        if (Descriptor == &MxOldFreeDescriptor) continue;
+
+        /* Add this descriptor to the database */
+        MiAddDescriptorToDatabase(BasePage, PageCount, Descriptor->MemoryType);
+    }
+
+    /* At this point the whole pfn database is mapped. We are about to add the
+       pages from the free descriptor to the database, so from now on we cannot
+       use it anymore. */
+
+    /* Now add the free descriptor */
+    BasePage = MxFreeDescriptor->BasePage;
+    PageCount = MxFreeDescriptor->PageCount;
+    MiAddDescriptorToDatabase(BasePage, PageCount, LoaderFree);
+
+    /* And finally the memory we used */
+    BasePage = MxOldFreeDescriptor.BasePage;
+    PageCount = MxFreeDescriptor->BasePage - BasePage;
+    MiAddDescriptorToDatabase(BasePage, PageCount, LoaderMemoryData);
+
+    // Reset the descriptor back so we can create the correct memory blocks
+    *MxFreeDescriptor = MxOldFreeDescriptor;
+}
+
 NTSTATUS
 NTAPI
 INIT_FUNCTION
 MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
 {
-
+    KIRQL OldIrql;
+
+    ASSERT(MxPfnAllocation != 0);
+
+    /* Set some hardcoded addresses */
     MmHyperSpaceEnd = (PVOID)HYPER_SPACE_END;
+    MmNonPagedSystemStart = (PVOID)MM_SYSTEM_SPACE_START;
+    MmPfnDatabase = (PVOID)MI_PFN_DATABASE;
+    MmWorkingSetList = (PVOID)MI_WORKING_SET_LIST;
+
+
+//    PrototypePte.u.Proto.Valid = 1
+//    PrototypePte.u.ReadOnly
+//    PrototypePte.u.Prototype
+//    PrototypePte.u.Protection = MM_READWRITE;
+//    PrototypePte.u.ProtoAddress
+    PrototypePte.u.Soft.PageFileHigh = MI_PTE_LOOKUP_NEEDED;
+
 
     MiInitializePageTable();
 
@@ -403,5 +686,33 @@
 
     MiBuildSystemPteSpace();
 
+    /* Need to be at DISPATCH_LEVEL for MiInsertPageInFreeList */
+    KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
+
+    /* Map the PFN database pages */
+    MiBuildPfnDatabase(LoaderBlock);
+
+    /* Now process the page tables */
+    MiBuildPfnDatabaseFromPageTables();
+
+    MiPfnsInitialized = TRUE;
+
+    KeLowerIrql(OldIrql);
+
+    /* Initialize the balancer */
+    MmInitializeBalancer((ULONG)MmAvailablePages, 0);
+
+    /* Make sure we have everything we need */
+    ASSERT(MmPfnDatabase);
+    ASSERT(MmNonPagedSystemStart);
+    ASSERT(MmNonPagedPoolStart);
+    ASSERT(MmSizeOfNonPagedPoolInBytes);
+    ASSERT(MmMaximumNonPagedPoolInBytes);
+    ASSERT(MmNonPagedPoolExpansionStart);
+    ASSERT(MmHyperSpaceEnd);
+    ASSERT(MmNumberOfSystemPtes);
+    ASSERT(MiAddressToPde(MmNonPagedPoolStart)->u.Hard.Valid);
+    ASSERT(MiAddressToPte(MmNonPagedPoolStart)->u.Hard.Valid);
+
     return STATUS_SUCCESS;
 }


Reply via email to