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/a... ============================================================================== --- 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?re... ============================================================================== --- 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; }