From: Jiewen Yao Date: Thu, 8 Mar 2018 11:42:49 +0000 (+0800) Subject: IntelSiliconPkg/Vtd: Add MapHandleInfo in VtdDxe. X-Git-Tag: edk2-stable201903~2219 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=6d2d2e6e5b6619dd46d944b90629739c97ee8a65;ds=sidebyside 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 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao Reviewed-by: Star Zeng --- 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,11 +36,95 @@ 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 @@ -113,6 +113,24 @@ IoMmuFreeBuffer ( IN VOID *HostAddress ); +/** + 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. @@ -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; }