diff options
author | Jiewen Yao <jiewen.yao@intel.com> | 2018-03-08 19:42:49 +0800 |
---|---|---|
committer | Jiewen Yao <jiewen.yao@intel.com> | 2018-03-09 10:27:52 +0800 |
commit | 6d2d2e6e5b6619dd46d944b90629739c97ee8a65 (patch) | |
tree | 874d5289d41d73cdd909039613b0bc58f306e67f | |
parent | 73ee3abab1a1b3593de6f31224c0f990dc113bc9 (diff) | |
download | edk2-6d2d2e6e5b6619dd46d944b90629739c97ee8a65.tar.gz edk2-6d2d2e6e5b6619dd46d944b90629739c97ee8a65.tar.bz2 edk2-6d2d2e6e5b6619dd46d944b90629739c97ee8a65.zip |
IntelSiliconPkg/Vtd: Add MapHandleInfo in VtdDxe.
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>
-rw-r--r-- | IntelSiliconPkg/Feature/VTd/IntelVTdDxe/BmDma.c | 104 | ||||
-rw-r--r-- | IntelSiliconPkg/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 57e086a64d..bf3c1ed99a 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 841a5a9264..25d7c80af1 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;
}
|