public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Laszlo Ersek <lersek@redhat.com>
To: edk2-devel-01 <edk2-devel@lists.01.org>
Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>,
	Brijesh Singh <brijesh.singh@amd.com>,
	Jiewen Yao <jiewen.yao@intel.com>,
	Jordan Justen <jordan.l.justen@intel.com>
Subject: [PATCH 08/10] OvmfPkg/IoMmuDxe: track all mappings
Date: Fri,  8 Sep 2017 00:41:14 +0200	[thread overview]
Message-ID: <20170907224116.895-9-lersek@redhat.com> (raw)
In-Reply-To: <20170907224116.895-1-lersek@redhat.com>

The "mRecycledMapInfos" list implements an internal pool of unused
MAP_INFO structures between the IoMmuUnmap() and IoMmuMap() functions. The
original goal was to allow IoMmuUnmap() to tear down CommonBuffer mappings
without releasing any memory: IoMmuUnmap() would recycle the MAP_INFO
structure to the list, and IoMmuMap() would always check the list first,
before allocating a brand new MAP_INFO structure.

In one of the following patches, we'll change OvmfPkg/IoMmuDxe so that it
unmaps all existent bus master operations (CommonBuffer, Read, Write) at
ExitBootServices(), strictly after the individual device drivers abort
pending DMA on the devices they manage, in their own ExitBootServices()
notification functions.

For this, rename and repurpose the list to track all live mappings.

This means that IoMmuUnmap() will always release a MAP_INFO structure
(even when cleaning up a CommonBuffer operation). That's fine (for now),
because device drivers are no longer expected to call Unmap() in their
ExitBootServices() notification functions.

In theory, we could also move the allocation and freeing of the stash
buffer from IoMmuAllocateBuffer() and IoMmuFreeBuffer(), respectively, to
IoMmuMap() and IoMmuUnmap(). However, this would require allocating and
freeing a stash buffer in *both* IoMmuMap() and IoMmuUnmap(), as
IoMmuMap() performs in-place decryption for CommonBuffer operations, and
IoMmuUnmap() performs in-place encryption for the same.

By keeping the stash buffer allocation as-is, not only do we keep the code
almost fully undisturbed, but

- we also continue to guarantee that IoMmuUnmap() succeeds: allocating a
  stash buffer in IoMmuUnmap(), for in-place encryption after a
  CommonBuffer operation, could fail;

- we also keep IoMmuUnmap() largely reusable for ExitBootServices()
  callback context: allocating a stash buffer in IoMmuUnmap() would simply
  be forbidden in that context.

Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Cc: Brijesh Singh <brijesh.singh@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 49 +++++++-------------
 1 file changed, 18 insertions(+), 31 deletions(-)

diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
index bc57de5b572b..c86e73498555 100644
--- a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
@@ -31,18 +31,15 @@ typedef struct {
   EFI_PHYSICAL_ADDRESS                      CryptedAddress;
   EFI_PHYSICAL_ADDRESS                      PlainTextAddress;
 } MAP_INFO;
 
 //
-// List of MAP_INFO structures recycled by Unmap().
+// List of the MAP_INFO structures that have been set up by IoMmuMap() and not
+// yet torn down by IoMmuUnmap(). The list represents the full set of mappings
+// currently in effect.
 //
-// Recycled MAP_INFO structures are equally good for future recycling and
-// freeing.
-//
-STATIC LIST_ENTRY mRecycledMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (
-                                        mRecycledMapInfos
-                                        );
+STATIC LIST_ENTRY mMapInfos = INITIALIZE_LIST_HEAD_VARIABLE (mMapInfos);
 
 #define COMMON_BUFFER_SIG SIGNATURE_64 ('C', 'M', 'N', 'B', 'U', 'F', 'F', 'R')
 
 //
 // ASCII names for EDKII_IOMMU_OPERATION constants, for debug logging.
@@ -121,11 +118,10 @@ IoMmuMap (
   OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
   OUT    VOID                                       **Mapping
   )
 {
   EFI_STATUS                                        Status;
-  LIST_ENTRY                                        *RecycledMapInfo;
   MAP_INFO                                          *MapInfo;
   EFI_ALLOCATE_TYPE                                 AllocateType;
   COMMON_BUFFER_HEADER                              *CommonBufferHeader;
   VOID                                              *DecryptionSource;
 
@@ -148,23 +144,14 @@ IoMmuMap (
 
   //
   // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
   // called later.
   //
-  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);
+  MapInfo = AllocatePool (sizeof (MAP_INFO));
+  if (MapInfo == NULL) {
+    Status = EFI_OUT_OF_RESOURCES;
+    goto Failed;
   }
 
   //
   // Initialize the MAP_INFO structure, except the PlainTextAddress field
   //
@@ -296,10 +283,14 @@ IoMmuMap (
       DecryptionSource,
       MapInfo->NumberOfBytes
       );
   }
 
+  //
+  // Track all MAP_INFO structures.
+  //
+  InsertHeadList (&mMapInfos, &MapInfo->Link);
   //
   // Populate output parameters.
   //
   *DeviceAddress = MapInfo->PlainTextAddress;
   *Mapping       = MapInfo;
@@ -428,28 +419,24 @@ IoMmuUnmap (
     CopyMem (
       (VOID *)(UINTN)MapInfo->CryptedAddress,
       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);
   }
 
+  //
+  // Forget and free the MAP_INFO structure.
+  //
+  RemoveEntryList (&MapInfo->Link);
+  FreePool (MapInfo);
+
   return EFI_SUCCESS;
 }
 
 /**
   Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
-- 
2.14.1.3.gb7cf6e02401b




  parent reply	other threads:[~2017-09-07 22:38 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-07 22:41 [PATCH 00/10] MdeModulePkg, OvmfPkg: unmap DMA buffers at ExitBootServices Laszlo Ersek
2017-09-07 22:41 ` [PATCH 01/10] MdeModulePkg/AtaAtapiPassThru: cache EnabledPciAttributes Laszlo Ersek
2017-09-07 22:41 ` [PATCH 02/10] MdeModulePkg/AtaAtapiPassThru: unmap DMA buffers after disabling BM DMA Laszlo Ersek
2017-09-07 22:41 ` [PATCH 03/10] MdeModulePkg/AtaAtapiPassThru: disable the device at ExitBootServices() Laszlo Ersek
2017-10-25 15:26   ` Laszlo Ersek
2017-10-25 20:11     ` Ard Biesheuvel
2017-10-26  5:08       ` Zeng, Star
2017-10-26 14:09         ` Laszlo Ersek
2017-10-26 14:12           ` Ard Biesheuvel
2017-09-07 22:41 ` [PATCH 04/10] OvmfPkg/VirtioBlkDxe: don't unmap VRING " Laszlo Ersek
2017-09-07 22:41 ` [PATCH 05/10] OvmfPkg/VirtioGpuDxe: don't unmap VRING & BackingStore at ExitBootServices Laszlo Ersek
2017-09-07 22:41 ` [PATCH 06/10] OvmfPkg/VirtioRngDxe: don't unmap VRING at ExitBootServices() Laszlo Ersek
2017-09-07 22:41 ` [PATCH 07/10] OvmfPkg/VirtioScsiDxe: " Laszlo Ersek
2017-09-07 22:41 ` Laszlo Ersek [this message]
2017-09-07 22:41 ` [PATCH 09/10] OvmfPkg/IoMmuDxe: generalize IoMmuUnmap() to IoMmuUnmapWorker() Laszlo Ersek
2017-09-07 22:41 ` [PATCH 10/10] OvmfPkg/IoMmuDxe: unmap all IOMMU mappings at ExitBootServices() Laszlo Ersek
2017-09-08  7:28 ` [PATCH 00/10] MdeModulePkg, OvmfPkg: unmap DMA buffers at ExitBootServices Yao, Jiewen
2017-09-08  8:28   ` Yao, Jiewen
2017-09-08  7:29 ` Zeng, Star
2017-09-08  8:53 ` Ard Biesheuvel
2017-09-08  9:48   ` Laszlo Ersek
2017-09-08 11:25     ` Ard Biesheuvel
2017-09-08 15:50 ` Brijesh Singh
2017-09-08 16:00   ` Laszlo Ersek
2017-09-08 18:28 ` Laszlo Ersek

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170907224116.895-9-lersek@redhat.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox