]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
IntelSiliconPkg: Add VTd driver.
[mirror_edk2.git] / IntelSiliconPkg / IntelVTdDxe / DmaProtection.h
diff --git a/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h b/IntelSiliconPkg/IntelVTdDxe/DmaProtection.h
new file mode 100644 (file)
index 0000000..6efed6e
--- /dev/null
@@ -0,0 +1,501 @@
+/** @file\r
+\r
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+  This program and the accompanying materials\r
+  are licensed and made available under the terms and conditions of the BSD License\r
+  which accompanies this distribution.  The full text of the license may be found at\r
+  http://opensource.org/licenses/bsd-license.php.\r
+\r
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#ifndef _DMAR_PROTECTION_H_\r
+#define _DMAR_PROTECTION_H_\r
+\r
+#include <Uefi.h>\r
+#include <PiDxe.h>\r
+\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/UefiBootServicesTableLib.h>\r
+#include <Library/IoLib.h>\r
+#include <Library/PciSegmentLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/UefiLib.h>\r
+\r
+#include <Guid/EventGroup.h>\r
+#include <Guid/Acpi.h>\r
+\r
+#include <Protocol/DxeSmmReadyToLock.h>\r
+#include <Protocol/PciRootBridgeIo.h>\r
+#include <Protocol/PciIo.h>\r
+#include <Protocol/PciEnumerationComplete.h>\r
+#include <Protocol/AcpiSystemDescriptionTable.h>\r
+#include <Protocol/PlatformVtdPolicy.h>\r
+#include <Protocol/IoMmu.h>\r
+\r
+#include <IndustryStandard/Pci.h>\r
+#include <IndustryStandard/DmaRemappingReportingTable.h>\r
+#include <IndustryStandard/Vtd.h>\r
+\r
+#define ALIGN_VALUE_UP(Value, Alignment)  (((Value) + (Alignment) - 1) & (~((Alignment) - 1)))\r
+#define ALIGN_VALUE_LOW(Value, Alignment) ((Value) & (~((Alignment) - 1)))\r
+\r
+//\r
+// This is the initial max PCI descriptor.\r
+// The number may be enlarged later.\r
+//\r
+#define MAX_PCI_DESCRIPTORS             0x100\r
+\r
+typedef struct {\r
+  BOOLEAN                IncludeAllFlag;\r
+  UINTN                  PciDescriptorNumber;\r
+  UINTN                  PciDescriptorMaxNumber;\r
+  BOOLEAN                *IsRealPciDevice;\r
+  VTD_SOURCE_ID          *PciDescriptors;\r
+} PCI_DEVICE_INFORMATION;\r
+\r
+typedef struct {\r
+  UINTN                            VtdUnitBaseAddress;\r
+  UINT16                           Segment;\r
+  VTD_CAP_REG                      CapReg;\r
+  VTD_ECAP_REG                     ECapReg;\r
+  VTD_ROOT_ENTRY                   *RootEntryTable;\r
+  VTD_EXT_ROOT_ENTRY               *ExtRootEntryTable;\r
+  VTD_SECOND_LEVEL_PAGING_ENTRY    *FixedSecondLevelPagingEntry;\r
+  BOOLEAN                          HasDirtyPages;\r
+  PCI_DEVICE_INFORMATION           PciDeviceInfo;\r
+} VTD_UNIT_INFORMATION;\r
+\r
+extern EFI_ACPI_DMAR_HEADER  *mAcpiDmarTable;\r
+\r
+extern UINT64                           mVtdHostAddressWidthMask;\r
+extern UINTN                            mVtdUnitNumber;\r
+extern VTD_UNIT_INFORMATION             *mVtdUnitInformation;\r
+\r
+extern UINT64                           mBelow4GMemoryLimit;\r
+extern UINT64                           mAbove4GMemoryLimit;\r
+\r
+extern EDKII_PLATFORM_VTD_POLICY_PROTOCOL   *mPlatformVTdPolicy;\r
+\r
+/**\r
+  Prepare VTD configuration.\r
+**/\r
+VOID\r
+PrepareVtdConfig (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Setup VTd translation table.\r
+\r
+  @retval EFI_SUCCESS           Setup translation table successfully.\r
+  @retval EFI_OUT_OF_RESOURCE   Setup translation table fail.\r
+**/\r
+EFI_STATUS\r
+SetupTranslationTable (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Enable DMAR translation.\r
+\r
+  @retval EFI_SUCCESS           DMAR translation is enabled.\r
+  @retval EFI_DEVICE_ERROR      DMAR translation is not enabled.\r
+**/\r
+EFI_STATUS\r
+EnableDmar (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Disable DMAR translation.\r
+\r
+  @retval EFI_SUCCESS           DMAR translation is disabled.\r
+  @retval EFI_DEVICE_ERROR      DMAR translation is not disabled.\r
+**/\r
+EFI_STATUS\r
+DisableDmar (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Invalid VTd IOTLB page.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+  @param[in]  Address               The address of IOTLB page.\r
+  @param[in]  AddressMode           The address mode of IOTLB page.\r
+  @param[in]  DomainIdentifier      The domain ID of the source.\r
+\r
+  @retval EFI_SUCCESS           VTd IOTLB page is invalidated.\r
+  @retval EFI_DEVICE_ERROR      VTd IOTLB page is not invalidated.\r
+**/\r
+EFI_STATUS\r
+InvalidateVtdIOTLBPage (\r
+  IN UINTN  VtdIndex,\r
+  IN UINT64 Address,\r
+  IN UINT8  AddressMode,\r
+  IN UINT16 DomainIdentifier\r
+  );\r
+\r
+/**\r
+  Invalid VTd IOTLB domain.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+  @param[in]  DomainIdentifier      The domain ID of the source.\r
+\r
+  @retval EFI_SUCCESS           VTd IOTLB domain is invalidated.\r
+  @retval EFI_DEVICE_ERROR      VTd IOTLB domain is not invalidated.\r
+**/\r
+EFI_STATUS\r
+InvalidateVtdIOTLBDomain (\r
+  IN UINTN  VtdIndex,\r
+  IN UINT16 DomainIdentifier\r
+  );\r
+\r
+/**\r
+  Invalid VTd global IOTLB.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+\r
+  @retval EFI_SUCCESS           VTd global IOTLB is invalidated.\r
+  @retval EFI_DEVICE_ERROR      VTd global IOTLB is not invalidated.\r
+**/\r
+EFI_STATUS\r
+InvalidateVtdIOTLBGlobal (\r
+  IN UINTN  VtdIndex\r
+  );\r
+\r
+/**\r
+  Dump VTd registers.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+**/\r
+VOID\r
+DumpVtdRegs (\r
+  IN UINTN  VtdIndex\r
+  );\r
+\r
+/**\r
+  Dump VTd registers for all VTd engine.\r
+**/\r
+VOID\r
+DumpVtdRegsAll (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Dump VTd capability registers.\r
+\r
+  @param[in]  CapReg              The capability register.\r
+**/\r
+VOID\r
+DumpVtdCapRegs (\r
+  IN VTD_CAP_REG *CapReg\r
+  );\r
+\r
+/**\r
+  Dump VTd extended capability registers.\r
+\r
+  @param[in]  ECapReg              The extended capability register.\r
+**/\r
+VOID\r
+DumpVtdECapRegs (\r
+  IN VTD_ECAP_REG *ECapReg\r
+  );\r
+\r
+/**\r
+  Register PCI device to VTd engine as PCI descriptor.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+  @param[in]  Segment               The segment of the source.\r
+  @param[in]  SourceId              The SourceId of the source.\r
+  @param[in]  IsRealPciDevice       TRUE: It is a real PCI device.\r
+                                    FALSE: It is not a real PCI device.\r
+  @param[in]  CheckExist            TRUE: ERROR will be returned if the PCI device is already registered.\r
+                                    FALSE: SUCCESS will be returned if the PCI device is registered.\r
+\r
+  @retval EFI_SUCCESS           The PCI device is registered.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough resource to register a new PCI device.\r
+  @retval EFI_ALREADY_STARTED   The device is already registered.\r
+**/\r
+EFI_STATUS\r
+RegisterPciDevice (\r
+  IN UINTN          VtdIndex,\r
+  IN UINT16         Segment,\r
+  IN VTD_SOURCE_ID  SourceId,\r
+  IN BOOLEAN        IsRealPciDevice,\r
+  IN BOOLEAN        CheckExist\r
+  );\r
+\r
+/**\r
+  Scan PCI bus and register PCI devices under the bus.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+  @param[in]  Segment               The segment of the source.\r
+  @param[in]  Bus                   The bus of the source.\r
+\r
+  @retval EFI_SUCCESS           The PCI devices under the bus are registered.\r
+  @retval EFI_OUT_OF_RESOURCES  No enough resource to register a new PCI device.\r
+**/\r
+EFI_STATUS\r
+ScanPciBus (\r
+  IN UINTN          VtdIndex,\r
+  IN UINT16         Segment,\r
+  IN UINT8          Bus\r
+  );\r
+\r
+/**\r
+  Dump the PCI device information managed by this VTd engine.\r
+\r
+  @param[in]  VtdIndex              The index of VTd engine.\r
+**/\r
+VOID\r
+DumpPciDeviceInfo (\r
+  IN UINTN  VtdIndex\r
+  );\r
+\r
+/**\r
+  Find the VTd index by the Segment and SourceId.\r
+\r
+  @param[in]  Segment               The segment of the source.\r
+  @param[in]  SourceId              The SourceId of the source.\r
+  @param[out] ExtContextEntry       The ExtContextEntry of the source.\r
+  @param[out] ContextEntry          The ContextEntry of the source.\r
+\r
+  @return The index of the PCI descriptor.\r
+  @retval (UINTN)-1  The PCI descriptor is not found.\r
+**/\r
+UINTN\r
+FindVtdIndexByPciDevice (\r
+  IN  UINT16                  Segment,\r
+  IN  VTD_SOURCE_ID           SourceId,\r
+  OUT VTD_EXT_CONTEXT_ENTRY   **ExtContextEntry,\r
+  OUT VTD_CONTEXT_ENTRY       **ContextEntry\r
+  );\r
+\r
+/**\r
+  Get the DMAR ACPI table.\r
+\r
+  @retval EFI_SUCCESS    The DMAR ACPI table is got.\r
+  @retval EFI_NOT_FOUND  The DMAR ACPI table is not found.\r
+**/\r
+EFI_STATUS\r
+GetDmarAcpiTable (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Parse DMAR DRHD table.\r
+\r
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableDrhd (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Parse DMAR RMRR table.\r
+\r
+  @return EFI_SUCCESS  The DMAR RMRR table is parsed.\r
+**/\r
+EFI_STATUS\r
+ParseDmarAcpiTableRmrr (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Dump DMAR context entry table.\r
+\r
+  @param[in]  RootEntry DMAR root entry.\r
+**/\r
+VOID\r
+DumpDmarContextEntryTable (\r
+  IN VTD_ROOT_ENTRY *RootEntry\r
+  );\r
+\r
+/**\r
+  Dump DMAR extended context entry table.\r
+\r
+  @param[in]  ExtRootEntry DMAR extended root entry.\r
+**/\r
+VOID\r
+DumpDmarExtContextEntryTable (\r
+  IN VTD_EXT_ROOT_ENTRY *ExtRootEntry\r
+  );\r
+\r
+/**\r
+  Dump DMAR second level paging entry.\r
+\r
+  @param[in]  SecondLevelPagingEntry The second level paging entry.\r
+**/\r
+VOID\r
+DumpSecondLevelPagingEntry (\r
+  IN VOID *SecondLevelPagingEntry\r
+  );\r
+\r
+/**\r
+  Set VTd attribute for a system memory.\r
+\r
+  @param[in]  VtdIndex                The index used to identify a VTd engine.\r
+  @param[in]  SecondLevelPagingEntry  The second level paging entry in VTd table for the device.\r
+  @param[in]  BaseAddress             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
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range specified by BaseAddress and Length.\r
+  @retval EFI_INVALID_PARAMETER  BaseAddress is not IoMmu Page size aligned.\r
+  @retval EFI_INVALID_PARAMETER  Length is not IoMmu Page size aligned.\r
+  @retval EFI_INVALID_PARAMETER  Length is 0.\r
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination of access.\r
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported by the IOMMU.\r
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range specified by BaseAddress and Length.\r
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to modify the IOMMU access.\r
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while attempting the operation.\r
+**/\r
+EFI_STATUS\r
+SetPageAttribute (\r
+  IN UINTN                         VtdIndex,\r
+  IN VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry,\r
+  IN UINT64                        BaseAddress,\r
+  IN UINT64                        Length,\r
+  IN UINT64                        IoMmuAccess\r
+  );\r
+\r
+/**\r
+  Set VTd attribute for a system memory.\r
+\r
+  @param[in]  Segment           The Segment used to identify a VTd engine.\r
+  @param[in]  SourceId          The SourceId used to identify a VTd engine and table entry.\r
+  @param[in]  BaseAddress       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
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range specified by BaseAddress and Length.\r
+  @retval EFI_INVALID_PARAMETER  BaseAddress is not IoMmu Page size aligned.\r
+  @retval EFI_INVALID_PARAMETER  Length is not IoMmu Page size aligned.\r
+  @retval EFI_INVALID_PARAMETER  Length is 0.\r
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination of access.\r
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported by the IOMMU.\r
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range specified by BaseAddress and Length.\r
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to modify the IOMMU access.\r
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while attempting the operation.\r
+**/\r
+EFI_STATUS\r
+SetAccessAttribute (\r
+  IN UINT16                Segment,\r
+  IN VTD_SOURCE_ID         SourceId,\r
+  IN UINT64                BaseAddress,\r
+  IN UINT64                Length,\r
+  IN UINT64                IoMmuAccess\r
+  );\r
+\r
+/**\r
+  Return the index of PCI descriptor.\r
+\r
+  @param[in]  VtdIndex          The index used to identify a VTd engine.\r
+  @param[in]  Segment           The Segment used to identify a VTd engine.\r
+  @param[in]  SourceId          The SourceId used to identify a VTd engine and table entry.\r
+\r
+  @return The index of the PCI descriptor.\r
+  @retval (UINTN)-1  The PCI descriptor is not found.\r
+**/\r
+UINTN\r
+GetPciDescriptor (\r
+  IN UINTN          VtdIndex,\r
+  IN UINT16         Segment,\r
+  IN VTD_SOURCE_ID  SourceId\r
+  );\r
+\r
+/**\r
+  Dump VTd registers if there is error.\r
+**/\r
+VOID\r
+DumpVtdIfError (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Initialize platform VTd policy.\r
+**/\r
+VOID\r
+InitializePlatformVTdPolicy (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Always enable the VTd page attribute for the device.\r
+\r
+  @param[in]  Segment           The Segment used to identify a VTd engine.\r
+  @param[in]  SourceId          The SourceId used to identify a VTd engine and table entry.\r
+\r
+  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device.\r
+**/\r
+EFI_STATUS\r
+AlwaysEnablePageAttribute (\r
+  IN UINT16                  Segment,\r
+  IN VTD_SOURCE_ID           SourceId\r
+  );\r
+\r
+/**\r
+  Convert the DeviceHandle to SourceId and Segment.\r
+\r
+  @param[in]  DeviceHandle      The device who initiates the DMA access request.\r
+  @param[out] Segment           The Segment used to identify a VTd engine.\r
+  @param[out] SourceId          The SourceId used to identify a VTd engine and table entry.\r
+\r
+  @retval EFI_SUCCESS            The Segment and SourceId are returned.\r
+  @retval EFI_INVALID_PARAMETER  DeviceHandle is an invalid handle.\r
+  @retval EFI_UNSUPPORTED        DeviceHandle is unknown by the IOMMU.\r
+**/\r
+EFI_STATUS\r
+DeviceHandleToSourceId (\r
+  IN EFI_HANDLE            DeviceHandle,\r
+  OUT UINT16               *Segment,\r
+  OUT VTD_SOURCE_ID        *SourceId\r
+  );\r
+\r
+/**\r
+  Get device information from mapping.\r
+\r
+  @param[in]  Mapping        The mapping.\r
+  @param[out] DeviceAddress  The device address of the mapping.\r
+  @param[out] NumberOfPages  The number of pages of the mapping.\r
+\r
+  @retval EFI_SUCCESS            The device information is returned.\r
+  @retval EFI_INVALID_PARAMETER  The mapping is invalid.\r
+**/\r
+EFI_STATUS\r
+GetDeviceInfoFromMapping (\r
+  IN  VOID                                     *Mapping,\r
+  OUT EFI_PHYSICAL_ADDRESS                     *DeviceAddress,\r
+  OUT UINTN                                    *NumberOfPages\r
+  );\r
+\r
+/**\r
+  Initialize DMA protection.\r
+**/\r
+VOID\r
+InitializeDmaProtection (\r
+  VOID\r
+  );\r
+\r
+/**\r
+  Allocate zero pages.\r
+\r
+  @param[in]  Pages the number of pages.\r
+\r
+  @return the page address.\r
+  @retval NULL No resource to allocate pages.\r
+**/\r
+VOID *\r
+EFIAPI\r
+AllocateZeroPages (\r
+  IN UINTN  Pages\r
+  );\r
+\r
+#endif\r