]> git.proxmox.com Git - mirror_edk2.git/blobdiff - OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
OvmfPkg/IoMmuDxe: generalize IoMmuUnmap() to IoMmuUnmapWorker()
[mirror_edk2.git] / OvmfPkg / IoMmuDxe / AmdSevIoMmu.c
index bc57de5b572b6048b6be7a4954ca1ca149a078df..34e1c6ee4a7434a3b698ebdb627e80b49370cf89 100644 (file)
@@ -33,14 +33,11 @@ typedef struct {
 } MAP_INFO;\r
 \r
 //\r
-// List of MAP_INFO structures recycled by Unmap().\r
+// List of the MAP_INFO structures that have been set up by IoMmuMap() and not\r
+// yet torn down by IoMmuUnmap(). The list represents the full set of mappings\r
+// currently in effect.\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
+STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);\r
 \r
 #define COMMON_BUFFER_SIG SIGNATURE_64 ('C', 'M', 'N', 'B', 'U', 'F', 'F', 'R')\r
 \r
@@ -123,7 +120,6 @@ 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
@@ -150,19 +146,10 @@ IoMmuMap (
   // Allocate a MAP_INFO structure to remember the mapping when Unmap() is\r
   // called later.\r
   //\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
+  MapInfo = AllocatePool (sizeof (MAP_INFO));\r
+  if (MapInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Failed;\r
   }\r
 \r
   //\r
@@ -298,6 +285,10 @@ IoMmuMap (
       );\r
   }\r
 \r
+  //\r
+  // Track all MAP_INFO structures.\r
+  //\r
+  InsertHeadList (&mMapInfos, &MapInfo->Link);\r
   //\r
   // Populate output parameters.\r
   //\r
@@ -327,8 +318,14 @@ Failed:
 /**\r
   Completes the Map() operation and releases any corresponding resources.\r
 \r
+  This is an internal worker function that only extends the Map() API with\r
+  the MemoryMapLocked parameter.\r
+\r
   @param  This                  The protocol instance pointer.\r
   @param  Mapping               The mapping value returned from Map().\r
+  @param  MemoryMapLocked       The function is executing on the stack of\r
+                                gBS->ExitBootServices(); changes to the UEFI\r
+                                memory map are forbidden.\r
 \r
   @retval EFI_SUCCESS           The range was unmapped.\r
   @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by\r
@@ -336,11 +333,13 @@ Failed:
   @retval EFI_DEVICE_ERROR      The data was not committed to the target system\r
                                 memory.\r
 **/\r
+STATIC\r
 EFI_STATUS\r
 EFIAPI\r
-IoMmuUnmap (\r
+IoMmuUnmapWorker (\r
   IN  EDKII_IOMMU_PROTOCOL                     *This,\r
-  IN  VOID                                     *Mapping\r
+  IN  VOID                                     *Mapping,\r
+  IN  BOOLEAN                                  MemoryMapLocked\r
   )\r
 {\r
   MAP_INFO                 *MapInfo;\r
@@ -348,7 +347,13 @@ IoMmuUnmap (
   COMMON_BUFFER_HEADER     *CommonBufferHeader;\r
   VOID                     *EncryptionTarget;\r
 \r
-  DEBUG ((DEBUG_VERBOSE, "%a: Mapping=0x%p\n", __FUNCTION__, Mapping));\r
+  DEBUG ((\r
+    DEBUG_VERBOSE,\r
+    "%a: Mapping=0x%p MemoryMapLocked=%d\n",\r
+    __FUNCTION__,\r
+    Mapping,\r
+    MemoryMapLocked\r
+    ));\r
 \r
   if (Mapping == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -421,7 +426,8 @@ IoMmuUnmap (
   // original (now encrypted) location.\r
   //\r
   // For all other operations, fill the late bounce buffer (which existed as\r
-  // plaintext at some point) with zeros, and then release it.\r
+  // plaintext at some point) with zeros, and then release it (unless the UEFI\r
+  // memory map is locked).\r
   //\r
   if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
       MapInfo->Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
@@ -430,27 +436,54 @@ 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
+    if (!MemoryMapLocked) {\r
+      gBS->FreePages (MapInfo->PlainTextAddress, MapInfo->NumberOfPages);\r
+    }\r
+  }\r
 \r
-    //\r
-    // Free the MAP_INFO structure.\r
-    //\r
+  //\r
+  // Forget the MAP_INFO structure, then free it (unless the UEFI memory map is\r
+  // locked).\r
+  //\r
+  RemoveEntryList (&MapInfo->Link);\r
+  if (!MemoryMapLocked) {\r
     FreePool (MapInfo);\r
   }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Completes the Map() operation and releases any corresponding resources.\r
+\r
+  @param  This                  The protocol instance pointer.\r
+  @param  Mapping               The mapping value returned from Map().\r
+\r
+  @retval EFI_SUCCESS           The range was unmapped.\r
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by\r
+                                Map().\r
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system\r
+                                memory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+IoMmuUnmap (\r
+  IN  EDKII_IOMMU_PROTOCOL                     *This,\r
+  IN  VOID                                     *Mapping\r
+  )\r
+{\r
+  return IoMmuUnmapWorker (\r
+           This,\r
+           Mapping,\r
+           FALSE    // MemoryMapLocked\r
+           );\r
+}\r
+\r
 /**\r
   Allocates pages that are suitable for an OperationBusMasterCommonBuffer or\r
   OperationBusMasterCommonBuffer64 mapping.\r