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 ULONG MmHighestPhysicalPage;
extern PVOID MmPfnDatabase;
extern ULONG_PTR MiKSeg0Start, MiKSeg0End;
struct _KTRAP_FRAME;
struct _EPROCESS;
@ -560,8 +559,7 @@ MiShutdownMemoryManager(VOID);
VOID
NTAPI
MmInit1(
PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount
VOID
);
BOOLEAN
@ -968,8 +966,7 @@ MmGetLockCountPage(PFN_TYPE Page);
VOID
NTAPI
MmInitializePageList(
PADDRESS_RANGE BIOSMemoryMap,
ULONG AddressRangeCount
VOID
);
PFN_TYPE

View file

@ -29,11 +29,6 @@ typedef struct _BIOS_MEMORY_DESCRIPTOR
/* GLOBALS *******************************************************************/
/* FreeLDR Memory Data */
ULONG_PTR MmFreeLdrFirstKrnlPhysAddr, MmFreeLdrLastKrnlPhysAddr;
ULONG_PTR MmFreeLdrLastKernelAddress;
ULONG MmFreeLdrPageDirectoryEnd;
/* FreeLDR Loader Data */
PROS_LOADER_PARAMETER_BLOCK KeRosLoaderBlock;
BOOLEAN AcpiTableDetected;
@ -925,8 +920,6 @@ KiRosFrldrLpbToNtLpb(IN PROS_LOADER_PARAMETER_BLOCK RosLoaderBlock,
/* First get some kernel-loader globals */
AcpiTableDetected = (RosLoaderBlock->Flags & MB_FLAGS_ACPI_TABLE) ? TRUE : FALSE;
MmFreeLdrPageDirectoryEnd = RosLoaderBlock->PageDirectoryEnd;
if (!MmFreeLdrPageDirectoryEnd) MmFreeLdrPageDirectoryEnd = 0x40000;
/* Set the NT Loader block and initialize it */
*NtLoaderBlock = KeLoaderBlock = LoaderBlock = &BldrLoaderBlock;
@ -1288,22 +1281,6 @@ KiRosPrepareForSystemStartup(IN ULONG Dummy,
/* Save pointer to ROS Block */
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 */
KeMemoryMapRangeCount = 0;

View file

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

View file

@ -237,63 +237,17 @@ MmGetContinuousPages(ULONG NumberOfBytes,
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
NTAPI
MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
IN ULONG AddressRangeCount)
MmInitializePageList(VOID)
{
ULONG i;
ULONG Reserved;
NTSTATUS Status;
PFN_TYPE Pfn = 0;
PHYSICAL_PAGE UsedPage;
ULONG PdeStart = PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart;
ULONG PdePageStart, PdePageEnd;
ULONG VideoPageStart, VideoPageEnd;
ULONG KernelPageStart, KernelPageEnd;
ULONG_PTR KernelStart, KernelEnd;
PLIST_ENTRY NextEntry;
PMEMORY_ALLOCATION_DESCRIPTOR Md;
/* Initialize the page lists */
KeInitializeSpinLock(&PageListLock);
@ -345,113 +299,73 @@ MmInitializePageList(IN PADDRESS_RANGE BIOSMemoryMap,
UsedPage.Flags.Consumer = MC_NPPOOL;
UsedPage.ReferenceCount = 2;
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:
// The kernel seems to crash if the region of memory that FreeLDR maps
// (those evil 6MB) is not *entirely* marked "in use", even though only
// 3 or 4MB of it may actually be in use.
// This wasn't noticed before, because the PFN database pages which are
// *VIRTUALLY* continous after the kernel end were also marked as
// *PHYSICALLY* continous (even though they were allocated at the very far
// end of physical memory).
//
// So we'll simply gobble up whatever is left of what FreeLDR mapped.
//
// PS. This is really sinister
//
KernelEnd += (KernelStart + 0x600000) - KernelEnd;
KernelPageEnd = KernelEnd / PAGE_SIZE;
/* Loop every page on the system */
for (i = 0; i <= MmPageArraySize; i++)
{
/* Check if it's part of RAM */
if (MiIsPfnRam(BIOSMemoryMap, AddressRangeCount, i))
/* Loop the memory descriptors */
for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink;
NextEntry != &KeLoaderBlock->MemoryDescriptorListHead;
NextEntry = NextEntry->Flink)
{
/* Get the descriptor */
Md = CONTAINING_RECORD(NextEntry,
MEMORY_ALLOCATION_DESCRIPTOR,
ListEntry);
/* Skip bad memory */
if ((Md->MemoryType == LoaderFirmwarePermanent) ||
(Md->MemoryType == LoaderBBTMemory) ||
(Md->MemoryType == LoaderSpecialMemory) ||
(Md->MemoryType == LoaderBad))
{
/* Apply assumptions that all computers are built the same way */
if (i == 0)
/* Loop every page part of the block but valid in the database */
for (i = 0; i < Md->PageCount; i++)
{
/* Page 0 is reserved for the IVT */
MmPageArray[i] = UsedPage;
/* Skip memory we ignore completely */
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++;
}
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 */
MmPageArray[i] = UsedPage;
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;
/* Mark it as a free page */
MmPageArray[Md->BasePage + i].Flags.Type = MM_PHYSICAL_PAGE_FREE;
InsertTailList(&FreeUnzeroedPageListHead,
&MmPageArray[i].ListEntry);
&MmPageArray[Md->BasePage + i].ListEntry);
UnzeroedPageCount++;
MmStats.NrFreePages++;
MmStats.NrFreePages++;
}
}
else
{
/* These are pages reserved by the BIOS/ROMs */
MmPageArray[i].Flags.Type = MM_PHYSICAL_PAGE_BIOS;
MmPageArray[i].Flags.Consumer = MC_NPPOOL;
MmStats.NrSystemPages++;
/* Loop every page part of the block */
for (i = 0; i < Md->PageCount; i++)
{
/* 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);
DPRINT("Pages: %x %x\n", MmStats.NrFreePages, MmStats.NrSystemPages);

View file

@ -275,23 +275,6 @@ MiDbgKernelLayout(VOID)
"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
NTAPI
MiDbgDumpMemoryDescriptors(VOID)
@ -342,14 +325,12 @@ MiGetLastKernelAddress(VOID)
VOID
INIT_FUNCTION
NTAPI
MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
IN ULONG AddressRangeCount)
MmInit1(VOID)
{
PLDR_DATA_TABLE_ENTRY LdrEntry;
/* Dump memory descriptors */
if (MiDbgEnableMdDump) MiDbgDumpMemoryDescriptors();
if (MiDbgEnableMdDump) MiDbgDumpBiosMap(BIOSMemoryMap, AddressRangeCount);
/* Set the page directory */
PsGetCurrentProcess()->Pcb.DirectoryTableBase.LowPart = (ULONG)MmGetPageDirectory();
@ -419,7 +400,7 @@ MmInit1(IN PADDRESS_RANGE BIOSMemoryMap,
MiDbgKernelLayout();
/* Initialize the page list */
MmInitializePageList(BIOSMemoryMap, AddressRangeCount);
MmInitializePageList();
/* Unmap low memory */
MmDeletePageTable(NULL, 0);