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/…
==============================================================================
--- 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?r…
==============================================================================
--- 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;
}