mirror of
https://github.com/reactos/reactos.git
synced 2024-10-05 00:43:21 +00:00
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). svn path=/trunk/; revision=32368
This commit is contained in:
parent
6b9215e607
commit
131f74225c
|
@ -18,6 +18,11 @@ extern ULONG MmNumberOfPhysicalPages;
|
|||
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;
|
||||
struct _MM_RMAP_ENTRY;
|
||||
|
@ -261,6 +266,29 @@ typedef struct
|
|||
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;
|
||||
|
||||
typedef struct _MM_PAGEOP
|
||||
|
@ -532,12 +560,8 @@ MiShutdownMemoryManager(VOID);
|
|||
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 @@ ULONG
|
|||
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
|
||||
);
|
||||
|
|
|
@ -537,12 +537,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
|
|||
((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] =
|
||||
|
|
|
@ -26,29 +26,6 @@
|
|||
#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 @@ MiIsPfnRam(PADDRESS_RANGE BIOSMemoryMap,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
PVOID
|
||||
INIT_FUNCTION
|
||||
VOID
|
||||
NTAPI
|
||||
MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
|
||||
IN ULONG_PTR LastPhysKernelAddress,
|
||||
IN ULONG HighestPage,
|
||||
IN ULONG_PTR LastKernelAddress,
|
||||
IN PADDRESS_RANGE BIOSMemoryMap,
|
||||
MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
|
||||
IN ULONG AddressRangeCount)
|
||||
{
|
||||
ULONG i;
|
||||
|
@ -318,11 +289,11 @@ MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
|
|||
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 @@ MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
|
|||
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 @@ MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
|
|||
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 @@ MmInitializePageList(IN ULONG_PTR FirstPhysKernelAddress,
|
|||
|
||||
MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + MmStats.NrUserPages;
|
||||
MmInitializeBalancer(MmStats.NrFreePages, MmStats.NrSystemPages);
|
||||
return((PVOID)LastKernelAddress);
|
||||
}
|
||||
|
||||
VOID
|
||||
|
|
|
@ -49,7 +49,10 @@ MM_SYSTEMSIZE MmSystemSize = MmSmallSystem;
|
|||
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 @@ MiShutdownMemoryManager(VOID)
|
|||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
|
||||
ULONG KernelLength)
|
||||
MmInitVirtualMemory()
|
||||
{
|
||||
PVOID BaseAddress;
|
||||
ULONG Length;
|
||||
|
@ -80,25 +82,10 @@ MmInitVirtualMemory(ULONG_PTR LastKernelAddress,
|
|||
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);
|
||||
|
||||
|
@ -261,6 +248,32 @@ MiCountFreePagesInLoaderBlock(PLOADER_PARAMETER_BLOCK LoaderBlock)
|
|||
}
|
||||
}
|
||||
|
||||
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,
|
||||
|
@ -306,7 +319,7 @@ MiGetLastKernelAddress(VOID)
|
|||
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 @@ MiGetLastKernelAddress(VOID)
|
|||
LastKrnlPhysAddr = Md->BasePage+Md->PageCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Convert to a physical address */
|
||||
return LastKrnlPhysAddr << PAGE_SHIFT;
|
||||
}
|
||||
|
@ -328,16 +341,11 @@ MiGetLastKernelAddress(VOID)
|
|||
VOID
|
||||
INIT_FUNCTION
|
||||
NTAPI
|
||||
MmInit1(ULONG_PTR FirstKrnlPhysAddr,
|
||||
ULONG_PTR LastKrnlPhysAddr,
|
||||
ULONG_PTR LastKernelAddress,
|
||||
PADDRESS_RANGE BIOSMemoryMap,
|
||||
ULONG AddressRangeCount,
|
||||
ULONG MaxMem)
|
||||
MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
|
||||
IN ULONG AddressRangeCount)
|
||||
{
|
||||
ULONG kernel_len;
|
||||
PLDR_DATA_TABLE_ENTRY LdrEntry;
|
||||
|
||||
|
||||
/* Dump memory descriptors */
|
||||
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
|
||||
if (MiDbgEnableMdDump) MiDbgDumpBiosMap(BIOSMemoryMap, AddressRangeCount);
|
||||
|
@ -345,18 +353,9 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr,
|
|||
/* 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 @@ MmInit1(ULONG_PTR FirstKrnlPhysAddr,
|
|||
/* 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();
|
||||
|
|
Loading…
Reference in a new issue