X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FPool.c;h=734fc94bf6129ad20f3e8846c9cf13aaee7266ab;hp=77ca5671dcfea69d08273d18c8823f871c8d32e3;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=235a4490c8ce8b6dbac49e6ae3559cb73d6bf620 diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c index 77ca5671dc..734fc94bf6 100644 --- a/MdeModulePkg/Core/Dxe/Mem/Pool.c +++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c @@ -1,20 +1,14 @@ /** @file UEFI Memory pool management functions. -Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at -http://opensource.org/licenses/bsd-license.php - -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "DxeMain.h" #include "Imem.h" -#include "HeapGuard.h" +#include "HeapGuard.h" STATIC EFI_LOCK mPoolMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY); @@ -26,7 +20,8 @@ typedef struct { } POOL_FREE; -#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0') +#define POOL_HEAD_SIGNATURE SIGNATURE_32('p','h','d','0') +#define POOLPAGE_HEAD_SIGNATURE SIGNATURE_32('p','h','d','1') typedef struct { UINT32 Signature; UINT32 Reserved; @@ -170,7 +165,7 @@ LookupPoolHead ( } } - Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE); + Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE); if (Pool == NULL) { return NULL; } @@ -215,8 +210,8 @@ CoreInternalAllocatePool ( OUT VOID **Buffer ) { - EFI_STATUS Status; - BOOLEAN NeedGuard; + EFI_STATUS Status; + BOOLEAN NeedGuard; // // If it's not a valid type, fail it @@ -240,8 +235,8 @@ CoreInternalAllocatePool ( return EFI_OUT_OF_RESOURCES; } - NeedGuard = IsPoolTypeToGuard (PoolType) && !mOnGuarding; - + NeedGuard = IsPoolTypeToGuard (PoolType) && !mOnGuarding; + // // Acquire the memory lock and make the allocation // @@ -250,7 +245,7 @@ CoreInternalAllocatePool ( return EFI_OUT_OF_RESOURCES; } - *Buffer = CoreAllocatePoolI (PoolType, Size, NeedGuard); + *Buffer = CoreAllocatePoolI (PoolType, Size, NeedGuard); CoreReleaseLock (&mPoolMemoryLock); return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES; } @@ -302,7 +297,7 @@ CoreAllocatePool ( @param PoolType The type of memory for the new pool pages @param NoPages No of pages to allocate @param Granularity Bits to align. - @param NeedGuard Flag to indicate Guard page is needed or not + @param NeedGuard Flag to indicate Guard page is needed or not @return The allocated memory, or NULL @@ -312,8 +307,8 @@ VOID * CoreAllocatePoolPagesI ( IN EFI_MEMORY_TYPE PoolType, IN UINTN NoPages, - IN UINTN Granularity, - IN BOOLEAN NeedGuard + IN UINTN Granularity, + IN BOOLEAN NeedGuard ) { VOID *Buffer; @@ -324,14 +319,14 @@ CoreAllocatePoolPagesI ( return NULL; } - Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard); + Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard); CoreReleaseMemoryLock (); if (Buffer != NULL) { - if (NeedGuard) { - SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages); - } - ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType, + if (NeedGuard) { + SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages); + } + ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType, (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages)); } return Buffer; @@ -343,7 +338,7 @@ CoreAllocatePoolPagesI ( @param PoolType Type of pool to allocate @param Size The amount of pool to allocate - @param NeedGuard Flag to indicate Guard page is needed or not + @param NeedGuard Flag to indicate Guard page is needed or not @return The allocate pool, or NULL @@ -351,8 +346,8 @@ CoreAllocatePoolPagesI ( VOID * CoreAllocatePoolI ( IN EFI_MEMORY_TYPE PoolType, - IN UINTN Size, - IN BOOLEAN NeedGuard + IN UINTN Size, + IN BOOLEAN NeedGuard ) { POOL *Pool; @@ -366,7 +361,8 @@ CoreAllocatePoolI ( UINTN Offset, MaxOffset; UINTN NoPages; UINTN Granularity; - BOOLEAN HasPoolTail; + BOOLEAN HasPoolTail; + BOOLEAN PageAsPool; ASSERT_LOCKED (&mPoolMemoryLock); @@ -384,9 +380,10 @@ CoreAllocatePoolI ( // Adjust the size by the pool header & tail overhead // - HasPoolTail = !(NeedGuard && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); - + HasPoolTail = !(NeedGuard && + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); + PageAsPool = (IsHeapGuardEnabled (GUARD_HEAP_TYPE_FREED) && !mOnGuarding); + // // Adjusting the Size to be of proper alignment so that // we don't get an unaligned access fault later when @@ -406,16 +403,16 @@ CoreAllocatePoolI ( // If allocation is over max size, just allocate pages for the request // (slow) // - if (Index >= SIZE_TO_LIST (Granularity) || NeedGuard) { - if (!HasPoolTail) { - Size -= sizeof (POOL_TAIL); - } - NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; + if (Index >= SIZE_TO_LIST (Granularity) || NeedGuard || PageAsPool) { + if (!HasPoolTail) { + Size -= sizeof (POOL_TAIL); + } + NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); - Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard); - if (NeedGuard) { - Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size); - } + Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard); + if (NeedGuard) { + Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size); + } goto Done; } @@ -443,8 +440,8 @@ CoreAllocatePoolI ( // // Get another page // - NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity), - Granularity, NeedGuard); + NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity), + Granularity, NeedGuard); if (NewPage == NULL) { goto Done; } @@ -490,36 +487,36 @@ Done: if (Head != NULL) { - // - // Account the allocation - // - Pool->Used += Size; - + // + // Account the allocation + // + Pool->Used += Size; + // // If we have a pool buffer, fill in the header & tail info // - Head->Signature = POOL_HEAD_SIGNATURE; + Head->Signature = (PageAsPool) ? POOLPAGE_HEAD_SIGNATURE : POOL_HEAD_SIGNATURE; Head->Size = Size; Head->Type = (EFI_MEMORY_TYPE) PoolType; Buffer = Head->Data; - - if (HasPoolTail) { - Tail = HEAD_TO_TAIL (Head); - Tail->Signature = POOL_TAIL_SIGNATURE; - Tail->Size = Size; - - Size -= POOL_OVERHEAD; - } else { - Size -= SIZE_OF_POOL_HEAD; - } - - DEBUG_CLEAR_MEMORY (Buffer, Size); + + if (HasPoolTail) { + Tail = HEAD_TO_TAIL (Head); + Tail->Signature = POOL_TAIL_SIGNATURE; + Tail->Size = Size; + + Size -= POOL_OVERHEAD; + } else { + Size -= SIZE_OF_POOL_HEAD; + } + + DEBUG_CLEAR_MEMORY (Buffer, Size); DEBUG (( DEBUG_POOL, "AllocatePoolI: Type %x, Addr %p (len %lx) %,ld\n", PoolType, Buffer, - (UINT64)Size, + (UINT64)Size, (UINT64) Pool->Used )); @@ -615,38 +612,47 @@ CoreFreePoolPagesI ( CoreFreePoolPages (Memory, NoPages); CoreReleaseMemoryLock (); + GuardFreedPagesChecked (Memory, NoPages); ApplyMemoryProtectionPolicy (PoolType, EfiConventionalMemory, (EFI_PHYSICAL_ADDRESS)(UINTN)Memory, EFI_PAGES_TO_SIZE (NoPages)); } -/** - Internal function. Frees guarded pool pages. - - @param PoolType The type of memory for the pool pages - @param Memory The base address to free - @param NoPages The number of pages to free - -**/ -STATIC -VOID -CoreFreePoolPagesWithGuard ( - IN EFI_MEMORY_TYPE PoolType, - IN EFI_PHYSICAL_ADDRESS Memory, - IN UINTN NoPages - ) -{ - EFI_PHYSICAL_ADDRESS MemoryGuarded; - UINTN NoPagesGuarded; - - MemoryGuarded = Memory; - NoPagesGuarded = NoPages; - - AdjustMemoryF (&Memory, &NoPages); - CoreFreePoolPagesI (PoolType, Memory, NoPages); - - UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded); -} - +/** + Internal function. Frees guarded pool pages. + + @param PoolType The type of memory for the pool pages + @param Memory The base address to free + @param NoPages The number of pages to free + +**/ +STATIC +VOID +CoreFreePoolPagesWithGuard ( + IN EFI_MEMORY_TYPE PoolType, + IN EFI_PHYSICAL_ADDRESS Memory, + IN UINTN NoPages + ) +{ + EFI_PHYSICAL_ADDRESS MemoryGuarded; + UINTN NoPagesGuarded; + + MemoryGuarded = Memory; + NoPagesGuarded = NoPages; + + AdjustMemoryF (&Memory, &NoPages); + // + // It's safe to unset Guard page inside memory lock because there should + // be no memory allocation occurred in updating memory page attribute at + // this point. And unsetting Guard page before free will prevent Guard + // page just freed back to pool from being allocated right away before + // marking it usable (from non-present to present). + // + UnsetGuardForMemory (MemoryGuarded, NoPagesGuarded); + if (NoPages > 0) { + CoreFreePoolPagesI (PoolType, Memory, NoPages); + } +} + /** Internal function to free a pool entry. Caller must have the memory lock held @@ -675,46 +681,51 @@ CoreFreePoolI ( UINTN Offset; BOOLEAN AllFree; UINTN Granularity; - BOOLEAN IsGuarded; - BOOLEAN HasPoolTail; + BOOLEAN IsGuarded; + BOOLEAN HasPoolTail; + BOOLEAN PageAsPool; ASSERT(Buffer != NULL); // // Get the head & tail of the pool entry // - Head = CR (Buffer, POOL_HEAD, Data, POOL_HEAD_SIGNATURE); + Head = BASE_CR (Buffer, POOL_HEAD, Data); ASSERT(Head != NULL); - if (Head->Signature != POOL_HEAD_SIGNATURE) { + if (Head->Signature != POOL_HEAD_SIGNATURE && + Head->Signature != POOLPAGE_HEAD_SIGNATURE) { + ASSERT (Head->Signature == POOL_HEAD_SIGNATURE || + Head->Signature == POOLPAGE_HEAD_SIGNATURE); return EFI_INVALID_PARAMETER; } - IsGuarded = IsPoolTypeToGuard (Head->Type) && - IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); - HasPoolTail = !(IsGuarded && - ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); - - if (HasPoolTail) { - Tail = HEAD_TO_TAIL (Head); - ASSERT (Tail != NULL); - - // - // Debug - // - ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE); - ASSERT (Head->Size == Tail->Size); - - if (Tail->Signature != POOL_TAIL_SIGNATURE) { - return EFI_INVALID_PARAMETER; - } - - if (Head->Size != Tail->Size) { - return EFI_INVALID_PARAMETER; - } + IsGuarded = IsPoolTypeToGuard (Head->Type) && + IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); + HasPoolTail = !(IsGuarded && + ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0)); + PageAsPool = (Head->Signature == POOLPAGE_HEAD_SIGNATURE); + + if (HasPoolTail) { + Tail = HEAD_TO_TAIL (Head); + ASSERT (Tail != NULL); + + // + // Debug + // + ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE); + ASSERT (Head->Size == Tail->Size); + + if (Tail->Signature != POOL_TAIL_SIGNATURE) { + return EFI_INVALID_PARAMETER; + } + + if (Head->Size != Tail->Size) { + return EFI_INVALID_PARAMETER; + } } - ASSERT_LOCKED (&mPoolMemoryLock); - + ASSERT_LOCKED (&mPoolMemoryLock); + // // Determine the pool type and account for it // @@ -749,27 +760,27 @@ CoreFreePoolI ( // // If it's not on the list, it must be pool pages // - if (Index >= SIZE_TO_LIST (Granularity) || IsGuarded) { + if (Index >= SIZE_TO_LIST (Granularity) || IsGuarded || PageAsPool) { // // Return the memory pages back to free memory // - NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; + NoPages = EFI_SIZE_TO_PAGES (Size) + EFI_SIZE_TO_PAGES (Granularity) - 1; NoPages &= ~(UINTN)(EFI_SIZE_TO_PAGES (Granularity) - 1); - if (IsGuarded) { - Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); - CoreFreePoolPagesWithGuard ( - Pool->MemoryType, - (EFI_PHYSICAL_ADDRESS)(UINTN)Head, - NoPages - ); - } else { - CoreFreePoolPagesI ( - Pool->MemoryType, - (EFI_PHYSICAL_ADDRESS)(UINTN)Head, - NoPages - ); - } + if (IsGuarded) { + Head = AdjustPoolHeadF ((EFI_PHYSICAL_ADDRESS)(UINTN)Head); + CoreFreePoolPagesWithGuard ( + Pool->MemoryType, + (EFI_PHYSICAL_ADDRESS)(UINTN)Head, + NoPages + ); + } else { + CoreFreePoolPagesI ( + Pool->MemoryType, + (EFI_PHYSICAL_ADDRESS)(UINTN)Head, + NoPages + ); + } } else {