X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=MdeModulePkg%2FCore%2FDxe%2FMem%2FPool.c;h=734fc94bf6129ad20f3e8846c9cf13aaee7266ab;hp=528c8e8ce9a52326d0db5e1d6dd718e158b13475;hb=9d510e61fceee7b92955ef9a3c20343752d8ce3f;hpb=2eb989bc29c2c0bacae6d79fc7e066c58ec12b5e
diff --git a/MdeModulePkg/Core/Dxe/Mem/Pool.c b/MdeModulePkg/Core/Dxe/Mem/Pool.c
index 528c8e8ce9..734fc94bf6 100644
--- a/MdeModulePkg/Core/Dxe/Mem/Pool.c
+++ b/MdeModulePkg/Core/Dxe/Mem/Pool.c
@@ -1,19 +1,16 @@
/** @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"
+
+STATIC EFI_LOCK mPoolMemoryLock = EFI_INITIALIZE_LOCK_VARIABLE (TPL_NOTIFY);
#define POOL_FREE_SIGNATURE SIGNATURE_32('p','f','r','0')
typedef struct {
@@ -23,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;
@@ -52,13 +50,13 @@ typedef struct {
// as we would in a strict power-of-2 sequence
//
STATIC CONST UINT16 mPoolSizeTable[] = {
- 64, 128, 192, 320, 512, 832, 1344, 2176, 3520, 5696, 9216, 14912, 24128
+ 128, 256, 384, 640, 1024, 1664, 2688, 4352, 7040, 11392, 18432, 29824
};
#define SIZE_TO_LIST(a) (GetPoolIndexFromSize (a))
#define LIST_TO_SIZE(a) (mPoolSizeTable [a])
-#define MAX_POOL_LIST (sizeof (mPoolSizeTable) / sizeof (mPoolSizeTable[0]))
+#define MAX_POOL_LIST (ARRAY_SIZE (mPoolSizeTable))
#define MAX_POOL_SIZE (MAX_ADDRESS - POOL_OVERHEAD)
@@ -167,7 +165,7 @@ LookupPoolHead (
}
}
- Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL));
+ Pool = CoreAllocatePoolI (EfiBootServicesData, sizeof (POOL), FALSE);
if (Pool == NULL) {
return NULL;
}
@@ -212,7 +210,8 @@ CoreInternalAllocatePool (
OUT VOID **Buffer
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ BOOLEAN NeedGuard;
//
// If it's not a valid type, fail it
@@ -236,16 +235,18 @@ CoreInternalAllocatePool (
return EFI_OUT_OF_RESOURCES;
}
+ NeedGuard = IsPoolTypeToGuard (PoolType) && !mOnGuarding;
+
//
// Acquire the memory lock and make the allocation
//
- Status = CoreAcquireLockOrFail (&gMemoryLock);
+ Status = CoreAcquireLockOrFail (&mPoolMemoryLock);
if (EFI_ERROR (Status)) {
return EFI_OUT_OF_RESOURCES;
}
- *Buffer = CoreAllocatePoolI (PoolType, Size);
- CoreReleaseMemoryLock ();
+ *Buffer = CoreAllocatePoolI (PoolType, Size, NeedGuard);
+ CoreReleaseLock (&mPoolMemoryLock);
return (*Buffer != NULL) ? EFI_SUCCESS : EFI_OUT_OF_RESOURCES;
}
@@ -276,17 +277,68 @@ CoreAllocatePool (
Status = CoreInternalAllocatePool (PoolType, Size, Buffer);
if (!EFI_ERROR (Status)) {
- CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionAllocatePool, PoolType, Size, *Buffer);
+ CoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+ MemoryProfileActionAllocatePool,
+ PoolType,
+ Size,
+ *Buffer,
+ NULL
+ );
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);
}
return Status;
}
+/**
+ Internal function. Used by the pool functions to allocate pages
+ to back pool allocation requests.
+
+ @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
+
+ @return The allocated memory, or NULL
+
+**/
+STATIC
+VOID *
+CoreAllocatePoolPagesI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN UINTN NoPages,
+ IN UINTN Granularity,
+ IN BOOLEAN NeedGuard
+ )
+{
+ VOID *Buffer;
+ EFI_STATUS Status;
+
+ Status = CoreAcquireLockOrFail (&gMemoryLock);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Buffer = CoreAllocatePoolPages (PoolType, NoPages, Granularity, NeedGuard);
+ CoreReleaseMemoryLock ();
+
+ if (Buffer != NULL) {
+ if (NeedGuard) {
+ SetGuardForMemory ((EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, NoPages);
+ }
+ ApplyMemoryProtectionPolicy(EfiConventionalMemory, PoolType,
+ (EFI_PHYSICAL_ADDRESS)(UINTN)Buffer, EFI_PAGES_TO_SIZE (NoPages));
+ }
+ return Buffer;
+}
+
/**
Internal function to allocate pool of a particular type.
Caller must have the memory lock held
@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
@return The allocate pool, or NULL
@@ -294,7 +346,8 @@ CoreAllocatePool (
VOID *
CoreAllocatePoolI (
IN EFI_MEMORY_TYPE PoolType,
- IN UINTN Size
+ IN UINTN Size,
+ IN BOOLEAN NeedGuard
)
{
POOL *Pool;
@@ -308,23 +361,29 @@ CoreAllocatePoolI (
UINTN Offset, MaxOffset;
UINTN NoPages;
UINTN Granularity;
+ BOOLEAN HasPoolTail;
+ BOOLEAN PageAsPool;
- ASSERT_LOCKED (&gMemoryLock);
+ ASSERT_LOCKED (&mPoolMemoryLock);
if (PoolType == EfiACPIReclaimMemory ||
PoolType == EfiACPIMemoryNVS ||
PoolType == EfiRuntimeServicesCode ||
PoolType == EfiRuntimeServicesData) {
- Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
} else {
- Granularity = DEFAULT_PAGE_ALLOCATION;
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
}
//
// Adjust the size by the pool header & tail overhead
//
+ 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
@@ -344,10 +403,16 @@ CoreAllocatePoolI (
// If allocation is over max size, just allocate pages for the request
// (slow)
//
- if (Index >= SIZE_TO_LIST (Granularity)) {
- 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 = CoreAllocatePoolPages (PoolType, NoPages, Granularity);
+ Head = CoreAllocatePoolPagesI (PoolType, NoPages, Granularity, NeedGuard);
+ if (NeedGuard) {
+ Head = AdjustPoolHeadA ((EFI_PHYSICAL_ADDRESS)(UINTN)Head, NoPages, Size);
+ }
goto Done;
}
@@ -375,7 +440,8 @@ CoreAllocatePoolI (
//
// Get another page
//
- NewPage = CoreAllocatePoolPages(PoolType, EFI_SIZE_TO_PAGES (Granularity), Granularity);
+ NewPage = CoreAllocatePoolPagesI (PoolType, EFI_SIZE_TO_PAGES (Granularity),
+ Granularity, NeedGuard);
if (NewPage == NULL) {
goto Done;
}
@@ -421,30 +487,39 @@ Done:
if (Head != NULL) {
+ //
+ // 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;
- Tail = HEAD_TO_TAIL (Head);
- Tail->Signature = POOL_TAIL_SIGNATURE;
- Tail->Size = Size;
Buffer = Head->Data;
- DEBUG_CLEAR_MEMORY (Buffer, Size - POOL_OVERHEAD);
+
+ 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 - POOL_OVERHEAD),
+ (UINT64)Size,
(UINT64) Pool->Used
));
- //
- // Account the allocation
- //
- Pool->Used += Size;
} else {
DEBUG ((DEBUG_ERROR | DEBUG_POOL, "AllocatePool: failed to allocate %ld bytes\n", (UINT64) Size));
@@ -459,6 +534,7 @@ Done:
Frees pool.
@param Buffer The allocated pool entry to free
+ @param PoolType Pointer to pool type
@retval EFI_INVALID_PARAMETER Buffer is not a valid value.
@retval EFI_SUCCESS Pool successfully freed.
@@ -467,7 +543,8 @@ Done:
EFI_STATUS
EFIAPI
CoreInternalFreePool (
- IN VOID *Buffer
+ IN VOID *Buffer,
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL
)
{
EFI_STATUS Status;
@@ -476,9 +553,9 @@ CoreInternalFreePool (
return EFI_INVALID_PARAMETER;
}
- CoreAcquireMemoryLock ();
- Status = CoreFreePoolI (Buffer);
- CoreReleaseMemoryLock ();
+ CoreAcquireLock (&mPoolMemoryLock);
+ Status = CoreFreePoolI (Buffer, PoolType);
+ CoreReleaseLock (&mPoolMemoryLock);
return Status;
}
@@ -497,20 +574,91 @@ CoreFreePool (
IN VOID *Buffer
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ EFI_MEMORY_TYPE PoolType;
- Status = CoreInternalFreePool (Buffer);
+ Status = CoreInternalFreePool (Buffer, &PoolType);
if (!EFI_ERROR (Status)) {
- CoreUpdateProfile ((EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0), MemoryProfileActionFreePool, (EFI_MEMORY_TYPE) 0, 0, Buffer);
+ CoreUpdateProfile (
+ (EFI_PHYSICAL_ADDRESS) (UINTN) RETURN_ADDRESS (0),
+ MemoryProfileActionFreePool,
+ PoolType,
+ 0,
+ Buffer,
+ NULL
+ );
+ InstallMemoryAttributesTableOnMemoryAllocation (PoolType);
}
return Status;
}
+/**
+ Internal function. Frees pool pages allocated via CoreAllocatePoolPagesI().
+
+ @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
+CoreFreePoolPagesI (
+ IN EFI_MEMORY_TYPE PoolType,
+ IN EFI_PHYSICAL_ADDRESS Memory,
+ IN UINTN NoPages
+ )
+{
+ CoreAcquireMemoryLock ();
+ 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);
+ //
+ // 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
@param Buffer The allocated pool entry to free
+ @param PoolType Pointer to pool type
@retval EFI_INVALID_PARAMETER Buffer not valid
@retval EFI_SUCCESS Buffer successfully freed.
@@ -518,7 +666,8 @@ CoreFreePool (
**/
EFI_STATUS
CoreFreePoolI (
- IN VOID *Buffer
+ IN VOID *Buffer,
+ OUT EFI_MEMORY_TYPE *PoolType OPTIONAL
)
{
POOL *Pool;
@@ -532,36 +681,51 @@ CoreFreePoolI (
UINTN Offset;
BOOLEAN AllFree;
UINTN Granularity;
+ 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;
}
- Tail = HEAD_TO_TAIL (Head);
- ASSERT(Tail != NULL);
+ IsGuarded = IsPoolTypeToGuard (Head->Type) &&
+ IsMemoryGuarded ((EFI_PHYSICAL_ADDRESS)(UINTN)Head);
+ HasPoolTail = !(IsGuarded &&
+ ((PcdGet8 (PcdHeapGuardPropertyMask) & BIT7) == 0));
+ PageAsPool = (Head->Signature == POOLPAGE_HEAD_SIGNATURE);
- //
- // Debug
- //
- ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
- ASSERT (Head->Size == Tail->Size);
- ASSERT_LOCKED (&gMemoryLock);
+ if (HasPoolTail) {
+ Tail = HEAD_TO_TAIL (Head);
+ ASSERT (Tail != NULL);
- if (Tail->Signature != POOL_TAIL_SIGNATURE) {
- return EFI_INVALID_PARAMETER;
- }
+ //
+ // Debug
+ //
+ ASSERT (Tail->Signature == POOL_TAIL_SIGNATURE);
+ ASSERT (Head->Size == Tail->Size);
- if (Head->Size != Tail->Size) {
- return EFI_INVALID_PARAMETER;
+ if (Tail->Signature != POOL_TAIL_SIGNATURE) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Head->Size != Tail->Size) {
+ return EFI_INVALID_PARAMETER;
+ }
}
+ ASSERT_LOCKED (&mPoolMemoryLock);
+
//
// Determine the pool type and account for it
//
@@ -578,9 +742,13 @@ CoreFreePoolI (
Head->Type == EfiRuntimeServicesCode ||
Head->Type == EfiRuntimeServicesData) {
- Granularity = EFI_ACPI_RUNTIME_PAGE_ALLOCATION_ALIGNMENT;
+ Granularity = RUNTIME_PAGE_ALLOCATION_GRANULARITY;
} else {
- Granularity = DEFAULT_PAGE_ALLOCATION;
+ Granularity = DEFAULT_PAGE_ALLOCATION_GRANULARITY;
+ }
+
+ if (PoolType != NULL) {
+ *PoolType = Head->Type;
}
//
@@ -592,14 +760,27 @@ CoreFreePoolI (
//
// If it's not on the list, it must be pool pages
//
- if (Index >= SIZE_TO_LIST (Granularity)) {
+ 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);
- CoreFreePoolPages ((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 {
@@ -655,7 +836,8 @@ CoreFreePoolI (
//
// Free the page
//
- CoreFreePoolPages ((EFI_PHYSICAL_ADDRESS) (UINTN)NewPage, EFI_SIZE_TO_PAGES (Granularity));
+ CoreFreePoolPagesI (Pool->MemoryType, (EFI_PHYSICAL_ADDRESS) (UINTN)NewPage,
+ EFI_SIZE_TO_PAGES (Granularity));
}
}
}
@@ -667,7 +849,7 @@ CoreFreePoolI (
//
if (((UINT32) Pool->MemoryType >= MEMORY_TYPE_OEM_RESERVED_MIN) && Pool->Used == 0) {
RemoveEntryList (&Pool->Link);
- CoreFreePoolI (Pool);
+ CoreFreePoolI (Pool, NULL);
}
return EFI_SUCCESS;