]> git.proxmox.com Git - mirror_edk2.git/commitdiff
OvmfPkg/IoMmuDxe: Unmap(): recycle MAP_INFO after BusMasterCommonBuffer[64]
authorLaszlo Ersek <lersek@redhat.com>
Wed, 2 Aug 2017 18:31:08 +0000 (20:31 +0200)
committerLaszlo Ersek <lersek@redhat.com>
Fri, 4 Aug 2017 23:31:53 +0000 (01:31 +0200)
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>
OvmfPkg/IoMmuDxe/AmdSevIoMmu.c

index 452d5c47753bb9b013d59ab6dcb752d43b6491c0..ec625166f4591c2fb6cc6bd30dfe65abb8565afe 100644 (file)
 \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
@@ -28,6 +32,16 @@ typedef struct {
   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
@@ -96,6 +110,7 @@ IoMmuMap (
   )\r
 {\r
   EFI_STATUS                                        Status;\r
+  LIST_ENTRY                                        *RecycledMapInfo;\r
   MAP_INFO                                          *MapInfo;\r
   EFI_ALLOCATE_TYPE                                 AllocateType;\r
   COMMON_BUFFER_HEADER                              *CommonBufferHeader;\r
@@ -110,15 +125,26 @@ IoMmuMap (
   // 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
@@ -387,18 +413,24 @@ IoMmuUnmap (
       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