]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ArmPkg/ArmMmuLib: use a pool allocation for the root table
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Fri, 9 Sep 2016 08:50:21 +0000 (09:50 +0100)
committerArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 13 Sep 2016 12:43:11 +0000 (13:43 +0100)
Currently, we allocate a full page for the root translation table, even
if the configured translation only requires two entries (16 bytes) for
the root level, which happens to be the case for a 40 bit VA. Likewise,
for a 36-bit VA space, the root table only needs 16 entries of 8 bytes
each, adding up to 128 bytes.

So switch to a pool allocation for the root table if we can, but take into
account that the architecture requires it to be naturally aligned to its
size, i.e., a 64 byte table requires 64 byte alignment, whereas pool
allocations in general are only guaranteed to be aligned to 8 bytes.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Reviewed-by: Leif Lindholm <leif.lindholm@linaro.org>
ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c

index 1ff584ec9eec69ebc62764b058cb60b9b75d60e5..57e789f68b3b7527e495fc6d81be4dfa4153ca50 100644 (file)
@@ -553,12 +553,14 @@ ArmConfigureMmu (
   )\r
 {\r
   VOID*                         TranslationTable;\r
   )\r
 {\r
   VOID*                         TranslationTable;\r
+  VOID*                         TranslationTableBuffer;\r
   UINT32                        TranslationTableAttribute;\r
   ARM_MEMORY_REGION_DESCRIPTOR *MemoryTableEntry;\r
   UINT64                        MaxAddress;\r
   UINT64                        TopAddress;\r
   UINTN                         T0SZ;\r
   UINTN                         RootTableEntryCount;\r
   UINT32                        TranslationTableAttribute;\r
   ARM_MEMORY_REGION_DESCRIPTOR *MemoryTableEntry;\r
   UINT64                        MaxAddress;\r
   UINT64                        TopAddress;\r
   UINTN                         T0SZ;\r
   UINTN                         RootTableEntryCount;\r
+  UINTN                         RootTableEntrySize;\r
   UINT64                        TCR;\r
   RETURN_STATUS                 Status;\r
 \r
   UINT64                        TCR;\r
   RETURN_STATUS                 Status;\r
 \r
@@ -638,8 +640,19 @@ ArmConfigureMmu (
   // Set TCR\r
   ArmSetTCR (TCR);\r
 \r
   // Set TCR\r
   ArmSetTCR (TCR);\r
 \r
-  // Allocate pages for translation table\r
-  TranslationTable = AllocatePages (1);\r
+  // Allocate pages for translation table. Pool allocations are 8 byte aligned,\r
+  // but we may require a higher alignment based on the size of the root table.\r
+  RootTableEntrySize = RootTableEntryCount * sizeof(UINT64);\r
+  if (RootTableEntrySize < EFI_PAGE_SIZE / 2) {\r
+    TranslationTableBuffer = AllocatePool (2 * RootTableEntrySize - 8);\r
+    //\r
+    // Naturally align the root table. Preserves possible NULL value\r
+    //\r
+    TranslationTable = (VOID *)((UINTN)(TranslationTableBuffer - 1) | (RootTableEntrySize - 1)) + 1;\r
+  } else {\r
+    TranslationTable = AllocatePages (1);\r
+    TranslationTableBuffer = NULL;\r
+  }\r
   if (TranslationTable == NULL) {\r
     return RETURN_OUT_OF_RESOURCES;\r
   }\r
   if (TranslationTable == NULL) {\r
     return RETURN_OUT_OF_RESOURCES;\r
   }\r
@@ -653,10 +666,10 @@ ArmConfigureMmu (
   }\r
 \r
   if (TranslationTableSize != NULL) {\r
   }\r
 \r
   if (TranslationTableSize != NULL) {\r
-    *TranslationTableSize = RootTableEntryCount * sizeof(UINT64);\r
+    *TranslationTableSize = RootTableEntrySize;\r
   }\r
 \r
   }\r
 \r
-  ZeroMem (TranslationTable, RootTableEntryCount * sizeof(UINT64));\r
+  ZeroMem (TranslationTable, RootTableEntrySize);\r
 \r
   // Disable MMU and caches. ArmDisableMmu() also invalidates the TLBs\r
   ArmDisableMmu ();\r
 \r
   // Disable MMU and caches. ArmDisableMmu() also invalidates the TLBs\r
   ArmDisableMmu ();\r
@@ -716,7 +729,11 @@ ArmConfigureMmu (
   return RETURN_SUCCESS;\r
 \r
 FREE_TRANSLATION_TABLE:\r
   return RETURN_SUCCESS;\r
 \r
 FREE_TRANSLATION_TABLE:\r
-  FreePages (TranslationTable, 1);\r
+  if (TranslationTableBuffer != NULL) {\r
+    FreePool (TranslationTableBuffer);\r
+  } else {\r
+    FreePages (TranslationTable, 1);\r
+  }\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r