summaryrefslogtreecommitdiffstats
path: root/IntelSiliconPkg/Feature
diff options
context:
space:
mode:
authorJiewen Yao <jiewen.yao@intel.com>2017-09-23 16:27:50 +0800
committerJiewen Yao <jiewen.yao@intel.com>2017-10-30 09:27:55 +0800
commita1e7cd0b020ac024015095068b02e03a68edd96c (patch)
tree14d380b67d1d7d82d85297f75d0946431a34a605 /IntelSiliconPkg/Feature
parente5d847476ab6386bef4e3c70e76f5d26c606ed5e (diff)
downloadedk2-a1e7cd0b020ac024015095068b02e03a68edd96c.tar.gz
edk2-a1e7cd0b020ac024015095068b02e03a68edd96c.tar.bz2
edk2-a1e7cd0b020ac024015095068b02e03a68edd96c.zip
IntelSiliconPkg/VtdPmrPei: Add premem support.
Remove memory discovered dependency to support both premem VTD_INFO_PPI and postmem VTD_INFO_PPI. If VTD_INFO_PPI is installed before memory is ready, this driver protects all memory region. If VTD_INFO_PPI is installed or reinstalled after memory is ready, this driver allocates DMA buffer and protect rest. Cc: Star Zeng <star.zeng@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
Diffstat (limited to 'IntelSiliconPkg/Feature')
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c580
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c130
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c847
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h93
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf11
-rw-r--r--IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c293
6 files changed, 1358 insertions, 596 deletions
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
new file mode 100644
index 0000000000..891efa6546
--- /dev/null
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
@@ -0,0 +1,580 @@
+/** @file
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/HobLib.h>
+#include <IndustryStandard/Vtd.h>
+#include <Ppi/VtdInfo.h>
+
+#include "IntelVTdPmrPei.h"
+
+/**
+ Dump DMAR DeviceScopeEntry.
+
+ @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
+**/
+VOID
+DumpDmarDeviceScopeEntry (
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
+ )
+{
+ UINTN PciPathNumber;
+ UINTN PciPathIndex;
+ EFI_ACPI_DMAR_PCI_PATH *PciPath;
+
+ if (DmarDeviceScopeEntry == NULL) {
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " *************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " * DMA-Remapping Device Scope Entry Structure *\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " *************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ (sizeof(UINTN) == sizeof(UINT64)) ?
+ " DMAR Device Scope Entry address ...................... 0x%016lx\n" :
+ " DMAR Device Scope Entry address ...................... 0x%08x\n",
+ DmarDeviceScopeEntry
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Device Scope Entry Type ............................ 0x%02x\n",
+ DmarDeviceScopeEntry->Type
+ ));
+ switch (DmarDeviceScopeEntry->Type) {
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
+ DEBUG ((DEBUG_INFO,
+ " PCI Endpoint Device\n"
+ ));
+ break;
+ case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
+ DEBUG ((DEBUG_INFO,
+ " PCI Sub-hierachy\n"
+ ));
+ break;
+ default:
+ break;
+ }
+ DEBUG ((DEBUG_INFO,
+ " Length ............................................. 0x%02x\n",
+ DmarDeviceScopeEntry->Length
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Enumeration ID ..................................... 0x%02x\n",
+ DmarDeviceScopeEntry->EnumerationId
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Starting Bus Number ................................ 0x%02x\n",
+ DmarDeviceScopeEntry->StartBusNumber
+ ));
+
+ PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
+ PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
+ for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
+ DEBUG ((DEBUG_INFO,
+ " Device ............................................. 0x%02x\n",
+ PciPath[PciPathIndex].Device
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Function ........................................... 0x%02x\n",
+ PciPath[PciPathIndex].Function
+ ));
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " *************************************************************************\n\n"
+ ));
+
+ return;
+}
+
+/**
+ Dump DMAR RMRR table.
+
+ @param[in] Rmrr DMAR RMRR table
+**/
+VOID
+DumpDmarRmrr (
+ IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
+ )
+{
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
+ INTN RmrrLen;
+
+ if (Rmrr == NULL) {
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " * Reserved Memory Region Reporting Structure *\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ (sizeof(UINTN) == sizeof(UINT64)) ?
+ " RMRR address ........................................... 0x%016lx\n" :
+ " RMRR address ........................................... 0x%08x\n",
+ Rmrr
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Type ................................................. 0x%04x\n",
+ Rmrr->Header.Type
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Length ............................................... 0x%04x\n",
+ Rmrr->Header.Length
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Segment Number ....................................... 0x%04x\n",
+ Rmrr->SegmentNumber
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Reserved Memory Region Base Address .................. 0x%016lx\n",
+ Rmrr->ReservedMemoryRegionBaseAddress
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Reserved Memory Region Limit Address ................. 0x%016lx\n",
+ Rmrr->ReservedMemoryRegionLimitAddress
+ ));
+
+ RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
+ while (RmrrLen > 0) {
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+ RmrrLen -= DmarDeviceScopeEntry->Length;
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n\n"
+ ));
+
+ return;
+}
+
+/**
+ Dump DMAR DRHD table.
+
+ @param[in] Drhd DMAR DRHD table
+**/
+VOID
+DumpDmarDrhd (
+ IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+ )
+{
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
+ INTN DrhdLen;
+
+ if (Drhd == NULL) {
+ return;
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " * DMA-Remapping Hardware Definition Structure *\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ (sizeof(UINTN) == sizeof(UINT64)) ?
+ " DRHD address ........................................... 0x%016lx\n" :
+ " DRHD address ........................................... 0x%08x\n",
+ Drhd
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Type ................................................. 0x%04x\n",
+ Drhd->Header.Type
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Length ............................................... 0x%04x\n",
+ Drhd->Header.Length
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Flags ................................................ 0x%02x\n",
+ Drhd->Flags
+ ));
+ DEBUG ((DEBUG_INFO,
+ " INCLUDE_PCI_ALL .................................... 0x%02x\n",
+ Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Segment Number ....................................... 0x%04x\n",
+ Drhd->SegmentNumber
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Register Base Address ................................ 0x%016lx\n",
+ Drhd->RegisterBaseAddress
+ ));
+
+ DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
+ while (DrhdLen > 0) {
+ DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+ DrhdLen -= DmarDeviceScopeEntry->Length;
+ DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
+ }
+
+ DEBUG ((DEBUG_INFO,
+ " ***************************************************************************\n\n"
+ ));
+
+ return;
+}
+
+/**
+ Dump DMAR ACPI table.
+
+ @param[in] Dmar DMAR ACPI table
+**/
+VOID
+DumpAcpiDMAR (
+ IN EFI_ACPI_DMAR_HEADER *Dmar
+ )
+{
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+ INTN DmarLen;
+
+ if (Dmar == NULL) {
+ return;
+ }
+
+ //
+ // Dump Dmar table
+ //
+ DEBUG ((DEBUG_INFO,
+ "*****************************************************************************\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ "* DMAR Table *\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ "*****************************************************************************\n"
+ ));
+
+ DEBUG ((DEBUG_INFO,
+ (sizeof(UINTN) == sizeof(UINT64)) ?
+ "DMAR address ............................................. 0x%016lx\n" :
+ "DMAR address ............................................. 0x%08x\n",
+ Dmar
+ ));
+
+ DEBUG ((DEBUG_INFO,
+ " Table Contents:\n"
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Host Address Width ................................... 0x%02x\n",
+ Dmar->HostAddressWidth
+ ));
+ DEBUG ((DEBUG_INFO,
+ " Flags ................................................ 0x%02x\n",
+ Dmar->Flags
+ ));
+ DEBUG ((DEBUG_INFO,
+ " INTR_REMAP ......................................... 0x%02x\n",
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
+ ));
+ DEBUG ((DEBUG_INFO,
+ " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
+ Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
+ ));
+
+ DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
+ while (DmarLen > 0) {
+ switch (DmarHeader->Type) {
+ case EFI_ACPI_DMAR_TYPE_DRHD:
+ DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+ break;
+ case EFI_ACPI_DMAR_TYPE_RMRR:
+ DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+ break;
+ default:
+ break;
+ }
+ DmarLen -= DmarHeader->Length;
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ }
+
+ DEBUG ((DEBUG_INFO,
+ "*****************************************************************************\n\n"
+ ));
+
+ return;
+}
+
+/**
+ Get VTd engine number.
+
+ @param[in] AcpiDmarTable DMAR ACPI table
+
+ @return the VTd engine number.
+**/
+UINTN
+GetVtdEngineNumber (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
+ )
+{
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+ UINTN VtdIndex;
+
+ VtdIndex = 0;
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
+ while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
+ switch (DmarHeader->Type) {
+ case EFI_ACPI_DMAR_TYPE_DRHD:
+ VtdIndex++;
+ break;
+ default:
+ break;
+ }
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ }
+ return VtdIndex ;
+}
+
+/**
+ Process DMAR DHRD table.
+
+ @param[in] VTdInfo The VTd engine context information.
+ @param[in] VtdIndex The index of VTd engine.
+ @param[in] DmarDrhd The DRHD table.
+**/
+VOID
+ProcessDhrd (
+ IN VTD_INFO *VTdInfo,
+ IN UINTN VtdIndex,
+ IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
+ )
+{
+ DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
+ VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
+}
+
+/**
+ Parse DMAR DRHD table.
+
+ @param[in] AcpiDmarTable DMAR ACPI table
+
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.
+**/
+EFI_STATUS
+ParseDmarAcpiTableDrhd (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
+ )
+{
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+ UINTN VtdUnitNumber;
+ UINTN VtdIndex;
+ VTD_INFO *VTdInfo;
+
+ VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
+ if (VtdUnitNumber == 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
+ ASSERT(VTdInfo != NULL);
+ if (VTdInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Initialize the engine mask to all.
+ //
+ VTdInfo->AcpiDmarTable = AcpiDmarTable;
+ VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+ VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+ VTdInfo->VTdEngineCount = VtdUnitNumber;
+
+ VtdIndex = 0;
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
+ while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
+ switch (DmarHeader->Type) {
+ case EFI_ACPI_DMAR_TYPE_DRHD:
+ ASSERT (VtdIndex < VtdUnitNumber);
+ ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+ VtdIndex++;
+
+ break;
+
+ default:
+ break;
+ }
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ }
+ ASSERT (VtdIndex == VtdUnitNumber);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Return the VTd engine index according to the Segment and DevScopeEntry.
+
+ @param AcpiDmarTable DMAR ACPI table
+ @param Segment The segment of the VTd engine
+ @param DevScopeEntry The DevScopeEntry of the VTd engine
+
+ @return The VTd engine index according to the Segment and DevScopeEntry.
+ @retval -1 The VTd engine is not found.
+**/
+UINTN
+GetVTdEngineFromDevScopeEntry (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
+ IN UINT16 Segment,
+ IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+ )
+{
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+ UINTN VtdIndex;
+ EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
+
+ VtdIndex = 0;
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
+ while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
+ switch (DmarHeader->Type) {
+ case EFI_ACPI_DMAR_TYPE_DRHD:
+ DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
+ if (DmarDrhd->SegmentNumber != Segment) {
+ // Mismatch
+ break;
+ }
+ if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
+ ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
+ // No DevScopeEntry
+ // Do not handle PCI_ALL
+ break;
+ }
+ ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
+ while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
+ if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
+ (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
+ return VtdIndex;
+ }
+ ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
+ }
+ break;
+ default:
+ break;
+ }
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ }
+ return (UINTN)-1;
+}
+
+/**
+ Process DMAR RMRR table.
+
+ @param[in] VTdInfo The VTd engine context information.
+ @param[in] DmarRmrr The RMRR table.
+**/
+VOID
+ProcessRmrr (
+ IN VTD_INFO *VTdInfo,
+ IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
+ )
+{
+ EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
+ UINTN VTdIndex;
+ UINT64 RmrrMask;
+ UINTN LowBottom;
+ UINTN LowTop;
+ UINTN HighBottom;
+ UINT64 HighTop;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+
+ AcpiDmarTable = VTdInfo->AcpiDmarTable;
+
+ DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
+
+ if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
+ (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
+ return ;
+ }
+
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));
+ while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
+ ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
+
+ VTdIndex = GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->SegmentNumber, DmarDevScopeEntry);
+ if (VTdIndex != (UINTN)-1) {
+ RmrrMask = LShiftU64 (1, VTdIndex);
+
+ LowBottom = 0;
+ LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
+ HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
+ HighTop = GetTopMemory ();
+
+ SetDmaProtectedRange (
+ VTdInfo,
+ RmrrMask,
+ 0,
+ (UINT32)(LowTop - LowBottom),
+ HighBottom,
+ HighTop - HighBottom
+ );
+
+ //
+ // Remove the engine from the engine mask.
+ // The assumption is that any other PEI driver does not access
+ // the device covered by this engine.
+ //
+ VTdInfo->EngineMask = VTdInfo->EngineMask & (~RmrrMask);
+ }
+
+ DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+ }
+}
+
+/**
+ Parse DMAR DRHD table.
+
+ @param[in] VTdInfo The VTd engine context information.
+**/
+VOID
+ParseDmarAcpiTableRmrr (
+ IN VTD_INFO *VTdInfo
+ )
+{
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+
+ AcpiDmarTable = VTdInfo->AcpiDmarTable;
+
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
+ while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
+ switch (DmarHeader->Type) {
+ case EFI_ACPI_DMAR_TYPE_RMRR:
+ ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+ break;
+ default:
+ break;
+ }
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ }
+}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
index 6179dfe5dc..000a81ba18 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
@@ -22,17 +22,17 @@
#include "IntelVTdPmrPei.h"
-extern VTD_INFO *mVTdInfo;
-
/**
Get protected low memory alignment.
+ @param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected low memory alignment.
**/
UINT32
GetPlmrAlignment (
+ IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
@@ -48,19 +48,18 @@ GetPlmrAlignment (
/**
Get protected high memory alignment.
+ @param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected high memory alignment.
**/
UINT64
GetPhmrAlignment (
+ IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
UINT64 Data64;
- UINT8 HostAddressWidth;
-
- HostAddressWidth = mVTdInfo->HostAddressWidth;
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
@@ -73,12 +72,14 @@ GetPhmrAlignment (
/**
Get protected low memory alignment.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected low memory alignment.
**/
UINT32
GetLowMemoryAlignment (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
@@ -87,11 +88,11 @@ GetLowMemoryAlignment (
UINT32 FinalAlignment;
FinalAlignment = 0;
- for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
- Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
+ Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
@@ -102,12 +103,14 @@ GetLowMemoryAlignment (
/**
Get protected high memory alignment.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected high memory alignment.
**/
UINT64
GetHighMemoryAlignment (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
@@ -116,11 +119,11 @@ GetHighMemoryAlignment (
UINT64 FinalAlignment;
FinalAlignment = 0;
- for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
- Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
+ Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
@@ -144,12 +147,19 @@ EnablePmr (
UINT32 Reg32;
VTD_CAP_REG CapReg;
+ DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));
+
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
return EFI_UNSUPPORTED;
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+ if (Reg32 == 0xFFFFFFFF) {
+ DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
+ ASSERT(FALSE);
+ }
+
if ((Reg32 & BIT0) == 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
do {
@@ -157,6 +167,8 @@ EnablePmr (
} while((Reg32 & BIT0) == 0);
}
+ DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));
+
return EFI_SUCCESS;
}
@@ -182,6 +194,11 @@ DisablePmr (
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+ if (Reg32 == 0xFFFFFFFF) {
+ DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
+ ASSERT(FALSE);
+ }
+
if ((Reg32 & BIT0) != 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
do {
@@ -195,6 +212,7 @@ DisablePmr (
/**
Set PMR region in the VTd engine.
+ @param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@@ -206,6 +224,7 @@ DisablePmr (
**/
EFI_STATUS
SetPmrRegion (
+ IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -225,9 +244,9 @@ SetPmrRegion (
return EFI_UNSUPPORTED;
}
- PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);
+ PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
- PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);
+ PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
@@ -247,8 +266,10 @@ SetPmrRegion (
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);
+ DEBUG ((DEBUG_INFO, "PLMR set done\n"));
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, HighMemoryBase);
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
+ DEBUG ((DEBUG_INFO, "PHMR set done\n"));
return EFI_SUCCESS;
}
@@ -256,6 +277,7 @@ SetPmrRegion (
/**
Set DMA protected region.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@@ -267,6 +289,7 @@ SetPmrRegion (
**/
EFI_STATUS
SetDmaProtectedRange (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -279,13 +302,14 @@ SetDmaProtectedRange (
DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
- for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
- DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
+ DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
Status = SetPmrRegion (
- (UINTN)mVTdInfo->VTdEngineAddress[Index],
+ VTdInfo->HostAddressWidth,
+ (UINTN)VTdInfo->VTdEngineAddress[Index],
LowMemoryBase,
LowMemoryLength,
HighMemoryBase,
@@ -294,7 +318,7 @@ SetDmaProtectedRange (
if (EFI_ERROR(Status)) {
return Status;
}
- Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
+ Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
@@ -306,25 +330,29 @@ SetDmaProtectedRange (
/**
Diable DMA protection.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
- @retval DMA protection is disabled.
+ @retval EFI_SUCCESS DMA protection is disabled.
**/
EFI_STATUS
DisableDmaProtection (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
EFI_STATUS Status;
- DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
+ DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index));
- for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
- Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
+ Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
@@ -332,3 +360,67 @@ DisableDmaProtection (
return EFI_SUCCESS;
}
+
+/**
+ Return if the PMR is enabled.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+
+ @retval TRUE PMR is enabled.
+ @retval FALSE PMR is disabled or unsupported.
+**/
+BOOLEAN
+IsPmrEnabled (
+ IN UINTN VtdUnitBaseAddress
+ )
+{
+ UINT32 Reg32;
+ VTD_CAP_REG CapReg;
+
+ CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+ if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+ return FALSE;
+ }
+
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+ if ((Reg32 & BIT0) == 0) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Return the mask of the VTd engine which is enabled.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+
+ @return the mask of the VTd engine which is enabled.
+**/
+UINT64
+GetDmaProtectionEnabledEngineMask (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ )
+{
+ UINTN Index;
+ BOOLEAN Result;
+ UINT64 EnabledEngineMask;
+
+ DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask));
+
+ EnabledEngineMask = 0;
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ if ((EngineMask & LShiftU64(1, Index)) == 0) {
+ continue;
+ }
+ Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);
+ if (Result) {
+ EnabledEngineMask |= LShiftU64(1, Index);
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask));
+ return EnabledEngineMask;
+}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
index 3fe6d654cd..240a6d2817 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -24,6 +24,7 @@
#include <IndustryStandard/Vtd.h>
#include <Ppi/IoMmu.h>
#include <Ppi/VtdInfo.h>
+#include <Ppi/MemoryDiscovered.h>
#include <Ppi/EndOfPeiPhase.h>
#include "IntelVTdPmrPei.h"
@@ -31,13 +32,20 @@
#define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
#define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB
-EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
-VTD_INFO *mVTdInfo;
-UINT64 mEngineMask;
-UINTN mDmaBufferBase;
-UINTN mDmaBufferSize;
-UINTN mDmaBufferCurrentTop;
-UINTN mDmaBufferCurrentBottom;
+EFI_GUID mVTdInfoGuid = {
+ 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }
+};
+
+EFI_GUID mDmaBufferInfoGuid = {
+ 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }
+};
+
+typedef struct {
+ UINTN DmaBufferBase;
+ UINTN DmaBufferSize;
+ UINTN DmaBufferCurrentTop;
+ UINTN DmaBufferCurrentBottom;
+} DMA_BUFFER_INFO;
#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
typedef struct {
@@ -83,7 +91,6 @@ typedef struct {
+------------------+ <=============== PLMR.Base (0)
**/
-
/**
Set IOMMU attribute for a system memory.
@@ -149,8 +156,13 @@ PeiIoMmuMap (
OUT VOID **Mapping
)
{
- MAP_INFO *MapInfo;
- UINTN Length;
+ MAP_INFO *MapInfo;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
@@ -160,18 +172,18 @@ PeiIoMmuMap (
}
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = *NumberOfBytes + sizeof(MAP_INFO);
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
- *DeviceAddress = mDmaBufferCurrentBottom;
- mDmaBufferCurrentBottom += Length;
+ *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;
+ DmaBufferInfo->DmaBufferCurrentBottom += Length;
MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
MapInfo->Signature = MAP_INFO_SIGNATURE;
@@ -216,16 +228,21 @@ PeiIoMmuUnmap (
IN VOID *Mapping
)
{
- MAP_INFO *MapInfo;
- UINTN Length;
+ MAP_INFO *MapInfo;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
if (Mapping == NULL) {
return EFI_SUCCESS;
}
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
MapInfo = Mapping;
ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
@@ -246,8 +263,8 @@ PeiIoMmuUnmap (
}
Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
- if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
- mDmaBufferCurrentBottom -= Length;
+ if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
+ DmaBufferInfo->DmaBufferCurrentBottom -= Length;
}
return EFI_SUCCESS;
@@ -282,20 +299,25 @@ PeiIoMmuAllocateBuffer (
IN UINT64 Attributes
)
{
- UINTN Length;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = EFI_PAGES_TO_SIZE(Pages);
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
- *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
- mDmaBufferCurrentTop -= Length;
+ *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);
+ DmaBufferInfo->DmaBufferCurrentTop -= Length;
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
return EFI_SUCCESS;
@@ -321,15 +343,20 @@ PeiIoMmuFreeBuffer (
IN VOID *HostAddress
)
{
- UINTN Length;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = EFI_PAGES_TO_SIZE(Pages);
- if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
- mDmaBufferCurrentTop += Length;
+ if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {
+ DmaBufferInfo->DmaBufferCurrentTop += Length;
}
return EFI_SUCCESS;
@@ -506,6 +533,7 @@ GetTopMemory (
/**
Initialize DMA protection.
+ @param VTdInfo The VTd engine context information.
@param DmaBufferSize the DMA buffer size
@param DmaBufferBase the DMA buffer base
@@ -514,8 +542,9 @@ GetTopMemory (
**/
EFI_STATUS
InitDmaProtection (
- IN UINTN DmaBufferSize,
- OUT UINTN *DmaBufferBase
+ IN VTD_INFO *VTdInfo,
+ IN UINTN DmaBufferSize,
+ OUT UINTN *DmaBufferBase
)
{
EFI_STATUS Status;
@@ -537,8 +566,8 @@ InitDmaProtection (
ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
- LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
- HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
+ LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
+ HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
if (LowMemoryAlignment < HighMemoryAlignment) {
MemoryAlignment = (UINTN)HighMemoryAlignment;
} else {
@@ -558,12 +587,13 @@ InitDmaProtection (
HighTop = GetTopMemory ();
Status = SetDmaProtectedRange (
- mEngineMask,
- (UINT32)LowBottom,
- (UINT32)(LowTop - LowBottom),
- HighBottom,
- HighTop - HighBottom
- );
+ VTdInfo,
+ VTdInfo->EngineMask,
+ (UINT32)LowBottom,
+ (UINT32)(LowTop - LowBottom),
+ HighBottom,
+ HighTop - HighBottom
+ );
if (EFI_ERROR(Status)) {
FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
@@ -573,542 +603,191 @@ InitDmaProtection (
}
/**
- Dump DMAR DeviceScopeEntry.
+ Initializes the Intel VTd Info.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
**/
-VOID
-DumpDmarDeviceScopeEntry (
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
+EFI_STATUS
+InitVTdInfo (
+ VOID
)
{
- UINTN PciPathNumber;
- UINTN PciPathIndex;
- EFI_ACPI_DMAR_PCI_PATH *PciPath;
-
- if (DmarDeviceScopeEntry == NULL) {
- return;
- }
-
- DEBUG ((DEBUG_INFO,
- " *************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- " * DMA-Remapping Device Scope Entry Structure *\n"
- ));
- DEBUG ((DEBUG_INFO,
- " *************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- (sizeof(UINTN) == sizeof(UINT64)) ?
- " DMAR Device Scope Entry address ...................... 0x%016lx\n" :
- " DMAR Device Scope Entry address ...................... 0x%08x\n",
- DmarDeviceScopeEntry
- ));
- DEBUG ((DEBUG_INFO,
- " Device Scope Entry Type ............................ 0x%02x\n",
- DmarDeviceScopeEntry->Type
- ));
- switch (DmarDeviceScopeEntry->Type) {
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
- DEBUG ((DEBUG_INFO,
- " PCI Endpoint Device\n"
- ));
- break;
- case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
- DEBUG ((DEBUG_INFO,
- " PCI Sub-hierachy\n"
- ));
- break;
- default:
- break;
- }
- DEBUG ((DEBUG_INFO,
- " Length ............................................. 0x%02x\n",
- DmarDeviceScopeEntry->Length
- ));
- DEBUG ((DEBUG_INFO,
- " Enumeration ID ..................................... 0x%02x\n",
- DmarDeviceScopeEntry->EnumerationId
- ));
- DEBUG ((DEBUG_INFO,
- " Starting Bus Number ................................ 0x%02x\n",
- DmarDeviceScopeEntry->StartBusNumber
- ));
-
- PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
- PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
- for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
- DEBUG ((DEBUG_INFO,
- " Device ............................................. 0x%02x\n",
- PciPath[PciPathIndex].Device
- ));
- DEBUG ((DEBUG_INFO,
- " Function ........................................... 0x%02x\n",
- PciPath[PciPathIndex].Function
- ));
- }
-
- DEBUG ((DEBUG_INFO,
- " *************************************************************************\n\n"
- ));
-
- return;
-}
+ EFI_STATUS Status;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ VOID *Hob;
-/**
- Dump DMAR RMRR table.
+ Status = PeiServicesLocatePpi (
+ &gEdkiiVTdInfoPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&AcpiDmarTable
+ );
+ ASSERT_EFI_ERROR(Status);
- @param[in] Rmrr DMAR RMRR table
-**/
-VOID
-DumpDmarRmrr (
- IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
- INTN RmrrLen;
+ DumpAcpiDMAR (AcpiDmarTable);
- if (Rmrr == NULL) {
- return;
+ //
+ // Clear old VTdInfo Hob.
+ //
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ if (Hob != NULL) {
+ ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));
}
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- " * Reserved Memory Region Reporting Structure *\n"
- ));
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- (sizeof(UINTN) == sizeof(UINT64)) ?
- " RMRR address ........................................... 0x%016lx\n" :
- " RMRR address ........................................... 0x%08x\n",
- Rmrr
- ));
- DEBUG ((DEBUG_INFO,
- " Type ................................................. 0x%04x\n",
- Rmrr->Header.Type
- ));
- DEBUG ((DEBUG_INFO,
- " Length ............................................... 0x%04x\n",
- Rmrr->Header.Length
- ));
- DEBUG ((DEBUG_INFO,
- " Segment Number ....................................... 0x%04x\n",
- Rmrr->SegmentNumber
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Base Address .................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionBaseAddress
- ));
- DEBUG ((DEBUG_INFO,
- " Reserved Memory Region Limit Address ................. 0x%016lx\n",
- Rmrr->ReservedMemoryRegionLimitAddress
- ));
-
- RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
- while (RmrrLen > 0) {
- DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
- RmrrLen -= DmarDeviceScopeEntry->Length;
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
+ //
+ // Get DMAR information to local VTdInfo
+ //
+ Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);
+ if (EFI_ERROR(Status)) {
+ return Status;
}
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
+ //
+ // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.
+ //
- return;
+ return EFI_SUCCESS;
}
/**
- Dump DMAR DRHD table.
+ Initializes the Intel VTd PMR for all memory.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] Drhd DMAR DRHD table
**/
-VOID
-DumpDmarDrhd (
- IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+EFI_STATUS
+InitVTdPmrForAll (
+ VOID
)
{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
- INTN DrhdLen;
+ EFI_STATUS Status;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ UINTN LowBottom;
+ UINTN LowTop;
+ UINTN HighBottom;
+ UINT64 HighTop;
- if (Drhd == NULL) {
- return;
- }
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- " * DMA-Remapping Hardware Definition Structure *\n"
- ));
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- (sizeof(UINTN) == sizeof(UINT64)) ?
- " DRHD address ........................................... 0x%016lx\n" :
- " DRHD address ........................................... 0x%08x\n",
- Drhd
- ));
- DEBUG ((DEBUG_INFO,
- " Type ................................................. 0x%04x\n",
- Drhd->Header.Type
- ));
- DEBUG ((DEBUG_INFO,
- " Length ............................................... 0x%04x\n",
- Drhd->Header.Length
- ));
- DEBUG ((DEBUG_INFO,
- " Flags ................................................ 0x%02x\n",
- Drhd->Flags
- ));
- DEBUG ((DEBUG_INFO,
- " INCLUDE_PCI_ALL .................................... 0x%02x\n",
- Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
- ));
- DEBUG ((DEBUG_INFO,
- " Segment Number ....................................... 0x%04x\n",
- Drhd->SegmentNumber
- ));
- DEBUG ((DEBUG_INFO,
- " Register Base Address ................................ 0x%016lx\n",
- Drhd->RegisterBaseAddress
- ));
-
- DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
- while (DrhdLen > 0) {
- DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
- DrhdLen -= DmarDeviceScopeEntry->Length;
- DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
- }
+ LowBottom = 0;
+ LowTop = 0;
+ HighBottom = 0;
+ HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth);
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
+ Status = SetDmaProtectedRange (
+ VTdInfo,
+ VTdInfo->EngineMask,
+ (UINT32)LowBottom,
+ (UINT32)(LowTop - LowBottom),
+ HighBottom,
+ HighTop - HighBottom
+ );
- return;
+ return Status;
}
/**
- Dump DMAR ACPI table.
+ Initializes the Intel VTd PMR for DMA buffer.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] Dmar DMAR ACPI table
**/
-VOID
-DumpAcpiDMAR (
- IN EFI_ACPI_DMAR_HEADER *Dmar
+EFI_STATUS
+InitVTdPmrForDma (
+ VOID
)
{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- INTN DmarLen;
+ EFI_STATUS Status;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ DMA_BUFFER_INFO *DmaBufferInfo;
- if (Dmar == NULL) {
- return;
- }
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
//
- // Dump Dmar table
+ // If there is RMRR memory, parse it here.
//
- DEBUG ((DEBUG_INFO,
- "*****************************************************************************\n"
- ));
- DEBUG ((DEBUG_INFO,
- "* DMAR Table *\n"
- ));
- DEBUG ((DEBUG_INFO,
- "*****************************************************************************\n"
- ));
-
- DEBUG ((DEBUG_INFO,
- (sizeof(UINTN) == sizeof(UINT64)) ?
- "DMAR address ............................................. 0x%016lx\n" :
- "DMAR address ............................................. 0x%08x\n",
- Dmar
- ));
-
- DEBUG ((DEBUG_INFO,
- " Table Contents:\n"
- ));
- DEBUG ((DEBUG_INFO,
- " Host Address Width ................................... 0x%02x\n",
- Dmar->HostAddressWidth
- ));
- DEBUG ((DEBUG_INFO,
- " Flags ................................................ 0x%02x\n",
- Dmar->Flags
- ));
- DEBUG ((DEBUG_INFO,
- " INTR_REMAP ......................................... 0x%02x\n",
- Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
- ));
- DEBUG ((DEBUG_INFO,
- " X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
- Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
- ));
-
- DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
- while (DmarLen > 0) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_DRHD:
- DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
- break;
- case EFI_ACPI_DMAR_TYPE_RMRR:
- DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
- break;
- default:
- break;
- }
- DmarLen -= DmarHeader->Length;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
-
- DEBUG ((DEBUG_INFO,
- "*****************************************************************************\n\n"
- ));
-
- return;
-}
+ ParseDmarAcpiTableRmrr (VTdInfo);
-/**
- Get VTd engine number.
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
- @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdIndex;
-
- VtdIndex = 0;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_DRHD:
- VtdIndex++;
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));
+ //
+ // Find a pre-memory in resource hob as DMA buffer
+ // Mark PEI memory to be DMA protected.
+ //
+ Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);
+ if (EFI_ERROR(Status)) {
+ return Status;
}
- return VtdIndex ;
-}
-
-/**
- Process DMAR DHRD table.
-
- @param[in] VtdIndex The index of VTd engine.
- @param[in] DmarDrhd The DRHD table.
-**/
-VOID
-ProcessDhrd (
- IN UINTN VtdIndex,
- IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
- )
-{
- DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
- mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
-}
-/**
- Parse DMAR DRHD table.
-
- @return EFI_SUCCESS The DMAR DRHD table is parsed.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdUnitNumber;
- UINTN VtdIndex;
+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));
- VtdUnitNumber = GetVtdEngineNumber ();
- if (VtdUnitNumber == 0) {
- return EFI_UNSUPPORTED;
- }
-
- mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
- if (mVTdInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
- mVTdInfo->VTdEngineCount = VtdUnitNumber;
-
- VtdIndex = 0;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_DRHD:
- ASSERT (VtdIndex < VtdUnitNumber);
- ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
- VtdIndex++;
-
- break;
-
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
- ASSERT (VtdIndex == VtdUnitNumber);
+ DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
+ DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
//
- // Initialize the engine mask to all.
+ // Install PPI.
//
- mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+ Status = PeiServicesInstallPpi (&mIoMmuPpiList);
+ ASSERT_EFI_ERROR(Status);
- return EFI_SUCCESS;
+ return Status;
}
/**
- Return the VTd engine index according to the Segment and DevScopeEntry.
+ This function handles S3 resume task at the end of PEI
- @param Segment The segment of the VTd engine
- @param DevScopeEntry The DevScopeEntry of the VTd engine
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
- @return The VTd engine index according to the Segment and DevScopeEntry.
- @retval -1 The VTd engine is not found.
+ @retval EFI_STATUS Always return EFI_SUCCESS
**/
-UINTN
-GetVTdEngineFromDevScopeEntry (
- IN UINT16 Segment,
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+EFI_STATUS
+EFIAPI
+S3EndOfPeiNotify(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
)
{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdIndex;
- EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
-
- VtdIndex = 0;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_DRHD:
- DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
- if (DmarDrhd->SegmentNumber != Segment) {
- // Mismatch
- break;
- }
- if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
- ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
- // No DevScopeEntry
- // Do not handle PCI_ALL
- break;
- }
- ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
- while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
- if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
- (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
- return VtdIndex;
- }
- ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
- }
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
- return (UINTN)-1;
-}
-
-/**
- Process DMAR RMRR table.
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ UINT64 EngineMask;
- @param[in] DmarRmrr The RMRR table.
-**/
-VOID
-ProcessRmrr (
- IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
- )
-{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
- UINTN VTdIndex;
- UINT64 RmrrMask;
- UINTN LowBottom;
- UINTN LowTop;
- UINTN HighBottom;
- UINT64 HighTop;
-
- DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
- if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
- (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
- return ;
- }
+ DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));
- while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
- ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
-
- VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
- if (VTdIndex != (UINTN)-1) {
- RmrrMask = LShiftU64 (1, VTdIndex);
-
- LowBottom = 0;
- LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
- HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
- HighTop = GetTopMemory ();
-
- SetDmaProtectedRange (
- RmrrMask,
- 0,
- (UINT32)(LowTop - LowBottom),
- HighBottom,
- HighTop - HighBottom
- );
-
- //
- // Remove the engine from the engine mask.
- // The assumption is that any other PEI driver does not access
- // the device covered by this engine.
- //
- mEngineMask = mEngineMask & (~RmrrMask);
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ if (Hob == NULL) {
+ return EFI_SUCCESS;
}
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+ EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
+ DisableDmaProtection (VTdInfo, EngineMask);
}
+ return EFI_SUCCESS;
}
-/**
- Parse DMAR DRHD table.
-**/
-VOID
-ParseDmarAcpiTableRmrr (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
-
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_RMRR:
- ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
-}
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ S3EndOfPeiNotify
+};
/**
- This function handles S3 resume task at the end of PEI
+ This function handles VTd engine setup
@param[in] PeiServices Pointer to PEI Services Table.
@param[in] NotifyDesc Pointer to the descriptor for the Notification event that
@@ -1119,27 +798,80 @@ ParseDmarAcpiTableRmrr (
**/
EFI_STATUS
EFIAPI
-S3EndOfPeiNotify(
+VTdInfoNotify (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
- UINT64 EngineMask;
+ EFI_STATUS Status;
+ VOID *MemoryDiscovered;
+ UINT64 EnabledEngineMask;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ BOOLEAN MemoryInitialized;
- DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
+ DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));
+
+ //
+ // Check if memory is initialized.
+ //
+ MemoryInitialized = FALSE;
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ 0,
+ NULL,
+ &MemoryDiscovered
+ );
+ if (!EFI_ERROR(Status)) {
+ MemoryInitialized = TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));
+
+ if (!MemoryInitialized) {
+ //
+ // If the memory is not initialized,
+ // Protect all system memory
+ //
+ InitVTdInfo ();
+ InitVTdPmrForAll ();
+ } else {
+ //
+ // If the memory is initialized,
+ // Allocate DMA buffer and protect rest system memory
+ //
+
+ //
+ // NOTE: We need reinit VTdInfo because previous information might be overriden.
+ //
+ InitVTdInfo ();
+
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
+
+ //
+ // NOTE: We need check if PMR is enabled or not.
+ //
+ EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);
+ if (EnabledEngineMask != 0) {
+ EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
+ DisableDmaProtection (VTdInfo, EnabledEngineMask);
+ }
+ InitVTdPmrForDma ();
+ if (EnabledEngineMask != 0) {
+ DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);
+ }
- if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
- EngineMask = LShiftU64 (1, mVTdInfo->VTdEngineCount) - 1;
- DisableDmaProtection (EngineMask);
}
+
return EFI_SUCCESS;
}
-EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiEndOfPeiSignalPpiGuid,
- S3EndOfPeiNotify
+ &gEdkiiVTdInfoPpiGuid,
+ VTdInfoNotify
};
/**
@@ -1161,71 +893,40 @@ IntelVTdPmrInitialize (
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
return EFI_UNSUPPORTED;
}
- PeiServicesGetBootMode (&BootMode);
-
- Status = PeiServicesLocatePpi (
- &gEdkiiVTdInfoPpiGuid,
- 0,
- NULL,
- (VOID **)&mAcpiDmarTable
- );
- ASSERT_EFI_ERROR(Status);
-
- DumpAcpiDMAR (mAcpiDmarTable);
-
- //
- // Get DMAR information to local VTdInfo
- //
- Status = ParseDmarAcpiTableDrhd ();
- if (EFI_ERROR(Status)) {
- return Status;
+ DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));
+ ASSERT(DmaBufferInfo != NULL);
+ if (DmaBufferInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
}
+ ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));
- //
- // If there is RMRR memory, parse it here.
- //
- ParseDmarAcpiTableRmrr ();
+ PeiServicesGetBootMode (&BootMode);
if (BootMode == BOOT_ON_S3_RESUME) {
- mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
} else {
- mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
- }
- DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
-
- //
- // Find a pre-memory in resource hob as DMA buffer
- // Mark PEI memory to be DMA protected.
- //
- Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
- if (EFI_ERROR(Status)) {
- return Status;
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
}
- DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
-
- mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
- mDmaBufferCurrentBottom = mDmaBufferBase;
-
- //
- // Install PPI.
- //
- Status = PeiServicesInstallPpi (&mIoMmuPpiList);
- ASSERT_EFI_ERROR(Status);
+ Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
//
- // Register EndOfPei Notify for S3 to run FSP NotifyPhase
+ // Register EndOfPei Notify for S3
//
if (BootMode == BOOT_ON_S3_RESUME) {
Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
ASSERT_EFI_ERROR (Status);
}
- return Status;
+ return EFI_SUCCESS;
}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
index 720f5d42c3..499119d3ff 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -16,6 +16,8 @@
#define __DMA_ACCESS_LIB_H__
typedef struct {
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ UINT64 EngineMask;
UINT8 HostAddressWidth;
UINTN VTdEngineCount;
UINT64 VTdEngineAddress[1];
@@ -24,6 +26,7 @@ typedef struct {
/**
Set DMA protected region.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@@ -35,6 +38,7 @@ typedef struct {
**/
EFI_STATUS
SetDmaProtectedRange (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -45,38 +49,127 @@ SetDmaProtectedRange (
/**
Diable DMA protection.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@retval DMA protection is disabled.
**/
EFI_STATUS
DisableDmaProtection (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ );
+
+/**
+ Return if the DMA protection is enabled.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+
+ @retval TRUE DMA protection is enabled in at least one VTd engine.
+ @retval FALSE DMA protection is disabled in all VTd engines.
+**/
+UINT64
+GetDmaProtectionEnabledEngineMask (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Get protected low memory alignment.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected low memory alignment.
**/
UINT32
GetLowMemoryAlignment (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
Get protected high memory alignment.
+ @param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected high memory alignment.
**/
UINT64
GetHighMemoryAlignment (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ );
+
+/**
+ Enable VTd translation table protection.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+**/
+VOID
+EnableVTdTranslationProtection (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ );
+
+/**
+ Disable VTd translation table protection.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+**/
+VOID
+DisableVTdTranslationProtection (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
+/**
+ Parse DMAR DRHD table.
+
+ @param[in] AcpiDmarTable DMAR ACPI table
+
+ @return EFI_SUCCESS The DMAR DRHD table is parsed.
+**/
+EFI_STATUS
+ParseDmarAcpiTableDrhd (
+ IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
+ );
+
+/**
+ Parse DMAR DRHD table.
+
+ @param VTdInfo The VTd engine context information.
+**/
+VOID
+ParseDmarAcpiTableRmrr (
+ IN VTD_INFO *VTdInfo
+ );
+
+/**
+ Dump DMAR ACPI table.
+
+ @param[in] Dmar DMAR ACPI table
+**/
+VOID
+DumpAcpiDMAR (
+ IN EFI_ACPI_DMAR_HEADER *Dmar
+ );
+
+/**
+ Get the highest memory.
+
+ @return the highest memory.
+**/
+UINT64
+GetTopMemory (
+ VOID
+ );
+
+extern EFI_GUID mVTdInfoGuid;
+
#endif
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
index 4d0e187dc3..e6d0323acc 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
@@ -33,6 +33,8 @@
IntelVTdPmrPei.c
IntelVTdPmrPei.h
IntelVTdPmr.c
+ DmarTable.c
+ VtdReg.c
[LibraryClasses]
DebugLib
@@ -42,17 +44,18 @@
PeiServicesLib
HobLib
IoLib
+ CacheMaintenanceLib
[Ppis]
- gEdkiiIoMmuPpiGuid ## PRODUCES
- gEdkiiVTdInfoPpiGuid ## CONSUMES
- gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gEdkiiIoMmuPpiGuid ## PRODUCES
+ gEdkiiVTdInfoPpiGuid ## CONSUMES
+ gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
[Depex]
- gEfiPeiMemoryDiscoveredPpiGuid AND
gEfiPeiMasterBootModePpiGuid AND
gEdkiiVTdInfoPpiGuid
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
new file mode 100644
index 0000000000..888905d40d
--- /dev/null
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
@@ -0,0 +1,293 @@
+/** @file
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License which accompanies this distribution.
+ The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/CacheMaintenanceLib.h>
+#include <IndustryStandard/Vtd.h>
+#include <Ppi/VtdInfo.h>
+
+#include "IntelVTdPmrPei.h"
+
+/**
+ Flush VTD page table and context table memory.
+
+ This action is to make sure the IOMMU engine can get final data in memory.
+
+ @param[in] Base The base address of memory to be flushed.
+ @param[in] Size The size of memory in bytes to be flushed.
+**/
+VOID
+FlushPageTableMemory (
+ IN UINTN Base,
+ IN UINTN Size
+ )
+{
+ WriteBackDataCacheRange ((VOID *)Base, Size);
+}
+
+/**
+ Flush VTd engine write buffer.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+**/
+VOID
+FlushWriteBuffer (
+ IN UINTN VtdUnitBaseAddress
+ )
+{
+ UINT32 Reg32;
+ VTD_CAP_REG CapReg;
+
+ CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+
+ if (CapReg.Bits.RWBF != 0) {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);
+ do {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_WBF) != 0);
+ }
+}
+
+/**
+ Invalidate VTd context cache.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+**/
+EFI_STATUS
+InvalidateContextCache (
+ IN UINTN VtdUnitBaseAddress
+ )
+{
+ UINT64 Reg64;
+
+ Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
+ if ((Reg64 & B_CCMD_REG_ICC) != 0) {
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n",VtdUnitBaseAddress));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
+ Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
+ MmioWrite64 (VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+
+ do {
+ Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
+ } while ((Reg64 & B_CCMD_REG_ICC) != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Invalidate VTd IOTLB.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+**/
+EFI_STATUS
+InvalidateIOTLB (
+ IN UINTN VtdUnitBaseAddress
+ )
+{
+ UINT64 Reg64;
+ VTD_ECAP_REG ECapReg;
+
+ ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
+
+ Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
+ DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VtdUnitBaseAddress));
+ return EFI_DEVICE_ERROR;
+ }
+
+ Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
+ Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
+ MmioWrite64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+
+ do {
+ Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+ } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enable DMAR translation.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+ @param RootEntryTable The address of the VTd RootEntryTable.
+
+ @retval EFI_SUCCESS DMAR translation is enabled.
+ @retval EFI_DEVICE_ERROR DMAR translation is not enabled.
+**/
+EFI_STATUS
+EnableDmar (
+ IN UINTN VtdUnitBaseAddress,
+ IN UINTN RootEntryTable
+ )
+{
+ UINT32 Reg32;
+
+ DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
+
+ DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)RootEntryTable);
+
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
+
+ DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
+ do {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+
+ //
+ // Init DMAr Fault Event and Data registers
+ //
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
+
+ //
+ // Write Buffer Flush before invalidation
+ //
+ FlushWriteBuffer (VtdUnitBaseAddress);
+
+ //
+ // Invalidate the context cache
+ //
+ InvalidateContextCache (VtdUnitBaseAddress);
+
+ //
+ // Invalidate the IOTLB cache
+ //
+ InvalidateIOTLB (VtdUnitBaseAddress);
+
+ //
+ // Enable VTd
+ //
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_TE);
+ DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
+ do {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ } while ((Reg32 & B_GSTS_REG_TE) == 0);
+
+ DEBUG ((DEBUG_INFO,"VTD () enabled!<<<<<<\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Disable DMAR translation.
+
+ @param VtdUnitBaseAddress The base address of the VTd engine.
+
+ @retval EFI_SUCCESS DMAR translation is disabled.
+ @retval EFI_DEVICE_ERROR DMAR translation is not disabled.
+**/
+EFI_STATUS
+DisableDmar (
+ IN UINTN VtdUnitBaseAddress
+ )
+{
+ UINT32 Reg32;
+
+ DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));
+
+ //
+ // Write Buffer Flush before invalidation
+ //
+ FlushWriteBuffer (VtdUnitBaseAddress);
+
+ //
+ // Disable VTd
+ //
+ MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
+ do {
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+
+ Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+ DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
+
+ MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);
+
+ DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Enable VTd translation table protection.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+**/
+VOID
+EnableVTdTranslationProtection (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ )
+{
+ UINTN Index;
+ VOID *RootEntryTable;
+
+ DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtection - 0x%lx\n", EngineMask));
+
+ RootEntryTable = AllocatePages (1);
+ ASSERT (RootEntryTable != NULL);
+ if (RootEntryTable == NULL) {
+ DEBUG ((DEBUG_INFO, " EnableVTdTranslationProtection : OutOfResource\n"));
+ return ;
+ }
+
+ ZeroMem (RootEntryTable, EFI_PAGES_TO_SIZE(1));
+ FlushPageTableMemory ((UINTN)RootEntryTable, EFI_PAGES_TO_SIZE(1));
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ if ((EngineMask & LShiftU64(1, Index)) == 0) {
+ continue;
+ }
+ EnableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index], (UINTN)RootEntryTable);
+ }
+
+ return ;
+}
+
+/**
+ Disable VTd translation table protection.
+
+ @param VTdInfo The VTd engine context information.
+ @param EngineMask The mask of the VTd engine to be accessed.
+**/
+VOID
+DisableVTdTranslationProtection (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ )
+{
+ UINTN Index;
+
+ DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask));
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ if ((EngineMask & LShiftU64(1, Index)) == 0) {
+ continue;
+ }
+ DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]);
+ }
+
+ return ;
+}