[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

svn path=/trunk/; revision=55403
This commit is contained in:
Timo Kreuzer 2012-02-04 10:40:27 +00:00
parent adffed162f
commit 0fcb7d138d
2 changed files with 395 additions and 63 deletions

View file

@ -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
@ -75,6 +84,13 @@
#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)
#define MM_EMPTY_LIST ((ULONG_PTR)-1)
@ -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

View file

@ -32,13 +32,12 @@ MMPTE DemandZeroPte = {{MM_READWRITE << MM_PTE_SOFTWARE_PROTECTION_BITS}};
/* 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 @@ MiInitializeSessionSpaceLayout()
/* 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 @@ MiMapPPEs(
{
/* 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 @@ MiMapPDEs(
{
/* 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 @@ MiMapPTEs(
{
/* 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 @@ MiInitializePageTable()
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 @@ MiInitializePageTable()
}
}
/* 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 @@ MiInitializePageTable()
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 @@ MiBuildNonPagedPool(VOID)
MmMaximumNonPagedPoolInBytes = MI_MAX_NONPAGED_POOL_SIZE;
}
/* Put non paged pool to the end of the region */
MmNonPagedPoolStart = (PCHAR)MmNonPagedPoolEnd - MmMaximumNonPagedPoolInBytes;
/* Convert nonpaged pool size from bytes to pages */
MmMaximumNonPagedPoolInPages = MmMaximumNonPagedPoolInBytes >> PAGE_SHIFT;
/* 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));
/* 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 @@ MiBuildSystemPteSpace()
/* 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;
/* Put system PTEs at the start of the system VA space */
MiSystemPteSpaceStart = MmNonPagedSystemStart;
MiSystemPteSpaceEnd = (PUCHAR)MiSystemPteSpaceStart + MiNonPagedSystemSize;
/* Reduce the amount of system PTEs to reach this point */
MmNumberOfSystemPtes = (ULONG)(((ULONG64)MmPfnDatabase -
(ULONG64)MmNonPagedSystemStart) >>
PAGE_SHIFT);
MmNumberOfSystemPtes--;
ASSERT(MmNumberOfSystemPtes > 1000);
}
/* Map the PPEs and PDEs for the system PTEs */
MiMapPPEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
MiMapPDEs(MiSystemPteSpaceStart, MiSystemPteSpaceEnd);
/* 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);
/* 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 @@ MiBuildSystemPteSpace()
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 @@ MiInitMachineDependent(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
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;
}