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