[BOOTLIB]: Implement MmMdTruncateDescriptors
authorAlex Ionescu <aionescu@gmail.com>
Sun, 14 May 2017 00:39:30 +0000 (00:39 +0000)
committerAlex Ionescu <aionescu@gmail.com>
Sun, 14 May 2017 00:39:30 +0000 (00:39 +0000)
[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
reactos/boot/environ/lib/mm/descriptor.c
reactos/boot/environ/lib/mm/i386/mmx86.c
reactos/boot/environ/lib/mm/pagealloc.c

index 79952fb..be09dd9 100644 (file)
@@ -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,
index c44ad77..d11c36f 100644 (file)
@@ -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,
index 1f79680..c8a6020 100644 (file)
@@ -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;
index c4810d7..8f1aafb 100644 (file)
@@ -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