[edk2] [PATCH V2] IntelSiliconPkg/Vtd: Add MapHandleInfo in VtdDxe.

Star Zeng posted 1 patch 6 years, 1 month ago
Failed in applying to current master (apply log)
IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c    | 104 +++++++++++++++++++++
.../Feature/VTd/IntelVTdDxe/IntelVTdDxe.c          |  53 ++++++++---
2 files changed, 144 insertions(+), 13 deletions(-)
[edk2] [PATCH V2] IntelSiliconPkg/Vtd: Add MapHandleInfo in VtdDxe.
Posted by Star Zeng 6 years, 1 month ago
From: Jiewen Yao <jiewen.yao@intel.com>

This information is to record which device requested which DMA buffer.
It can be used for DMA buffer analysis.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Star Zeng <star.zeng@intel.com>
---
 IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c    | 104 +++++++++++++++++++++
 .../Feature/VTd/IntelVTdDxe/IntelVTdDxe.c          |  53 ++++++++---
 2 files changed, 144 insertions(+), 13 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c
index 57e086a64dbc..bf3c1ed99ae2 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c
@@ -18,6 +18,15 @@
 #define DMA_MEMORY_TOP          MAX_UINTN
 //#define DMA_MEMORY_TOP          0x0000000001FFFFFFULL
 
+#define MAP_HANDLE_INFO_SIGNATURE  SIGNATURE_32 ('H', 'M', 'A', 'P')
+typedef struct {
+  UINT32                                    Signature;
+  LIST_ENTRY                                Link;
+  EFI_HANDLE                                DeviceHandle;
+  UINT64                                    IoMmuAccess;
+} MAP_HANDLE_INFO;
+#define MAP_HANDLE_INFO_FROM_LINK(a) CR (a, MAP_HANDLE_INFO, Link, MAP_HANDLE_INFO_SIGNATURE)
+
 #define MAP_INFO_SIGNATURE  SIGNATURE_32 ('D', 'M', 'A', 'P')
 typedef struct {
   UINT32                                    Signature;
@@ -27,12 +36,96 @@ typedef struct {
   UINTN                                     NumberOfPages;
   EFI_PHYSICAL_ADDRESS                      HostAddress;
   EFI_PHYSICAL_ADDRESS                      DeviceAddress;
+  LIST_ENTRY                                HandleList;
 } MAP_INFO;
 #define MAP_INFO_FROM_LINK(a) CR (a, MAP_INFO, Link, MAP_INFO_SIGNATURE)
 
 LIST_ENTRY                        gMaps = INITIALIZE_LIST_HEAD_VARIABLE(gMaps);
 
 /**
+  This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,
+  based upon the DeviceAddress.
+
+  @param[in]  DeviceHandle      The device who initiates the DMA access request.
+  @param[in]  DeviceAddress     The base of device memory address to be used as the DMA memory.
+  @param[in]  Length            The length of device memory address to be used as the DMA memory.
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+**/
+VOID
+SyncDeviceHandleToMapInfo (
+  IN EFI_HANDLE            DeviceHandle,
+  IN EFI_PHYSICAL_ADDRESS  DeviceAddress,
+  IN UINT64                Length,
+  IN UINT64                IoMmuAccess
+  )
+{
+  MAP_INFO                 *MapInfo;
+  MAP_HANDLE_INFO          *MapHandleInfo;
+  LIST_ENTRY               *Link;
+  EFI_TPL                  OriginalTpl;
+
+  //
+  // Find MapInfo according to DeviceAddress
+  //
+  OriginalTpl = gBS->RaiseTPL (VTD_TPL_LEVEL);
+  MapInfo = NULL;
+  for (Link = GetFirstNode (&gMaps)
+       ; !IsNull (&gMaps, Link)
+       ; Link = GetNextNode (&gMaps, Link)
+       ) {
+    MapInfo = MAP_INFO_FROM_LINK (Link);
+    if (MapInfo->DeviceAddress == DeviceAddress) {
+      break;
+    }
+  }
+  if ((MapInfo == NULL) || (MapInfo->DeviceAddress != DeviceAddress)) {
+    DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: DeviceAddress(0x%lx) - not found\n", DeviceAddress));
+    gBS->RestoreTPL (OriginalTpl);
+    return ;
+  }
+
+  //
+  // Find MapHandleInfo according to DeviceHandle
+  //
+  MapHandleInfo = NULL;
+  for (Link = GetFirstNode (&MapInfo->HandleList)
+       ; !IsNull (&MapInfo->HandleList, Link)
+       ; Link = GetNextNode (&MapInfo->HandleList, Link)
+       ) {
+    MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (Link);
+    if (MapHandleInfo->DeviceHandle == DeviceHandle) {
+      break;
+    }
+  }
+  if ((MapHandleInfo != NULL) && (MapHandleInfo->DeviceHandle == DeviceHandle)) {
+    MapHandleInfo->IoMmuAccess       = IoMmuAccess;
+    gBS->RestoreTPL (OriginalTpl);
+    return ;
+  }
+
+  //
+  // No DeviceHandle
+  // Initialize and insert the MAP_HANDLE_INFO structure
+  //
+  MapHandleInfo = AllocatePool (sizeof (MAP_HANDLE_INFO));
+  if (MapHandleInfo == NULL) {
+    DEBUG ((DEBUG_ERROR, "SyncDeviceHandleToMapInfo: %r\n", EFI_OUT_OF_RESOURCES));
+    gBS->RestoreTPL (OriginalTpl);
+    return ;
+  }
+
+  MapHandleInfo->Signature         = MAP_HANDLE_INFO_SIGNATURE;
+  MapHandleInfo->DeviceHandle      = DeviceHandle;
+  MapHandleInfo->IoMmuAccess       = IoMmuAccess;
+
+  InsertTailList (&MapInfo->HandleList, &MapHandleInfo->Link);
+  gBS->RestoreTPL (OriginalTpl);
+
+  return ;
+}
+
+/**
   Provides the controller-specific addresses required to access system memory from a
   DMA bus master.
 
@@ -156,6 +249,7 @@ IoMmuMap (
   MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
   MapInfo->HostAddress       = PhysicalAddress;
   MapInfo->DeviceAddress     = DmaMemoryTop;
+  InitializeListHead(&MapInfo->HandleList);
 
   //
   // Allocate a buffer below 4GB to map the transfer to.
@@ -227,6 +321,7 @@ IoMmuUnmap (
   )
 {
   MAP_INFO                 *MapInfo;
+  MAP_HANDLE_INFO          *MapHandleInfo;
   LIST_ENTRY               *Link;
   EFI_TPL                  OriginalTpl;
 
@@ -259,6 +354,15 @@ IoMmuUnmap (
   RemoveEntryList (&MapInfo->Link);
   gBS->RestoreTPL (OriginalTpl);
 
+  //
+  // remove all nodes in MapInfo->HandleList
+  //
+  while (!IsListEmpty (&MapInfo->HandleList)) {
+    MapHandleInfo = MAP_HANDLE_INFO_FROM_LINK (MapInfo->HandleList.ForwardLink);
+    RemoveEntryList (&MapHandleInfo->Link);
+    FreePool (MapHandleInfo);
+  }
+
   if (MapInfo->DeviceAddress != MapInfo->HostAddress) {
     //
     // If this is a write operation from the Bus Master's point of view,
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.c b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.c
index 841a5a9264aa..25d7c80af1d4 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.c
@@ -114,6 +114,24 @@ IoMmuFreeBuffer (
   );
 
 /**
+  This function fills DeviceHandle/IoMmuAccess to the MAP_HANDLE_INFO,
+  based upon the DeviceAddress.
+
+  @param[in]  DeviceHandle      The device who initiates the DMA access request.
+  @param[in]  DeviceAddress     The base of device memory address to be used as the DMA memory.
+  @param[in]  Length            The length of device memory address to be used as the DMA memory.
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+**/
+VOID
+SyncDeviceHandleToMapInfo (
+  IN EFI_HANDLE            DeviceHandle,
+  IN EFI_PHYSICAL_ADDRESS  DeviceAddress,
+  IN UINT64                Length,
+  IN UINT64                IoMmuAccess
+  );
+
+/**
   Convert the DeviceHandle to SourceId and Segment.
 
   @param[in]  DeviceHandle      The device who initiates the DMA access request.
@@ -236,21 +254,30 @@ VTdSetAttribute (
     // Record the entry to driver global variable.
     // As such once VTd is activated, the setting can be adopted.
     //
-    return RequestAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
+    Status = RequestAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
+  } else {
+    PERF_CODE (
+      AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);
+      Identifier = (Segment << 16) | SourceId.Uint16;
+      PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
+    );
+
+    Status = SetAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
+
+    PERF_CODE (
+      Identifier = (Segment << 16) | SourceId.Uint16;
+      PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
+    );
   }
 
-  PERF_CODE (
-    AsciiSPrint (PerfToken, sizeof(PerfToken), "S%04xB%02xD%02xF%01x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function);
-    Identifier = (Segment << 16) | SourceId.Uint16;
-    PERF_START_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
-  );
-
-  Status = SetAccessAttribute (Segment, SourceId, DeviceAddress, Length, IoMmuAccess);
-
-  PERF_CODE (
-    Identifier = (Segment << 16) | SourceId.Uint16;
-    PERF_END_EX (gImageHandle, PerfToken, "IntelVTD", 0, Identifier);
-  );
+  if (!EFI_ERROR(Status)) {
+    SyncDeviceHandleToMapInfo (
+      DeviceHandle,
+      DeviceAddress,
+      Length,
+      IoMmuAccess
+      );
+  }
 
   return Status;
 }
-- 
2.7.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel