\r
#include "AmdSevIoMmu.h"\r
\r
+#define MAP_INFO_SIG SIGNATURE_64 ('M', 'A', 'P', '_', 'I', 'N', 'F', 'O')\r
+\r
typedef struct {\r
+ UINT64 Signature;\r
+ LIST_ENTRY Link;\r
EDKII_IOMMU_OPERATION Operation;\r
UINTN NumberOfBytes;\r
UINTN NumberOfPages;\r
EFI_PHYSICAL_ADDRESS PlainTextAddress;\r
} MAP_INFO;\r
\r
+//\r
+// List of MAP_INFO structures recycled by Unmap().\r
+//\r
+// Recycled MAP_INFO structures are equally good for future recycling and\r
+// freeing.\r
+//\r
+STATIC LIST_ENTRY mRecycledMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (\r
+ mRecycledMapInfos\r
+ );\r
+\r
#define COMMON_BUFFER_SIG SIGNATURE_64 ('C', 'M', 'N', 'B', 'U', 'F', 'F', 'R')\r
\r
//\r
)\r
{\r
EFI_STATUS Status;\r
+ LIST_ENTRY *RecycledMapInfo;\r
MAP_INFO *MapInfo;\r
EFI_ALLOCATE_TYPE AllocateType;\r
COMMON_BUFFER_HEADER *CommonBufferHeader;\r
// Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
// called later.\r
//\r
- MapInfo = AllocatePool (sizeof (MAP_INFO));\r
- if (MapInfo == NULL) {\r
- Status = EFI_OUT_OF_RESOURCES;\r
- goto Failed;\r
+ RecycledMapInfo = GetFirstNode (&mRecycledMapInfos);\r
+ if (RecycledMapInfo == &mRecycledMapInfos) {\r
+ //\r
+ // No recycled MAP_INFO structure, allocate a new one.\r
+ //\r
+ MapInfo = AllocatePool (sizeof (MAP_INFO));\r
+ if (MapInfo == NULL) {\r
+ Status = EFI_OUT_OF_RESOURCES;\r
+ goto Failed;\r
+ }\r
+ } else {\r
+ MapInfo = CR (RecycledMapInfo, MAP_INFO, Link, MAP_INFO_SIG);\r
+ RemoveEntryList (RecycledMapInfo);\r
}\r
\r
//\r
// Initialize the MAP_INFO structure, except the PlainTextAddress field\r
//\r
+ ZeroMem (&MapInfo->Link, sizeof MapInfo->Link);\r
+ MapInfo->Signature = MAP_INFO_SIG;\r
MapInfo->Operation = Operation;\r
MapInfo->NumberOfBytes = *NumberOfBytes;\r
MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);\r
CommonBufferHeader->StashBuffer,\r
MapInfo->NumberOfBytes\r
);\r
+\r
+ //\r
+ // Recycle the MAP_INFO structure.\r
+ //\r
+ InsertTailList (&mRecycledMapInfos, &MapInfo->Link);\r
} else {\r
ZeroMem (\r
(VOID *)(UINTN)MapInfo->PlainTextAddress,\r
EFI_PAGES_TO_SIZE (MapInfo->NumberOfPages)\r
);\r
gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);\r
+\r
+ //\r
+ // Free the MAP_INFO structure.\r
+ //\r
+ FreePool (MapInfo);\r
}\r
\r
- //\r
- // Free the MAP_INFO structure.\r
- //\r
- FreePool (Mapping);\r
return EFI_SUCCESS;\r
}\r
\r