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 ALIGN_VALUE_UP(Value, Alignment) (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))
45 #define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))
48 // This is the initial max PCI descriptor.
49 // The number may be enlarged later.
51 #define MAX_PCI_DESCRIPTORS 0x100
54 BOOLEAN IncludeAllFlag
;
55 UINTN PciDescriptorNumber
;
56 UINTN PciDescriptorMaxNumber
;
57 BOOLEAN
*IsRealPciDevice
;
58 VTD_SOURCE_ID
*PciDescriptors
;
59 } PCI_DEVICE_INFORMATION
;
62 UINTN VtdUnitBaseAddress
;
66 VTD_ROOT_ENTRY
*RootEntryTable
;
67 VTD_EXT_ROOT_ENTRY
*ExtRootEntryTable
;
68 VTD_SECOND_LEVEL_PAGING_ENTRY
*FixedSecondLevelPagingEntry
;
69 BOOLEAN HasDirtyPages
;
70 PCI_DEVICE_INFORMATION PciDeviceInfo
;
71 } VTD_UNIT_INFORMATION
;
73 extern EFI_ACPI_DMAR_HEADER
*mAcpiDmarTable
;
75 extern UINT64 mVtdHostAddressWidthMask
;
76 extern UINTN mVtdUnitNumber
;
77 extern VTD_UNIT_INFORMATION
*mVtdUnitInformation
;
79 extern UINT64 mBelow4GMemoryLimit
;
80 extern UINT64 mAbove4GMemoryLimit
;
82 extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL
*mPlatformVTdPolicy
;
85 Prepare VTD configuration.
93 Setup VTd translation table.
95 @retval EFI_SUCCESS Setup translation table successfully.
96 @retval EFI_OUT_OF_RESOURCE Setup translation table fail.
99 SetupTranslationTable (
104 Enable DMAR translation.
106 @retval EFI_SUCCESS DMAR translation is enabled.
107 @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
115 Disable DMAR translation.
117 @retval EFI_SUCCESS DMAR translation is disabled.
118 @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
126 Invalid VTd IOTLB page.
128 @param[in] VtdIndex The index of VTd engine.
129 @param[in] Address The address of IOTLB page.
130 @param[in] AddressMode The address mode of IOTLB page.
131 @param[in] DomainIdentifier The domain ID of the source.
133 @retval EFI_SUCCESS VTd IOTLB page is invalidated.
134 @retval EFI_DEVICE_ERROR VTd IOTLB page is not invalidated.
137 InvalidateVtdIOTLBPage (
140 IN UINT8 AddressMode
,
141 IN UINT16 DomainIdentifier
145 Invalid VTd IOTLB domain.
147 @param[in] VtdIndex The index of VTd engine.
148 @param[in] DomainIdentifier The domain ID of the source.
150 @retval EFI_SUCCESS VTd IOTLB domain is invalidated.
151 @retval EFI_DEVICE_ERROR VTd IOTLB domain is not invalidated.
154 InvalidateVtdIOTLBDomain (
156 IN UINT16 DomainIdentifier
160 Invalid VTd global IOTLB.
162 @param[in] VtdIndex The index of VTd engine.
164 @retval EFI_SUCCESS VTd global IOTLB is invalidated.
165 @retval EFI_DEVICE_ERROR VTd global IOTLB is not invalidated.
168 InvalidateVtdIOTLBGlobal (
175 @param[in] VtdIndex The index of VTd engine.
183 Dump VTd registers for all VTd engine.
191 Dump VTd capability registers.
193 @param[in] CapReg The capability register.
197 IN VTD_CAP_REG
*CapReg
201 Dump VTd extended capability registers.
203 @param[in] ECapReg The extended capability register.
207 IN VTD_ECAP_REG
*ECapReg
211 Register PCI device to VTd engine as PCI descriptor.
213 @param[in] VtdIndex The index of VTd engine.
214 @param[in] Segment The segment of the source.
215 @param[in] SourceId The SourceId of the source.
216 @param[in] IsRealPciDevice TRUE: It is a real PCI device.
217 FALSE: It is not a real PCI device.
218 @param[in] CheckExist TRUE: ERROR will be returned if the PCI device is already registered.
219 FALSE: SUCCESS will be returned if the PCI device is registered.
221 @retval EFI_SUCCESS The PCI device is registered.
222 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
223 @retval EFI_ALREADY_STARTED The device is already registered.
229 IN VTD_SOURCE_ID SourceId
,
230 IN BOOLEAN IsRealPciDevice
,
231 IN BOOLEAN CheckExist
235 Scan PCI bus and register PCI devices under the bus.
237 @param[in] VtdIndex The index of VTd engine.
238 @param[in] Segment The segment of the source.
239 @param[in] Bus The bus of the source.
241 @retval EFI_SUCCESS The PCI devices under the bus are registered.
242 @retval EFI_OUT_OF_RESOURCES No enough resource to register a new PCI device.
252 Dump the PCI device information managed by this VTd engine.
254 @param[in] VtdIndex The index of VTd engine.
262 Find the VTd index by the Segment and SourceId.
264 @param[in] Segment The segment of the source.
265 @param[in] SourceId The SourceId of the source.
266 @param[out] ExtContextEntry The ExtContextEntry of the source.
267 @param[out] ContextEntry The ContextEntry of the source.
269 @return The index of the PCI descriptor.
270 @retval (UINTN)-1 The PCI descriptor is not found.
273 FindVtdIndexByPciDevice (
275 IN VTD_SOURCE_ID SourceId
,
276 OUT VTD_EXT_CONTEXT_ENTRY
**ExtContextEntry
,
277 OUT VTD_CONTEXT_ENTRY
**ContextEntry
281 Get the DMAR ACPI table.
283 @retval EFI_SUCCESS The DMAR ACPI table is got.
284 @retval EFI_NOT_FOUND The DMAR ACPI table is not found.
292 Parse DMAR DRHD table.
294 @return EFI_SUCCESS The DMAR DRHD table is parsed.
297 ParseDmarAcpiTableDrhd (
302 Parse DMAR RMRR table.
304 @return EFI_SUCCESS The DMAR RMRR table is parsed.
307 ParseDmarAcpiTableRmrr (
312 Dump DMAR context entry table.
314 @param[in] RootEntry DMAR root entry.
317 DumpDmarContextEntryTable (
318 IN VTD_ROOT_ENTRY
*RootEntry
322 Dump DMAR extended context entry table.
324 @param[in] ExtRootEntry DMAR extended root entry.
327 DumpDmarExtContextEntryTable (
328 IN VTD_EXT_ROOT_ENTRY
*ExtRootEntry
332 Dump DMAR second level paging entry.
334 @param[in] SecondLevelPagingEntry The second level paging entry.
337 DumpSecondLevelPagingEntry (
338 IN VOID
*SecondLevelPagingEntry
342 Set VTd attribute for a system memory.
344 @param[in] VtdIndex The index used to identify a VTd engine.
345 @param[in] SecondLevelPagingEntry The second level paging entry in VTd table for the device.
346 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
347 @param[in] Length The length of device memory address to be used as the DMA memory.
348 @param[in] IoMmuAccess The IOMMU access.
350 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
351 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
352 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
353 @retval EFI_INVALID_PARAMETER Length is 0.
354 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
355 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
356 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
357 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
358 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
363 IN VTD_SECOND_LEVEL_PAGING_ENTRY
*SecondLevelPagingEntry
,
364 IN UINT64 BaseAddress
,
366 IN UINT64 IoMmuAccess
370 Set VTd attribute for a system memory.
372 @param[in] Segment The Segment used to identify a VTd engine.
373 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
374 @param[in] BaseAddress The base of device memory address to be used as the DMA memory.
375 @param[in] Length The length of device memory address to be used as the DMA memory.
376 @param[in] IoMmuAccess The IOMMU access.
378 @retval EFI_SUCCESS The IoMmuAccess is set for the memory range specified by BaseAddress and Length.
379 @retval EFI_INVALID_PARAMETER BaseAddress is not IoMmu Page size aligned.
380 @retval EFI_INVALID_PARAMETER Length is not IoMmu Page size aligned.
381 @retval EFI_INVALID_PARAMETER Length is 0.
382 @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
383 @retval EFI_UNSUPPORTED The bit mask of IoMmuAccess is not supported by the IOMMU.
384 @retval EFI_UNSUPPORTED The IOMMU does not support the memory range specified by BaseAddress and Length.
385 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to modify the IOMMU access.
386 @retval EFI_DEVICE_ERROR The IOMMU device reported an error while attempting the operation.
391 IN VTD_SOURCE_ID SourceId
,
392 IN UINT64 BaseAddress
,
394 IN UINT64 IoMmuAccess
398 Return the index of PCI descriptor.
400 @param[in] VtdIndex The index used to identify a VTd engine.
401 @param[in] Segment The Segment used to identify a VTd engine.
402 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
404 @return The index of the PCI descriptor.
405 @retval (UINTN)-1 The PCI descriptor is not found.
411 IN VTD_SOURCE_ID SourceId
415 Dump VTd registers if there is error.
423 Initialize platform VTd policy.
426 InitializePlatformVTdPolicy (
431 Always enable the VTd page attribute for the device.
433 @param[in] Segment The Segment used to identify a VTd engine.
434 @param[in] SourceId The SourceId used to identify a VTd engine and table entry.
436 @retval EFI_SUCCESS The VTd entry is updated to always enable all DMA access for the specific device.
439 AlwaysEnablePageAttribute (
441 IN VTD_SOURCE_ID SourceId
445 Convert the DeviceHandle to SourceId and Segment.
447 @param[in] DeviceHandle The device who initiates the DMA access request.
448 @param[out] Segment The Segment used to identify a VTd engine.
449 @param[out] SourceId The SourceId used to identify a VTd engine and table entry.
451 @retval EFI_SUCCESS The Segment and SourceId are returned.
452 @retval EFI_INVALID_PARAMETER DeviceHandle is an invalid handle.
453 @retval EFI_UNSUPPORTED DeviceHandle is unknown by the IOMMU.
456 DeviceHandleToSourceId (
457 IN EFI_HANDLE DeviceHandle
,
459 OUT VTD_SOURCE_ID
*SourceId
463 Get device information from mapping.
465 @param[in] Mapping The mapping.
466 @param[out] DeviceAddress The device address of the mapping.
467 @param[out] NumberOfPages The number of pages of the mapping.
469 @retval EFI_SUCCESS The device information is returned.
470 @retval EFI_INVALID_PARAMETER The mapping is invalid.
473 GetDeviceInfoFromMapping (
475 OUT EFI_PHYSICAL_ADDRESS
*DeviceAddress
,
476 OUT UINTN
*NumberOfPages
480 Initialize DMA protection.
483 InitializeDmaProtection (
490 @param[in] Pages the number of pages.
492 @return the page address.
493 @retval NULL No resource to allocate pages.