summaryrefslogtreecommitdiffstats
path: root/OvmfPkg/IoMmuDxe
diff options
context:
space:
mode:
Diffstat (limited to 'OvmfPkg/IoMmuDxe')
-rw-r--r--OvmfPkg/IoMmuDxe/AmdSevIoMmu.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
index 452d5c4775..ec625166f4 100644
--- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
@@ -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;
}