3 Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 #ifndef _DMAR_PROTECTION_H_
15 #define _DMAR_PROTECTION_H_
20 #include <Library/BaseLib.h>
21 #include <Library/BaseMemoryLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/UefiBootServicesTableLib.h>
24 #include <Library/IoLib.h>
25 #include <Library/PciSegmentLib.h>
26 #include <Library/DebugLib.h>
27 #include <Library/UefiLib.h>
29 #include <Guid/EventGroup.h>
30 #include <Guid/Acpi.h>
32 #include <Protocol/DxeSmmReadyToLock.h>
33 #include <Protocol/PciRootBridgeIo.h>
34 #include <Protocol/PciIo.h>
35 #include <Protocol/PciEnumerationComplete.h>
36 #include <Protocol/AcpiSystemDescriptionTable.h>
37 #include <Protocol/PlatformVtdPolicy.h>
38 #include <Protocol/IoMmu.h>
40 #include <IndustryStandard/Pci.h>
41 #include <IndustryStandard/DmaRemappingReportingTable.h>
42 #include <IndustryStandard/Vtd.h>
44 #define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))
46 #define ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))
47 #define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))
50 // This is the initial max PCI descriptor.
51 // The number may be enlarged later.
53 #define MAX_PCI_DESCRIPTORS 0x100
56 BOOLEAN IncludeAllFlag
;
57 UINTN PciDescriptorNumber
;
58 UINTN PciDescriptorMaxNumber
;
59 BOOLEAN
*IsRealPciDevice
;
60 VTD_SOURCE_ID
*PciDescriptors
;
61 } PCI_DEVICE_INFORMATION
;
64 UINTN VtdUnitBaseAddress
;
68 VTD_ROOT_ENTRY
*RootEntryTable
;
69 VTD_EXT_ROOT_ENTRY
*ExtRootEntryTable
;
70 VTD_SECOND_LEVEL_PAGING_ENTRY
*FixedSecondLevelPagingEntry
;
71 BOOLEAN HasDirtyPages
;
72 PCI_DEVICE_INFORMATION PciDeviceInfo
;
73 } VTD_UNIT_INFORMATION
;
75 extern EFI_ACPI_DMAR_HEADER
*mAcpiDmarTable
;
77 extern UINT64 mVtdHostAddressWidthMask
;
78 extern UINTN mVtdUnitNumber
;
79 extern VTD_UNIT_INFORMATION
*mVtdUnitInformation
;
81 extern UINT64 mBelow4GMemoryLimit
;
82 extern UINT64 mAbove4GMemoryLimit
;
84 extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*mPlatformVTdPolicy
;
87 Prepare VTD configuration.
95 Setup VTd translation table.
97 @retval EFI_SUCCESS Setup translation table successfully.
98 @retval EFI_OUT_OF_RESOURCE Setup translation table fail.
101 SetupTranslationTable (
106 Enable DMAR translation.
108 @retval EFI_SUCCESS DMAR translation is enabled.
109 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
117 Disable DMAR translation.
119 @retval EFI_SUCCESS DMAR translation is disabled.
120 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
128 Invalid VTd IOTLB page.
130 @param[in] VtdIndex The index of VTd engine.
131 @param[in] Address The address of IOTLB page.
132 @param[in] AddressMode The address mode of IOTLB page.
133 @param[in] DomainIdentifier The domain ID of the source.
135 @retval EFI_SUCCESS VTd IOTLB page is invalidated.
136 @retval EFI_DEVICE_ERROR VTd IOTLB page is not invalidated.
139 InvalidateVtdIOTLBPage (
142 IN UINT8 AddressMode
,
143 IN UINT16 DomainIdentifier
147 Invalid VTd IOTLB domain.
149 @param[in] VtdIndex The index of VTd engine.
150 @param[in] DomainIdentifier The domain ID of the source.
152 @retval EFI_SUCCESS VTd IOTLB domain is invalidated.
153 @retval EFI_DEVICE_ERROR VTd IOTLB domain is not invalidated.
156 InvalidateVtdIOTLBDomain (
158 IN UINT16 DomainIdentifier
162 Invalid VTd global IOTLB.
164 @param[in] VtdIndex The index of VTd engine.
166 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
167 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
170 InvalidateVtdIOTLBGlobal (
177 @param[in] VtdIndex The index of VTd engine.
185 Dump VTd registers for all VTd engine.
193 Dump VTd capability registers.
195 @param[in] CapReg The capability register.
199 IN VTD_CAP_REG
*CapReg
203 Dump VTd extended capability registers.
205 @param[in] ECapReg The extended capability register.
209 IN VTD_ECAP_REG
*ECapReg
213 Register PCI device to VTd engine as PCI descriptor.
215 @param[in] VtdIndex The index of VTd engine.
216 @param[in] Segment The segment of the source.
217 @param[in] SourceId The SourceId of the source.
218 @param[in] IsRealPciDevice TRUE: It is a real PCI device.
219 FALSE: It is not a real PCI device.
220 @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.
221 FALSE: SUCCESS will be returned if the PCI device is registered.
223 @retval EFI_SUCCESS The PCI device is registered.
224 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
225 @retval EFI_ALREADY_STARTED The device is already registered.
231 IN VTD_SOURCE_ID SourceId
,
232 IN BOOLEAN IsRealPciDevice
,
233 IN BOOLEAN CheckExist
237 Scan PCI bus and register PCI devices under the bus.
239 @param[in] VtdIndex The index of VTd engine.
240 @param[in] Segment The segment of the source.
241 @param[in] Bus The bus of the source.
243 @retval EFI_SUCCESS The PCI devices under the bus are registered.
244 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
254 Dump the PCI device information managed by this VTd engine.
256 @param[in] VtdIndex The index of VTd engine.
264 Find the VTd index by the Segment and SourceId.
266 @param[in] Segment The segment of the source.
267 @param[in] SourceId The SourceId of the source.
268 @param[out] ExtContextEntry The ExtContextEntry of the source.
269 @param[out] ContextEntry The ContextEntry of the source.
271 @return The index of the PCI descriptor.
272 @retval (UINTN)-1 The PCI descriptor is not found.
275 FindVtdIndexByPciDevice (
277 IN VTD_SOURCE_ID SourceId
,
278 OUT VTD_EXT_CONTEXT_ENTRY
**ExtContextEntry
,
279 OUT VTD_CONTEXT_ENTRY
**ContextEntry
283 Get the DMAR ACPI table.
285 @retval EFI_SUCCESS The DMAR ACPI table is got.
286 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.
294 Parse DMAR DRHD table.
296 @return EFI_SUCCESS The DMAR DRHD table is parsed.
299 ParseDmarAcpiTableDrhd (
304 Parse DMAR RMRR table.
306 @return EFI_SUCCESS The DMAR RMRR table is parsed.
309 ParseDmarAcpiTableRmrr (
314 Dump DMAR context entry table.
316 @param[in] RootEntry DMAR root entry.
319 DumpDmarContextEntryTable (
320 IN VTD_ROOT_ENTRY
*RootEntry
324 Dump DMAR extended context entry table.
326 @param[in] ExtRootEntry DMAR extended root entry.
329 DumpDmarExtContextEntryTable (
330 IN VTD_EXT_ROOT_ENTRY
*ExtRootEntry
334 Dump DMAR second level paging entry.
336 @param[in] SecondLevelPagingEntry The second level paging entry.
339 DumpSecondLevelPagingEntry (
340 IN VOID
*SecondLevelPagingEntry
344 Set VTd attribute for a system memory.
346 @param[in] VtdIndex The index used to identify a VTd engine.
347 @param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
348 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
349 @param[in] Length The length of device memory address to be used as the DMA memory.
350 @param[in] IoMmuAccess The IOMMU access.
352 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
353 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
354 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
355 @retval EFI_INVALID_PARAMETER Length is 0.
356 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
357 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
358 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
359 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
360 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
365 IN VTD_SECOND_LEVEL_PAGING_ENTRY
*SecondLevelPagingEntry
,
366 IN UINT64 BaseAddress
,
368 IN UINT64 IoMmuAccess
372 Set VTd attribute for a system memory.
374 @param[in] Segment The Segment used to identify a VTd engine.
375 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
376 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
377 @param[in] Length The length of device memory address to be used as the DMA memory.
378 @param[in] IoMmuAccess The IOMMU access.
380 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
381 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
382 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
383 @retval EFI_INVALID_PARAMETER Length is 0.
384 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
385 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
386 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
387 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
388 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
393 IN VTD_SOURCE_ID SourceId
,
394 IN UINT64 BaseAddress
,
396 IN UINT64 IoMmuAccess
400 Return the index of PCI descriptor.
402 @param[in] VtdIndex The index used to identify a VTd engine.
403 @param[in] Segment The Segment used to identify a VTd engine.
404 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
406 @return The index of the PCI descriptor.
407 @retval (UINTN)-1 The PCI descriptor is not found.
413 IN VTD_SOURCE_ID SourceId
417 Dump VTd registers if there is error.
425 Initialize platform VTd policy.
428 InitializePlatformVTdPolicy (
433 Always enable the VTd page attribute for the device.
435 @param[in] Segment The Segment used to identify a VTd engine.
436 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
438 @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
441 AlwaysEnablePageAttribute (
443 IN VTD_SOURCE_ID SourceId
447 Convert the DeviceHandle to SourceId and Segment.
449 @param[in] DeviceHandle The device who initiates the DMA access request.
450 @param[out] Segment The Segment used to identify a VTd engine.
451 @param[out] SourceId The SourceId used to identify a VTd engine and table entry.
453 @retval EFI_SUCCESS The Segment and SourceId are returned.
454 @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
455 @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
458 DeviceHandleToSourceId (
459 IN EFI_HANDLE DeviceHandle
,
461 OUT VTD_SOURCE_ID
*SourceId
465 Get device information from mapping.
467 @param[in] Mapping The mapping.
468 @param[out] DeviceAddress The device address of the mapping.
469 @param[out] NumberOfPages The number of pages of the mapping.
471 @retval EFI_SUCCESS The device information is returned.
472 @retval EFI_INVALID_PARAMETER The mapping is invalid.
475 GetDeviceInfoFromMapping (
477 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
478 OUT UINTN
*NumberOfPages
482 Initialize DMA protection.
485 InitializeDmaProtection (
492 @param[in] Pages the number of pages.
494 @return the page address.
495 @retval NULL No resource to allocate pages.