mirror of https://github.com/acidanthera/audk.git
OvmfPkg/IoMmuDxe: Unmap(): recycle MAP_INFO after BusMasterCommonBuffer[64]
In order for Unmap() to be callable from ExitBootServices() event handler context (for cleaning up a BusMasterCommonBuffer[64] operation), we have to completely liberate the affected path in Unmap() from dynamic memory management. The last remaining piece is the release of the MAP_INFO structure. Rather than freeing it with FreePool(), recycle it to an internal list. Elements of this "free list" can be reused for any kind of Map() operation, and can be freed later, or recycled again. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Cc: Brijesh Singh <brijesh.singh@amd.com> Cc: Jordan Justen <jordan.l.justen@intel.com> Cc: Tom Lendacky <thomas.lendacky@amd.com> Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Tested-by: Brijesh Singh <brijesh.singh@amd.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com>
This commit is contained in:
parent
f1658838c2
commit
d0c9afea42
|
@ -20,7 +20,11 @@
|
|||
|
||||
#include "AmdSevIoMmu.h"
|
||||
|
||||
#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O')
|
||||
|
||||
typedef struct {
|
||||
UINT64 Signature;
|
||||
LIST_ENTRY Link;
|
||||
EDKII_IOMMU_OPERATION Operation;
|
||||
UINTN NumberOfBytes;
|
||||
UINTN NumberOfPages;
|
||||
|
@ -28,6 +32,16 @@ typedef struct {
|
|||
EFI_PHYSICAL_ADDRESS PlainTextAddress;
|
||||
} MAP_INFO;
|
||||
|
||||
//
|
||||
// List of MAP_INFO structures recycled by Unmap().
|
||||
//
|
||||
// Recycled MAP_INFO structures are equally good for future recycling and
|
||||
// freeing.
|
||||
//
|
||||
STATIC LIST_ENTRY mRecycledMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (
|
||||
mRecycledMapInfos
|
||||
);
|
||||
|
||||
#define COMMON_BUFFER_SIG SIGNATURE_64 ('C', 'M', 'N', 'B', 'U', 'F', 'F', 'R')
|
||||
|
||||
//
|
||||
|
@ -96,6 +110,7 @@ IoMmuMap (
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
LIST_ENTRY *RecycledMapInfo;
|
||||
MAP_INFO *MapInfo;
|
||||
EFI_ALLOCATE_TYPE AllocateType;
|
||||
COMMON_BUFFER_HEADER *CommonBufferHeader;
|
||||
|
@ -110,15 +125,26 @@ IoMmuMap (
|
|||
// Allocate a MAP_INFO structure to remember the mapping when Unmap() is
|
||||
// called later.
|
||||
//
|
||||
MapInfo = AllocatePool (sizeof (MAP_INFO));
|
||||
if (MapInfo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Failed;
|
||||
RecycledMapInfo = GetFirstNode (&mRecycledMapInfos);
|
||||
if (RecycledMapInfo == &mRecycledMapInfos) {
|
||||
//
|
||||
// No recycled MAP_INFO structure, allocate a new one.
|
||||
//
|
||||
MapInfo = AllocatePool (sizeof (MAP_INFO));
|
||||
if (MapInfo == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Failed;
|
||||
}
|
||||
} else {
|
||||
MapInfo = CR (RecycledMapInfo, MAP_INFO, Link, MAP_INFO_SIG);
|
||||
RemoveEntryList (RecycledMapInfo);
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize the MAP_INFO structure, except the PlainTextAddress field
|
||||
//
|
||||
ZeroMem (&MapInfo->Link, sizeof MapInfo->Link);
|
||||
MapInfo->Signature = MAP_INFO_SIG;
|
||||
MapInfo->Operation = Operation;
|
||||
MapInfo->NumberOfBytes = *NumberOfBytes;
|
||||
MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
|
||||
|
@ -387,18 +413,24 @@ IoMmuUnmap (
|
|||
CommonBufferHeader->StashBuffer,
|
||||
MapInfo->NumberOfBytes
|
||||
);
|
||||
|
||||
//
|
||||
// Recycle the MAP_INFO structure.
|
||||
//
|
||||
InsertTailList (&mRecycledMapInfos, &MapInfo->Link);
|
||||
} else {
|
||||
ZeroMem (
|
||||
(VOID *)(UINTN)MapInfo->PlainTextAddress,
|
||||
EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages)
|
||||
);
|
||||
gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);
|
||||
|
||||
//
|
||||
// Free the MAP_INFO structure.
|
||||
//
|
||||
FreePool (MapInfo);
|
||||
}
|
||||
|
||||
//
|
||||
// Free the MAP_INFO structure.
|
||||
//
|
||||
FreePool (Mapping);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue