]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Core/Dxe/Mem/Page.c
MdeModulePkg DxeCore: Enhance "ConvertPages: Incompatible memory types"
[mirror_edk2.git] / MdeModulePkg / Core / Dxe / Mem / Page.c
index 2f4ff8ecfdab6fe22ed2baa8b1060bd31a1c8830..a142c79ee2cabd0faea99a54ce79f7637177b6f3 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   UEFI Memory page management functions.\r
 \r
-Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2007 - 2017, Intel Corporation. All rights reserved.<BR>\r
 This program and the accompanying materials\r
 are licensed and made available under the terms and conditions of the BSD License\r
 which accompanies this distribution.  The full text of the license may be found at\r
@@ -15,8 +15,6 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 #include "DxeMain.h"\r
 #include "Imem.h"\r
 \r
-#define EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT  (EFI_PAGE_SIZE)\r
-\r
 //\r
 // Entry for tracking the memory regions for each memory type to coalesce similar memory types\r
 //\r
@@ -204,7 +202,7 @@ CoreAddRange (
   // If we are in EFI 1.10 compatability mode no event groups will be\r
   // found and nothing will happen we we call this function. These events\r
   // will get signaled but since a lock is held around the call to this\r
-  // function the notificaiton events will only be called after this funciton\r
+  // function the notificaiton events will only be called after this function\r
   // returns and the lock is released.\r
   //\r
   CoreNotifySignalList (&gEfiEventMemoryMapChangeGuid);\r
@@ -287,12 +285,14 @@ AllocateMemoryMapEntry (
     //\r
     // The list is empty, to allocate one page to refuel the list\r
     //\r
-    FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData, EFI_SIZE_TO_PAGES(DEFAULT_PAGE_ALLOCATION), DEFAULT_PAGE_ALLOCATION);\r
-    if(FreeDescriptorEntries != NULL) {\r
+    FreeDescriptorEntries = CoreAllocatePoolPages (EfiBootServicesData,\r
+                              EFI_SIZE_TO_PAGES (DEFAULT_PAGE_ALLOCATION_GRANULARITY),\r
+                              DEFAULT_PAGE_ALLOCATION_GRANULARITY);\r
+    if (FreeDescriptorEntries != NULL) {\r
       //\r
       // Enque the free memmory map entries into the list\r
       //\r
-      for (Index = 0; Index< DEFAULT_PAGE_ALLOCATION / sizeof(MEMORY_MAP); Index++) {\r
+      for (Index = 0; Index < DEFAULT_PAGE_ALLOCATION_GRANULARITY / sizeof(MEMORY_MAP); Index++) {\r
         FreeDescriptorEntries[Index].Signature = MEMORY_MAP_SIGNATURE;\r
         InsertTailList (&mFreeMemoryMapEntryList, &FreeDescriptorEntries[Index].Link);\r
       }\r
@@ -553,6 +553,9 @@ CoreAddMemoryDescriptor (
   CoreFreeMemoryMapStack ();\r
   CoreReleaseMemoryLock ();\r
 \r
+  ApplyMemoryProtectionPolicy (EfiMaxMemoryType, Type, Start,\r
+    LShiftU64 (NumberOfPages, EFI_PAGE_SHIFT));\r
+\r
   //\r
   // If Loading Module At Fixed Address feature is enabled. try to allocate memory with Runtime code & Boot time code type\r
   //\r
@@ -751,6 +754,17 @@ CoreConvertPagesEx (
       return EFI_NOT_FOUND;\r
     }\r
 \r
+    //\r
+    // If we are converting the type of the range from EfiConventionalMemory to\r
+    // another type, we have to ensure that the entire range is covered by a\r
+    // single entry.\r
+    //\r
+    if (ChangingType && (NewType != EfiConventionalMemory)) {\r
+      if (Entry->End < End) {\r
+        DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: range %lx - %lx covers multiple entries\n", Start, End));\r
+        return EFI_NOT_FOUND;\r
+      }\r
+    }\r
     //\r
     // Convert range to the end, or to the end of the descriptor\r
     // if that's all we've got\r
@@ -774,7 +788,12 @@ CoreConvertPagesEx (
       // Debug code - verify conversion is allowed\r
       //\r
       if (!(NewType == EfiConventionalMemory ? 1 : 0) ^ (Entry->Type == EfiConventionalMemory ? 1 : 0)) {\r
-        DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types\n"));\r
+        DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "ConvertPages: Incompatible memory types, "));\r
+        if (Entry->Type == EfiConventionalMemory) {\r
+          DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to free have been freed\n"));\r
+        } else {\r
+          DEBUG ((DEBUG_ERROR | DEBUG_PAGE, "the pages to allocate have been allocated\n"));\r
+        }\r
         return EFI_NOT_FOUND;\r
       }\r
 \r
@@ -1219,14 +1238,14 @@ CoreInternalAllocatePages (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;\r
+  Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
 \r
   if  (MemoryType == EfiACPIReclaimMemory   ||\r
        MemoryType == EfiACPIMemoryNVS       ||\r
        MemoryType == EfiRuntimeServicesCode ||\r
        MemoryType == EfiRuntimeServicesData) {\r
 \r
-    Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+    Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
   }\r
 \r
   if (Type == AllocateAddress) {\r
@@ -1335,7 +1354,17 @@ CoreAllocatePages (
 \r
   Status = CoreInternalAllocatePages (Type, MemoryType, NumberOfPages, Memory);\r
   if (!EFI_ERROR (Status)) {\r
-    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePages, MemoryType, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) *Memory);\r
+    CoreUpdateProfile (\r
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r
+      MemoryProfileActionAllocatePages,\r
+      MemoryType,\r
+      EFI_PAGES_TO_SIZE (NumberOfPages),\r
+      (VOID *) (UINTN) *Memory,\r
+      NULL\r
+      );\r
+    InstallMemoryAttributesTableOnMemoryAllocation (MemoryType);\r
+    ApplyMemoryProtectionPolicy (EfiConventionalMemory, MemoryType, *Memory,\r
+      EFI_PAGES_TO_SIZE (NumberOfPages));\r
   }\r
   return Status;\r
 }\r
@@ -1345,6 +1374,7 @@ CoreAllocatePages (
 \r
   @param  Memory                 Base address of memory being freed\r
   @param  NumberOfPages          The number of pages to free\r
+  @param  MemoryType             Pointer to memory type\r
 \r
   @retval EFI_NOT_FOUND          Could not find the entry that covers the range\r
   @retval EFI_INVALID_PARAMETER  Address not aligned\r
@@ -1355,7 +1385,8 @@ EFI_STATUS
 EFIAPI\r
 CoreInternalFreePages (\r
   IN EFI_PHYSICAL_ADDRESS   Memory,\r
-  IN UINTN                  NumberOfPages\r
+  IN UINTN                  NumberOfPages,\r
+  OUT EFI_MEMORY_TYPE       *MemoryType OPTIONAL\r
   )\r
 {\r
   EFI_STATUS      Status;\r
@@ -1383,7 +1414,7 @@ CoreInternalFreePages (
     goto Done;\r
   }\r
 \r
-  Alignment = EFI_DEFAULT_PAGE_ALLOCATION_ALIGNMENT;\r
+  Alignment = DEFAULT_PAGE_ALLOCATION_GRANULARITY;\r
 \r
   ASSERT (Entry != NULL);\r
   if  (Entry->Type == EfiACPIReclaimMemory   ||\r
@@ -1391,7 +1422,7 @@ CoreInternalFreePages (
        Entry->Type == EfiRuntimeServicesCode ||\r
        Entry->Type == EfiRuntimeServicesData) {\r
 \r
-    Alignment = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;\r
+    Alignment = RUNTIME_PAGE_ALLOCATION_GRANULARITY;\r
 \r
   }\r
 \r
@@ -1403,6 +1434,10 @@ CoreInternalFreePages (
   NumberOfPages += EFI_SIZE_TO_PAGES (Alignment) - 1;\r
   NumberOfPages &= ~(EFI_SIZE_TO_PAGES (Alignment) - 1);\r
 \r
+  if (MemoryType != NULL) {\r
+    *MemoryType = Entry->Type;\r
+  }\r
+\r
   Status = CoreConvertPages (Memory, NumberOfPages, EfiConventionalMemory);\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -1432,11 +1467,22 @@ CoreFreePages (
   IN UINTN                 NumberOfPages\r
   )\r
 {\r
-  EFI_STATUS  Status;\r
+  EFI_STATUS        Status;\r
+  EFI_MEMORY_TYPE   MemoryType;\r
 \r
-  Status = CoreInternalFreePages (Memory, NumberOfPages);\r
+  Status = CoreInternalFreePages (Memory, NumberOfPages, &MemoryType);\r
   if (!EFI_ERROR (Status)) {\r
-    CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePages, (EFI_MEMORY_TYPE) 0, EFI_PAGES_TO_SIZE (NumberOfPages), (VOID *) (UINTN) Memory);\r
+    CoreUpdateProfile (\r
+      (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),\r
+      MemoryProfileActionFreePages,\r
+      MemoryType,\r
+      EFI_PAGES_TO_SIZE (NumberOfPages),\r
+      (VOID *) (UINTN) Memory,\r
+      NULL\r
+      );\r
+    InstallMemoryAttributesTableOnMemoryAllocation (MemoryType);\r
+    ApplyMemoryProtectionPolicy (MemoryType, EfiConventionalMemory, Memory,\r
+      EFI_PAGES_TO_SIZE (NumberOfPages));\r
   }\r
   return Status;\r
 }\r
@@ -1895,12 +1941,12 @@ CoreTerminateMemoryMap (
         if (mMemoryTypeStatistics[Entry->Type].Runtime) {\r
           ASSERT (Entry->Type != EfiACPIReclaimMemory);\r
           ASSERT (Entry->Type != EfiACPIMemoryNVS);\r
-          if ((Entry->Start & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) {\r
+          if ((Entry->Start & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {\r
             DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));\r
             Status =  EFI_INVALID_PARAMETER;\r
             goto Done;\r
           }\r
-          if (((Entry->End + 1) & (EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT - 1)) != 0) {\r
+          if (((Entry->End + 1) & (RUNTIME_PAGE_ALLOCATION_GRANULARITY - 1)) != 0) {\r
             DEBUG((DEBUG_ERROR | DEBUG_PAGE, "ExitBootServices: A RUNTIME memory entry is not on a proper alignment.\n"));\r
             Status =  EFI_INVALID_PARAMETER;\r
             goto Done;\r