From d4534e81e1574ffd5292725116b6095726bf1b60 Mon Sep 17 00:00:00 2001 From: Alex Ionescu Date: Sun, 14 May 2017 00:39:30 +0000 Subject: [PATCH] [BOOTLIB]: Implement MmMdTruncateDescriptors [BOOTLIB]: Implement MmPaTruncateMemory and call it during paging initialization to remove > 4GB memory.c [BOOTLIB]: Implement BlpMmInitializeConstraints if those BCD options are used. svn path=/trunk/; revision=74542 --- reactos/boot/environ/include/bl.h | 12 ++++ reactos/boot/environ/lib/mm/descriptor.c | 76 ++++++++++++++++++++++ reactos/boot/environ/lib/mm/i386/mmx86.c | 6 +- reactos/boot/environ/lib/mm/pagealloc.c | 81 ++++++++++++++++++++++-- 4 files changed, 165 insertions(+), 10 deletions(-) diff --git a/reactos/boot/environ/include/bl.h b/reactos/boot/environ/include/bl.h index 79952fb38de..be09dd9b5ac 100644 --- a/reactos/boot/environ/include/bl.h +++ b/reactos/boot/environ/include/bl.h @@ -2088,6 +2088,13 @@ MmMdAddDescriptorToList ( _In_ ULONG Flags ); +NTSTATUS +MmMdTruncateDescriptors ( + _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, + _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, + _In_ ULONGLONG BasePage + ); + VOID MmMdRemoveDescriptorFromList ( _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, @@ -2123,6 +2130,11 @@ MmMdFreeDescriptor ( /* PAGE ALLOCATOR ROUTINES ***************************************************/ +NTSTATUS +MmPaTruncateMemory ( + _In_ ULONGLONG BasePage + ); + NTSTATUS BlMmAllocatePhysicalPages( _Inout_ PPHYSICAL_ADDRESS Address, diff --git a/reactos/boot/environ/lib/mm/descriptor.c b/reactos/boot/environ/lib/mm/descriptor.c index c44ad77859c..d11c36f1463 100644 --- a/reactos/boot/environ/lib/mm/descriptor.c +++ b/reactos/boot/environ/lib/mm/descriptor.c @@ -408,6 +408,82 @@ MmMdInitByteGranularDescriptor ( return MemoryDescriptor; } +NTSTATUS +MmMdTruncateDescriptors ( + _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, + _In_ PBL_MEMORY_DESCRIPTOR_LIST NewList, + _In_ ULONGLONG BasePage + ) +{ + PLIST_ENTRY ListHead, NextEntry; + PBL_MEMORY_DESCRIPTOR Descriptor, NewDescriptor; + ULONGLONG FoundEndPage; + + /* Search the descriptor list */ + ListHead = MdList->First; + NextEntry = ListHead->Flink; + while (NextEntry != ListHead) + { + /* Get the current descriptor */ + Descriptor = CONTAINING_RECORD(NextEntry, + BL_MEMORY_DESCRIPTOR, + ListEntry); + + /* Go to the next entry in case we have to remove */ + NextEntry = NextEntry->Flink; + + /* Don't touch anything else but free RAM */ + if (((Descriptor->Type >> BL_MEMORY_CLASS_SHIFT) == BlSystemClass) && + (Descriptor->Type != BlConventionalMemory)) + { + continue; + } + + /* Check if this page is within the descriptor's region */ + FoundEndPage = Descriptor->BasePage + Descriptor->PageCount; + if (BasePage > Descriptor->BasePage) + { + /* Check if it doesn't go beyond the descriptor */ + if (BasePage < FoundEndPage) + { + /* Create a new descriptor to describe this region */ + EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n", + Descriptor->Type, Descriptor->BasePage, FoundEndPage); + NewDescriptor = MmMdInitByteGranularDescriptor(Descriptor->Flags, + Descriptor->Type, + BasePage, + 0, + FoundEndPage - BasePage); + if (!NewDescriptor) + { + return STATUS_NO_MEMORY; + } + + /* Cut off this descriptor to make it shorter */ + Descriptor->PageCount = BasePage - Descriptor->BasePage; + + /* Add the region to the new list */ + MmMdAddDescriptorToList(NewList, + NewDescriptor, + BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG); + } + } + else + { + /* This whole descriptor covers the truncated area */ + EfiPrintf(L"Truncating descriptor type %lx base: %llx end: %llx\r\n", + Descriptor->Type, Descriptor->BasePage, FoundEndPage); + MmMdRemoveDescriptorFromList(MdList, Descriptor); + MmMdAddDescriptorToList(NewList, + Descriptor, + BL_MM_ADD_DESCRIPTOR_COALESCE_FLAG); + } + } + + /* All good if we got here */ + return STATUS_SUCCESS; +} + BOOLEAN MmMdpTruncateDescriptor ( _In_ PBL_MEMORY_DESCRIPTOR_LIST MdList, diff --git a/reactos/boot/environ/lib/mm/i386/mmx86.c b/reactos/boot/environ/lib/mm/i386/mmx86.c index 1f796805f41..c8a60205d8b 100644 --- a/reactos/boot/environ/lib/mm/i386/mmx86.c +++ b/reactos/boot/environ/lib/mm/i386/mmx86.c @@ -939,10 +939,8 @@ MmDefInitializeTranslation ( Mmx86SelfMapBase.QuadPart = 0; MmArchReferencePage = NULL; - /* Truncate all memory above 4GB so that we don't use it @TODO: FIXME */ - EfiPrintf(L"Warning: not truncating > 4GB memory. Don't boot with more than 4GB of RAM!\r\n"); - //Status = MmPaTruncateMemory(0x100000); - Status = STATUS_SUCCESS; + /* Truncate all memory above 4GB so that we don't use it */ + Status = MmPaTruncateMemory(0x100000); if (!NT_SUCCESS(Status)) { goto Quickie; diff --git a/reactos/boot/environ/lib/mm/pagealloc.c b/reactos/boot/environ/lib/mm/pagealloc.c index c4810d7f0ea..8f1aafb8e4a 100644 --- a/reactos/boot/environ/lib/mm/pagealloc.c +++ b/reactos/boot/environ/lib/mm/pagealloc.c @@ -47,13 +47,72 @@ BL_MEMORY_DESCRIPTOR_LIST MmMdlMappingTrackers; /* FUNCTIONS *****************************************************************/ +NTSTATUS +MmPaTruncateMemory ( + _In_ ULONGLONG BasePage + ) +{ + NTSTATUS Status; + + /* Increase nesting depth */ + ++MmDescriptorCallTreeCount; + + /* Set the maximum page to the truncated request */ + if (BasePage < PapMaximumPhysicalPage) + { + PapMaximumPhysicalPage = BasePage; + } + + /* Truncate mapped and allocated memory */ + Status = MmMdTruncateDescriptors(&MmMdlMappedAllocated, + &MmMdlTruncatedMemory, + BasePage); + if (NT_SUCCESS(Status)) + { + /* Truncate unmapped and allocated memory */ + Status = MmMdTruncateDescriptors(&MmMdlUnmappedAllocated, + &MmMdlTruncatedMemory, + BasePage); + if (NT_SUCCESS(Status)) + { + /* Truncate mapped and unallocated memory */ + Status = MmMdTruncateDescriptors(&MmMdlMappedUnallocated, + &MmMdlTruncatedMemory, + BasePage); + if (NT_SUCCESS(Status)) + { + /* Truncate unmapped and unallocated memory */ + Status = MmMdTruncateDescriptors(&MmMdlUnmappedUnallocated, + &MmMdlTruncatedMemory, + BasePage); + if (NT_SUCCESS(Status)) + { + /* Truncate reserved memory */ + Status = MmMdTruncateDescriptors(&MmMdlReservedAllocated, + &MmMdlTruncatedMemory, + BasePage); + } + } + } + } + + /* Restore the nesting depth */ + MmMdFreeGlobalDescriptors(); + --MmDescriptorCallTreeCount; + return Status; +} + NTSTATUS BlpMmInitializeConstraints ( VOID ) { - NTSTATUS Status; + NTSTATUS Status, ReturnStatus; ULONGLONG LowestAddressValid, HighestAddressValid; + ULONGLONG LowestPage, HighestPage; + + /* Assume success */ + ReturnStatus = STATUS_SUCCESS; /* Check for LOWMEM */ Status = BlGetBootOptionInteger(BlpApplicationEntry.BcdData, @@ -61,8 +120,15 @@ BlpMmInitializeConstraints ( &LowestAddressValid); if (NT_SUCCESS(Status)) { - EfiPrintf(L"/LOWMEM not supported\r\n"); - return STATUS_NOT_IMPLEMENTED; + /* Align the address */ + LowestAddressValid = (ULONG_PTR)PAGE_ALIGN(LowestAddressValid); + LowestPage = LowestAddressValid >> PAGE_SHIFT; + + /* Make sure it's below 4GB */ + if (LowestPage <= 0x100000) + { + PapMinimumPhysicalPage = LowestPage; + } } /* Check for MAXMEM */ @@ -71,12 +137,15 @@ BlpMmInitializeConstraints ( &HighestAddressValid); if (NT_SUCCESS(Status)) { - EfiPrintf(L"/MAXMEM not supported\r\n"); - return STATUS_NOT_IMPLEMENTED; + /* Get the page */ + HighestPage = HighestAddressValid >> PAGE_SHIFT; + + /* Truncate memory above this page */ + ReturnStatus = MmPaTruncateMemory(HighestPage); } /* Return back to the caller */ - return STATUS_SUCCESS; + return ReturnStatus; } NTSTATUS