[edk2] ArmPkg/ArmMmuLib: use a pool allocation for the root table

Message ID 1473411633-25763-1-git-send-email-ard.biesheuvel@linaro.org
State New
Headers show

Commit Message

Ard Biesheuvel Sept. 9, 2016, 9 a.m.
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, 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>

---
 ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 23 +++++++++++++-------
 1 file changed, 15 insertions(+), 8 deletions(-)

-- 
2.7.4

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Comments

Ard Biesheuvel Sept. 9, 2016, 10:07 a.m. | #1
Please disregard, I will follow up with a more elaborate series.

On 9 September 2016 at 10:00, Ard Biesheuvel <ard.biesheuvel@linaro.org> wrote:
> 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, 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>

> ---

>  ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 23 +++++++++++++-------

>  1 file changed, 15 insertions(+), 8 deletions(-)

>

> diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c

> index b5900a761f80..297771a42761 100644

> --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c

> +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c

> @@ -580,11 +580,12 @@ ArmConfigureMmu (

>    )

>  {

>    VOID*                         TranslationTable;

> -  UINTN                         TranslationTablePageCount;

> +  VOID*                         TranslationTableBuffer;

>    UINT32                        TranslationTableAttribute;

>    UINT64                        MaxAddress;

>    UINTN                         T0SZ;

>    UINTN                         RootTableEntryCount;

> +  UINTN                         RootTableEntrySize;

>    UINT64                        TCR;

>    RETURN_STATUS                 Status;

>

> @@ -656,12 +657,18 @@ ArmConfigureMmu (

>    // Set TCR

>    ArmSetTCR (TCR);

>

> -  // Allocate pages for translation table

> -  TranslationTablePageCount = EFI_SIZE_TO_PAGES(RootTableEntryCount * sizeof(UINT64));

> -  TranslationTable = (UINT64*)AllocateAlignedPages (TranslationTablePageCount, TT_ALIGNMENT_DESCRIPTION_TABLE);

> -  if (TranslationTable == NULL) {

> +  // Allocate pages for translation table. Pool allocations are 8 byte aligned,

> +  // but we may require a higher alignment based on the size of the root table.

> +  RootTableEntrySize = RootTableEntryCount * sizeof(UINT64);

> +  TranslationTableBuffer = AllocatePool (2 * RootTableEntrySize - 8);

> +    if (TranslationTableBuffer == NULL) {

>      return RETURN_OUT_OF_RESOURCES;

>    }

> +  //

> +  // Naturally align the root table

> +  //

> +  TranslationTable = (VOID *)((UINTN)(TranslationTableBuffer - 1) | (RootTableEntrySize - 1)) + 1;

> +

>    // We set TTBR0 just after allocating the table to retrieve its location from the subsequent

>    // functions without needing to pass this value across the functions. The MMU is only enabled

>    // after the translation tables are populated.

> @@ -672,10 +679,10 @@ ArmConfigureMmu (

>    }

>

>    if (TranslationTableSize != NULL) {

> -    *TranslationTableSize = RootTableEntryCount * sizeof(UINT64);

> +    *TranslationTableSize = RootTableEntrySize;

>    }

>

> -  ZeroMem (TranslationTable, RootTableEntryCount * sizeof(UINT64));

> +  ZeroMem (TranslationTable, RootTableEntrySize);

>

>    // Disable MMU and caches. ArmDisableMmu() also invalidates the TLBs

>    ArmDisableMmu ();

> @@ -735,7 +742,7 @@ ArmConfigureMmu (

>    return RETURN_SUCCESS;

>

>  FREE_TRANSLATION_TABLE:

> -  FreePages (TranslationTable, TranslationTablePageCount);

> +  FreePool (TranslationTableBuffer);

>    return Status;

>  }

>

> --

> 2.7.4

>

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Patch

diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
index b5900a761f80..297771a42761 100644
--- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
+++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c
@@ -580,11 +580,12 @@  ArmConfigureMmu (
   )
 {
   VOID*                         TranslationTable;
-  UINTN                         TranslationTablePageCount;
+  VOID*                         TranslationTableBuffer;
   UINT32                        TranslationTableAttribute;
   UINT64                        MaxAddress;
   UINTN                         T0SZ;
   UINTN                         RootTableEntryCount;
+  UINTN                         RootTableEntrySize;
   UINT64                        TCR;
   RETURN_STATUS                 Status;
 
@@ -656,12 +657,18 @@  ArmConfigureMmu (
   // Set TCR
   ArmSetTCR (TCR);
 
-  // Allocate pages for translation table
-  TranslationTablePageCount = EFI_SIZE_TO_PAGES(RootTableEntryCount * sizeof(UINT64));
-  TranslationTable = (UINT64*)AllocateAlignedPages (TranslationTablePageCount, TT_ALIGNMENT_DESCRIPTION_TABLE);
-  if (TranslationTable == NULL) {
+  // Allocate pages for translation table. Pool allocations are 8 byte aligned,
+  // but we may require a higher alignment based on the size of the root table.
+  RootTableEntrySize = RootTableEntryCount * sizeof(UINT64);
+  TranslationTableBuffer = AllocatePool (2 * RootTableEntrySize - 8);
+    if (TranslationTableBuffer == NULL) {
     return RETURN_OUT_OF_RESOURCES;
   }
+  //
+  // Naturally align the root table
+  //
+  TranslationTable = (VOID *)((UINTN)(TranslationTableBuffer - 1) | (RootTableEntrySize - 1)) + 1;
+
   // We set TTBR0 just after allocating the table to retrieve its location from the subsequent
   // functions without needing to pass this value across the functions. The MMU is only enabled
   // after the translation tables are populated.
@@ -672,10 +679,10 @@  ArmConfigureMmu (
   }
 
   if (TranslationTableSize != NULL) {
-    *TranslationTableSize = RootTableEntryCount * sizeof(UINT64);
+    *TranslationTableSize = RootTableEntrySize;
   }
 
-  ZeroMem (TranslationTable, RootTableEntryCount * sizeof(UINT64));
+  ZeroMem (TranslationTable, RootTableEntrySize);
 
   // Disable MMU and caches. ArmDisableMmu() also invalidates the TLBs
   ArmDisableMmu ();
@@ -735,7 +742,7 @@  ArmConfigureMmu (
   return RETURN_SUCCESS;
 
 FREE_TRANSLATION_TABLE:
-  FreePages (TranslationTable, TranslationTablePageCount);
+  FreePool (TranslationTableBuffer);
   return Status;
 }