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>
---
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c | 580 ++++++++++++++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c | 130 ++-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 846 +++++++-------------
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h | 93 +++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf | 11 +-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c | 293 +++++++
6 files changed, 1356 insertions(+), 597 deletions(-)
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
new file mode 100644
index 0000000..891efa6
--- /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 6179dfe..000a81b 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 3fe6d65..b6ff799 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,188 @@ 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);
+ 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 +795,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 +890,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 720f5d4..499119d 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 4d0e187..e6d0323 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 0000000..888905d
--- /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 ;
+}
--
2.7.4.windows.1
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel
Reviewed-by: Star Zeng <star.zeng@intel.com> -----Original Message----- From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao Sent: Friday, October 27, 2017 1:40 PM To: edk2-devel@lists.01.org Cc: Zeng, Star <star.zeng@intel.com> Subject: [edk2] [PATCH V2 1/2] 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> --- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c | 580 ++++++++++++++ IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c | 130 ++- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 846 +++++++------------- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h | 93 +++ IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf | 11 +- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c | 293 +++++++ 6 files changed, 1356 insertions(+), 597 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c new file mode 100644 index 0000000..891efa6 --- /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 6179dfe..000a81b 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 3fe6d65..b6ff799 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,188 @@ 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); + 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 +795,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 +890,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 720f5d4..499119d 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 4d0e187..e6d0323 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 0000000..888905d --- /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 ; +} -- 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel
© 2016 - 2024 Red Hat, Inc.