Author: tkreuzer
Date: Sat Jul 31 02:47:50 2010
New Revision: 48374
URL:
http://svn.reactos.org/svn/reactos?rev=48374&view=rev
Log:
[NTOS]
- Completely rework MiBuildPfnDatabaseFromPages to be portable and support PAE and 64 bit
as well. The pfn setting code has been factored out and is used for every level of page
tables. MiIsRegularMemory is completely removed, it's a waste of time to loop all MADs
for each and every valid PTE. The PFNs that are used for the page tables themselves must
be memory tracked by the PFN database anyway, the actual mapped pages might not be, but a
check if the page index is below MmHighestPhysicalPage and the PFN entry is in mapped
memory is enough. This way we might set PFN entries that are not actually tracked, but
that doesn't hurt. Also don't check for some arbitrary value when handling the
pfns, no reason to exclude some part of the page table from this procedure.
- Remove an unneccessary Update of the ListEntry pointer in MiMapPfnDatabase
Modified:
branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/mm.h
branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/i386/mm.h
branches/ros-amd64-bringup/reactos/ntoskrnl/mm/ARM3/mminit.c
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/mm.h
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1]
(original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/amd64/mm.h [iso-8859-1]
Sat Jul 31 02:47:50 2010
@@ -11,6 +11,7 @@
#define PAE_PAGE_MASK(x) ((x)&(~0xfffLL))
/* Memory layout base addresses */
+#define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0xFFFF080000000000ULL
#define HYPER_SPACE 0xFFFFF70000000000ULL
#define HYPER_SPACE_END 0xFFFFF77FFFFFFFFFULL
#define MI_SESSION_SPACE_MINIMUM (PVOID)0xFFFFF90000000000ULL
@@ -24,7 +25,6 @@
#define MI_DEBUG_MAPPING (PVOID)0xFFFFFFFF80000000ULL // FIXME
#define MI_HIGHEST_SYSTEM_ADDRESS (PVOID)0xFFFFFFFFFFFFFFFFULL
#define MI_SYSTEM_CACHE_WS_START (PVOID)0xFFFFF78000001000ULL // CHECKME
-
#define MI_LOWEST_VAD_ADDRESS (PVOID)0x000000007FF00000ULL
#define MI_SYSTEM_PTE_BASE (PVOID)MiAddressToPte(KSEG0_BASE)
@@ -123,13 +123,34 @@
/* Convert a PTE into a corresponding address */
PVOID
FORCEINLINE
-MiPteToAddress(PMMPTE Pte)
-{
- /* Use signed math */
- LONG64 Temp = (LONG64)Pte;
- Temp <<= 25;
- Temp >>= 16;
- return (PVOID)Temp;
+MiPteToAddress(PMMPTE PointerPte)
+{
+ /* Use signed math */
+ return (PVOID)(((LONG64)PointerPte << 25) >> 16);
+}
+
+PVOID
+FORCEINLINE
+MiPdeToAddress(PMMPTE PointerPde)
+{
+ /* Use signed math */
+ return (PVOID)(((LONG64)PointerPde << 34) >> 16);
+}
+
+PVOID
+FORCEINLINE
+MiPpeToAddress(PMMPTE PointerPpe)
+{
+ /* Use signed math */
+ return (PVOID)(((LONG64)PointerPpe << 43) >> 16);
+}
+
+PVOID
+FORCEINLINE
+MiPxeToAddress(PMMPTE PointerPxe)
+{
+ /* Use signed math */
+ return (PVOID)(((LONG64)PointerPxe << 52) >> 16);
}
BOOLEAN
@@ -172,6 +193,9 @@
/* Easy accessing PFN in PTE */
#define PFN_FROM_PTE(v) ((v)->u.Hard.PageFrameNumber)
+#define PFN_FROM_PDE(v) ((v)->u.Hard.PageFrameNumber)
+#define PFN_FROM_PPE(v) ((v)->u.Hard.PageFrameNumber)
+#define PFN_FROM_PXE(v) ((v)->u.Hard.PageFrameNumber)
// FIXME, only copied from x86
#define MI_MAKE_LOCAL_PAGE(x) ((x)->u.Hard.Global = 0)
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/i386/mm.h
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/i386/mm.h [iso-8859-1]
(original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/include/internal/i386/mm.h [iso-8859-1]
Sat Jul 31 02:47:50 2010
@@ -20,14 +20,18 @@
#define PAGETABLE_MAP (0xc0000000)
#define PAGEDIRECTORY_MAP (0xc0000000 + (PAGETABLE_MAP / (1024)))
+#define MI_DEFAULT_SYSTEM_RANGE_START (PVOID)0x80000000
+
/* FIXME: These are different for PAE */
#define PTE_BASE 0xC0000000
#define PDE_BASE 0xC0300000
#define PDE_TOP 0xC0300FFF
#define PTE_TOP 0xC03FFFFF
-#define PTE_PER_PAGE 1024
#define HYPER_SPACE 0xC0400000
#define HYPER_SPACE_END 0xC07FFFFF
+
+#define PDE_PER_PAGE 1024
+#define PTE_PER_PAGE 1024
/* Converting address to a corresponding PDE or PTE entry */
#define MiAddressToPde(x) \
@@ -41,6 +45,7 @@
// Convert a PTE into a corresponding address
//
#define MiPteToAddress(PTE) ((PVOID)((ULONG)(PTE) << 10))
+#define MiPdeToAddress(PDE) ((PVOID)((ULONG)(PDE) << 20))
#define MiIsPdeForAddressValid(Pde) (MiAddressToPde(Address)->u.Hard.Valid)
#define ADDR_TO_PAGE_TABLE(v) (((ULONG)(v)) / (1024 * PAGE_SIZE))
@@ -51,6 +56,7 @@
/* Easy accessing PFN in PTE */
#define PFN_FROM_PTE(v) ((v)->u.Hard.PageFrameNumber)
+#define PFN_FROM_PDE(v) ((v)->u.Hard.PageFrameNumber)
#define MI_MAKE_LOCAL_PAGE(x) ((x)->u.Hard.Global = 0)
#define MI_MAKE_DIRTY_PAGE(x) ((x)->u.Hard.Dirty = 1)
Modified: branches/ros-amd64-bringup/reactos/ntoskrnl/mm/ARM3/mminit.c
URL:
http://svn.reactos.org/svn/reactos/branches/ros-amd64-bringup/reactos/ntosk…
==============================================================================
--- branches/ros-amd64-bringup/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] (original)
+++ branches/ros-amd64-bringup/reactos/ntoskrnl/mm/ARM3/mminit.c [iso-8859-1] Sat Jul 31
02:47:50 2010
@@ -12,7 +12,7 @@
#define NDEBUG
#include <debug.h>
-#line 15 "ARM³::INIT"
+#line 16 "mminit.c"
#define MODULE_INVOLVED_IN_ARM3
#include "miarm.h"
@@ -607,70 +607,12 @@
}
}
-BOOLEAN
-NTAPI
-MiIsRegularMemory(IN PLOADER_PARAMETER_BLOCK LoaderBlock,
- IN PFN_NUMBER Pfn)
-{
- PLIST_ENTRY NextEntry;
- PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
-
- /* Loop the memory descriptors */
- NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
- while (NextEntry != &LoaderBlock->MemoryDescriptorListHead)
- {
- /* Get the memory descriptor */
- MdBlock = CONTAINING_RECORD(NextEntry,
- MEMORY_ALLOCATION_DESCRIPTOR,
- ListEntry);
-
- /* Check if this PFN could be part of the block */
- if (Pfn >= (MdBlock->BasePage))
- {
- /* Check if it really is part of the block */
- if (Pfn < (MdBlock->BasePage + MdBlock->PageCount))
- {
- /* Check if the block is actually memory we don't map */
- if ((MdBlock->MemoryType == LoaderFirmwarePermanent) ||
- (MdBlock->MemoryType == LoaderBBTMemory) ||
- (MdBlock->MemoryType == LoaderSpecialMemory))
- {
- /* We don't need PFN database entries for this memory */
- break;
- }
-
- /* This is memory we want to map */
- return TRUE;
- }
- }
- else
- {
- /* Blocks are ordered, so if it's not here, it doesn't exist */
- break;
- }
-
- /* Get to the next descriptor */
- NextEntry = MdBlock->ListEntry.Flink;
- }
-
- /* Check if this PFN is actually from our free memory descriptor */
- if ((Pfn >= MxOldFreeDescriptor.BasePage) &&
- (Pfn < MxOldFreeDescriptor.BasePage + MxOldFreeDescriptor.PageCount))
- {
- /* We use these pages for initial mappings, so we do want to count them */
- return TRUE;
- }
-
- /* Otherwise this isn't memory that we describe or care about */
- return FALSE;
-}
-
VOID
NTAPI
MiMapPfnDatabase(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
ULONG BasePage, PageCount, PageFrameIndex;
- PLIST_ENTRY NextEntry;
+ PLIST_ENTRY ListEntry;
PMEMORY_ALLOCATION_DESCRIPTOR MdBlock;
PMMPTE PointerPte, LastPte;
MMPTE TempPte = ValidKernelPte;
@@ -681,12 +623,12 @@
OldIrql = KeAcquireQueuedSpinLock(LockQueuePfnLock);
/* Loop the memory descriptors */
- for (NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
- NextEntry != &LoaderBlock->MemoryDescriptorListHead;
- NextEntry = MdBlock->ListEntry.Flink)
+ for (ListEntry = LoaderBlock->MemoryDescriptorListHead.Flink;
+ ListEntry != &LoaderBlock->MemoryDescriptorListHead;
+ ListEntry = ListEntry->Flink)
{
/* Get the descriptor */
- MdBlock = CONTAINING_RECORD(NextEntry,
+ MdBlock = CONTAINING_RECORD(ListEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
@@ -788,9 +730,6 @@
Pfn1++;
}
}
-
- /* Do the next address range */
- NextEntry = MdBlock->ListEntry.Flink;
}
/* Now handle the remaininng pages from the free descriptor */
@@ -813,104 +752,121 @@
KeReleaseQueuedSpinLock(LockQueuePfnLock, OldIrql);
}
+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)) &&
+ (MmIsAddressValid(Pfn + 1)))
+ {
+ /* 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));
+ ASSERT(Pfn != NULL);
+ Pfn->u2.ShareCount++;
+}
+
VOID
NTAPI
MiBuildPfnDatabaseFromPages(IN PLOADER_PARAMETER_BLOCK LoaderBlock)
{
+ PVOID Address = NULL;
+ PFN_NUMBER PageFrameIndex;
PMMPDE PointerPde;
PMMPTE PointerPte;
- ULONG i, Count, j;
- PFN_NUMBER PageFrameIndex, StartupPdIndex, PtePageIndex;
- PMMPFN Pfn1, Pfn2;
- ULONG_PTR BaseAddress = 0;
-
- /* PFN of the startup page directory */
- StartupPdIndex = PFN_FROM_PTE(MiAddressToPde(PDE_BASE));
-
- /* Start with the first PDE and scan them all */
- PointerPde = MiAddressToPde(NULL);
- Count = PD_COUNT * PDE_COUNT;
- for (i = 0; i < Count; i++)
- {
- /* Check for valid PDE */
- if (PointerPde->u.Hard.Valid == 1)
- {
- /* Get the PFN from it */
- PageFrameIndex = PFN_FROM_PTE(PointerPde);
-
- /* Do we want a PFN entry for this page? */
- if (MiIsRegularMemory(LoaderBlock, PageFrameIndex))
+ ULONG k, l;
+#if (_MI_PAGING_LEVELS >= 3)
+ PMMPDE PointerPpe;
+ ULONG j;
+#endif
+#if (_MI_PAGING_LEVELS == 4)
+ PMMPDE PointerPxe;
+ ULONG i;
+#endif
+
+#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++)
{
- /* Yes we do, set it up */
- Pfn1 = MiGetPfnEntry(PageFrameIndex);
- Pfn1->u4.PteFrame = StartupPdIndex;
- Pfn1->PteAddress = PointerPde;
- Pfn1->u2.ShareCount++;
- Pfn1->u3.e2.ReferenceCount = 1;
- Pfn1->u3.e1.PageLocation = ActiveAndValid;
- Pfn1->u3.e1.CacheAttribute = MiNonCached;
+ /* 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);
+ }
}
- else
- {
- /* No PFN entry */
- Pfn1 = NULL;
- }
-
- /* Now get the PTE and scan the pages */
- PointerPte = MiAddressToPte(BaseAddress);
- for (j = 0; j < PTE_COUNT; j++)
- {
- /* Check for a valid PTE */
- if (PointerPte->u.Hard.Valid == 1)
- {
- /* Increase the shared count of the PFN entry for the PDE */
- ASSERT(Pfn1 != NULL);
- Pfn1->u2.ShareCount++;
-
- /* Now check if the PTE is valid memory too */
- PtePageIndex = PFN_FROM_PTE(PointerPte);
- if (MiIsRegularMemory(LoaderBlock, PtePageIndex))
- {
- /*
- * Only add pages above the end of system code or pages
- * that are part of nonpaged pool
- */
- if ((BaseAddress >= 0xA0000000) ||
- ((BaseAddress >= (ULONG_PTR)MmNonPagedPoolStart)
&&
- (BaseAddress < (ULONG_PTR)MmNonPagedPoolStart +
- MmSizeOfNonPagedPoolInBytes)))
- {
- /* Get the PFN entry and make sure it too is valid */
- Pfn2 = MiGetPfnEntry(PtePageIndex);
- if ((MmIsAddressValid(Pfn2)) &&
- (MmIsAddressValid(Pfn2 + 1)))
- {
- /* Setup the PFN entry */
- Pfn2->u4.PteFrame = PageFrameIndex;
- Pfn2->PteAddress = PointerPte;
- Pfn2->u2.ShareCount++;
- Pfn2->u3.e2.ReferenceCount = 1;
- Pfn2->u3.e1.PageLocation = ActiveAndValid;
- Pfn2->u3.e1.CacheAttribute = MiNonCached;
- }
- }
- }
- }
-
- /* Next PTE */
- PointerPte++;
- BaseAddress += PAGE_SIZE;
- }
- }
- else
- {
- /* Next PDE mapped address */
- BaseAddress += PDE_MAPPED_VA;
- }
-
- /* Next PTE */
- PointerPde++;
- }
+#if (_MI_PAGING_LEVELS >= 3)
+ }
+#endif
+#if (_MI_PAGING_LEVELS == 4)
+ }
+#endif
}
VOID