diff --git a/reactos/ntoskrnl/mm/ARM3/init.c b/reactos/ntoskrnl/mm/ARM3/init.c index f946909b93c..20739755851 100644 --- a/reactos/ntoskrnl/mm/ARM3/init.c +++ b/reactos/ntoskrnl/mm/ARM3/init.c @@ -108,12 +108,16 @@ ULONG MmNumberOfSystemPtes; // ULONG MxPfnAllocation; - // // The ARM³ PFN Database // PMMPFN MmArmPfnDatabase; +// +// This structure describes the different pieces of RAM-backed address space +// +PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock; + /* PRIVATE FUNCTIONS **********************************************************/ // @@ -139,6 +143,142 @@ MiSyncARM3WithROS(IN PVOID AddressStart, } } +PPHYSICAL_MEMORY_DESCRIPTOR +NTAPI +MmInitializeMemoryLimits(IN PLOADER_PARAMETER_BLOCK LoaderBlock, + IN PBOOLEAN IncludeType) +{ + PLIST_ENTRY NextEntry; + ULONG Run = 0, InitialRuns = 0; + PFN_NUMBER NextPage = -1, PageCount = 0; + PPHYSICAL_MEMORY_DESCRIPTOR Buffer, NewBuffer; + PMEMORY_ALLOCATION_DESCRIPTOR MdBlock; + + // + // Scan the memory descriptors + // + NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) + { + // + // For each one, increase the memory allocation estimate + // + InitialRuns++; + NextEntry = NextEntry->Flink; + } + + // + // Allocate the maximum we'll ever need + // + Buffer = ExAllocatePoolWithTag(NonPagedPool, + sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + + sizeof(PHYSICAL_MEMORY_RUN) * + (InitialRuns - 1), + 'lMmM'); + if (!Buffer) return NULL; + + // + // For now that's how many runs we have + // + Buffer->NumberOfRuns = InitialRuns; + + // + // Now loop through the descriptors again + // + NextEntry = LoaderBlock->MemoryDescriptorListHead.Flink; + while (NextEntry != &LoaderBlock->MemoryDescriptorListHead) + { + // + // Grab each one, and check if it's one we should include + // + MdBlock = CONTAINING_RECORD(NextEntry, + MEMORY_ALLOCATION_DESCRIPTOR, + ListEntry); + if ((MdBlock->MemoryType < LoaderMaximum) && + (IncludeType[MdBlock->MemoryType])) + { + // + // Add this to our running total + // + PageCount += MdBlock->PageCount; + + // + // Check if the next page is described by the next descriptor + // + if (MdBlock->BasePage == NextPage) + { + // + // Combine it into the same physical run + // + ASSERT(MdBlock->PageCount != 0); + Buffer->Run[Run - 1].PageCount += MdBlock->PageCount; + NextPage += MdBlock->PageCount; + } + else + { + // + // Otherwise just duplicate the descriptor's contents + // + Buffer->Run[Run].BasePage = MdBlock->BasePage; + Buffer->Run[Run].PageCount = MdBlock->PageCount; + NextPage = Buffer->Run[Run].BasePage + Buffer->Run[Run].PageCount; + + // + // And in this case, increase the number of runs + // + Run++; + } + } + + // + // Try the next descriptor + // + NextEntry = MdBlock->ListEntry.Flink; + } + + // + // We should not have been able to go past our initial estimate + // + ASSERT(Run <= Buffer->NumberOfRuns); + + // + // Our guess was probably exaggerated... + // + if (InitialRuns > Run) + { + // + // Allocate a more accurately sized buffer + // + NewBuffer = ExAllocatePoolWithTag(NonPagedPool, + sizeof(PHYSICAL_MEMORY_DESCRIPTOR) + + sizeof(PHYSICAL_MEMORY_RUN) * + (Run - 1), + 'lMmM'); + if (NewBuffer) + { + // + // Copy the old buffer into the new, then free it + // + RtlCopyMemory(NewBuffer->Run, + NewBuffer->Run, + sizeof(PHYSICAL_MEMORY_RUN) * Run); + ExFreePool(Buffer); + + // + // Now use the new buffer + // + Buffer = NewBuffer; + } + } + + // + // Write the final numbers, and return it + // + Buffer->NumberOfRuns = Run; + Buffer->NumberOfPages = PageCount; + return Buffer; +} + NTSTATUS NTAPI MmArmInitSystem(IN ULONG Phase, @@ -152,6 +292,8 @@ MmArmInitSystem(IN ULONG Phase, PVOID NonPagedPoolExpansionVa, BaseAddress; NTSTATUS Status; ULONG OldCount; + BOOLEAN IncludeType[LoaderMaximum]; + ULONG i; BoundaryAddressMultiple.QuadPart = Low.QuadPart = 0; High.QuadPart = -1; @@ -565,6 +707,36 @@ MmArmInitSystem(IN ULONG Phase, MiSyncARM3WithROS(MmNonPagedPoolStart, (PVOID)((ULONG_PTR)MmNonPagedPoolStart + MmSizeOfNonPagedPoolInBytes - 1)); MiSyncARM3WithROS((PVOID)HYPER_SPACE, (PVOID)(HYPER_SPACE + PAGE_SIZE - 1)); } + else + { + // + // Instantiate memory that we don't consider RAM/usable + // We use the same exclusions that Windows does, in order to try to be + // compatible with WinLDR-style booting + // + for (i = 0; i < LoaderMaximum; i++) IncludeType[i] = TRUE; + IncludeType[LoaderBad] = FALSE; + IncludeType[LoaderFirmwarePermanent] = FALSE; + IncludeType[LoaderSpecialMemory] = FALSE; + IncludeType[LoaderBBTMemory] = FALSE; + + // + // Build the physical memory block + // + MmPhysicalMemoryBlock = MmInitializeMemoryLimits(LoaderBlock, + IncludeType); + for (i = 0; i < MmPhysicalMemoryBlock->NumberOfRuns; i++) + { + // + // Dump it for debugging + // + PPHYSICAL_MEMORY_RUN Run; + Run = &MmPhysicalMemoryBlock->Run[i]; + DPRINT1("PHYSICAL RAM [0x%08p to 0x%08p]\n", + Run->BasePage << PAGE_SHIFT, + (Run->BasePage + Run->PageCount) << PAGE_SHIFT); + } + } // // Always return success for now diff --git a/reactos/ntoskrnl/mm/ARM3/miarm.h b/reactos/ntoskrnl/mm/ARM3/miarm.h index 9d490471701..aa9850b649d 100644 --- a/reactos/ntoskrnl/mm/ARM3/miarm.h +++ b/reactos/ntoskrnl/mm/ARM3/miarm.h @@ -28,6 +28,19 @@ typedef enum _MI_PFN_CACHE_ATTRIBUTE MiNotMapped } MI_PFN_CACHE_ATTRIBUTE, *PMI_PFN_CACHE_ATTRIBUTE; +typedef struct _PHYSICAL_MEMORY_RUN +{ + ULONG BasePage; + ULONG PageCount; +} PHYSICAL_MEMORY_RUN, *PPHYSICAL_MEMORY_RUN; + +typedef struct _PHYSICAL_MEMORY_DESCRIPTOR +{ + ULONG NumberOfRuns; + ULONG NumberOfPages; + PHYSICAL_MEMORY_RUN Run[1]; +} PHYSICAL_MEMORY_DESCRIPTOR, *PPHYSICAL_MEMORY_DESCRIPTOR; + extern MMPTE HyperTemplatePte; extern ULONG MmSizeOfNonPagedPoolInBytes; @@ -36,6 +49,7 @@ extern PVOID MmNonPagedPoolStart; extern PVOID MmNonPagedPoolExpansionStart; extern PMMPTE MmFirstReservedMappingPte, MmLastReservedMappingPte; extern PMMPTE MiFirstReservedZeroingPte; +extern PPHYSICAL_MEMORY_DESCRIPTOR MmPhysicalMemoryBlock; VOID NTAPI diff --git a/reactos/ntoskrnl/mm/mminit.c b/reactos/ntoskrnl/mm/mminit.c index 84806ef8d7e..117bbcc11a3 100644 --- a/reactos/ntoskrnl/mm/mminit.c +++ b/reactos/ntoskrnl/mm/mminit.c @@ -376,7 +376,7 @@ MmInit1(VOID) MmInitializePageList(); // - // Initialize ARM³ + // Initialize ARM³ in phase 0 // MmArmInitSystem(0, KeLoaderBlock); @@ -391,6 +391,11 @@ MmInit1(VOID) /* Initialize working sets */ MmInitializeMemoryConsumer(MC_USER, MmTrimUserMemory); + + // + // Initialize ARM³ in phase 1 + // + MmArmInitSystem(1, KeLoaderBlock); } BOOLEAN