From d32702d2c2aa23e828363a7f88829b78ce36c3af Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Fri, 9 Sep 2016 09:50:21 +0100 Subject: [PATCH] ArmPkg/ArmMmuLib: use a pool allocation for the root table 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 Reviewed-by: Leif Lindholm --- .../Library/ArmMmuLib/AArch64/ArmMmuLibCore.c | 27 +++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c index 1ff584ec9e..57e789f68b 100644 --- a/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c +++ b/ArmPkg/Library/ArmMmuLib/AArch64/ArmMmuLibCore.c @@ -553,12 +553,14 @@ ArmConfigureMmu ( ) { VOID* TranslationTable; + VOID* TranslationTableBuffer; UINT32 TranslationTableAttribute; ARM_MEMORY_REGION_DESCRIPTOR *MemoryTableEntry; UINT64 MaxAddress; UINT64 TopAddress; UINTN T0SZ; UINTN RootTableEntryCount; + UINTN RootTableEntrySize; UINT64 TCR; RETURN_STATUS Status; @@ -638,8 +640,19 @@ ArmConfigureMmu ( // Set TCR ArmSetTCR (TCR); - // Allocate pages for translation table - TranslationTable = AllocatePages (1); + // 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); + if (RootTableEntrySize < EFI_PAGE_SIZE / 2) { + TranslationTableBuffer = AllocatePool (2 * RootTableEntrySize - 8); + // + // Naturally align the root table. Preserves possible NULL value + // + TranslationTable = (VOID *)((UINTN)(TranslationTableBuffer - 1) | (RootTableEntrySize - 1)) + 1; + } else { + TranslationTable = AllocatePages (1); + TranslationTableBuffer = NULL; + } if (TranslationTable == NULL) { return RETURN_OUT_OF_RESOURCES; } @@ -653,10 +666,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 (); @@ -716,7 +729,11 @@ ArmConfigureMmu ( return RETURN_SUCCESS; FREE_TRANSLATION_TABLE: - FreePages (TranslationTable, 1); + if (TranslationTableBuffer != NULL) { + FreePool (TranslationTableBuffer); + } else { + FreePages (TranslationTable, 1); + } return Status; } -- 2.39.2