public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Sheng Wei" <w.sheng@intel.com>
To: devel@edk2.groups.io
Cc: Ray Ni <ray.ni@intel.com>,
	Rangasai V Chaganty <rangasai.v.chaganty@intel.com>,
	Jenny Huang <jenny.huang@intel.com>,
	Robert Kowalewski <robert.kowalewski@intel.com>
Subject: [PATCH v3 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
Date: Tue, 14 Dec 2021 13:35:38 +0800	[thread overview]
Message-ID: <20211214053538.2828-5-w.sheng@intel.com> (raw)
In-Reply-To: <20211214053538.2828-1-w.sheng@intel.com>

VTdInfoNotify may be called manay times, PEI DMA buffer should be
 generated only once.

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3667

Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Robert Kowalewski <robert.kowalewski@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 405 +++++-----------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 433 ++++++++----------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 507 ++++++++++++---------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 127 ++++--
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 201 ++++----
 5 files changed, 769 insertions(+), 904 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index e9c99d0a..31792189 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
@@ -1,6 +1,7 @@
 /** @file
 
-  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -413,142 +414,53 @@ GetPciBusDeviceFunction (
 }
 
 /**
-  Return the index of PCI data.
-
-  @param[in]  VTdUnitInfo       The VTd engine unit information.
-  @param[in]  Segment           The Segment used to identify a VTd engine.
-  @param[in]  SourceId          The SourceId used to identify a VTd engine and table entry.
-
-  @return The index of the PCI data.
-  @retval (UINTN)-1  The PCI data is not found.
-**/
-UINTN
-GetPciDataIndex (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId
-  )
-{
-  UINTN                         Index;
-  VTD_SOURCE_ID                 *PciSourceId;
-  PEI_PCI_DEVICE_DATA           *PciDeviceDataBase;
-
-  if (Segment != VTdUnitInfo->Segment) {
-    return (UINTN)-1;
-  }
-
-  for (Index = 0; Index < VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber; Index++) {
-    PciDeviceDataBase = (PEI_PCI_DEVICE_DATA*) (UINTN) VTdUnitInfo->PciDeviceInfo.PciDeviceData;
-    PciSourceId = &PciDeviceDataBase[Index].PciSourceId;
-    if ((PciSourceId->Bits.Bus == SourceId.Bits.Bus) &&
-        (PciSourceId->Bits.Device == SourceId.Bits.Device) &&
-        (PciSourceId->Bits.Function == SourceId.Bits.Function) ) {
-      return Index;
-    }
-  }
-
-  return (UINTN)-1;
-}
-
-
-/**
-  Register PCI device to VTd engine.
+  Parse DMAR DRHD table.
 
-  @param[in]  VTdUnitInfo       The VTd engine unit information.
-  @param[in]  Segment           The segment of the source.
-  @param[in]  SourceId          The SourceId of the source.
-  @param[in]  DeviceType        The DMAR device scope type.
-  @param[in]  CheckExist        TRUE: ERROR will be returned if the PCI device is already registered.
-                                FALSE: SUCCESS will be returned if the PCI device is registered.
+  @param[in]  AcpiDmarTable     DMAR ACPI table
+  @param[in]  Callback          Callback function for handle DRHD
+  @param[in]  Context           Callback function Context
 
-  @retval EFI_SUCCESS           The PCI device is registered.
-  @retval EFI_OUT_OF_RESOURCES  No enough resource to register a new PCI device.
-  @retval EFI_ALREADY_STARTED   The device is already registered.
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
 
 **/
 EFI_STATUS
-RegisterPciDevice (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT8                      DeviceType,
-  IN BOOLEAN                    CheckExist
+ParseDmarAcpiTableDrhd (
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   )
 {
-  PEI_PCI_DEVICE_INFORMATION    *PciDeviceInfo;
-  VTD_SOURCE_ID                 *PciSourceId;
-  UINTN                         PciDataIndex;
-  UINTN                         PciDeviceDataSize;
-  PEI_PCI_DEVICE_DATA           *NewPciDeviceData;
-  PEI_PCI_DEVICE_DATA           *PciDeviceDataBase;
-
-  PciDeviceInfo = &VTdUnitInfo->PciDeviceInfo;
-
-  PciDataIndex = GetPciDataIndex (VTdUnitInfo, Segment, SourceId);
-  if (PciDataIndex == (UINTN)-1) {
-    //
-    // Register new
-    //
-
-    if (PciDeviceInfo->PciDeviceDataNumber >= PciDeviceInfo->PciDeviceDataMaxNumber) {
-      //
-      // Reallocate
-      //
-      PciDeviceDataSize = sizeof(*NewPciDeviceData) * (PciDeviceInfo->PciDeviceDataMaxNumber + MAX_VTD_PCI_DATA_NUMBER);
-      DEBUG ((DEBUG_INFO, "New PciDeviceDataSize:%d Page:%d\n", PciDeviceDataSize, EFI_SIZE_TO_PAGES (PciDeviceDataSize)));
-      NewPciDeviceData = AllocateZeroPages (EFI_SIZE_TO_PAGES(PciDeviceDataSize));
-      if (NewPciDeviceData == NULL) {
-        return EFI_OUT_OF_RESOURCES;
-      }
-      PciDeviceInfo->PciDeviceDataMaxNumber += MAX_VTD_PCI_DATA_NUMBER;
-      if (PciDeviceInfo->PciDeviceData != 0) {
-        CopyMem (NewPciDeviceData, (VOID *) (UINTN) PciDeviceInfo->PciDeviceData, sizeof (*NewPciDeviceData) * PciDeviceInfo->PciDeviceDataNumber);
-        FreePages((VOID *) (UINTN) PciDeviceInfo->PciDeviceData, PciDeviceInfo->PciDeviceDataPageSize);
-      }
-      PciDeviceInfo->PciDeviceData = (UINT32) (UINTN) NewPciDeviceData;
-      PciDeviceInfo->PciDeviceDataPageSize = (UINT32) EFI_SIZE_TO_PAGES (PciDeviceDataSize);
-    }
-
-    ASSERT (PciDeviceInfo->PciDeviceDataNumber < PciDeviceInfo->PciDeviceDataMaxNumber);
-
-    PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) PciDeviceInfo->PciDeviceData;
-    PciSourceId = &PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].PciSourceId;
-    PciSourceId->Bits.Bus = SourceId.Bits.Bus;
-    PciSourceId->Bits.Device = SourceId.Bits.Device;
-    PciSourceId->Bits.Function = SourceId.Bits.Function;
-
-    DEBUG ((DEBUG_INFO, "  RegisterPciDevice: PCI S%04x B%02x D%02x F%02x", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-
-    PciDeviceDataBase[PciDeviceInfo->PciDeviceDataNumber].DeviceType = DeviceType;
-
-    if ((DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) &&
-        (DeviceType != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE)) {
-      DEBUG ((DEBUG_INFO, " (*)"));
-    }
-    DEBUG ((DEBUG_INFO, "\n"));
+  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
+  UINT32                                VtdIndex;
 
-    PciDeviceInfo->PciDeviceDataNumber++;
-  } else {
-    if (CheckExist) {
-      DEBUG ((DEBUG_INFO, "  RegisterPciDevice: PCI S%04x B%02x D%02x F%02x already registered\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-      return EFI_ALREADY_STARTED;
+  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:
+      Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      VtdIndex++;
+      break;
+    default:
+      break;
     }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
   }
 
   return EFI_SUCCESS;
 }
 
 /**
-  Process DMAR DRHD table.
+  Parse DMAR RMRR table to get device number.
+
+  @param[in]  DmarRmrr          The RMRR table.
 
-  @param[in]  VTdUnitInfo       The VTd engine unit information.
-  @param[in]  DmarDrhd          The DRHD table.
+  @return the device number
 
 **/
-VOID
-ProcessDrhd (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+UINTN
+ProcessRmrrGetDeviceNumber (
+  IN EFI_ACPI_DMAR_RMRR_HEADER                    *DmarRmrr
   )
 {
   EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
@@ -556,189 +468,83 @@ ProcessDrhd (
   UINT8                                           Device;
   UINT8                                           Function;
   EFI_STATUS                                      Status;
-  VTD_SOURCE_ID                                   SourceId;
-
-  DEBUG ((DEBUG_INFO,"  VTD BaseAddress -  0x%016lx\n", DmarDrhd->RegisterBaseAddress));
-  VTdUnitInfo->VtdUnitBaseAddress = (UINT32) DmarDrhd->RegisterBaseAddress;
-
-  VTdUnitInfo->EnableQueuedInvalidation = 0;
-
-  DEBUG ((DEBUG_INFO,"  VTD Segment - %d\n", DmarDrhd->SegmentNumber));
-  VTdUnitInfo->Segment = DmarDrhd->SegmentNumber;
-
-  VTdUnitInfo->FixedSecondLevelPagingEntry = 0;
-  VTdUnitInfo->RmrrSecondLevelPagingEntry = 0;
-  VTdUnitInfo->RootEntryTable = 0;
-  VTdUnitInfo->ExtRootEntryTable = 0;
-  VTdUnitInfo->RootEntryTablePageSize = 0;
-  VTdUnitInfo->ExtRootEntryTablePageSize = 0;
-
-  VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
-
-  if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
-    VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
-  } else {
-    VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
-  }
+  UINTN                                           DeviceNumber;
 
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
+  DEBUG ((DEBUG_INFO,"  PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
 
-  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1));
-  while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) {
+  DeviceNumber = 0;
 
-    Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
-    if (EFI_ERROR (Status)) {
-      return;
-    }
+  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
+      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
+    return DeviceNumber;
+  }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
-    switch (DmarDevScopeEntry->Type) {
-      case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
-      DEBUG ((DEBUG_INFO,"PCI Endpoint"));
-      break;
-    case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
-      DEBUG ((DEBUG_INFO,"PCI-PCI bridge"));
-      break;
-    case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
-      DEBUG ((DEBUG_INFO,"IOAPIC"));
-      break;
-    case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
-      DEBUG ((DEBUG_INFO,"MSI Capable HPET"));
-      break;
-    case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
-      DEBUG ((DEBUG_INFO,"ACPI Namespace Device"));
-      break;
+  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1));
+  while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) {
+    if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {
+      DEBUG ((DEBUG_INFO,"RMRR DevScopeEntryType is not endpoint, type[0x%x] \n", DmarDevScopeEntry->Type));
+      return DeviceNumber;
     }
-    DEBUG ((DEBUG_INFO," S%04x B%02x D%02x F%02x\n", DmarDrhd->SegmentNumber, Bus, Device, Function));
-
-    SourceId.Bits.Bus = Bus;
-    SourceId.Bits.Device = Device;
-    SourceId.Bits.Function = Function;
 
-    Status = RegisterPciDevice (VTdUnitInfo, DmarDrhd->SegmentNumber, SourceId, DmarDevScopeEntry->Type, TRUE);
+    Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
     if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
+      continue;
     }
 
-    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
-  }
-}
-
-/**
-  Dump the PCI device information managed by this VTd engine.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  VtdIndex          The index of VTd engine.
-
-**/
-VOID
-DumpPciDeviceInfo (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINTN                      VtdIndex
-  )
-{
-  UINTN                         Index;
-  PEI_PCI_DEVICE_DATA           *PciDeviceDataBase;
-
-  DEBUG ((DEBUG_INFO,"PCI Device Information (Number 0x%x, IncludeAll - %d):\n",
-    VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber,
-    VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag
-    ));
+    DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function));
 
-  PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
+    DeviceNumber++;
 
-  for (Index = 0; Index < VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceDataNumber; Index++) {
-    DEBUG ((DEBUG_INFO,"  S%04x B%02x D%02x F%02x\n",
-      VTdInfo->VtdUnitInfo[VtdIndex].Segment,
-      PciDeviceDataBase[Index].PciSourceId.Bits.Bus,
-      PciDeviceDataBase[Index].PciSourceId.Bits.Device,
-      PciDeviceDataBase[Index].PciSourceId.Bits.Function
-      ));
+    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
   }
+
+  return DeviceNumber;
 }
 
 /**
-  Parse DMAR DRHD table.
+  Get VTd DMAR RMRR device number.
 
   @param[in]  AcpiDmarTable     DMAR ACPI table
 
-  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
-
+  @return the device number
 **/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable
+UINTN
+GetVtdRmrrDeviceNumber (
+  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;
-  }
+  UINTN                               DeviceNumber;
+  EFI_ACPI_DMAR_STRUCTURE_HEADER      *DmarHeader;
 
-  VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) + (VtdUnitNumber - 1) * sizeof (VTD_UNIT_INFO));
-  ASSERT(VTdInfo != NULL);
-  if (VTdInfo == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-
-  //
-  // Initialize the engine mask to all.
-  //
-  VTdInfo->AcpiDmarTable    = (UINT32) (UINTN) AcpiDmarTable;
-  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
-  VTdInfo->VTdEngineCount   = (UINT32) VtdUnitNumber;
+  DeviceNumber = 0;
 
-  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);
-      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
-      VtdIndex++;
-
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      DeviceNumber += ProcessRmrrGetDeviceNumber ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
       break;
-
     default:
       break;
     }
     DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
   }
-  ASSERT (VtdIndex == VtdUnitNumber);
-
-  for (VtdIndex = 0; VtdIndex < VtdUnitNumber; VtdIndex++) {
-    DumpPciDeviceInfo (VTdInfo, VtdIndex);
-  }
-
-  return EFI_SUCCESS;
+  return DeviceNumber;
 }
 
-
 /**
-  Process DMAR RMRR table.
+  Parse RMRR table.
 
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  DmarRmrr          The RMRR table.
+  @param[in]  DmarRmrr         RMRR table
+  @param[out] RmrrInfo         The VTd RMRR information.
+
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
 
 **/
 VOID
 ProcessRmrr (
-  IN VTD_INFO                                     *VTdInfo,
-  IN EFI_ACPI_DMAR_RMRR_HEADER                    *DmarRmrr
+  IN  EFI_ACPI_DMAR_RMRR_HEADER                   *DmarRmrr,
+  OUT VTD_RMRR_INFO                               *RmrrInfo
   )
 {
   EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
@@ -746,7 +552,7 @@ ProcessRmrr (
   UINT8                                           Device;
   UINT8                                           Function;
   EFI_STATUS                                      Status;
-  VTD_SOURCE_ID                                   SourceId;
+  UINTN                                           DeviceIndex;
 
   DEBUG ((DEBUG_INFO,"  PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
 
@@ -755,6 +561,11 @@ ProcessRmrr (
     return ;
   }
 
+  RmrrInfo->SegmentNumber = DmarRmrr->SegmentNumber;
+  RmrrInfo->ReservedMemoryRegionBaseAddress = DmarRmrr->ReservedMemoryRegionBaseAddress;
+  RmrrInfo->ReservedMemoryRegionLimitAddress = DmarRmrr->ReservedMemoryRegionLimitAddress;
+  DeviceIndex = 0;
+
   DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1));
   while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) {
     if (DmarDevScopeEntry->Type != EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT) {
@@ -766,50 +577,39 @@ ProcessRmrr (
     if (EFI_ERROR (Status)) {
       continue;
     }
+    ASSERT (DeviceIndex < RmrrInfo->DeviceNumber);
 
     DEBUG ((DEBUG_INFO,"RMRR S%04x B%02x D%02x F%02x\n", DmarRmrr->SegmentNumber, Bus, Device, Function));
 
-    SourceId.Bits.Bus = Bus;
-    SourceId.Bits.Device = Device;
-    SourceId.Bits.Function = Function;
-
-    Status = EnableRmrrPageAttribute (
-               VTdInfo,
-               DmarRmrr->SegmentNumber,
-               SourceId,
-               DmarRmrr->ReservedMemoryRegionBaseAddress,
-               DmarRmrr->ReservedMemoryRegionLimitAddress,
-               EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
-               );
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute : %r\n", Status));
-    }
+    RmrrInfo->SourceId[DeviceIndex].Bits.Bus = Bus;
+    RmrrInfo->SourceId[DeviceIndex].Bits.Device = Device;
+    RmrrInfo->SourceId[DeviceIndex].Bits.Function = Function;
+    DeviceIndex++;
 
     DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
   }
 }
 
 /**
-  Parse DMAR DRHD table.
+  Parse DMAR RMRR table.
 
-  @param[in]  VTdInfo           The VTd engine context information.
+  @param[in]  AcpiDmarTable    DMAR ACPI table
+  @param[out] RmrrInfo         The VTd RMRR information.
 
 **/
 VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                           *VTdInfo
+ParseRmrrDmarAcpiTable (
+  IN  EFI_ACPI_DMAR_HEADER              *AcpiDmarTable,
+  OUT VTD_RMRR_INFO                     *RmrrInfo
   )
 {
-  EFI_ACPI_DMAR_HEADER                  *AcpiDmarTable;
   EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
 
-  AcpiDmarTable = (EFI_ACPI_DMAR_HEADER *) (UINTN) 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);
+      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader, RmrrInfo);
       break;
     default:
       break;
@@ -818,3 +618,36 @@ ParseDmarAcpiTableRmrr (
   }
 }
 
+/**
+  Get RMRR Info from ACPI DMAR Table.
+
+  @param[in]  AcpiDmarTable  DMAR ACPI table
+
+  @return the VTd engine number.
+**/
+VTD_RMRR_INFO *
+GetVtdRmrrInfo (
+  IN EFI_ACPI_DMAR_HEADER                    *AcpiDmarTable
+  )
+{
+  UINTN              DeviceNumber;
+  VTD_RMRR_INFO      *RmrrInfo;
+  UINTN              InfoSize;
+
+  RmrrInfo = NULL;
+  DeviceNumber = GetVtdRmrrDeviceNumber (AcpiDmarTable);
+
+  if (DeviceNumber > 0) {
+    InfoSize = sizeof (VTD_RMRR_INFO) - sizeof (VTD_SOURCE_ID) + sizeof (VTD_SOURCE_ID) * DeviceNumber;
+    RmrrInfo = (VTD_RMRR_INFO *) AllocateZeroPages (EFI_SIZE_TO_PAGES (InfoSize));
+    if (RmrrInfo == NULL) {
+      DEBUG ((DEBUG_ERROR, "GetVtdRmrrInfo - OUT_OF_RESOURCE\n"));
+      ASSERT (FALSE);
+      return NULL;
+    }
+
+    RmrrInfo->DeviceNumber = DeviceNumber;
+    ParseRmrrDmarAcpiTable (AcpiDmarTable, RmrrInfo);
+  }
+  return RmrrInfo;
+}
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 63397a1a..b51b38a0 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -79,77 +79,73 @@ PerpareCacheInvalidationInterface (
   IN VTD_UNIT_INFO *VTdUnitInfo
   )
 {
-  UINT16         QueueSize;
+  UINT16         QiDescLength;
   UINT64         Reg64;
   UINT32         Reg32;
   VTD_ECAP_REG   ECapReg;
+  UINTN          VtdUnitBaseAddress;
 
+  VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
 
-  if (VTdUnitInfo->VerReg.Bits.Major <= 6) {
+  if (VTdUnitInfo->VerReg.Bits.Major <= 5) {
     VTdUnitInfo->EnableQueuedInvalidation = 0;
-    DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+    DEBUG ((DEBUG_INFO, "Use Register-based Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
     return EFI_SUCCESS;
   }
 
-  ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+  ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
   if (ECapReg.Bits.QI == 0) {
-    DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+    DEBUG ((DEBUG_ERROR, "Hardware does not support queued invalidations interface for engine [0x%x]\n", VtdUnitBaseAddress));
     return EFI_UNSUPPORTED;
   }
 
   VTdUnitInfo->EnableQueuedInvalidation = 1;
-  DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VTdUnitInfo->VtdUnitBaseAddress));
+  DEBUG ((DEBUG_INFO, "Use Queued Invalidation Interface for engine [0x%x]\n", VtdUnitBaseAddress));
 
-  Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   if ((Reg32 & B_GSTS_REG_QIES) != 0) {
     DEBUG ((DEBUG_INFO,"Queued Invalidation Interface was enabled.\n"));
     Reg32 &= (~B_GSTS_REG_QIES);
-    MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+    MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
     do {
-      Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+      Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
     } while ((Reg32 & B_GSTS_REG_QIES) != 0);
-    MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, 0);
-
-    if (VTdUnitInfo->QiDesc != NULL) {
-      FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength));
-      VTdUnitInfo->QiDesc = NULL;
-      VTdUnitInfo->QiDescLength = 0;
-    }
+    MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, 0);
   }
 
   //
   // Initialize the Invalidation Queue Tail Register to zero.
   //
-  MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, 0);
+  MmioWrite64 (VtdUnitBaseAddress + R_IQT_REG, 0);
 
   //
   // Setup the IQ address, size and descriptor width through the Invalidation Queue Address Register
   //
-  QueueSize = 0;
-  VTdUnitInfo->QiDescLength = 1 << (QueueSize + 8);
-  VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength));
-
   if (VTdUnitInfo->QiDesc == NULL) {
-    VTdUnitInfo->QiDescLength = 0;
-    DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
-    return EFI_OUT_OF_RESOURCES;
+    VTdUnitInfo->QueueSize = 0;
+    QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8);
+    VTdUnitInfo->QiDesc = (QI_DESC *) AllocatePages (EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength));
+    if (VTdUnitInfo->QiDesc == NULL) {
+      DEBUG ((DEBUG_ERROR,"Could not Alloc Invalidation Queue Buffer.\n"));
+      return EFI_OUT_OF_RESOURCES;
+    }
   }
 
-  DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", VTdUnitInfo->QiDescLength));
-  Reg64 = (UINT64)(UINTN)VTdUnitInfo->QiDesc;
-  Reg64 |= QueueSize;
-  MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQA_REG, Reg64);
+  DEBUG ((DEBUG_INFO, "Invalidation Queue Length : %d\n", QiDescLength));
+  Reg64 = (UINT64) (UINTN) VTdUnitInfo->QiDesc;
+  Reg64 |= VTdUnitInfo->QueueSize;
+  MmioWrite64 (VtdUnitBaseAddress + R_IQA_REG, Reg64);
 
   //
   // Enable the queued invalidation interface through the Global Command Register.
   // When enabled, hardware sets the QIES field in the Global Status Register.
   //
-  Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   Reg32 |= B_GMCD_REG_QIE;
-  MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32);
   DEBUG ((DEBUG_INFO, "Enable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
   do {
-    Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   } while ((Reg32 & B_GSTS_REG_QIES) == 0);
 
   VTdUnitInfo->QiFreeHead = 0;
@@ -167,21 +163,23 @@ DisableQueuedInvalidationInterface (
   IN VTD_UNIT_INFO *VTdUnitInfo
   )
 {
-  UINT32  Reg32;
+  UINT32         Reg32;
+  UINT16         QiDescLength;
 
   if (VTdUnitInfo->EnableQueuedInvalidation != 0) {
-    Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+    Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
     Reg32 &= (~B_GMCD_REG_QIE);
-    MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
+    MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32);
     DEBUG ((DEBUG_INFO, "Disable Queued Invalidation Interface. GCMD_REG = 0x%x\n", Reg32));
     do {
-      Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+      Reg32 = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
     } while ((Reg32 & B_GSTS_REG_QIES) != 0);
 
     if (VTdUnitInfo->QiDesc != NULL) {
-      FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * VTdUnitInfo->QiDescLength));
+      QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8);
+      FreePages(VTdUnitInfo->QiDesc, EFI_SIZE_TO_PAGES(sizeof(QI_DESC) * QiDescLength));
       VTdUnitInfo->QiDesc = NULL;
-      VTdUnitInfo->QiDescLength = 0;
+      VTdUnitInfo->QueueSize = 0;
     }
 
     VTdUnitInfo->EnableQueuedInvalidation = 0;
@@ -203,26 +201,11 @@ QueuedInvalidationCheckFault (
 {
   UINT32     FaultReg;
 
-  FaultReg = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
-
-  if (FaultReg & B_FSTS_REG_IQE) {
-    DEBUG((DEBUG_ERROR, "Detect Invalidation Queue Error [0x%08x]\n", FaultReg));
-    FaultReg |= B_FSTS_REG_IQE;
-    MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
-    return RETURN_DEVICE_ERROR;
-  }
-
-  if (FaultReg & B_FSTS_REG_ITE) {
-    DEBUG((DEBUG_ERROR, "Detect Invalidation Time-out Error [0x%08x]\n", FaultReg));
-    FaultReg |= B_FSTS_REG_ITE;
-    MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
-    return RETURN_DEVICE_ERROR;
-  }
-
-  if (FaultReg & B_FSTS_REG_ICE) {
-    DEBUG((DEBUG_ERROR, "Detect Invalidation Completion Error [0x%08x]\n", FaultReg));
-    FaultReg |= B_FSTS_REG_ICE;
-    MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
+  FaultReg = MmioRead32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG);
+  if (FaultReg & (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE)) {
+    DEBUG((DEBUG_ERROR, "Detect Queue Invalidation Error [0x%08x]\n", FaultReg));
+    FaultReg |= (B_FSTS_REG_IQE | B_FSTS_REG_ITE | B_FSTS_REG_ICE);
+    MmioWrite32 (VTdUnitInfo->VtdUnitBaseAddress + R_FSTS_REG, FaultReg);
     return RETURN_DEVICE_ERROR;
   }
 
@@ -256,7 +239,7 @@ SubmitQueuedInvalidationDescriptor (
     return EFI_INVALID_PARAMETER;
   }
 
-  QiDescLength = VTdUnitInfo->QiDescLength;
+  QiDescLength = 1 << (VTdUnitInfo->QueueSize + 8);
   BaseDesc = VTdUnitInfo->QiDesc;
 
   DEBUG((DEBUG_INFO, "[0x%x] Submit QI Descriptor [0x%08x, 0x%08x]\n", VTdUnitInfo->VtdUnitBaseAddress, Desc->Low, Desc->High));
@@ -268,12 +251,12 @@ SubmitQueuedInvalidationDescriptor (
   DEBUG((DEBUG_INFO,"QI Free Head=0x%x\n", VTdUnitInfo->QiFreeHead));
   VTdUnitInfo->QiFreeHead = (VTdUnitInfo->QiFreeHead + 1) % QiDescLength;
 
-  Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+  Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
   //
   // Update the HW tail register indicating the presence of new descriptors.
   //
   Reg64Iqt = VTdUnitInfo->QiFreeHead << DMAR_IQ_SHIFT;
-  MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
+  MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQT_REG, Reg64Iqt);
 
   Status = EFI_SUCCESS;
   do {
@@ -283,7 +266,7 @@ SubmitQueuedInvalidationDescriptor (
       break;
     }
 
-    Reg64Iqh = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
+    Reg64Iqh = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_IQH_REG);
   } while (Reg64Iqt != Reg64Iqh);
 
   DEBUG((DEBUG_ERROR,"SubmitQueuedInvalidationDescriptor end\n"));
@@ -307,18 +290,18 @@ InvalidateContextCache (
     //
     // Register-based Invalidation
     //
-    Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+    Reg64 = MmioRead64 (VTdUnitInfo->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", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+      DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n", VTdUnitInfo->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 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
+    MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG, Reg64);
 
     do {
-      Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
+      Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_CCMD_REG);
     } while ((Reg64 & B_CCMD_REG_ICC) != 0);
   } else {
     //
@@ -351,26 +334,26 @@ InvalidateIOTLB (
     //
     // Register-based Invalidation
     //
-    ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+    ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
 
-    Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+    Reg64 = MmioRead64 (VTdUnitInfo->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", (UINTN)VTdUnitInfo->VtdUnitBaseAddress));
+       DEBUG ((DEBUG_ERROR, "ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VTdUnitInfo->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 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
+    MmioWrite64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
 
     do {
-      Reg64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
+      Reg64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
     } while ((Reg64 & B_IOTLB_REG_IVT) != 0);
   } else {
     //
     // Queued Invalidation
     //
-    ECapReg.Uint64 = MmioRead64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
+    ECapReg.Uint64 = MmioRead64 (VTdUnitInfo->VtdUnitBaseAddress + R_ECAP_REG);
     QiDesc.Low = QI_IOTLB_DID(0) | QI_IOTLB_DR(CAP_READ_DRAIN(ECapReg.Uint64)) | QI_IOTLB_DW(CAP_WRITE_DRAIN(ECapReg.Uint64)) | QI_IOTLB_GRAN(1) | QI_IOTLB_TYPE;
     QiDesc.High = QI_IOTLB_ADDR(0) | QI_IOTLB_IH(0) | QI_IOTLB_AM(0);
 
@@ -392,14 +375,14 @@ InvalidateIOTLB (
 EFI_STATUS
 EnableDmarPreMem (
   IN UINTN                        VtdUnitBaseAddress,
-  IN UINTN                        RtaddrRegValue
+  IN UINT64                       RtaddrRegValue
   )
 {
   UINT32                          Reg32;
 
   DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress));
 
-  DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue));
+  DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));
   MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RtaddrRegValue);
 
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
@@ -452,30 +435,33 @@ EnableDmar (
   )
 {
   UINT32                        Reg32;
+  UINTN                         VtdUnitBaseAddress;
 
-  DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VTdUnitInfo->VtdUnitBaseAddress));
+  VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
+
+  DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
 
   DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
-  MmioWrite64 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
 
-  Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
 
   DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
   do {
-    Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   } while((Reg32 & B_GSTS_REG_RTPS) == 0);
   DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
 
   //
   // Init DMAr Fault Event and Data registers
   //
-  Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_FEDATA_REG);
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
 
   //
   // Write Buffer Flush before invalidation
   //
-  FlushWriteBuffer ((UINTN)VTdUnitInfo->VtdUnitBaseAddress);
+  FlushWriteBuffer (VtdUnitBaseAddress);
 
   //
   // Invalidate the context cache
@@ -490,11 +476,11 @@ EnableDmar (
   //
   // Enable VTd
   //
-  Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
   DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
   do {
-    Reg32 = MmioRead32 ((UINTN)VTdUnitInfo->VtdUnitBaseAddress + R_GSTS_REG);
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   } while ((Reg32 & B_GSTS_REG_TE) == 0);
 
   DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
@@ -566,139 +552,52 @@ DisableDmar (
 }
 
 /**
-  Dump VTd version registers.
+  Enable VTd translation table protection for block DMA
 
-  @param[in]  VerReg            The version register.
-**/
-VOID
-DumpVtdVerRegs (
-  IN VTD_VER_REG                *VerReg
-  )
-{
-  DEBUG ((DEBUG_INFO, "  VerReg:\n", VerReg->Uint32));
-  DEBUG ((DEBUG_INFO, "    Major    - 0x%x\n", VerReg->Bits.Major));
-  DEBUG ((DEBUG_INFO, "    Minor    - 0x%x\n", VerReg->Bits.Minor));
-}
-
-/**
-  Dump VTd capability registers.
-
-  @param[in]  CapReg            The capability register.
-**/
-VOID
-DumpVtdCapRegs (
-  IN VTD_CAP_REG                *CapReg
-  )
-{
-  DEBUG ((DEBUG_INFO, "  CapReg:\n", CapReg->Uint64));
-  DEBUG ((DEBUG_INFO, "    ND     - 0x%x\n", CapReg->Bits.ND));
-  DEBUG ((DEBUG_INFO, "    AFL    - 0x%x\n", CapReg->Bits.AFL));
-  DEBUG ((DEBUG_INFO, "    RWBF   - 0x%x\n", CapReg->Bits.RWBF));
-  DEBUG ((DEBUG_INFO, "    PLMR   - 0x%x\n", CapReg->Bits.PLMR));
-  DEBUG ((DEBUG_INFO, "    PHMR   - 0x%x\n", CapReg->Bits.PHMR));
-  DEBUG ((DEBUG_INFO, "    CM     - 0x%x\n", CapReg->Bits.CM));
-  DEBUG ((DEBUG_INFO, "    SAGAW  - 0x%x\n", CapReg->Bits.SAGAW));
-  DEBUG ((DEBUG_INFO, "    MGAW   - 0x%x\n", CapReg->Bits.MGAW));
-  DEBUG ((DEBUG_INFO, "    ZLR    - 0x%x\n", CapReg->Bits.ZLR));
-  DEBUG ((DEBUG_INFO, "    FRO    - 0x%x\n", CapReg->Bits.FRO));
-  DEBUG ((DEBUG_INFO, "    SLLPS  - 0x%x\n", CapReg->Bits.SLLPS));
-  DEBUG ((DEBUG_INFO, "    PSI    - 0x%x\n", CapReg->Bits.PSI));
-  DEBUG ((DEBUG_INFO, "    NFR    - 0x%x\n", CapReg->Bits.NFR));
-  DEBUG ((DEBUG_INFO, "    MAMV   - 0x%x\n", CapReg->Bits.MAMV));
-  DEBUG ((DEBUG_INFO, "    DWD    - 0x%x\n", CapReg->Bits.DWD));
-  DEBUG ((DEBUG_INFO, "    DRD    - 0x%x\n", CapReg->Bits.DRD));
-  DEBUG ((DEBUG_INFO, "    FL1GP  - 0x%x\n", CapReg->Bits.FL1GP));
-  DEBUG ((DEBUG_INFO, "    PI     - 0x%x\n", CapReg->Bits.PI));
-}
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
 
-/**
-  Dump VTd extended capability registers.
-
-  @param[in]  ECapReg           The extended capability register.
+  @retval EFI_SUCCESS         DMAR translation is enabled.
+  @retval EFI_DEVICE_ERROR    DMAR translation is not enabled.
 **/
-VOID
-DumpVtdECapRegs (
-  IN VTD_ECAP_REG               *ECapReg
-  )
-{
-  DEBUG ((DEBUG_INFO, "  ECapReg:\n", ECapReg->Uint64));
-  DEBUG ((DEBUG_INFO, "    C      - 0x%x\n", ECapReg->Bits.C));
-  DEBUG ((DEBUG_INFO, "    QI     - 0x%x\n", ECapReg->Bits.QI));
-  DEBUG ((DEBUG_INFO, "    DT     - 0x%x\n", ECapReg->Bits.DT));
-  DEBUG ((DEBUG_INFO, "    IR     - 0x%x\n", ECapReg->Bits.IR));
-  DEBUG ((DEBUG_INFO, "    EIM    - 0x%x\n", ECapReg->Bits.EIM));
-  DEBUG ((DEBUG_INFO, "    PT     - 0x%x\n", ECapReg->Bits.PT));
-  DEBUG ((DEBUG_INFO, "    SC     - 0x%x\n", ECapReg->Bits.SC));
-  DEBUG ((DEBUG_INFO, "    IRO    - 0x%x\n", ECapReg->Bits.IRO));
-  DEBUG ((DEBUG_INFO, "    MHMV   - 0x%x\n", ECapReg->Bits.MHMV));
-  DEBUG ((DEBUG_INFO, "    MTS    - 0x%x\n", ECapReg->Bits.MTS));
-  DEBUG ((DEBUG_INFO, "    NEST   - 0x%x\n", ECapReg->Bits.NEST));
-  DEBUG ((DEBUG_INFO, "    PASID  - 0x%x\n", ECapReg->Bits.PASID));
-  DEBUG ((DEBUG_INFO, "    PRS    - 0x%x\n", ECapReg->Bits.PRS));
-  DEBUG ((DEBUG_INFO, "    ERS    - 0x%x\n", ECapReg->Bits.ERS));
-  DEBUG ((DEBUG_INFO, "    SRS    - 0x%x\n", ECapReg->Bits.SRS));
-  DEBUG ((DEBUG_INFO, "    NWFS   - 0x%x\n", ECapReg->Bits.NWFS));
-  DEBUG ((DEBUG_INFO, "    EAFS   - 0x%x\n", ECapReg->Bits.EAFS));
-  DEBUG ((DEBUG_INFO, "    PSS    - 0x%x\n", ECapReg->Bits.PSS));
-  DEBUG ((DEBUG_INFO, "    ADMS   - 0x%x\n", ECapReg->Bits.ADMS));
-}
-
-
-/**
-  Enable VTd translation table protection for all.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  EngineMask        The mask of the VTd engine to be accessed.
-**/
-VOID
-EnableVTdTranslationProtectionAll (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT64                     EngineMask
+EFI_STATUS
+EnableVTdTranslationProtectionBlockDma (
+  IN UINTN                      VtdUnitBaseAddress
   )
 {
-  EFI_STATUS                                Status;
-  EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI       *RootEntryTable;
-  UINTN                                     Index;
+  EFI_STATUS                            Status;
+  VTD_ECAP_REG                          ECapReg;
+  EDKII_VTD_NULL_ROOT_ENTRY_TABLE_PPI   *RootEntryTable;
 
-  DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask));
+  DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress));
 
-  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
-    if ((EngineMask & LShiftU64(1, Index)) == 0) {
-      continue;
-    }
+  ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
+  DEBUG ((DEBUG_INFO, "ECapReg : 0%016lx\n", ECapReg.Uint64));
 
-    VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG);
-    DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg);
-    VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG);
-    DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg);
-    VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG);
-    DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg);
-
-    if (VTdInfo->VtdUnitInfo[Index].ECapReg.Bits.ADMS == 1) {
-      //
-      // Use Abort DMA Mode
-      //
-      Status = EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM);
-    } else {
-      //
-      // Use Null Root Entry Table
-      //
-      Status = PeiServicesLocatePpi (
-                 &gEdkiiVTdNullRootEntryTableGuid,
-                 0,
-                 NULL,
-                 (VOID **)&RootEntryTable
-                 );
-      if (EFI_ERROR(Status)) {
-        DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status));
-        ASSERT (FALSE);
-        return;
-      }
-      EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable);
+  if (ECapReg.Bits.ADMS == 1) {
+    //
+    // Use Abort DMA Mode
+    //
+    DEBUG ((DEBUG_INFO, "Enable abort DMA mode.\n"));
+    Status = EnableDmarPreMem (VtdUnitBaseAddress, V_RTADDR_REG_TTM_ADM);
+  } else {
+    //
+    // Use Null Root Entry Table
+    //
+    Status = PeiServicesLocatePpi (
+               &gEdkiiVTdNullRootEntryTableGuid,
+               0,
+               NULL,
+               (VOID **)&RootEntryTable
+               );
+    if (EFI_ERROR(Status)) {
+      DEBUG ((DEBUG_ERROR, "Locate Null Root Entry Table Ppi Failed : %r\n", Status));
+      ASSERT (FALSE);
+      return EFI_DEVICE_ERROR;
     }
+    Status = EnableDmarPreMem (VtdUnitBaseAddress, (UINT64) (*RootEntryTable));
   }
 
-  return;
+  return Status;
 }
 
 /**
@@ -715,18 +614,25 @@ EnableVTdTranslationProtection (
   )
 {
   EFI_STATUS                    Status;
-  UINTN                         VtdIndex;
+  UINTN                         Index;
+  VTD_UNIT_INFO                 *VtdUnitInfo;
 
-  for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) {
-    if (VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable != 0) {
-      DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable));
-      Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable);
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+    VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+    if (VtdUnitInfo->Done) {
+      DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) was enabled\n", Index));
+      continue;
+    }
+
+    if (VtdUnitInfo->ExtRootEntryTable != 0) {
+      DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) ExtRootEntryTable 0x%x\n", Index, VtdUnitInfo->ExtRootEntryTable));
+      Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->ExtRootEntryTable);
     } else {
-      DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", VtdIndex, VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable));
-      Status = EnableDmar (&VTdInfo->VtdUnitInfo[VtdIndex], VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable);
+      DEBUG ((DEBUG_INFO, "EnableVtdDmar (%d) RootEntryTable 0x%x\n", Index, VtdUnitInfo->RootEntryTable));
+      Status = EnableDmar (VtdUnitInfo, VtdUnitInfo->RootEntryTable);
     }
     if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", VtdIndex));
+      DEBUG ((DEBUG_ERROR, "EnableVtdDmar (%d) Failed !\n", Index));
       return Status;
     }
   }
@@ -737,23 +643,22 @@ EnableVTdTranslationProtection (
   Disable VTd translation table protection.
 
   @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  EngineMask        The mask of the VTd engine to be accessed.
 **/
 VOID
 DisableVTdTranslationProtection (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT64                     EngineMask
+  IN VTD_INFO                   *VTdInfo
   )
 {
   UINTN                         Index;
 
-  DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask));
+  if (VTdInfo == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - %d Vtd Engine\n", VTdInfo->VTdEngineCount));
 
   for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
-    if ((EngineMask & LShiftU64(1, Index)) == 0) {
-      continue;
-    }
-    DisableDmar ((UINTN) VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
+    DisableDmar (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress);
 
     DisableQueuedInvalidationInterface(&VTdInfo->VtdUnitInfo[Index]);
   }
@@ -786,6 +691,36 @@ PrepareVtdCacheInvalidationConfig (
   return EFI_SUCCESS;
 }
 
+/**
+
+**/
+EFI_STATUS
+VtdCheckUsing5LevelPaging (
+  IN  UINT8                            HostAddressWidth,
+  IN  VTD_UNIT_INFO                    *VtdUnitInfo,
+  OUT BOOLEAN                          *Is5LevelPaging
+  )
+{
+  DEBUG((DEBUG_INFO, "  CapReg SAGAW bits : 0x%02x\n", VtdUnitInfo->CapReg.Bits.SAGAW));
+
+  *Is5LevelPaging = FALSE;
+  if ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT3) != 0) {
+    *Is5LevelPaging = TRUE;
+    if ((HostAddressWidth <= 48) &&
+         ((VtdUnitInfo->CapReg.Bits.SAGAW & BIT2) != 0)) {
+      *Is5LevelPaging = FALSE;
+    } else {
+      return EFI_UNSUPPORTED;
+    }
+  }
+  if ((VtdUnitInfo->CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+  DEBUG((DEBUG_INFO, "  Using %d Level Paging\n", *Is5LevelPaging ? 5 : 4));
+  return EFI_SUCCESS;
+}
+
+
 /**
   Prepare VTD configuration.
 
@@ -798,43 +733,37 @@ PrepareVtdConfig (
   IN VTD_INFO                   *VTdInfo
   )
 {
+  EFI_STATUS                    Status;
   UINTN                         Index;
-  UINTN                         DomainNumber;
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+  UINTN                         VtdUnitBaseAddress;
 
   for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
-    DEBUG ((DEBUG_ERROR, "Dump VTd Capability (%d)\n", Index));
-    VTdInfo->VtdUnitInfo[Index].VerReg.Uint32 = MmioRead32 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_VER_REG);
-    DumpVtdVerRegs (&VTdInfo->VtdUnitInfo[Index].VerReg);
-    VTdInfo->VtdUnitInfo[Index].CapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_CAP_REG);
-    DumpVtdCapRegs (&VTdInfo->VtdUnitInfo[Index].CapReg);
-    VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG);
-    DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg);
-
-    VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE;
-    if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0) {
-      DEBUG ((DEBUG_INFO, "Support 4-level page-table on VTD %d\n", Index));
-    }
-    if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT3) != 0) {
-      DEBUG((DEBUG_INFO, "Support 5-level page-table on VTD %d\n", Index));
-      VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = TRUE;
-
-      if ((VTdInfo->HostAddressWidth <= 48) &&
-          ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & BIT2) != 0)) {
-        DEBUG ((DEBUG_INFO, "Rollback to 4-level page-table on VTD %d\n", Index));
-        VTdInfo->VtdUnitInfo[Index].Is5LevelPaging = FALSE;
-      }
+    VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+	if (VtdUnitInfo->Done) {
+      continue;
     }
-    if ((VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW & (BIT3 | BIT2)) == 0) {
-      DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported on VTD %d !!!!\n", Index, VTdInfo->VtdUnitInfo[Index].CapReg.Bits.SAGAW));
-      return EFI_UNSUPPORTED;
+    VtdUnitBaseAddress = VtdUnitInfo->VtdUnitBaseAddress;
+    DEBUG((DEBUG_INFO, "VTd Engine: 0x%08X\n", VtdUnitBaseAddress));
+
+    VtdUnitInfo->VerReg.Uint32 = MmioRead32 (VtdUnitBaseAddress + R_VER_REG);
+    VtdUnitInfo->CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+    VtdUnitInfo->ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
+    DEBUG((DEBUG_INFO, "  VerReg  : 0x%08X\n", VtdUnitInfo->VerReg.Uint32));
+    DEBUG((DEBUG_INFO, "  CapReg  : 0x%016lX\n", VtdUnitInfo->CapReg.Uint64));
+    DEBUG((DEBUG_INFO, "  ECapReg : 0x%016lX\n", VtdUnitInfo->ECapReg.Uint64));
+
+    Status = VtdCheckUsing5LevelPaging (VTdInfo->HostAddressWidth, VtdUnitInfo, &(VtdUnitInfo->Is5LevelPaging));
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "!!!! Page-table type 0x%X is not supported!!!!\n", VtdUnitInfo->CapReg.Bits.SAGAW));
+      return Status;
     }
 
-    DomainNumber = (UINTN)1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[Index].CapReg.Bits.ND * 2 + 4);
-    if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber >= DomainNumber) {
-      DEBUG ((DEBUG_ERROR, "!!!! Pci device Number(0x%x) >= DomainNumber(0x%x) !!!!\n", VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber, DomainNumber));
-      return EFI_UNSUPPORTED;
+    Status = PerpareCacheInvalidationInterface(VtdUnitInfo);
+    if (EFI_ERROR (Status)) {
+      return Status;
     }
   }
+
   return EFI_SUCCESS;
 }
-
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c
index a8f7bfee..3d38cbee 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c
@@ -1,6 +1,6 @@
 /** @file
 
-  Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -50,20 +50,20 @@ typedef struct {
   the device driver need use SetAttribute() to update the IOMMU
   attribute to request DMA access (read and/or write).
 
-  @param[in]  This              The PPI instance pointer.
-  @param[in]  DeviceHandle      The device who initiates the DMA access request.
-  @param[in]  Mapping           The mapping value returned from Map().
-  @param[in]  IoMmuAccess       The IOMMU access.
-
-  @retval EFI_SUCCESS           The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
-  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
-  @retval EFI_INVALID_PARAMETER IoMmuAccess specified an illegal combination of access.
-  @retval EFI_UNSUPPORTED       The bit mask of IoMmuAccess is not supported by the IOMMU.
-  @retval EFI_UNSUPPORTED       The IOMMU does not support the memory range specified by Mapping.
-  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to modify the IOMMU access.
-  @retval EFI_DEVICE_ERROR      The IOMMU device reported an error while attempting the operation.
-  @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are
-                                not available to be allocated yet.
+  @param[in]  This                  The PPI instance pointer.
+  @param[in]  DeviceHandle          The device who initiates the DMA access request.
+  @param[in]  Mapping               The mapping value returned from Map().
+  @param[in]  IoMmuAccess           The IOMMU access.
+
+  @retval EFI_SUCCESS               The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
+  @retval EFI_INVALID_PARAMETER     Mapping is not a value that was returned by Map().
+  @retval EFI_INVALID_PARAMETER     IoMmuAccess specified an illegal combination of access.
+  @retval EFI_UNSUPPORTED           The bit mask of IoMmuAccess is not supported by the IOMMU.
+  @retval EFI_UNSUPPORTED           The IOMMU does not support the memory range specified by Mapping.
+  @retval EFI_OUT_OF_RESOURCES      There are not enough resources available to modify the IOMMU access.
+  @retval EFI_DEVICE_ERROR          The IOMMU device reported an error while attempting the operation.
+  @retval EFI_NOT_AVAILABLE_YET     DMA protection has been enabled, but DMA buffer are
+                                    not available to be allocated yet.
 **/
 EFI_STATUS
 EFIAPI
@@ -93,22 +93,22 @@ PeiIoMmuSetAttribute (
   Provides the controller-specific addresses required to access system memory from a
   DMA bus master.
 
-  @param  This                  The PPI instance pointer.
-  @param  Operation             Indicates if the bus master is going to read or write to system memory.
-  @param  HostAddress           The system memory address to map to the PCI controller.
-  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
-                                that were mapped.
-  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
-                                access the hosts HostAddress.
-  @param  Mapping               A resulting value to pass to Unmap().
-
-  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
-  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
-  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
-  @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are
-                                not available to be allocated yet.
+  @param [in]       This            The PPI instance pointer.
+  @param [in]       Operation       Indicates if the bus master is going to read or write to system memory.
+  @param [in]       HostAddress     The system memory address to map to the PCI controller.
+  @param [in] [out] NumberOfBytes   On input the number of bytes to map. On output the number of bytes
+                                    that were mapped.
+  @param [out]      DeviceAddress   The resulting map address for the bus master PCI controller to use to
+                                    access the hosts HostAddress.
+  @param [out]      Mapping         A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS               The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED           The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER     One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES      The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR          The system hardware could not map the requested address.
+  @retval EFI_NOT_AVAILABLE_YET     DMA protection has been enabled, but DMA buffer are
+                                    not available to be allocated yet.
 **/
 EFI_STATUS
 EFIAPI
@@ -140,7 +140,7 @@ PeiIoMmuMap (
 
   if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
       Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
-    *DeviceAddress = (UINTN)HostAddress;
+    *DeviceAddress = (UINTN) HostAddress;
     *Mapping = NULL;
     return EFI_SUCCESS;
   }
@@ -184,14 +184,14 @@ PeiIoMmuMap (
 /**
   Completes the Map() operation and releases any corresponding resources.
 
-  @param  This                  The PPI instance pointer.
-  @param  Mapping               The mapping value returned from Map().
+  @param [in] This                  The PPI instance pointer.
+  @param [in] Mapping               The mapping value returned from Map().
 
-  @retval EFI_SUCCESS           The range was unmapped.
-  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
-  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
-  @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are
-                                not available to be allocated yet.
+  @retval EFI_SUCCESS               The range was unmapped.
+  @retval EFI_INVALID_PARAMETER     Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR          The data was not committed to the target system memory.
+  @retval EFI_NOT_AVAILABLE_YET     DMA protection has been enabled, but DMA buffer are
+                                    not available to be allocated yet.
 **/
 EFI_STATUS
 EFIAPI
@@ -250,21 +250,21 @@ PeiIoMmuUnmap (
   Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
   OperationBusMasterCommonBuffer64 mapping.
 
-  @param  This                  The PPI instance pointer.
-  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
-                                EfiRuntimeServicesData.
-  @param  Pages                 The number of pages to allocate.
-  @param  HostAddress           A pointer to store the base system memory address of the
-                                allocated range.
-  @param  Attributes            The requested bit mask of attributes for the allocated range.
-
-  @retval EFI_SUCCESS           The requested memory pages were allocated.
-  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
-                                MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
-  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
-  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
-  @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are
-                                not available to be allocated yet.
+  @param [in]       This            The PPI instance pointer.
+  @param [in]       MemoryType      The type of memory to allocate, EfiBootServicesData or
+                                    EfiRuntimeServicesData.
+  @param [in]       Pages           The number of pages to allocate.
+  @param [in] [out] HostAddress     A pointer to store the base system memory address of the
+                                    allocated range.
+  @param [in]       Attributes      The requested bit mask of attributes for the allocated range.
+
+  @retval EFI_SUCCESS               The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED           Attributes is unsupported. The only legal attribute bits are
+                                    MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.
+  @retval EFI_INVALID_PARAMETER     One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES      The memory pages could not be allocated.
+  @retval EFI_NOT_AVAILABLE_YET     DMA protection has been enabled, but DMA buffer are
+                                    not available to be allocated yet.
 **/
 EFI_STATUS
 EFIAPI
@@ -307,15 +307,15 @@ PeiIoMmuAllocateBuffer (
 /**
   Frees memory that was allocated with AllocateBuffer().
 
-  @param  This                  The PPI instance pointer.
-  @param  Pages                 The number of pages to free.
-  @param  HostAddress           The base system memory address of the allocated range.
+  @param [in] This                  The PPI instance pointer.
+  @param [in] Pages                 The number of pages to free.
+  @param [in] HostAddress           The base system memory address of the allocated range.
 
-  @retval EFI_SUCCESS           The requested memory pages were freed.
-  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
-                                was not allocated with AllocateBuffer().
-  @retval EFI_NOT_AVAILABLE_YET DMA protection has been enabled, but DMA buffer are
-                                not available to be allocated yet.
+  @retval EFI_SUCCESS               The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER     The memory range specified by HostAddress and Pages
+                                    was not allocated with AllocateBuffer().
+  @retval EFI_NOT_AVAILABLE_YET     DMA protection has been enabled, but DMA buffer are
+                                    not available to be allocated yet.
 **/
 EFI_STATUS
 EFIAPI
@@ -364,52 +364,147 @@ CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
 };
 
 /**
-  Release the momery in the Intel VTd Info
+  Get ACPI DMAT Table from EdkiiVTdInfo PPI
 
-  @param[in]  VTdInfo           The VTd engine context information.
+  @retval Address              ACPI DMAT Table address
+  @retval NULL                 Failed to get ACPI DMAT Table
 **/
-VOID
-ReleaseVTdInfo (
-  IN VTD_INFO                   *VTdInfo
+EFI_ACPI_DMAR_HEADER * GetAcpiDmarTable (
+  VOID
   )
 {
-  UINTN                         Index;
+  EFI_STATUS                  Status;
+  EFI_ACPI_DMAR_HEADER        *AcpiDmarTable;
 
-  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
-    DEBUG ((DEBUG_INFO, "Release momery in VTdInfo[%d]\n", Index));
+  //
+  // Get the DMAR table
+  //
+  Status = PeiServicesLocatePpi (
+             &gEdkiiVTdInfoPpiGuid,
+             0,
+             NULL,
+             (VOID **)&AcpiDmarTable
+             );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR, "Fail to get ACPI DMAR Table : %r\n", Status));
+    AcpiDmarTable = NULL;
+  } else {
+    DumpAcpiDMAR (AcpiDmarTable);
+  }
 
-    if (VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry) {
-      FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry, 1);
-      VTdInfo->VtdUnitInfo[Index].FixedSecondLevelPagingEntry = 0;
-    }
+  return AcpiDmarTable;
+}
 
-    if (VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry) {
-      FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry, 1);
-      VTdInfo->VtdUnitInfo[Index].RmrrSecondLevelPagingEntry = 0;
-    }
+/**
+  Get the VTd engine context information hob.
 
-    if (VTdInfo->VtdUnitInfo[Index].RootEntryTable) {
-      FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].RootEntryTable, VTdInfo->VtdUnitInfo[Index].RootEntryTablePageSize);
-      VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0;
-    }
+  @retval The VTd engine context information.
 
-    if (VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable) {
-      FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].ExtRootEntryTable, VTdInfo->VtdUnitInfo[Index].ExtRootEntryTablePageSize);
-      VTdInfo->VtdUnitInfo[Index].RootEntryTable = 0;
+**/
+VTD_INFO *
+GetVTdInfoHob (
+  VOID
+  )
+{
+  VOID                          *Hob;
+  VTD_INFO                      *VTdInfo;
+
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);
+  if (Hob == NULL) {
+    VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO));
+    if (VTdInfo != NULL) {
+      ZeroMem (VTdInfo, sizeof (VTD_INFO));
     }
+  } else {
+    VTdInfo = GET_GUID_HOB_DATA(Hob);
+  }
+  return VTdInfo;
+}
+
+/**
+  Callback function of parse DMAR DRHD table in pre-memory phase.
 
-    if (VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData) {
-      FreePages ((VOID *) (UINTN) VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData, VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize);
-      VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataPageSize = 0;
-      VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceData = 0;
-      VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataNumber = 0;
-      VTdInfo->VtdUnitInfo[Index].PciDeviceInfo.PciDeviceDataMaxNumber = 0;
+  @param [in] [out] Context          Callback function context.
+  @param [in]       VTdIndex         The VTd engine index.
+  @param [in]       DmarDrhd         The DRHD table.
+
+**/
+VOID
+ProcessDhrdPreMemory (
+  IN OUT VOID                       *Context,
+  IN     UINT32                     VTdIndex,
+  IN     EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  )
+{
+  DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress -  0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress));
+
+  EnableVTdTranslationProtectionBlockDma ((UINTN) DmarDrhd->RegisterBaseAddress);
+}
+
+
+/**
+  Compare 2 RMRR contexts are same or not.
+
+  @param[in]  Destin            Destiny RMRR Info
+  @param[in]  Source            Source RMRR Info
+
+  @retval Same or not same
+
+**/
+BOOLEAN
+CompareVTdRmrrInfo (
+  IN VTD_RMRR_INFO                 *Destin,
+  IN VTD_RMRR_INFO                 *Source
+  )
+{
+  UINTN InfoSize;
+
+  if ((Destin == NULL) && (Source == NULL)) {
+    return TRUE;
+  }
+
+  if ((Destin != NULL) && (Source != NULL)) {
+    if (Destin->DeviceNumber == Source->DeviceNumber) {
+      InfoSize = sizeof (VTD_RMRR_INFO) - sizeof (VTD_SOURCE_ID) + sizeof (VTD_SOURCE_ID) * Destin->DeviceNumber;
+      if (CompareMem (Destin, Source, InfoSize) == 0) {
+        return TRUE;
+      }
     }
   }
+  return FALSE;
+}
+
+/**
+  Callback function of parse DMAR DRHD table in post memory phase.
+
+  @param [in] [out] Context          Callback function context.
+  @param [in]       VTdIndex         The VTd engine index.
+  @param [in]       DmarDrhd         The DRHD table.
+
+**/
+VOID
+ProcessDrhdPostMemory (
+  IN OUT VOID                       *Context,
+  IN     UINT32                     VTdIndex,
+  IN     EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  )
+{
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+
+  VtdUnitInfo = (VTD_UNIT_INFO *) Context;
+  VtdUnitInfo += VTdIndex;
+
+  VtdUnitInfo->Done = FALSE;
+  VtdUnitInfo->VtdUnitBaseAddress = (UINTN) DmarDrhd->RegisterBaseAddress;
+  VtdUnitInfo->Segment = DmarDrhd->SegmentNumber;
+  VtdUnitInfo->Flags = DmarDrhd->Flags;
+
+  DEBUG ((DEBUG_INFO,"VTD (%d) BaseAddress -  0x%016lx\n", VTdIndex, DmarDrhd->RegisterBaseAddress));
+  DEBUG ((DEBUG_INFO,"  Segment - %d, Flags   - 0x%x\n", DmarDrhd->SegmentNumber, DmarDrhd->Flags));
 }
 
 /**
-  Initializes the Intel VTd Info.
+  Initializes the Intel VTd Info in post memory phase.
 
   @retval EFI_SUCCESS           Usb bot driver is successfully initialized.
   @retval EFI_OUT_OF_RESOURCES  Can't initialize the driver.
@@ -419,89 +514,96 @@ InitVTdInfo (
   VOID
   )
 {
-  EFI_STATUS                    Status;
   EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
-  VOID                          *Hob;
+  VTD_RMRR_INFO                 *RmrrInfo;
+  BOOLEAN                       RmrrInfoEqual;
   VTD_INFO                      *VTdInfo;
-  UINT64                        EngineMask;
-
-  Status = PeiServicesLocatePpi (
-             &gEdkiiVTdInfoPpiGuid,
-             0,
-             NULL,
-             (VOID **)&AcpiDmarTable
-             );
-  ASSERT_EFI_ERROR (Status);
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+  UINTN                         VtdUnitNumber;
+  EFI_STATUS                    Status;
+  UINTN                         i;
+  UINTN                         j;
 
-  DumpAcpiDMAR (AcpiDmarTable);
+  VTdInfo = GetVTdInfoHob ();
+  ASSERT (VTdInfo != NULL);
 
-  //
-  // Clear old VTdInfo Hob.
-  //
-  Hob = GetFirstGuidHob (&mVTdInfoGuid);
-  if (Hob != NULL) {
-    DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
+  AcpiDmarTable = GetAcpiDmarTable ();
+  ASSERT (AcpiDmarTable != NULL);
 
-    VTdInfo = GET_GUID_HOB_DATA(Hob);
-    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
-    EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
-
-    ReleaseVTdInfo (VTdInfo);
-    VTdInfo->VTdEngineCount = 0;
+  VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
+  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
+  RmrrInfo = GetVtdRmrrInfo (AcpiDmarTable);
+  RmrrInfoEqual = CompareVTdRmrrInfo (VTdInfo->VtdRmrrInfo, RmrrInfo);
 
-    ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
+  VtdUnitInfo = AllocateZeroPages (EFI_SIZE_TO_PAGES (sizeof (VTD_UNIT_INFO) * VtdUnitNumber));
+  if (VtdUnitInfo == NULL) {
+    DEBUG ((DEBUG_ERROR, "InitVTdInfo - OUT_OF_RESOURCE\n"));
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
   }
 
-  //
-  // Get DMAR information to local VTdInfo
-  //
-  Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);
-  if (EFI_ERROR(Status)) {
-    DEBUG ((DEBUG_ERROR, " ParseDmarAcpiTableDrhd : %r\n", Status));
+  Status = ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDrhdPostMemory, VtdUnitInfo);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
     return Status;
   }
 
   //
-  // NOTE: Do not parse RMRR here, because RMRR may cause DMAR programming.
+  // Check Host Address Width
   //
+  if ((AcpiDmarTable->HostAddressWidth == VTdInfo->HostAddressWidth) && RmrrInfoEqual) {
+    for (i = 0; i < VtdUnitNumber; i++) {
+      //
+      // Scan each new Vtd Unit
+      //
+      for (j = 0; j < VTdInfo->VTdEngineCount; j++) {
+        //
+        // Compare the new Vtd Unit with each exist VTd Unit
+        //
+        if (VtdUnitInfo[i].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[j].VtdUnitBaseAddress) {
+          DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n", VtdUnitInfo[i].VtdUnitBaseAddress));
+          CopyMem (&VtdUnitInfo[i], &VTdInfo->VtdUnitInfo[j], sizeof (VTD_UNIT_INFO));
+          VtdUnitInfo[i].Done = TRUE;
+
+          break;
+        }
+      }
+    }
+  }
+  VTdInfo->AcpiDmarTable = AcpiDmarTable;
+  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+  VTdInfo->VTdEngineCount = VtdUnitNumber;
+  VTdInfo->VtdUnitInfo = VtdUnitInfo;
+  VTdInfo->VtdRmrrInfo = RmrrInfo;
 
   return EFI_SUCCESS;
 }
 
 /**
-  Initializes the Intel VTd DMAR for all memory.
+  Initializes the Intel VTd DMAR for block all DMA.
 
   @retval EFI_SUCCESS           Driver is successfully initialized.
   @retval RETURN_NOT_READY      Fail to get VTdInfo Hob .
 **/
 EFI_STATUS
-InitVTdDmarForAll (
+InitVTdDmarBlockAll (
   VOID
   )
 {
-  VOID                          *Hob;
-  VTD_INFO                      *VTdInfo;
-  UINT64                        EngineMask;
-  EFI_STATUS                    Status;
-
-  Hob = GetFirstGuidHob (&mVTdInfoGuid);
-  if (Hob == NULL) {
-    DEBUG ((DEBUG_ERROR, "Fail to get VTdInfo Hob.\n"));
-    return RETURN_NOT_READY;
-  }
-  VTdInfo = GET_GUID_HOB_DATA (Hob);
-  EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
-
-  DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
-  Status = PrepareVtdConfig (VTdInfo);
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
-  }
+  EFI_ACPI_DMAR_HEADER      *AcpiDmarTable;
 
-  EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
+  //
+  // Get the DMAR table
+  //
+  AcpiDmarTable = GetAcpiDmarTable ();
+  ASSERT (AcpiDmarTable != NULL);
 
-  return EFI_SUCCESS;
+  //
+  // Parse the DMAR table and block all DMA
+  //
+  return ParseDmarAcpiTableDrhd (AcpiDmarTable, ProcessDhrdPreMemory, NULL);
 }
 
 /**
@@ -524,8 +626,8 @@ InitDmaBuffer(
   DEBUG ((DEBUG_INFO, "InitDmaBuffer :\n"));
 
   Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+  ASSERT(Hob != NULL);
   DmaBufferInfo = GET_GUID_HOB_DATA (Hob);
-  VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid);
 
   /**
   When gVtdPmrInfoDataHobGuid exists, it means:
@@ -535,7 +637,7 @@ InitDmaBuffer(
     4. Protection regions will be conveyed through VTD_PMR_INFO_HOB
 
   When gVtdPmrInfoDataHobGuid dosen't exist, it means:
-    1. IntelVTdDmar driver will calcuate the PMR memory alignment
+    1. IntelVTdDmarPei driver will calcuate the protected memory alignment
     2. Dma buffer is reserved by AllocateAlignedPages()
   **/
 
@@ -545,33 +647,40 @@ InitDmaBuffer(
     return EFI_INVALID_PARAMETER;
   }
 
-  if (VtdPmrHobPtr == NULL) {
-    //
-    // Allocate memory for DMA buffer
-    //
-    DmaBufferInfo->DmaBufferBase = (UINT64) (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES ((UINTN) DmaBufferInfo->DmaBufferSize), 0);
-    if (DmaBufferInfo->DmaBufferBase == 0) {
-      DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n"));
-      return EFI_OUT_OF_RESOURCES;
+  if (DmaBufferInfo->DmaBufferBase == 0) {
+    VtdPmrHobPtr = GetFirstGuidHob (&gVtdPmrInfoDataHobGuid);
+    if (VtdPmrHobPtr != NULL) {
+      //
+      // Get the protected memory ranges information from the VTd PMR hob
+      //
+      VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr);
+
+      if ((VtdPmrHob->ProtectedHighBase - VtdPmrHob->ProtectedLowLimit) < DmaBufferInfo->DmaBufferSize) {
+        DEBUG ((DEBUG_ERROR, " DmaBufferSize not enough\n"));
+        return EFI_INVALID_PARAMETER;
+      }
+      DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit;
+    } else {
+      //
+      // Allocate memory for DMA buffer
+      //
+      DmaBufferInfo->DmaBufferBase = (UINTN) AllocateAlignedPages (EFI_SIZE_TO_PAGES (DmaBufferInfo->DmaBufferSize), 0);
+      if (DmaBufferInfo->DmaBufferBase == 0) {
+        DEBUG ((DEBUG_ERROR, " InitDmaBuffer : OutOfResource\n"));
+        return EFI_OUT_OF_RESOURCES;
+      }
+      DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n"));
     }
-    DmaBufferInfo->DmaBufferLimit = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
-    DEBUG ((DEBUG_INFO, "Alloc DMA buffer success.\n"));
-  } else {
-    //
-    // Get the PMR ranges information for the VTd PMR hob
-    //
-    VtdPmrHob = GET_GUID_HOB_DATA (VtdPmrHobPtr);
-    DmaBufferInfo->DmaBufferBase = VtdPmrHob->ProtectedLowLimit;
-    DmaBufferInfo->DmaBufferLimit = VtdPmrHob->ProtectedHighBase;
+
+    DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
+    DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
+
+    DEBUG ((DEBUG_INFO, " DmaBufferSize          : 0x%x\n", DmaBufferInfo->DmaBufferSize));
+    DEBUG ((DEBUG_INFO, " DmaBufferBase          : 0x%x\n", DmaBufferInfo->DmaBufferBase));
   }
-  DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
-  DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
 
-  DEBUG ((DEBUG_INFO, " DmaBufferSize          : 0x%lx\n", DmaBufferInfo->DmaBufferSize));
-  DEBUG ((DEBUG_INFO, " DmaBufferBase          : 0x%lx\n", DmaBufferInfo->DmaBufferBase));
-  DEBUG ((DEBUG_INFO, " DmaBufferLimit         : 0x%lx\n", DmaBufferInfo->DmaBufferLimit));
-  DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop    : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentTop));
-  DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%lx\n", DmaBufferInfo->DmaBufferCurrentBottom));
+  DEBUG ((DEBUG_INFO, " DmaBufferCurrentTop    : 0x%x\n", DmaBufferInfo->DmaBufferCurrentTop));
+  DEBUG ((DEBUG_INFO, " DmaBufferCurrentBottom : 0x%x\n", DmaBufferInfo->DmaBufferCurrentBottom));
 
   return EFI_SUCCESS;
 }
@@ -588,14 +697,14 @@ InitVTdDmarForDma (
   VOID
   )
 {
-  VOID                          *Hob;
   VTD_INFO                      *VTdInfo;
+
   EFI_STATUS                    Status;
   EFI_PEI_PPI_DESCRIPTOR        *OldDescriptor;
   EDKII_IOMMU_PPI               *OldIoMmuPpi;
 
-  Hob = GetFirstGuidHob (&mVTdInfoGuid);
-  VTdInfo = GET_GUID_HOB_DATA (Hob);
+  VTdInfo = GetVTdInfoHob ();
+  ASSERT (VTdInfo != NULL);
 
   DEBUG ((DEBUG_INFO, "PrepareVtdConfig\n"));
   Status = PrepareVtdConfig (VTdInfo);
@@ -604,13 +713,6 @@ InitVTdDmarForDma (
     return Status;
   }
 
-  DEBUG ((DEBUG_INFO, "PrepareVtdCacheInvalidationConfig\n"));
-  Status = PrepareVtdCacheInvalidationConfig (VTdInfo);
-  if (EFI_ERROR (Status)) {
-    ASSERT_EFI_ERROR (Status);
-    return Status;
-  }
-
   // create root entry table
   DEBUG ((DEBUG_INFO, "SetupTranslationTable\n"));
   Status = SetupTranslationTable (VTdInfo);
@@ -620,8 +722,11 @@ InitVTdDmarForDma (
   }
 
   // If there is RMRR memory, parse it here.
-  DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
-  ParseDmarAcpiTableRmrr (VTdInfo);
+  Status = SetupRmrr (VTdInfo);
+  if (EFI_ERROR (Status)) {
+    ASSERT_EFI_ERROR (Status);
+    return Status;
+  }
 
   DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
   Status = EnableVTdTranslationProtection(VTdInfo);
@@ -668,21 +773,10 @@ S3EndOfPeiNotify(
   IN VOID                       *Ppi
   )
 {
-  VOID                          *Hob;
-  VTD_INFO                      *VTdInfo;
-  UINT64                        EngineMask;
-
   DEBUG((DEBUG_INFO, "VTd DMAR PEI S3EndOfPeiNotify\n"));
 
   if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
-    Hob = GetFirstGuidHob (&mVTdInfoGuid);
-    if (Hob == NULL) {
-      return EFI_SUCCESS;
-    }
-    VTdInfo = GET_GUID_HOB_DATA(Hob);
-
-    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
-    DisableVTdTranslationProtection (VTdInfo, EngineMask);
+    DisableVTdTranslationProtection (GetVTdInfoHob ());
   }
   return EFI_SUCCESS;
 }
@@ -733,18 +827,13 @@ VTdInfoNotify (
 
   DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));
 
-  //
-  // NOTE: We need reinit VTdInfo because previous information might be overriden.
-  //
-  InitVTdInfo ();
-
   if (!MemoryInitialized) {
     //
     // If the memory is not initialized,
     // Protect all system memory
     //
 
-    InitVTdDmarForAll ();
+    InitVTdDmarBlockAll ();
 
     //
     // Install PPI.
@@ -758,9 +847,16 @@ VTdInfoNotify (
     //
 
     Status = InitDmaBuffer ();
-    ASSERT_EFI_ERROR(Status);
+    ASSERT_EFI_ERROR (Status);
 
-    InitVTdDmarForDma ();
+    //
+    // NOTE: We need reinit VTdInfo because previous information might be overriden.
+    //
+    Status = InitVTdInfo ();
+    ASSERT_EFI_ERROR (Status);
+
+    Status = InitVTdDmarForDma ();
+    ASSERT_EFI_ERROR (Status);
   }
 
   return EFI_SUCCESS;
@@ -826,4 +922,3 @@ IntelVTdDmarInitialize (
 
   return EFI_SUCCESS;
 }
-
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
index e23a6c8e..e1894e39 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -9,68 +9,71 @@
 #ifndef __DMA_ACCESS_LIB_H__
 #define __DMA_ACCESS_LIB_H__
 
-#define MAX_VTD_PCI_DATA_NUMBER             0x100
-
 #define VTD_64BITS_ADDRESS(Lo, Hi) (LShiftU64 (Lo, 12) | LShiftU64 (Hi, 32))
 
 typedef struct {
-  UINT8                            DeviceType;
-  VTD_SOURCE_ID                    PciSourceId;
-} PEI_PCI_DEVICE_DATA;
-
-typedef struct {
-  BOOLEAN                          IncludeAllFlag;
-  UINT32                           PciDeviceDataNumber;
-  UINT32                           PciDeviceDataMaxNumber;
-  UINT32                           PciDeviceDataPageSize;
-  UINT32                           PciDeviceData;
-} PEI_PCI_DEVICE_INFORMATION;
+  UINT16                          SegmentNumber;
+  UINT64                          ReservedMemoryRegionBaseAddress;
+  UINT64                          ReservedMemoryRegionLimitAddress;
+  UINTN                           DeviceNumber;
+  VTD_SOURCE_ID                   SourceId[1];
+} VTD_RMRR_INFO;
 
 typedef struct {
-  UINT32                           VtdUnitBaseAddress;
+  BOOLEAN                          Done;
+  UINTN                            VtdUnitBaseAddress;
   UINT16                           Segment;
+  UINT8                            Flags;
   VTD_VER_REG                      VerReg;
   VTD_CAP_REG                      CapReg;
   VTD_ECAP_REG                     ECapReg;
   BOOLEAN                          Is5LevelPaging;
-  UINT32                           FixedSecondLevelPagingEntry;
-  UINT32                           RmrrSecondLevelPagingEntry;
-  UINT32                           RootEntryTable;
-  UINT32                           ExtRootEntryTable;
-  UINT16                           RootEntryTablePageSize;
-  UINT16                           ExtRootEntryTablePageSize;
-  PEI_PCI_DEVICE_INFORMATION       PciDeviceInfo;
   UINT8                            EnableQueuedInvalidation;
-  UINT16                           QiDescLength;
+  UINT16                           QueueSize;
   QI_DESC                          *QiDesc;
   UINT16                           QiFreeHead;
+  UINTN                            FixedSecondLevelPagingEntry;
+  UINTN                            RootEntryTable;
+  UINTN                            ExtRootEntryTable;
+  UINTN                            RootEntryTablePageSize;
+  UINTN                            ExtRootEntryTablePageSize;
+  UINTN                            RmrrSecondLevelPagingEntry;
 } VTD_UNIT_INFO;
 
 typedef struct {
-  UINT32                           AcpiDmarTable;
+  EFI_ACPI_DMAR_HEADER             *AcpiDmarTable;
   UINT8                            HostAddressWidth;
-  UINT32                           VTdEngineCount;
-  VTD_UNIT_INFO                    VtdUnitInfo[1];
+  UINTN                            VTdEngineCount;
+  VTD_UNIT_INFO                    *VtdUnitInfo;
+  VTD_RMRR_INFO                    *VtdRmrrInfo;
 } VTD_INFO;
 
 typedef struct {
-  UINT64                            DmaBufferBase;
-  UINT64                            DmaBufferSize;
-  UINT64                            DmaBufferLimit;
-  UINT64                            DmaBufferCurrentTop;
-  UINT64                            DmaBufferCurrentBottom;
+  UINTN                             DmaBufferBase;
+  UINTN                             DmaBufferSize;
+  UINTN                             DmaBufferCurrentTop;
+  UINTN                             DmaBufferCurrentBottom;
 } DMA_BUFFER_INFO;
 
+typedef
+VOID
+(*PROCESS_DRHD_CALLBACK_FUNC) (
+  IN OUT VOID                       *Context,
+  IN     UINT32                     VTdIndex,
+  IN     EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  );
+
 /**
-  Enable VTd translation table protection.
+  Enable VTd translation table protection for block DMA
 
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  EngineMask        The mask of the VTd engine to be accessed.
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+
+  @retval EFI_SUCCESS           DMAR translation is enabled.
+  @retval EFI_DEVICE_ERROR      DMAR translation is not enabled.
 **/
-VOID
-EnableVTdTranslationProtectionAll (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT64                     EngineMask
+EFI_STATUS
+EnableVTdTranslationProtectionBlockDma (
+  IN UINTN                      VtdUnitBaseAddress
   );
 
 /**
@@ -90,34 +93,39 @@ EnableVTdTranslationProtection (
   Disable VTd translation table protection.
 
   @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  EngineMask        The mask of the VTd engine to be accessed.
 **/
 VOID
 DisableVTdTranslationProtection (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT64                     EngineMask
+  IN VTD_INFO                   *VTdInfo
   );
 
 /**
   Parse DMAR DRHD table.
 
   @param[in]  AcpiDmarTable     DMAR ACPI table
+  @param[in]  Callback          Callback function for handle DRHD
+  @param[in]  Context           Callback function Context
+
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
 
-  @return EFI_SUCCESS           The DMAR DRHD table is parsed.
 **/
 EFI_STATUS
 ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   );
 
 /**
-  Parse DMAR DRHD table.
+  Get RMRR Info from ACPI DMAR Table.
 
-  @param[in]  VTdInfo           The VTd engine context information.
+  @param[in]  AcpiDmarTable     DMAR ACPI table
+
+  @return the VTd engine number.
 **/
-VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                   *VTdInfo
+VTD_RMRR_INFO *
+GetVtdRmrrInfo (
+  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
   );
 
 /**
@@ -167,6 +175,30 @@ SetupTranslationTable (
   IN VTD_INFO                   *VTdInfo
   );
 
+/**
+  Get VTd engine number.
+
+  @param[in]  AcpiDmarTable     DMAR ACPI table
+
+  @return the VTd engine number.
+**/
+UINTN
+GetVtdEngineNumber (
+  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
+  );
+
+/**
+  Setup VTd RMRR in translation table.
+
+  @param[in]  VTdInfo           The VTd engine context information.
+
+  @return the VTd engine number.
+**/
+EFI_STATUS
+SetupRmrr (
+  IN VTD_INFO                   *VTdInfo
+  );
+
 /**
   Flush VTD page table and context table memory.
 
@@ -240,4 +272,3 @@ extern EFI_GUID mVTdInfoGuid;
 extern EFI_GUID mDmaBufferInfoGuid;
 
 #endif
-
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
index a309d566..2e14632a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
@@ -1,6 +1,7 @@
 /** @file
 
   Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>
+
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -129,12 +130,12 @@ CreateSecondLevelPagingEntryTable (
     FlushPageTableMemory (VTdUnitInfo, (UINTN) SecondLevelPagingEntry, EFI_PAGES_TO_SIZE (1));
   }
 
-  DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", SecondLevelPagingEntry));
+  DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
   //
   // If no access is needed, just create not present entry.
   //
   if (IoMmuAccess == 0) {
-    DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN) SecondLevelPagingEntry));
+    DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx Access 0\n", (UINT64) (UINTN) SecondLevelPagingEntry));
     return SecondLevelPagingEntry;
   }
 
@@ -244,7 +245,7 @@ CreateSecondLevelPagingEntryTable (
   }
   FlushPageTableMemory (VTdUnitInfo, (UINTN) &Lvl5PtEntry[Lvl5Start], (UINTN) &Lvl5PtEntry[Lvl5End + 1] - (UINTN) &Lvl5PtEntry[Lvl5Start]);
 
-  DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINTN)SecondLevelPagingEntry));
+  DEBUG ((DEBUG_INFO, " SecondLevelPagingEntry:0x%016lx\n", (UINT64) (UINTN) SecondLevelPagingEntry));
   return SecondLevelPagingEntry;
 }
 
@@ -276,6 +277,10 @@ CreateContextEntry (
   VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
   UINT64                        Pt;
 
+  if (VTdUnitInfo->RootEntryTable != 0) {
+    return EFI_SUCCESS;
+  }
+
   RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER);
   ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER);
   EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);
@@ -286,8 +291,8 @@ CreateContextEntry (
   }
 
   DEBUG ((DEBUG_ERROR, "RootEntryTable address - 0x%x\n", Buffer));
-  VTdUnitInfo->RootEntryTable = (UINT32) (UINTN) Buffer;
-  VTdUnitInfo->RootEntryTablePageSize = (UINT16) EntryTablePages;
+  VTdUnitInfo->RootEntryTable = (UINTN) Buffer;
+  VTdUnitInfo->RootEntryTablePageSize = EntryTablePages;
   RootEntryBase = (VTD_ROOT_ENTRY *) Buffer;
   Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
 
@@ -317,7 +322,7 @@ CreateContextEntry (
       ContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
 
       if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
-        SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+        SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
         Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
         ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
         ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);
@@ -359,6 +364,10 @@ CreateExtContextEntry (
   VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
   UINT64                        Pt;
 
+  if (VTdUnitInfo->ExtRootEntryTable != 0) {
+    return EFI_SUCCESS;
+  }
+
   RootPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_ROOT_ENTRY) * VTD_ROOT_ENTRY_NUMBER);
   ContextPages = EFI_SIZE_TO_PAGES (sizeof (VTD_EXT_CONTEXT_ENTRY) * VTD_CONTEXT_ENTRY_NUMBER);
   EntryTablePages = RootPages + ContextPages * (VTD_ROOT_ENTRY_NUMBER);
@@ -369,8 +378,8 @@ CreateExtContextEntry (
   }
 
   DEBUG ((DEBUG_ERROR, "ExtRootEntryTable address - 0x%x\n", Buffer));
-  VTdUnitInfo->ExtRootEntryTable = (UINT32) (UINTN) Buffer;
-  VTdUnitInfo->ExtRootEntryTablePageSize = (UINT16) EntryTablePages;
+  VTdUnitInfo->ExtRootEntryTable = (UINTN) Buffer;
+  VTdUnitInfo->ExtRootEntryTablePageSize = EntryTablePages;
   ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) Buffer;
   Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (RootPages);
 
@@ -403,7 +412,7 @@ CreateExtContextEntry (
       ExtContextEntry->Bits.AddressWidth = VTdUnitInfo->Is5LevelPaging ? 0x3 : 0x2;
 
       if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
-        SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry;
+        SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VTdUnitInfo->FixedSecondLevelPagingEntry;
         Pt = (UINT64)RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
 
         ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
@@ -791,9 +800,6 @@ SetSecondLevelPagingAttribute (
     SplitAttribute = NeedSplitPage (BaseAddress, Length, PageAttribute);
     if (SplitAttribute == PageNone) {
       ConvertSecondLevelPageEntryAttribute (VTdUnitInfo, PageEntry, IoMmuAccess, &IsEntryModified);
-      if (IsEntryModified) {
-        //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
-      }
       //
       // Convert success, move to next
       //
@@ -805,7 +811,6 @@ SetSecondLevelPagingAttribute (
         DEBUG ((DEBUG_ERROR, "SplitSecondLevelPage - %r\n", Status));
         return RETURN_UNSUPPORTED;
       }
-      //mVtdUnitInformation[VtdIndex].HasDirtyPages = TRUE;
       //
       // Just split current page
       // Convert success in next around
@@ -837,7 +842,11 @@ CreateFixedSecondLevelPagingEntry (
   VOID                          *Hob;
   DMA_BUFFER_INFO               *DmaBufferInfo;
 
-  VTdUnitInfo->FixedSecondLevelPagingEntry = (UINT32) (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
+  if (VTdUnitInfo->FixedSecondLevelPagingEntry != 0) {
+    return EFI_SUCCESS;
+  }
+
+  VTdUnitInfo->FixedSecondLevelPagingEntry = (UINTN) CreateSecondLevelPagingEntryTable (VTdUnitInfo, NULL, 0, SIZE_4GB, 0);
   if (VTdUnitInfo->FixedSecondLevelPagingEntry == 0) {
     DEBUG ((DEBUG_ERROR, "FixedSecondLevelPagingEntry is empty\n"));
     return EFI_OUT_OF_RESOURCES;
@@ -846,14 +855,14 @@ CreateFixedSecondLevelPagingEntry (
   Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
   DmaBufferInfo = GET_GUID_HOB_DATA (Hob);
   BaseAddress = DmaBufferInfo->DmaBufferBase;
-  Length = DmaBufferInfo->DmaBufferLimit - DmaBufferInfo->DmaBufferBase;
+  Length = DmaBufferInfo->DmaBufferSize;
   IoMmuAccess = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
 
   DEBUG ((DEBUG_INFO, "  BaseAddress = 0x%lx\n", BaseAddress));
   DEBUG ((DEBUG_INFO, "  Length = 0x%lx\n", Length));
   DEBUG ((DEBUG_INFO, "  IoMmuAccess = 0x%lx\n", IoMmuAccess));
 
-  Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) (UINTN) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
+  Status = SetSecondLevelPagingAttribute (VTdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) VTdUnitInfo->FixedSecondLevelPagingEntry, BaseAddress, Length, IoMmuAccess);
 
   return Status;
 }
@@ -877,6 +886,9 @@ SetupTranslationTable (
 
   for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
     VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+    if (VtdUnitInfo->Done) {
+      continue;
+    }
 
     Status = CreateFixedSecondLevelPagingEntry (VtdUnitInfo);
     if (EFI_ERROR (Status)) {
@@ -912,83 +924,45 @@ SetupTranslationTable (
 }
 
 /**
-  Find the VTd index by the Segment and SourceId.
+  Setup VTd RMRR in translation table.
 
   @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  Segment           The segment of the source.
-  @param[in]  SourceId          The SourceId of the source.
-  @param[out] ExtContextEntry   The ExtContextEntry of the source.
-  @param[out] ContextEntry      The ContextEntry of the source.
 
-  @return The index of the VTd engine.
-  @retval (UINTN)-1  The VTd engine is not found.
+  @return the VTd engine number.
 **/
-UINTN
-FindVtdIndexBySegmentSourceId (
-  IN  VTD_INFO                  *VTdInfo,
-  IN  UINT16                    Segment,
-  IN  VTD_SOURCE_ID             SourceId,
-  OUT VTD_EXT_CONTEXT_ENTRY     **ExtContextEntry,
-  OUT VTD_CONTEXT_ENTRY         **ContextEntry
+EFI_STATUS
+SetupRmrr (
+  IN VTD_INFO                   *VTdInfo
   )
 {
-  UINTN                         VtdIndex;
-  VTD_ROOT_ENTRY                *RootEntryBase;
-  VTD_ROOT_ENTRY                *RootEntry;
-  VTD_CONTEXT_ENTRY             *ContextEntryTable;
-  VTD_CONTEXT_ENTRY             *ThisContextEntry;
-  VTD_EXT_ROOT_ENTRY            *ExtRootEntryBase;
-  VTD_EXT_ROOT_ENTRY            *ExtRootEntry;
-  VTD_EXT_CONTEXT_ENTRY         *ExtContextEntryTable;
-  VTD_EXT_CONTEXT_ENTRY         *ThisExtContextEntry;
+  EFI_STATUS                    Status;
+  UINTN                         Index;
 
-  for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) {
-    if (GetPciDataIndex (&VTdInfo->VtdUnitInfo[VtdIndex], Segment, SourceId) != (UINTN)-1) {
-      DEBUG ((DEBUG_INFO, "Find VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-      break;
-    }
+  if (VTdInfo->VtdRmrrInfo == NULL) {
+    return EFI_SUCCESS;
   }
-  if (VtdIndex >= VTdInfo->VTdEngineCount) {
-    for (VtdIndex = 0; VtdIndex < VTdInfo->VTdEngineCount; VtdIndex++) {
-      if (Segment != VTdInfo->VtdUnitInfo[VtdIndex].Segment) {
-        continue;
-      }
-      if (VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.IncludeAllFlag) {
-        DEBUG ((DEBUG_INFO, "Find IncludeAllFlag VtdIndex(0x%x) for S%04x B%02x D%02x F%02x\n", VtdIndex, Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-        break;
-      }
-    }
+
+  if (VTdInfo->VtdRmrrInfo->DeviceNumber == 0) {
+    return EFI_SUCCESS;
   }
 
-  if (VtdIndex < VTdInfo->VTdEngineCount) {
-    ExtRootEntryBase = (VTD_EXT_ROOT_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].ExtRootEntryTable;
-    if (ExtRootEntryBase != 0) {
-      ExtRootEntry = &ExtRootEntryBase[SourceId.Index.RootIndex];
-      ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ;
-      ThisExtContextEntry  = &ExtContextEntryTable[SourceId.Index.ContextIndex];
-      if (ThisExtContextEntry->Bits.AddressWidth == 0) {
-        DEBUG ((DEBUG_INFO, "ExtContextEntry AddressWidth : 0x%x\n", ThisExtContextEntry->Bits.AddressWidth));
-        return (UINTN)-1;
-      }
-      *ExtContextEntry = ThisExtContextEntry;
-      *ContextEntry    = NULL;
-    } else {
-      RootEntryBase = (VTD_ROOT_ENTRY*) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RootEntryTable;
-      RootEntry = &RootEntryBase[SourceId.Index.RootIndex];
-      ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;
-      ThisContextEntry  = &ContextEntryTable[SourceId.Index.ContextIndex];
-      if (ThisContextEntry->Bits.AddressWidth == 0) {
-        DEBUG ((DEBUG_INFO, "ContextEntry AddressWidth : 0x%x\n", ThisContextEntry->Bits.AddressWidth));
-        return (UINTN)-1;
-      }
-      *ExtContextEntry = NULL;
-      *ContextEntry    = ThisContextEntry;
+  DEBUG ((DEBUG_INFO, "Setup Rmrr Info\n"));
+
+  for (Index = 0; Index < VTdInfo->VtdRmrrInfo->DeviceNumber; Index++) {
+    Status = EnableRmrrPageAttribute (
+               VTdInfo,
+               VTdInfo->VtdRmrrInfo->SegmentNumber,
+               VTdInfo->VtdRmrrInfo->SourceId[Index],
+               VTdInfo->VtdRmrrInfo->ReservedMemoryRegionBaseAddress,
+               VTdInfo->VtdRmrrInfo->ReservedMemoryRegionLimitAddress,
+               EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
+               );
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR, "EnableRmrrPageAttribute : %r\n", Status));
     }
-
-    return VtdIndex;
   }
 
-  return (UINTN)-1;
+  return EFI_SUCCESS;
 }
 
 /**
@@ -1013,8 +987,9 @@ EnableRmrrPageAttribute (
   IN UINT64                     IoMmuAccess
   )
 {
-  EFI_STATUS Status;
-  UINTN                         VtdIndex;
+  UINTN                         Index;
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+  EFI_STATUS                    Status;
   VTD_EXT_CONTEXT_ENTRY         *ExtContextEntry;
   VTD_CONTEXT_ENTRY             *ContextEntry;
   VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
@@ -1022,39 +997,41 @@ EnableRmrrPageAttribute (
 
   DEBUG ((DEBUG_INFO, "EnableRmrrPageAttribute (S%04x B%02x D%02x F%02x)\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
 
-  VtdIndex = FindVtdIndexBySegmentSourceId (VTdInfo, Segment, SourceId, &ExtContextEntry, &ContextEntry);
-  if (VtdIndex == (UINTN)-1) {
-    DEBUG ((DEBUG_ERROR, "EnableRmrrPageAttribute - Can not locate Pci device (S%04x B%02x D%02x F%02x) !\n", Segment, SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-    return EFI_DEVICE_ERROR;
-  }
-
-  if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) {
-    DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", VtdIndex));
-    VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry = (UINT32)(UINTN)CreateSecondLevelPagingEntryTable (&VTdInfo->VtdUnitInfo[VtdIndex], NULL, 0, SIZE_4GB, 0);
-    if (VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry == 0) {
-      return EFI_OUT_OF_RESOURCES;
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+    VtdUnitInfo = &VTdInfo->VtdUnitInfo[Index];
+    if (VtdUnitInfo->Done) {
+      continue;
     }
 
-    Status =SetSecondLevelPagingAttribute (&VTdInfo->VtdUnitInfo[VtdIndex], (VTD_SECOND_LEVEL_PAGING_ENTRY*)(UINTN)VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry, MemoryBase, MemoryLimit + 1 - MemoryBase, IoMmuAccess);
-    if (EFI_ERROR (Status)) {
-      return Status;
-    }
-  }
+    if (VtdUnitInfo->RmrrSecondLevelPagingEntry == 0) {
+      DEBUG ((DEBUG_INFO, "CreateSecondLevelPagingEntry - %d\n", Index));
+      VtdUnitInfo->RmrrSecondLevelPagingEntry = (UINTN) CreateSecondLevelPagingEntryTable (VtdUnitInfo, NULL, 0, SIZE_4GB, 0);
+      if (VtdUnitInfo->RmrrSecondLevelPagingEntry == 0) {
+        return EFI_OUT_OF_RESOURCES;
+      }
 
-  SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].RmrrSecondLevelPagingEntry;
-  Pt = (UINT64) RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
-  if (ExtContextEntry != NULL) {
-    ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
-    ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);
-    ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);
-    ExtContextEntry->Bits.Present = 1;
-    FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ExtContextEntry, sizeof(*ExtContextEntry));
-  } else if (ContextEntry != NULL) {
-    ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
-    ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64 (Pt, 20);
-    ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VTdInfo->VtdUnitInfo[VtdIndex].CapReg.Bits.ND * 2 + 4)) - 1);
-    ContextEntry->Bits.Present = 1;
-    FlushPageTableMemory (&VTdInfo->VtdUnitInfo[VtdIndex], (UINTN) ContextEntry, sizeof (*ContextEntry));
+      Status = SetSecondLevelPagingAttribute (VtdUnitInfo, (VTD_SECOND_LEVEL_PAGING_ENTRY*) VtdUnitInfo->RmrrSecondLevelPagingEntry, MemoryBase, MemoryLimit + 1 - MemoryBase, IoMmuAccess);
+      if (EFI_ERROR (Status)) {
+        return Status;
+      }
+    }
+    SecondLevelPagingEntry = (VTD_SECOND_LEVEL_PAGING_ENTRY *) VtdUnitInfo->RmrrSecondLevelPagingEntry;
+    ExtContextEntry = (VTD_EXT_CONTEXT_ENTRY *) VtdUnitInfo->ExtRootEntryTable;
+    ContextEntry = (VTD_CONTEXT_ENTRY *) VtdUnitInfo->RootEntryTable;
+    Pt = (UINT64) RShiftU64 ((UINT64) (UINTN) SecondLevelPagingEntry, 12);
+    if (ExtContextEntry != NULL) {
+      ExtContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
+      ExtContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64(Pt, 20);
+      ExtContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1);
+      ExtContextEntry->Bits.Present = 1;
+      FlushPageTableMemory (VtdUnitInfo, (UINTN) ExtContextEntry, sizeof (*ExtContextEntry));
+    } else if (ContextEntry != NULL) {
+      ContextEntry->Bits.SecondLevelPageTranslationPointerLo = (UINT32) Pt;
+      ContextEntry->Bits.SecondLevelPageTranslationPointerHi = (UINT32) RShiftU64 (Pt, 20);
+      ContextEntry->Bits.DomainIdentifier = ((1 << (UINT8) ((UINTN) VtdUnitInfo->CapReg.Bits.ND * 2 + 4)) - 1);
+      ContextEntry->Bits.Present = 1;
+      FlushPageTableMemory (VtdUnitInfo, (UINTN) ContextEntry, sizeof (*ContextEntry));
+    }
   }
 
   return EFI_SUCCESS;
-- 
2.16.2.windows.1


      parent reply	other threads:[~2021-12-14  5:35 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-12-14  5:35 [PATCH v3 0/4] There are 4 patches for VTd drivers Sheng Wei
2021-12-14  5:35 ` [PATCH v3 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
2021-12-14  5:35 ` [PATCH v3 2/4] IntelSiliconPkg/VTd: Update VTd register structs Sheng Wei
2021-12-14  5:35 ` [PATCH v3 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
2021-12-14  5:35 ` Sheng Wei [this message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20211214053538.2828-5-w.sheng@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox