From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.93; helo=mga11.intel.com; envelope-from=star.zeng@intel.com; receiver=edk2-devel@lists.01.org Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 83FBA20955F18 for ; Thu, 8 Mar 2018 03:36:37 -0800 (PST) X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 08 Mar 2018 03:42:53 -0800 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.47,440,1515484800"; d="scan'208";a="23944280" Received: from shwdeopenpsi068.ccr.corp.intel.com ([10.239.158.46]) by orsmga006.jf.intel.com with ESMTP; 08 Mar 2018 03:42:51 -0800 From: Star Zeng To: edk2-devel@lists.01.org Cc: Jiewen Yao , Star Zeng Date: Thu, 8 Mar 2018 19:42:49 +0800 Message-Id: <1520509370-14484-1-git-send-email-star.zeng@intel.com> X-Mailer: git-send-email 2.7.0.windows.1 Subject: [PATCH V2] IntelSiliconPkg/Vtd: Add MapHandleInfo in VtdDxe. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 08 Mar 2018 11:36:37 -0000 From: Jiewen Yao This information is to record which device requested which DMA buffer. It can be used for DMA buffer analysis. Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao Reviewed-by: Star Zeng --- 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