Author: ros-arm-bringup
Date: Fri Feb 15 02:39:31 2008
New Revision: 32368
URL:
http://svn.reactos.org/svn/reactos?rev=32368&view=rev
Log:
Review and fix the buildingg and mapping of boot-time kernel address space.
The selection of the non-paged pool base address was broken (ion's comment was
correct, but his implementation was not) -- NP pool now follows the PFN, or end of FreeLDR
mapping area.
There was no reason to put paged pool at a 4MB boundary away from NP pool -- it now
follows it immediately.
Got rid of multiple values which were calculated 3, even 4 times in a row, or even values
that were calculated but never used (such as kernel_len).
Got rid of the shuffling back and forth of kernel and virtual start/end addresses. A
global now keeps track of this, and MmInit1 is now solely responsible for assigning
addresses to each kernel region.
Added new debug routine to show the kernel regions mapped -- enabled by default for now to
visually detect any problems (once ReactOS's drivers go over 6MB, there may be).
Modified:
trunk/reactos/ntoskrnl/include/internal/mm.h
trunk/reactos/ntoskrnl/ke/i386/kiinit.c
trunk/reactos/ntoskrnl/mm/freelist.c
trunk/reactos/ntoskrnl/mm/mminit.c
Modified: trunk/reactos/ntoskrnl/include/internal/mm.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/mm.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/mm.h Fri Feb 15 02:39:31 2008
@@ -17,6 +17,11 @@
extern PVOID MmPagedPoolBase;
extern ULONG MmPagedPoolSize;
+
+extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
+extern ULONG MmHighestPhysicalPage;
+extern PVOID MmPfnDatabase;
+extern ULONG_PTR MiKSeg0Start, MiKSeg0End;
struct _KTRAP_FRAME;
struct _EPROCESS;
@@ -260,6 +265,29 @@
ULONG PagingRequestsInLastFiveMinutes;
ULONG PagingRequestsInLastFifteenMinutes;
} MM_STATS;
+
+typedef struct _PHYSICAL_PAGE
+{
+ union
+ {
+ struct
+ {
+ ULONG Type: 2;
+ ULONG Consumer: 3;
+ ULONG Zero: 1;
+ }
+ Flags;
+ ULONG AllFlags;
+ };
+
+ LIST_ENTRY ListEntry;
+ ULONG ReferenceCount;
+ SWAPENTRY SavedSwapEntry;
+ ULONG LockCount;
+ ULONG MapCount;
+ struct _MM_RMAP_ENTRY* RmapListHead;
+}
+PHYSICAL_PAGE, *PPHYSICAL_PAGE;
extern MM_STATS MmStats;
@@ -532,12 +560,8 @@
VOID
NTAPI
MmInit1(
- ULONG_PTR FirstKernelPhysAddress,
- ULONG_PTR LastKernelPhysAddress,
- ULONG_PTR LastKernelAddress,
PADDRESS_RANGE BIOSMemoryMap,
- ULONG AddressRangeCount,
- ULONG MaxMemInMeg
+ ULONG AddressRangeCount
);
BOOLEAN
@@ -941,13 +965,9 @@
NTAPI
MmGetLockCountPage(PFN_TYPE Page);
-PVOID
+VOID
NTAPI
MmInitializePageList(
- ULONG_PTR FirstPhysKernelAddress,
- ULONG_PTR LastPhysKernelAddress,
- ULONG MemorySizeInPages,
- ULONG_PTR LastKernelBase,
PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount
);
Modified: trunk/reactos/ntoskrnl/ke/i386/kiinit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ke/i386/kiinit.c?…
==============================================================================
--- trunk/reactos/ntoskrnl/ke/i386/kiinit.c (original)
+++ trunk/reactos/ntoskrnl/ke/i386/kiinit.c Fri Feb 15 02:39:31 2008
@@ -537,12 +537,7 @@
((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
/* Initialize Kernel Memory Address Space */
- MmInit1(MmFreeLdrFirstKrnlPhysAddr,
- MmFreeLdrLastKrnlPhysAddr,
- MmFreeLdrLastKernelAddress,
- KeMemoryMap,
- KeMemoryMapRangeCount,
- 4096);
+ MmInit1(KeMemoryMap, KeMemoryMapRangeCount);
/* Set basic CPU Features that user mode can read */
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =
Modified: trunk/reactos/ntoskrnl/mm/freelist.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/freelist.c?rev…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/freelist.c (original)
+++ trunk/reactos/ntoskrnl/mm/freelist.c Fri Feb 15 02:39:31 2008
@@ -25,29 +25,6 @@
#define MM_PHYSICAL_PAGE_FREE (0x1)
#define MM_PHYSICAL_PAGE_USED (0x2)
#define MM_PHYSICAL_PAGE_BIOS (0x3)
-
-typedef struct _PHYSICAL_PAGE
-{
- union
- {
- struct
- {
- ULONG Type: 2;
- ULONG Consumer: 3;
- ULONG Zero: 1;
- }
- Flags;
- ULONG AllFlags;
- };
-
- LIST_ENTRY ListEntry;
- ULONG ReferenceCount;
- SWAPENTRY SavedSwapEntry;
- ULONG LockCount;
- ULONG MapCount;
- struct _MM_RMAP_ENTRY* RmapListHead;
-}
-PHYSICAL_PAGE, *PPHYSICAL_PAGE;
#define ASSERT_PFN(x) ASSERT((x)->Flags.Type != 0)
@@ -302,15 +279,9 @@
return TRUE;
}
-
-PVOID
-INIT_FUNCTION
-NTAPI
-MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
- IN ULONG_PTR LastPhysKernelAddress,
- IN ULONG HighestPage,
- IN ULONG_PTR LastKernelAddress,
- IN PADDRESS_RANGE BIOSMemoryMap,
+VOID
+NTAPI
+MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
IN ULONG AddressRangeCount)
{
ULONG i;
@@ -318,11 +289,11 @@
NTSTATUS Status;
PFN_TYPE Pfn = 0;
PHYSICAL_PAGE UsedPage;
- extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
ULONG PdeStart = PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart;
ULONG PdePageStart, PdePageEnd;
ULONG VideoPageStart, VideoPageEnd;
ULONG KernelPageStart, KernelPageEnd;
+ ULONG_PTR KernelStart, KernelEnd;
/* Initialize the page lists */
KeInitializeSpinLock(&PageListLock);
@@ -331,13 +302,9 @@
InitializeListHead(&FreeZeroedPageListHead);
/* Set the size and start of the PFN Database */
- MmPageArraySize = HighestPage;
- MmPageArray = (PHYSICAL_PAGE *)LastKernelAddress;
+ MmPageArray = (PHYSICAL_PAGE *)MmPfnDatabase;
+ MmPageArraySize = MmHighestPhysicalPage;
Reserved = PAGE_ROUND_UP((MmPageArraySize * sizeof(PHYSICAL_PAGE))) / PAGE_SIZE;
-
- /* Update the last kernel address pointers */
- LastKernelAddress = ((ULONG_PTR)LastKernelAddress + (Reserved * PAGE_SIZE));
- LastPhysKernelAddress = (ULONG_PTR)LastPhysKernelAddress + (Reserved * PAGE_SIZE);
/* Loop every page required to hold the PFN database */
for (i = 0; i < Reserved; i++)
@@ -380,12 +347,14 @@
UsedPage.MapCount = 1;
/* We'll be applying a bunch of hacks -- precompute some static values */
+ KernelStart = MiKSeg0Start - KSEG0_BASE;
+ KernelEnd = MiKSeg0End - KSEG0_BASE;
PdePageStart = PdeStart / PAGE_SIZE;
PdePageEnd = MmFreeLdrPageDirectoryEnd / PAGE_SIZE;
VideoPageStart = 0xA0000 / PAGE_SIZE;
VideoPageEnd = 0x100000 / PAGE_SIZE;
- KernelPageStart = FirstPhysKernelAddress / PAGE_SIZE;
- KernelPageEnd = LastPhysKernelAddress / PAGE_SIZE;
+ KernelPageStart = KernelStart / PAGE_SIZE;
+ KernelPageEnd = KernelEnd / PAGE_SIZE;
/* Loop every page on the system */
for (i = 0; i <= MmPageArraySize; i++)
@@ -470,7 +439,6 @@
MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages +
MmStats.NrUserPages;
MmInitializeBalancer(MmStats.NrFreePages, MmStats.NrSystemPages);
- return((PVOID)LastKernelAddress);
}
VOID
Modified: trunk/reactos/ntoskrnl/mm/mminit.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/mm/mminit.c?rev=3…
==============================================================================
--- trunk/reactos/ntoskrnl/mm/mminit.c (original)
+++ trunk/reactos/ntoskrnl/mm/mminit.c Fri Feb 15 02:39:31 2008
@@ -49,7 +49,10 @@
PHYSICAL_ADDRESS MmSharedDataPagePhysicalAddress;
PVOID MiNonPagedPoolStart;
ULONG MiNonPagedPoolLength;
+ULONG MmBootImageSize;
ULONG MmNumberOfPhysicalPages, MmHighestPhysicalPage, MmLowestPhysicalPage;
+ULONG_PTR MiKSeg0Start, MiKSeg0End;
+PVOID MmPfnDatabase;
PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
extern KMUTANT MmSystemLoadLock;
BOOLEAN MiDbgEnableMdDump =
@@ -71,8 +74,7 @@
VOID
INIT_FUNCTION
NTAPI
-MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
- ULONG KernelLength)
+MmInitVirtualMemory()
{
PVOID BaseAddress;
ULONG Length;
@@ -80,24 +82,9 @@
PHYSICAL_ADDRESS BoundaryAddressMultiple;
PMEMORY_AREA MArea;
- DPRINT("MmInitVirtualMemory(%x, %x)\n",LastKernelAddress, KernelLength);
-
BoundaryAddressMultiple.QuadPart = 0;
- LastKernelAddress = PAGE_ROUND_UP(LastKernelAddress);
MmInitMemoryAreas();
-
- /*
- * FreeLDR Marks 6MB "in use" at the start of the kernel base,
- * so start the non-paged pool at a boundary of 6MB from where
- * the last driver was loaded. This should be the end of the
- * FreeLDR-marked region.
- */
- MiNonPagedPoolStart = (PVOID)ROUND_UP((ULONG_PTR)LastKernelAddress + PAGE_SIZE,
0x600000);
- MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
-
- MmPagedPoolBase = (PVOID)ROUND_UP((ULONG_PTR)MiNonPagedPoolStart +
MiNonPagedPoolLength + PAGE_SIZE, 0x400000);
- MmPagedPoolSize = MM_PAGED_POOL_SIZE;
DPRINT("NonPagedPool %x - %x, PagedPool %x - %x\n", MiNonPagedPoolStart,
(ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength - 1,
MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize - 1);
@@ -263,6 +250,32 @@
VOID
NTAPI
+MiDbgKernelLayout(VOID)
+{
+ DPRINT1("%8s%12s\t\t%s\n", "Start", "End",
"Type");
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ KSEG0_BASE, MiKSeg0Start,
+ "Undefined region");
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ MiKSeg0Start, MmPfnDatabase,
+ "FreeLDR Kernel mapping region");
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ MmPfnDatabase, MiKSeg0End,
+ "PFN Database region");
+ if (MiKSeg0End != (ULONG_PTR)MiNonPagedPoolStart)
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ MiKSeg0End, MiNonPagedPoolStart,
+ "Remaining FreeLDR mapping");
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ MiNonPagedPoolStart, (ULONG_PTR)MiNonPagedPoolStart + MiNonPagedPoolLength,
+ "Non paged pool region");
+ DPRINT1("0x%p - 0x%p\t%s\n",
+ MmPagedPoolBase, (ULONG_PTR)MmPagedPoolBase + MmPagedPoolSize,
+ "Paged pool region");
+}
+
+VOID
+NTAPI
MiDbgDumpBiosMap(IN PADDRESS_RANGE BIOSMemoryMap,
IN ULONG AddressRangeCount)
{
@@ -306,7 +319,7 @@
PLIST_ENTRY NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR Md;
ULONG_PTR LastKrnlPhysAddr = 0;
-
+
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = NextEntry->Flink)
@@ -320,7 +333,7 @@
LastKrnlPhysAddr = Md->BasePage+Md->PageCount;
}
}
-
+
/* Convert to a physical address */
return LastKrnlPhysAddr << PAGE_SHIFT;
}
@@ -328,16 +341,11 @@
VOID
INIT_FUNCTION
NTAPI
-MmInit1(ULONG_PTR FirstKrnlPhysAddr,
- ULONG_PTR LastKrnlPhysAddr,
- ULONG_PTR LastKernelAddress,
- PADDRESS_RANGE BIOSMemoryMap,
- ULONG AddressRangeCount,
- ULONG MaxMem)
-{
- ULONG kernel_len;
+MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
+ IN ULONG AddressRangeCount)
+{
PLDR_DATA_TABLE_ENTRY LdrEntry;
-
+
/* Dump memory descriptors */
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
if (MiDbgEnableMdDump) MiDbgDumpBiosMap(BIOSMemoryMap, AddressRangeCount);
@@ -345,18 +353,9 @@
/* Set the page directory */
PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart =
(ULONG)MmGetPageDirectory();
- /* NTLDR Hacks */
- if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
-
- /* Get the first physical address */
- LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
- LDR_DATA_TABLE_ENTRY,
- InLoadOrderLinks);
- FirstKrnlPhysAddr = (ULONG_PTR)LdrEntry->DllBase - KSEG0_BASE;
-
- /* Get the last kernel address */
- LastKrnlPhysAddr = PAGE_ROUND_UP(MiGetLastKernelAddress());
- LastKernelAddress = LastKrnlPhysAddr | KSEG0_BASE;
+ /* Get the size of FreeLDR's image allocations */
+ MmBootImageSize = KeLoaderBlock->Extension->LoaderPagesSpanned;
+ MmBootImageSize *= PAGE_SIZE;
/* Set memory limits */
MmSystemRangeStart = (PVOID)KSEG0_BASE;
@@ -377,21 +376,55 @@
/* Initialize the kernel address space */
MmInitializeKernelAddressSpace();
MmInitGlobalKernelPageDirectory();
-
+
+ /* Get kernel address boundaries */
+ LdrEntry = CONTAINING_RECORD(KeLoaderBlock->LoadOrderListHead.Flink,
+ LDR_DATA_TABLE_ENTRY,
+ InLoadOrderLinks);
+ MiKSeg0Start = (ULONG_PTR)LdrEntry->DllBase | KSEG0_BASE;
+ MiKSeg0End = PAGE_ROUND_UP(MiGetLastKernelAddress() | KSEG0_BASE);
+
+ /* We'll put the PFN array right after the loaded modules */
+ MmPfnDatabase = (PVOID)MiKSeg0End;
+ MiKSeg0End += MmHighestPhysicalPage * sizeof(PHYSICAL_PAGE);
+ MiKSeg0End = PAGE_ROUND_UP(MiKSeg0End);
+
+ /*
+ * FreeLDR maps 6MB starting at the kernel base address, followed by the
+ * PFN database. If the PFN database doesn't go over the FreeLDR allocation
+ * then choose the end of the FreeLDR block. If it does go past the FreeLDR
+ * allocation, then choose the next PAGE_SIZE boundary.
+ */
+ if (MiKSeg0End < (MiKSeg0Start + 0x600000))
+ {
+ /* Use the first memory following FreeLDR's 6MB mapping */
+ MiNonPagedPoolStart = (PVOID)PAGE_ROUND_UP(MiKSeg0Start + 0x600000);
+ }
+ else
+ {
+ /* Use the next free available page */
+ MiNonPagedPoolStart = (PVOID)MiKSeg0End;
+ }
+
+ /* Length of non-paged pool */
+ MiNonPagedPoolLength = MM_NONPAGED_POOL_SIZE;
+
+ /* Put the paged pool after the non-paged pool */
+ MmPagedPoolBase = (PVOID)PAGE_ROUND_UP((ULONG_PTR)MiNonPagedPoolStart +
+ MiNonPagedPoolLength);
+ MmPagedPoolSize = MM_PAGED_POOL_SIZE;
+
+ /* Dump kernel memory layout */
+ MiDbgKernelLayout();
+
/* Initialize the page list */
- LastKernelAddress = (ULONG_PTR)MmInitializePageList(FirstKrnlPhysAddr,
- LastKrnlPhysAddr,
- MmHighestPhysicalPage,
-
PAGE_ROUND_UP(LastKernelAddress),
- BIOSMemoryMap,
- AddressRangeCount);
- kernel_len = LastKrnlPhysAddr - FirstKrnlPhysAddr;
+ MmInitializePageList(BIOSMemoryMap, AddressRangeCount);
/* Unmap low memory */
MmDeletePageTable(NULL, 0);
/* Intialize memory areas */
- MmInitVirtualMemory(LastKernelAddress, kernel_len);
+ MmInitVirtualMemory();
/* Initialize MDLs */
MmInitializeMdlImplementation();