Get rid of complete hack that MmInitializePageList was, and use the ARC Memory Descriptor Tree instead. No more magical assumptions about page numbers. No more BIOS Memory Map from FreeLDR. No more hard-coded/static addresses being pased from the bowels of FreeLDR to the kernel.

"Oh my God, I can't believe this is real."
We can now continue the ARM port since the ARM port uses real ARC memory descriptors and not the completely hacked up pages the kernel was previously crossing its fingers to get. As a side effect, this probably unblocks the final hurdle to get ReactOS booted by NTLDR.

svn path=/trunk/; revision=32372
This commit is contained in:
ReactOS Portable Systems Group 2008-02-15 01:19:46 +00:00
parent f19e397250
commit 63cd339c0c
5 changed files with 60 additions and 191 deletions

View file

@ -21,7 +21,6 @@ extern ULONG MmPagedPoolSize;
extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor; extern PMEMORY_ALLOCATION_DESCRIPTOR MiFreeDescriptor;
extern ULONG MmHighestPhysicalPage; extern ULONG MmHighestPhysicalPage;
extern PVOID MmPfnDatabase; extern PVOID MmPfnDatabase;
extern ULONG_PTR MiKSeg0Start, MiKSeg0End;
struct _KTRAP_FRAME; struct _KTRAP_FRAME;
struct _EPROCESS; struct _EPROCESS;
@ -560,8 +559,7 @@ MiShutdownMemoryManager(VOID);
VOID VOID
NTAPI NTAPI
MmInit1( MmInit1(
PADDRESS_RANGE BIOSMemoryMap, VOID
ULONG AddressRangeCount
); );
BOOLEAN BOOLEAN
@ -968,8 +966,7 @@ MmGetLockCountPage(PFN_TYPE Page);
VOID VOID
NTAPI NTAPI
MmInitializePageList( MmInitializePageList(
PADDRESS_RANGE BIOSMemoryMap, VOID
ULONG AddressRangeCount
); );
PFN_TYPE PFN_TYPE

View file

@ -29,11 +29,6 @@ typedef struct _BIOS_MEMORY_DESCRIPTOR
/* GLOBALS *******************************************************************/ /* GLOBALS *******************************************************************/
/* FreeLDR Memory Data */
ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
ULONG_PTR MmFreeLdrLastKernelAddress;
ULONG MmFreeLdrPageDirectoryEnd;
/* FreeLDR Loader Data */ /* FreeLDR Loader Data */
PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock; PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
BOOLEAN AcpiTableDetected; BOOLEAN AcpiTableDetected;
@ -925,8 +920,6 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
/* First get some kernel-loader globals */ /* First get some kernel-loader globals */
AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE; AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
/* Set the NT Loader block and initialize it */ /* Set the NT Loader block and initialize it */
*NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock; *NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
@ -1288,22 +1281,6 @@ KiRosPrepareForSystemStartup(IN ULONG Dummy,
/* Save pointer to ROS Block */ /* Save pointer to ROS Block */
KeRosLoaderBlock = LoaderBlock; KeRosLoaderBlock = LoaderBlock;
MmFreeLdrLastKernelAddress = PAGE_ROUND_UP(KeRosLoaderBlock->
ModsAddr[KeRosLoaderBlock->
ModsCount - 1].
ModEnd);
#if defined(_M_PPC)
MmFreeLdrFirstKrnlPhysAddr = KeRosLoaderBlock->ModsAddr[0].ModStart;
MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress;
MmFreeLdrLastKernelAddress = 0x80800000 + KeRosLoaderBlock->ModsAddr[KeRosLoaderBlock->ModsCount - 1].ModEnd - MmFreeLdrFirstKrnlPhysAddr;
DbgPrint("kernel phys = %08x-%08x\n",
MmFreeLdrFirstKrnlPhysAddr,
MmFreeLdrLastKrnlPhysAddr);
#else
MmFreeLdrFirstKrnlPhysAddr = KeRosLoaderBlock->ModsAddr[0].ModStart -
KSEG0_BASE;
MmFreeLdrLastKrnlPhysAddr = MmFreeLdrLastKernelAddress - KSEG0_BASE;
#endif
/* Save memory manager data */ /* Save memory manager data */
KeMemoryMapRangeCount = 0; KeMemoryMapRangeCount = 0;

View file

@ -537,7 +537,7 @@ KiInitializeKernel(IN PKPROCESS InitProcess,
((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess; ((PETHREAD)InitThread)->ThreadsProcess = (PEPROCESS)InitProcess;
/* Initialize Kernel Memory Address Space */ /* Initialize Kernel Memory Address Space */
MmInit1(KeMemoryMap, KeMemoryMapRangeCount); MmInit1();
/* Set basic CPU Features that user mode can read */ /* Set basic CPU Features that user mode can read */
SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] = SharedUserData->ProcessorFeatures[PF_MMX_INSTRUCTIONS_AVAILABLE] =

View file

@ -237,63 +237,17 @@ MmGetContinuousPages(ULONG NumberOfBytes,
return 0; return 0;
} }
BOOLEAN
NTAPI
MiIsPfnRam(PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount,
PFN_TYPE Pfn)
{
BOOLEAN IsUsable;
LARGE_INTEGER BaseAddress;
LARGE_INTEGER EndAddress;
ULONG i;
if (BIOSMemoryMap != NULL && AddressRangeCount > 0)
{
IsUsable = FALSE;
for (i = 0; i < AddressRangeCount; i++)
{
BaseAddress.u.LowPart = BIOSMemoryMap[i].BaseAddrLow;
BaseAddress.u.HighPart = BIOSMemoryMap[i].BaseAddrHigh;
EndAddress.u.LowPart = BIOSMemoryMap[i].LengthLow;
EndAddress.u.HighPart = BIOSMemoryMap[i].LengthHigh;
EndAddress.QuadPart += BaseAddress.QuadPart;
BaseAddress.QuadPart = PAGE_ROUND_DOWN(BaseAddress.QuadPart);
EndAddress.QuadPart = PAGE_ROUND_UP(EndAddress.QuadPart);
if ((BaseAddress.QuadPart >> PAGE_SHIFT) <= Pfn &&
Pfn < (EndAddress.QuadPart >> PAGE_SHIFT))
{
if (BIOSMemoryMap[i].Type == 1)
{
IsUsable = TRUE;
}
else
{
return FALSE;
}
}
}
return IsUsable;
}
return TRUE;
}
VOID VOID
NTAPI NTAPI
MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap, MmInitializePageList(VOID)
IN ULONG AddressRangeCount)
{ {
ULONG i; ULONG i;
ULONG Reserved; ULONG Reserved;
NTSTATUS Status; NTSTATUS Status;
PFN_TYPE Pfn = 0; PFN_TYPE Pfn = 0;
PHYSICAL_PAGE UsedPage; PHYSICAL_PAGE UsedPage;
ULONG PdeStart = PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart; PLIST_ENTRY NextEntry;
ULONG PdePageStart, PdePageEnd; PMEMORY_ALLOCATION_DESCRIPTOR Md;
ULONG VideoPageStart, VideoPageEnd;
ULONG KernelPageStart, KernelPageEnd;
ULONG_PTR KernelStart, KernelEnd;
/* Initialize the page lists */ /* Initialize the page lists */
KeInitializeSpinLock(&PageListLock); KeInitializeSpinLock(&PageListLock);
@ -345,113 +299,73 @@ MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
UsedPage.Flags.Consumer = MC_NPPOOL; UsedPage.Flags.Consumer = MC_NPPOOL;
UsedPage.ReferenceCount = 2; UsedPage.ReferenceCount = 2;
UsedPage.MapCount = 1; 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 = KernelStart / PAGE_SIZE;
KernelPageEnd = KernelEnd / PAGE_SIZE;
// Glorious Hack: /* Loop the memory descriptors */
// The kernel seems to crash if the region of memory that FreeLDR maps for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
// (those evil 6MB) is not *entirely* marked "in use", even though only NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
// 3 or 4MB of it may actually be in use. NextEntry = NextEntry->Flink)
// This wasn't noticed before, because the PFN database pages which are {
// *VIRTUALLY* continous after the kernel end were also marked as /* Get the descriptor */
// *PHYSICALLY* continous (even though they were allocated at the very far Md = CONTAINING_RECORD(NextEntry,
// end of physical memory). MEMORY_ALLOCATION_DESCRIPTOR,
// ListEntry);
// So we'll simply gobble up whatever is left of what FreeLDR mapped.
// /* Skip bad memory */
// PS. This is really sinister if ((Md->MemoryType == LoaderFirmwarePermanent) ||
// (Md->MemoryType == LoaderBBTMemory) ||
KernelEnd += (KernelStart + 0x600000) - KernelEnd; (Md->MemoryType == LoaderSpecialMemory) ||
KernelPageEnd = KernelEnd / PAGE_SIZE; (Md->MemoryType == LoaderBad))
/* Loop every page on the system */
for (i = 0; i <= MmPageArraySize; i++)
{
/* Check if it's part of RAM */
if (MiIsPfnRam(BIOSMemoryMap, AddressRangeCount, i))
{ {
/* Apply assumptions that all computers are built the same way */ /* Loop every page part of the block but valid in the database */
if (i == 0) for (i = 0; i < Md->PageCount; i++)
{ {
/* Page 0 is reserved for the IVT */ /* Skip memory we ignore completely */
MmPageArray[i] = UsedPage; if ((Md->BasePage + i) > MmPageArraySize) break;
/* These are pages reserved by the BIOS/ROMs */
MmPageArray[Md->BasePage + i].Flags.Type = MM_PHYSICAL_PAGE_BIOS;
MmPageArray[Md->BasePage + i].Flags.Consumer = MC_NPPOOL;
MmStats.NrSystemPages++; MmStats.NrSystemPages++;
} }
else if (i == 1) }
else if ((Md->MemoryType == LoaderFree) ||
(Md->MemoryType == LoaderLoadedProgram) ||
(Md->MemoryType == LoaderFirmwareTemporary) ||
(Md->MemoryType == LoaderOsloaderStack))
{
/* Loop every page part of the block */
for (i = 0; i < Md->PageCount; i++)
{ {
/* Page 1 is reserved for the PCR */ /* Mark it as a free page */
MmPageArray[i] = UsedPage; MmPageArray[Md->BasePage + i].Flags.Type = MM_PHYSICAL_PAGE_FREE;
MmStats.NrSystemPages++;
}
else if (i == 2)
{
/* Page 2 is reserved for the KUSER_SHARED_DATA */
MmPageArray[i] = UsedPage;
MmStats.NrSystemPages++;
}
else if ((i >= PdePageStart) && (i < PdePageEnd))
{
/* These pages contain the initial FreeLDR PDEs */
MmPageArray[i] = UsedPage;
MmStats.NrSystemPages++;
}
else if ((i >= VideoPageStart) && (i < VideoPageEnd))
{
/*
* These pages are usually for the Video ROM BIOS.
* Supposedly anyway. We'll simply ignore the fact that
* many systems have this area somewhere else entirely
* (which we'll assume to be "free" a couple of lines below)
*/
MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_BIOS;
MmPageArray[i].Flags.Consumer = MC_NPPOOL;
MmStats.NrSystemPages++;
}
else if ((i >= KernelPageStart) && (i < KernelPageEnd))
{
/* These are pages beloning to the kernel */
MmPageArray[i] = UsedPage;
MmStats.NrSystemPages++;
}
else if (i >= (MiFreeDescriptor->BasePage + MiFreeDescriptor->PageCount))
{
/* These are pages we allocated above to hold the PFN DB */
MmPageArray[i] = UsedPage;
MmStats.NrSystemPages++;
}
else
{
/*
* These are supposedly free pages.
* By the way, not all of them are, some contain vital
* FreeLDR data, but since we choose to ignore the Memory
* Descriptor List, why bother, right?
*/
MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_FREE;
MmPageArray[i].ReferenceCount = 0;
InsertTailList(&FreeUnzeroedPageListHead, InsertTailList(&FreeUnzeroedPageListHead,
&MmPageArray[i].ListEntry); &MmPageArray[Md->BasePage + i].ListEntry);
UnzeroedPageCount++; UnzeroedPageCount++;
MmStats.NrFreePages++; MmStats.NrFreePages++;
} }
} }
else else
{ {
/* These are pages reserved by the BIOS/ROMs */ /* Loop every page part of the block */
MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_BIOS; for (i = 0; i < Md->PageCount; i++)
MmPageArray[i].Flags.Consumer = MC_NPPOOL; {
MmStats.NrSystemPages++; /* Everything else is used memory */
MmPageArray[Md->BasePage + i] = UsedPage;
MmStats.NrSystemPages++;
}
} }
} }
/* Finally handle the pages describing the PFN database themselves */
for (i = (MiFreeDescriptor->BasePage + MiFreeDescriptor->PageCount);
i <= MmPageArraySize;
i++)
{
/* Mark them as used kernel memory */
MmPageArray[i] = UsedPage;
MmStats.NrSystemPages++;
}
KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE); KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE);
DPRINT("Pages: %x %x\n", MmStats.NrFreePages, MmStats.NrSystemPages); DPRINT("Pages: %x %x\n", MmStats.NrFreePages, MmStats.NrSystemPages);

View file

@ -275,23 +275,6 @@ MiDbgKernelLayout(VOID)
"Paged pool region"); "Paged pool region");
} }
VOID
NTAPI
MiDbgDumpBiosMap(IN PADDRESS_RANGE BIOSMemoryMap,
IN ULONG AddressRangeCount)
{
ULONG i;
DPRINT1("Base\t\tLength\t\tType\n");
for (i = 0; i < AddressRangeCount; i++)
{
DPRINT1("%08lX\t%08lX\t%d\n",
BIOSMemoryMap[i].BaseAddrLow,
BIOSMemoryMap[i].LengthLow,
BIOSMemoryMap[i].Type);
}
}
VOID VOID
NTAPI NTAPI
MiDbgDumpMemoryDescriptors(VOID) MiDbgDumpMemoryDescriptors(VOID)
@ -342,14 +325,12 @@ MiGetLastKernelAddress(VOID)
VOID VOID
INIT_FUNCTION INIT_FUNCTION
NTAPI NTAPI
MmInit1(IN PADDRESS_RANGE BIOSMemoryMap, MmInit1(VOID)
IN ULONG AddressRangeCount)
{ {
PLDR_DATA_TABLE_ENTRY LdrEntry; PLDR_DATA_TABLE_ENTRY LdrEntry;
/* Dump memory descriptors */ /* Dump memory descriptors */
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors(); if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
if (MiDbgEnableMdDump) MiDbgDumpBiosMap(BIOSMemoryMap, AddressRangeCount);
/* Set the page directory */ /* Set the page directory */
PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart = (ULONG)MmGetPageDirectory(); PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart = (ULONG)MmGetPageDirectory();
@ -419,7 +400,7 @@ MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
MiDbgKernelLayout(); MiDbgKernelLayout();
/* Initialize the page list */ /* Initialize the page list */
MmInitializePageList(BIOSMemoryMap, AddressRangeCount); MmInitializePageList();
/* Unmap low memory */ /* Unmap low memory */
MmDeletePageTable(NULL, 0); MmDeletePageTable(NULL, 0);