From d9fead36b69ae0504dc4e03aaaf81bad7138905e Mon Sep 17 00:00:00 2001 From: Aleksey Bragin Date: Sat, 16 Feb 2008 14:56:56 +0000 Subject: [PATCH] - Add a hacked and incorrect (due to absence of checking for BIOS-reserved memory areas) MiInitializePageList from 32371. This allows 1st stage to work, and 2nd stage to work from the first power up. - Real, new, [bugless] MiInitializePageList is #if0-#endif'ed until a problem in it is identified and fixed. svn path=/trunk/; revision=32386 --- reactos/ntoskrnl/ke/freeldr.c | 4 + reactos/ntoskrnl/mm/freelist.c | 204 ++++++++++++++++++++++++++++++++- 2 files changed, 203 insertions(+), 5 deletions(-) diff --git a/reactos/ntoskrnl/ke/freeldr.c b/reactos/ntoskrnl/ke/freeldr.c index 1558700629f..f2cbbf2e16e 100644 --- a/reactos/ntoskrnl/ke/freeldr.c +++ b/reactos/ntoskrnl/ke/freeldr.c @@ -21,6 +21,8 @@ #define KERNEL_DESCRIPTOR_PAGE(x) (((ULONG_PTR)x &~ KSEG0_BASE) >> PAGE_SHIFT) #endif +ULONG MmFreeLdrPageDirectoryEnd; + typedef struct _BIOS_MEMORY_DESCRIPTOR { ULONG BlockBase; @@ -920,6 +922,8 @@ 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; diff --git a/reactos/ntoskrnl/mm/freelist.c b/reactos/ntoskrnl/mm/freelist.c index 8abadad1c7c..aba8aefb40c 100644 --- a/reactos/ntoskrnl/mm/freelist.c +++ b/reactos/ntoskrnl/mm/freelist.c @@ -251,6 +251,7 @@ MmAllocEarlyPage(VOID) return Pfn; } +#if 0 VOID NTAPI MmInitializePageList(VOID) @@ -312,8 +313,8 @@ MmInitializePageList(VOID) UsedPage.Flags.Consumer = MC_NPPOOL; UsedPage.ReferenceCount = 2; UsedPage.MapCount = 1; - - /* Loop the memory descriptors */ + + /* Loop the memory descriptors */ for (NextEntry = KeLoaderBlock->MemoryDescriptorListHead.Flink; NextEntry != &KeLoaderBlock->MemoryDescriptorListHead; NextEntry = NextEntry->Flink) @@ -322,7 +323,7 @@ MmInitializePageList(VOID) Md = CONTAINING_RECORD(NextEntry, MEMORY_ALLOCATION_DESCRIPTOR, ListEntry); - + /* Skip bad memory */ if ((Md->MemoryType == LoaderFirmwarePermanent) || (Md->MemoryType == LoaderBBTMemory) || @@ -354,7 +355,7 @@ MmInitializePageList(VOID) InsertTailList(&FreeUnzeroedPageListHead, &MmPageArray[Md->BasePage + i].ListEntry); UnzeroedPageCount++; - MmStats.NrFreePages++; + MmStats.NrFreePages++; } } else @@ -380,11 +381,204 @@ MmInitializePageList(VOID) } KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE); - + DPRINT("Pages: %x %x\n", MmStats.NrFreePages, MmStats.NrSystemPages); MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + MmStats.NrUserPages; MmInitializeBalancer(MmStats.NrFreePages, MmStats.NrSystemPages); } +#endif + +VOID +NTAPI +MmInitializePageList() +{ + 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; + extern ULONG MiKSeg0Start, MiKSeg0End, MmFreeLdrPageDirectoryEnd; + + /* Initialize the page lists */ + KeInitializeSpinLock(&PageListLock); + InitializeListHead(&UserPageListHead); + InitializeListHead(&FreeUnzeroedPageListHead); + InitializeListHead(&FreeZeroedPageListHead); + + DPRINT1("HACK: Using old incorrect MmInitializePageList(). " + "Please bugfix the new version and delete this one\n"); + + /* Set the size and start of the PFN Database */ + MmPageArray = (PHYSICAL_PAGE *)MmPfnDatabase; + MmPageArraySize = MmHighestPhysicalPage; + Reserved = PAGE_ROUND_UP((MmPageArraySize * sizeof(PHYSICAL_PAGE))) / PAGE_SIZE; + + /* Loop every page required to hold the PFN database */ + for (i = 0; i < Reserved; i++) + { + PVOID Address = (char*)MmPageArray + (i * PAGE_SIZE); + + /* Check if FreeLDR has already allocated it for us */ + if (!MmIsPagePresent(NULL, Address)) + { + /* Use one of our highest usable pages */ + Pfn = MiFreeDescriptor->BasePage + MiFreeDescriptor->PageCount - 1; + MiFreeDescriptor->PageCount--; + + /* Set the PFN */ + Status = MmCreateVirtualMappingForKernel(Address, + PAGE_READWRITE, + &Pfn, + 1); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Unable to create virtual mapping\n"); + KEBUGCHECK(0); + } + } + else + { + /* Setting the page protection is necessary to set the global bit */ + MmSetPageProtect(NULL, Address, PAGE_READWRITE); + } + } + + /* Clear the PFN database */ + RtlZeroMemory(MmPageArray, (MmPageArraySize + 1) * sizeof(PHYSICAL_PAGE)); + + /* This is what a used page looks like */ + RtlZeroMemory(&UsedPage, sizeof(UsedPage)); + UsedPage.Flags.Type = MM_PHYSICAL_PAGE_USED; + 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)*/TRUE) + { + /* Apply assumptions that all computers are built the same way */ + if (i == 0) + { + /* Page 0 is reserved for the IVT */ + MmPageArray[i] = UsedPage; + MmStats.NrSystemPages++; + } + else if (i == 1) + { + /* 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; + InsertTailList(&FreeUnzeroedPageListHead, + &MmPageArray[i].ListEntry); + UnzeroedPageCount++; + 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++; + } + } + + KeInitializeEvent(&ZeroPageThreadEvent, NotificationEvent, TRUE); + DPRINT("Pages: %x %x\n", MmStats.NrFreePages, MmStats.NrSystemPages); + /* + DPRINT1("Unzeroed pages: %x\n", UnzeroedPageCount); + { + ULONG j = 0; + for (j=0; j<=MmPageArraySize; j++) + { + if (j % 0x10 == 0) DbgPrint ("\n0x%x\t", j); + DbgPrint("0x%x\t", MmPageArray[j].AllFlags); + } + }*/ + MmStats.NrTotalPages = MmStats.NrFreePages + MmStats.NrSystemPages + MmStats.NrUserPages; + MmInitializeBalancer(MmStats.NrFreePages, MmStats.NrSystemPages); +} VOID NTAPI