mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 18:15:11 +00:00
[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:
parent
adffed162f
commit
0fcb7d138d
2 changed files with 395 additions and 63 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue