public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v5 0/4] There are 4 patches for VTd drivers
@ 2022-01-18  8:14 Sheng Wei
  2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
                   ` (4 more replies)
  0 siblings, 5 replies; 12+ messages in thread
From: Sheng Wei @ 2022-01-18  8:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski

[PATCH 1/4] IntelSiliconPkg/VTd: Fix typos
[PATCH 2/4] IntelSiliconPkg/VTd: Update VTd register structs
[PATCH 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode
[PATCH 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.

Patch v2 update:
Fix build error in [PATCH 2/4] and [PATCH 4/4]

Patch v3 update:
Refine code for PEI 64 bit build compatible.
Change the condition for using Register-based Invalidation.

Patch v4 update:
[PATCH 4/4] Remove unused code.
[PATCH 4/4] Refine comments and vriable name.
[PATCH 4/4] Add empty pointer check.

Patch v5 update:
[PATCH 2/4] Add debug log

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>

Sheng Wei (4):
  IntelSiliconPkg/VTd: Fix typos
  IntelSiliconPkg/VTd: Update VTd register structs
  IntelSiliconPkg/VTd: Support VTd Abort DMA Mode
  IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.

 .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 545 +--------------------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 429 +++++++---------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 474 ++++++++++--------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 119 ++---
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 215 ++------
 .../Feature/VTd/IntelVTdDxe/DmarAcpiTable.c        |  12 +-
 .../Feature/VTd/IntelVTdDxe/TranslationTable.c     |  22 +-
 .../Feature/VTd/IntelVTdDxe/VtdReg.c               |   7 +-
 .../Feature/VTd/IntelVTdPmrPei/DmarTable.c         |   6 +-
 .../IntelSiliconPkg/Include/IndustryStandard/Vtd.h |  34 +-
 10 files changed, 609 insertions(+), 1254 deletions(-)

-- 
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos
  2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
@ 2022-01-18  8:14 ` Sheng Wei
  2022-01-18  8:31   ` Huang, Jenny
  2022-01-19  8:26   ` Kowalewski, Robert
  2022-01-18  8:14 ` [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs Sheng Wei
                   ` (3 subsequent siblings)
  4 siblings, 2 replies; 12+ messages in thread
From: Sheng Wei @ 2022-01-18  8:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski

It is DRHD(DMA Remapping Hardware Unit Definition).

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c  | 12 ++++++------
 .../IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c  | 12 ++++++------
 .../IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c   |  6 +++---
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index 2154690d..e9c99d0a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
@@ -539,14 +539,14 @@ RegisterPciDevice (
 }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdUnitInfo       The VTd engine unit information.
   @param[in]  DmarDrhd          The DRHD table.
 
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_UNIT_INFO              *VTdUnitInfo,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -581,10 +581,10 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
   } else {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
@@ -600,7 +600,7 @@ ProcessDhrd (
       return;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
       case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint"));
@@ -708,7 +708,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
       VtdIndex++;
 
       break;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
index 1ee290b7..75fbd53e 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
@@ -662,7 +662,7 @@ GetPciBusDeviceFunction (
 }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
@@ -670,7 +670,7 @@ GetPciBusDeviceFunction (
   @retval EFI_SUCCESS The DRHD table is processed.
 **/
 EFI_STATUS
-ProcessDhrd (
+ProcessDrhd (
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -690,7 +690,7 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
 
     Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice);
     if (EFI_ERROR (Status)) {
@@ -698,7 +698,7 @@ ProcessDhrd (
     }
   } else {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
@@ -709,7 +709,7 @@ ProcessDhrd (
       return Status;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
     case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint"));
@@ -877,7 +877,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < mVtdUnitNumber);
-      Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      Status = ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
       if (EFI_ERROR (Status)) {
         return Status;
       }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
index d920d136..1bb74f40 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
@@ -356,14 +356,14 @@ GetVtdEngineNumber (
 }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdInfo   The VTd engine context information.
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_INFO                   *VTdInfo,
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
@@ -415,7 +415,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      ProcessDrhd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
       VtdIndex++;
 
       break;
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs
  2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
  2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
@ 2022-01-18  8:14 ` Sheng Wei
  2022-01-21  8:24   ` Huang, Jenny
  2022-01-18  8:14 ` [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 12+ messages in thread
From: Sheng Wei @ 2022-01-18  8:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski

Update VTd register structs accroding to VTd spec ver 3.3

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     |  3 +-
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 23 +++++++++++----
 .../Feature/VTd/IntelVTdDxe/TranslationTable.c     | 22 ++++++++++++--
 .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  7 +++--
 .../IntelSiliconPkg/Include/IndustryStandard/Vtd.h | 34 +++++++++++++++++-----
 5 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index c3a939c9..87ce9716 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -631,10 +631,8 @@ DumpVtdECapRegs (
   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, "    ECS    - 0x%x\n", ECapReg->Bits.ECS));
   DEBUG ((DEBUG_INFO, "    MTS    - 0x%x\n", ECapReg->Bits.MTS));
   DEBUG ((DEBUG_INFO, "    NEST   - 0x%x\n", ECapReg->Bits.NEST));
-  DEBUG ((DEBUG_INFO, "    DIS    - 0x%x\n", ECapReg->Bits.DIS));
   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));
@@ -642,6 +640,7 @@ DumpVtdECapRegs (
   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));
 }
 
 
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
index 6676b2a9..a309d566 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
@@ -884,13 +884,26 @@ SetupTranslationTable (
       return Status;
     }
 
-    if (VtdUnitInfo->ECapReg.Bits.ECS) {
-      DEBUG ((DEBUG_INFO, "CreateExtContextEntry - %d\n", Index));
-      Status = CreateExtContextEntry (VtdUnitInfo);
+    if (VtdUnitInfo->ECapReg.Bits.SMTS) {
+      if (VtdUnitInfo->ECapReg.Bits.DEP_24) {
+        DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));
+        ASSERT(FALSE);
+        Status = EFI_UNSUPPORTED;
+      } else {
+        Status = CreateExtContextEntry (VtdUnitInfo);
+      }
     } else {
-      DEBUG ((DEBUG_INFO, "CreateContextEntry - %d\n", Index));
-      Status = CreateContextEntry (VtdUnitInfo);
+      if (VtdUnitInfo->ECapReg.Bits.DEP_24) {
+        //
+        // To compatible with pervious VTd engine
+        // It was ECS(Extended Context Support) bit.
+        //
+        Status = CreateExtContextEntry (VtdUnitInfo);
+      } else {
+        Status = CreateContextEntry (VtdUnitInfo);
+      }
     }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
index ca5f65a8..48e38d56 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
@@ -382,11 +382,27 @@ SetupTranslationTable (
 
   for (Index = 0; Index < mVtdUnitNumber; Index++) {
     DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));
-    if (mVtdUnitInformation[Index].ECapReg.Bits.ECS) {
-      Status = CreateExtContextEntry (Index);
+
+    if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {
+      if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {
+        DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));
+        ASSERT(FALSE);
+        Status = EFI_UNSUPPORTED;
+      } else {
+        Status = CreateExtContextEntry (Index);
+      }
     } else {
-      Status = CreateContextEntry (Index);
+      if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {
+        //
+        // To compatible with pervious VTd engine
+        // It was ECS(Extended Context Support) bit.
+        //
+        Status = CreateExtContextEntry (Index);
+      } else {
+        Status = CreateContextEntry (Index);
+      }
     }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 1ce9c1c0..1aacd39a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -698,10 +698,8 @@ DumpVtdECapRegs (
   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, "    ECS    - 0x%x\n", ECapReg->Bits.ECS));
   DEBUG((DEBUG_INFO, "    MTS    - 0x%x\n", ECapReg->Bits.MTS));
   DEBUG((DEBUG_INFO, "    NEST   - 0x%x\n", ECapReg->Bits.NEST));
-  DEBUG((DEBUG_INFO, "    DIS    - 0x%x\n", ECapReg->Bits.DIS));
   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));
@@ -709,6 +707,8 @@ DumpVtdECapRegs (
   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, "    SMTS   - 0x%x\n", ECapReg->Bits.SMTS));
+  DEBUG((DEBUG_INFO, "    ADMS   - 0x%x\n", ECapReg->Bits.ADMS));
 }
 
 /**
@@ -769,9 +769,10 @@ DumpVtdRegs (
     DEBUG((DEBUG_INFO, "  FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));
     if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) {
       DEBUG((DEBUG_INFO, "    Fault Info - 0x%016lx\n", VTD_64BITS_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));
+      DEBUG((DEBUG_INFO, "    Fault Bit - %d\n", FrcdReg.Bits.F));
       SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID;
       DEBUG((DEBUG_INFO, "    Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-      DEBUG((DEBUG_INFO, "    Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write"));
+      DEBUG((DEBUG_INFO, "    Type - 0x%02x\n", (FrcdReg.Bits.T1 << 1) | FrcdReg.Bits.T2));
       DEBUG((DEBUG_INFO, "    Reason - %x (Refer to VTd Spec, Appendix A)\n", FrcdReg.Bits.FR));
     }
   }
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index a759ca10..32fbdd02 100644
--- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -216,6 +216,7 @@ typedef union {
 #define   B_GSTS_REG_RTPS      BIT30
 #define   B_GSTS_REG_TE        BIT31
 #define R_RTADDR_REG     0x20
+#define   V_RTADDR_REG_TTM_ADM    (BIT11|BIT10)
 #define R_CCMD_REG       0x28
 #define   B_CCMD_REG_CIRG_MASK    (BIT62|BIT61)
 #define   V_CCMD_REG_CIRG_GLOBAL  BIT61
@@ -334,7 +335,10 @@ typedef union {
     UINT8         FL1GP:1; // First Level 1-GByte Page Support
     UINT8         Rsvd_57:2;
     UINT8         PI:1; // Posted Interrupts Support
-    UINT8         Rsvd_60:4;
+    UINT8         FL5LP:1; // First Level 5-level Paging Support
+    UINT8         Rsvd_61:1;
+    UINT8         ESIRTPS:1; // Enhanced Set Interrupt Remap Table Pointer Support
+    UINT8         ESRTPS:1; // Enhanced Set Root Table Pointer Support
   } Bits;
   UINT64     Uint64;
 } VTD_CAP_REG;
@@ -346,7 +350,7 @@ typedef union {
     UINT8         DT:1; // Device-TLB support
     UINT8         IR:1; // Interrupt Remapping support
     UINT8         EIM:1; // Extended Interrupt Mode
-    UINT8         Rsvd_5:1;
+    UINT8         DEP_5:1;
     UINT8         PT:1; // Pass Through
     UINT8         SC:1; // Snoop Control
 
@@ -354,11 +358,11 @@ typedef union {
     UINT16        Rsvd_18:2;
     UINT16        MHMV:4; // Maximum Handle Mask Value
 
-    UINT8         ECS:1; // Extended Context Support
+    UINT8         DEP_24:1;
     UINT8         MTS:1; // Memory Type Support
     UINT8         NEST:1; // Nested Translation Support
-    UINT8         DIS:1; // Deferred Invalidate Support
-    UINT8         PASID:1; // Process Address Space ID Support
+    UINT8         Rsvd_27:1;
+    UINT8         DEP_28:1;
     UINT8         PRS:1; // Page Request Support
     UINT8         ERS:1; // Execute Request Support
     UINT8         SRS:1; // Supervisor Request Support
@@ -367,7 +371,20 @@ typedef union {
     UINT32        NWFS:1; // No Write Flag Support
     UINT32        EAFS:1; // Extended Accessed Flag Support
     UINT32        PSS:5; // PASID Size Supported
-    UINT32        Rsvd_40:24;
+    UINT32        PASID:1; // Process Address Space ID Support
+    UINT32        DIT:1; // Device-TLB Invalidation Throttle
+    UINT32        PDS:1; // Page-request Drain Support
+    UINT32        SMTS:1; // Scalable Mode Translation Support
+    UINT32        VCS:1; // Virtual Command Support
+    UINT32        SLADS:1; // Second-Level Accessed Dirty Support
+    UINT32        SLTS:1; // Second-level Translation Support
+    UINT32        FLTS:1; // First-level Translation Support
+    UINT32        SMPWCS:1; // Scalable-Mode Page-walk Coherency Support
+    UINT32        RPS:1; // RID-PASID Support
+    UINT32        Rsvd_50:2;
+    UINT32        ADMS:1; // Abort DMA Mode Support
+    UINT32        RPRIVS:1; // RID_PRIV Support
+    UINT32        Rsvd_54:10;
   } Bits;
   UINT64     Uint64;
 } VTD_ECAP_REG;
@@ -379,7 +396,8 @@ typedef union {
     UINT32   FIHi:32;      // FaultInfo
 
     UINT32   SID:16;       // Source Identifier
-    UINT32   Rsvd_80:13;
+    UINT32   Rsvd_80:12;
+    UINT32   T2:1;         // Type bit2 (0: Write/Read, 1: Page/AtomicOp)
     UINT32   PRIV:1;       // Privilege Mode Requested
     UINT32   EXE:1;        // Execute Permission Requested
     UINT32   PP:1;         // PASID Present
@@ -387,7 +405,7 @@ typedef union {
     UINT32   FR:8;         // Fault Reason
     UINT32   PV:20;        // PASID Value
     UINT32   AT:2;         // Address Type
-    UINT32   T:1;          // Type (0: Write, 1: Read)
+    UINT32   T1:1;         // Type bit1 (0: Write/Page, 1: Read/AtomicOp)
     UINT32   F:1;          // Fault
   } Bits;
   UINT64     Uint64[2];
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode
  2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
  2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
  2022-01-18  8:14 ` [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs Sheng Wei
@ 2022-01-18  8:14 ` Sheng Wei
  2022-01-21  8:51   ` Huang, Jenny
  2022-01-18  8:14 ` [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once Sheng Wei
  2022-01-18  8:30 ` [PATCH v5 0/4] There are 4 patches for VTd drivers Huang, Jenny
  4 siblings, 1 reply; 12+ messages in thread
From: Sheng Wei @ 2022-01-18  8:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski

If VTd ECAP_REG.ADMS bit is set, abort DMA mode is supported.
When VTd Abort DMA Mode is enabled, hardware will abort all DMA
 operations without the need to set up a root-table with each
 entry marked as not-present.

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 43 +++++++++++++---------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 87ce9716..63397a1a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -384,7 +384,7 @@ InvalidateIOTLB (
   Enable DMAR translation inpre-mem phase.
 
   @param[in]  VtdUnitBaseAddress  The base address of the VTd engine.
-  @param[in]  RootEntryTable      The address of the VTd RootEntryTable.
+  @param[in]  RtaddrRegValue      The value of RTADDR_REG.
 
   @retval EFI_SUCCESS             DMAR translation is enabled.
   @retval EFI_DEVICE_ERROR        DMAR translation is not enabled.
@@ -392,15 +392,15 @@ InvalidateIOTLB (
 EFI_STATUS
 EnableDmarPreMem (
   IN UINTN                        VtdUnitBaseAddress,
-  IN UINTN                        RootEntryTable
+  IN UINTN                        RtaddrRegValue
   )
 {
   UINT32                          Reg32;
 
   DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress));
 
-  DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
-  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+  DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue));
+  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RtaddrRegValue);
 
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
@@ -662,18 +662,6 @@ EnableVTdTranslationProtectionAll (
 
   DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask));
 
-  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;
-  }
-
   for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
     if ((EngineMask & LShiftU64(1, Index)) == 0) {
       continue;
@@ -686,7 +674,28 @@ EnableVTdTranslationProtectionAll (
     VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG);
     DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg);
 
-    EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable);
+    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);
+    }
   }
 
   return;
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
  2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
                   ` (2 preceding siblings ...)
  2022-01-18  8:14 ` [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
@ 2022-01-18  8:14 ` Sheng Wei
  2022-01-21  8:35   ` Huang, Jenny
  2022-01-18  8:30 ` [PATCH v5 0/4] There are 4 patches for VTd drivers Huang, Jenny
  4 siblings, 1 reply; 12+ messages in thread
From: Sheng Wei @ 2022-01-18  8:14 UTC (permalink / raw)
  To: devel; +Cc: Ray Ni, Rangasai V Chaganty, Jenny Huang, Robert Kowalewski

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 545 +--------------------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 433 +++++++---------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 474 ++++++++++--------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 119 ++---
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
 5 files changed, 533 insertions(+), 1234 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index e9c99d0a..acfbc4a8 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
 
 **/
@@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
   return;
 }
 
-/**
-  Dump DMAR RMRR table.
-
-  @param[in]  Rmrr              DMAR RMRR table
-**/
-VOID
-DumpDmarRmrr (
-  IN EFI_ACPI_DMAR_RMRR_HEADER  *Rmrr
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry;
-  INTN                                            RmrrLen;
-
-  if (Rmrr == NULL) {
-    return;
-  }
-
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    "  *       Reserved Memory Region Reporting Structure                        *\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    (sizeof (UINTN) == sizeof (UINT64)) ?
-    "  RMRR address ........................................... 0x%016lx\n" :
-    "  RMRR address ........................................... 0x%08x\n",
-    Rmrr
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Type ................................................. 0x%04x\n",
-    Rmrr->Header.Type
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Length ............................................... 0x%04x\n",
-    Rmrr->Header.Length
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Segment Number ....................................... 0x%04x\n",
-    Rmrr->SegmentNumber
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
-    Rmrr->ReservedMemoryRegionBaseAddress
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
-    Rmrr->ReservedMemoryRegionLimitAddress
-    ));
-
-  RmrrLen  = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
-  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
-  while (RmrrLen > 0) {
-    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
-    RmrrLen -= DmarDeviceScopeEntry->Length;
-    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
-  }
-
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n\n"
-    ));
-
-  return;
-}
-
 /**
   Dump DMAR DRHD table.
 
@@ -312,9 +245,6 @@ DumpAcpiDMAR (
     case EFI_ACPI_DMAR_TYPE_DRHD:
       DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
       break;
-    case EFI_ACPI_DMAR_TYPE_RMRR:
-      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
-      break;
     default:
       break;
     }
@@ -329,492 +259,43 @@ DumpAcpiDMAR (
   return;
 }
 
-/**
-  Get VTd engine number.
-
-  @param[in]  AcpiDmarTable     DMAR ACPI table
-
-  @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
-  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
-  )
-{
-  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
-  UINTN                                 VtdIndex;
-
-  VtdIndex = 0;
-  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1));
-  while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) {
-    switch (DmarHeader->Type) {
-    case EFI_ACPI_DMAR_TYPE_DRHD:
-      VtdIndex++;
-      break;
-    default:
-      break;
-    }
-    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
-  }
-  return VtdIndex ;
-}
-
-/**
-  Get PCI device information from DMAR DevScopeEntry.
-
-  @param[in]  Segment           The segment number.
-  @param[in]  DmarDevScopeEntry DMAR DevScopeEntry
-  @param[out] Bus               The bus number.
-  @param[out] Device            The device number.
-  @param[out] Function          The function number.
-
-  @retval EFI_SUCCESS  The PCI device information is returned.
-**/
-EFI_STATUS
-GetPciBusDeviceFunction (
-  IN  UINT16                                      Segment,
-  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,
-  OUT UINT8                                       *Bus,
-  OUT UINT8                                       *Device,
-  OUT UINT8                                       *Function
-  )
-{
-  EFI_ACPI_DMAR_PCI_PATH                          *DmarPciPath;
-  UINT8                                           MyBus;
-  UINT8                                           MyDevice;
-  UINT8                                           MyFunction;
-
-  DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN) (DmarDevScopeEntry + 1));
-  MyBus = DmarDevScopeEntry->StartBusNumber;
-  MyDevice = DmarPciPath->Device;
-  MyFunction = DmarPciPath->Function;
-
-  switch (DmarDevScopeEntry->Type) {
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
-    while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) < (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
-      MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
-      DmarPciPath ++;
-      MyDevice = DmarPciPath->Device;
-      MyFunction = DmarPciPath->Function;
-    }
-    break;
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
-    break;
-  }
-
-  *Bus = MyBus;
-  *Device = MyDevice;
-  *Function = MyFunction;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  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.
-
-  @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.
-
-  @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.
-
-**/
-EFI_STATUS
-RegisterPciDevice (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT8                      DeviceType,
-  IN BOOLEAN                    CheckExist
-  )
-{
-  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"));
-
-    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;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Process DMAR DRHD table.
-
-  @param[in]  VTdUnitInfo       The VTd engine unit information.
-  @param[in]  DmarDrhd          The DRHD table.
-
-**/
-VOID
-ProcessDrhd (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
-  UINT8                                           Bus;
-  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"));
-  }
-
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
-
-  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1));
-  while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) {
-
-    Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
-    if (EFI_ERROR (Status)) {
-      return;
-    }
-
-    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;
-    }
-    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);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
-    }
-
-    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
-    ));
-
-  PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
-
-  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
-      ));
-  }
-}
-
 /**
   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.
 
 **/
 EFI_STATUS
 ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   )
 {
   EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
-  UINTN                                 VtdUnitNumber;
-  UINTN                                 VtdIndex;
-  VTD_INFO                              *VTdInfo;
-
-  VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
-  if (VtdUnitNumber == 0) {
-    return EFI_UNSUPPORTED;
-  }
-
-  VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) + (VtdUnitNumber - 1) * sizeof (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;
+  UINT32                                VtdIndex;
 
   VtdIndex = 0;
   DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1));
+
   while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) {
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
-      ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      if (Callback != NULL) {
+        Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      }
       VtdIndex++;
-
       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;
-}
-
-
-/**
-  Process DMAR RMRR table.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  DmarRmrr          The RMRR table.
-
-**/
-VOID
-ProcessRmrr (
-  IN VTD_INFO                                     *VTdInfo,
-  IN EFI_ACPI_DMAR_RMRR_HEADER                    *DmarRmrr
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
-  UINT8                                           Bus;
-  UINT8                                           Device;
-  UINT8                                           Function;
-  EFI_STATUS                                      Status;
-  VTD_SOURCE_ID                                   SourceId;
-
-  DEBUG ((DEBUG_INFO,"  PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
-  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
-      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
-    return ;
-  }
-
-  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1));
-  while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) {
-    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;
-    }
-
-    Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    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));
-    }
-
-    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
-  }
-}
-
-/**
-  Parse DMAR DRHD table.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-
-**/
-VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                           *VTdInfo
-  )
-{
-  EFI_ACPI_DMAR_HEADER                  *AcpiDmarTable;
-  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
 
-  AcpiDmarTable = (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);
-      break;
-    default:
-      break;
-    }
-    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
-  }
+  return VtdIndex;
 }
 
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 63397a1a..0ed216bb 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..ac91eac3 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,114 @@ 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;
 
-    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;
+  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.
+
+  @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);
 }
 
 /**
-  Initializes the Intel VTd Info.
+  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 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 +481,103 @@ InitVTdInfo (
   VOID
   )
 {
-  EFI_STATUS                    Status;
-  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
-  VOID                          *Hob;
   VTD_INFO                      *VTdInfo;
-  UINT64                        EngineMask;
+  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
+  UINTN                         VtdUnitNumber;
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+  EFI_STATUS                    Status;
+  UINTN                         NewUnitIndex;
+  UINTN                         PreviousUnitIndex;
 
-  Status = PeiServicesLocatePpi (
-             &gEdkiiVTdInfoPpiGuid,
-             0,
-             NULL,
-             (VOID **)&AcpiDmarTable
-             );
-  ASSERT_EFI_ERROR (Status);
+  VTdInfo = GetVTdInfoHob ();
+  ASSERT (VTdInfo != NULL);
 
-  DumpAcpiDMAR (AcpiDmarTable);
+  AcpiDmarTable = GetAcpiDmarTable ();
+  ASSERT (AcpiDmarTable != NULL);
 
   //
-  // Clear old VTdInfo Hob.
+  // Get VTd Unit Number
   //
-  Hob = GetFirstGuidHob (&mVTdInfoGuid);
-  if (Hob != NULL) {
-    DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
-
-    VTdInfo = GET_GUID_HOB_DATA(Hob);
-    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
-    EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
-
-    ReleaseVTdInfo (VTdInfo);
-    VTdInfo->VTdEngineCount = 0;
+  VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
+  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
 
-    ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
+  //
+  // Genrate a new Vtd Unit Info Table
+  //
+  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
+  // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
   //
-  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) {
+    //
+    // New Vtd Unit Info Table Loop
+    //
+    for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber; NewUnitIndex++) {
+      //
+      // Previous Vtd Unit Info Table Loop
+      //
+      for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo->VTdEngineCount; PreviousUnitIndex++) {
+        //
+        // Compare the new Vtd Unit with the previous VTd Unit
+        //
+        if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
+          DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n", VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
+          CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo->VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
+          VtdUnitInfo[NewUnitIndex].Done = TRUE;
+
+          break;
+        }
+      }
+    }
+  }
+  VTdInfo->AcpiDmarTable = AcpiDmarTable;
+  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+  VTdInfo->VTdEngineCount = VtdUnitNumber;
+  VTdInfo->VtdUnitInfo = VtdUnitInfo;
 
   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;
+  EFI_ACPI_DMAR_HEADER      *AcpiDmarTable;
 
-  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;
-  }
-
-  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 +600,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 +611,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 +621,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 +671,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 +687,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);
@@ -619,10 +695,6 @@ InitVTdDmarForDma (
     return Status;
   }
 
-  // If there is RMRR memory, parse it here.
-  DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
-  ParseDmarAcpiTableRmrr (VTdInfo);
-
   DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
   Status = EnableVTdTranslationProtection(VTdInfo);
   if (EFI_ERROR (Status)) {
@@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
     //
 
     Status = InitDmaBuffer ();
-    ASSERT_EFI_ERROR(Status);
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // NOTE: We need reinit VTdInfo because previous information might be overriden.
+    //
+    Status = InitVTdInfo ();
+    ASSERT_EFI_ERROR (Status);
 
-    InitVTdDmarForDma ();
+    Status = InitVTdDmarForDma ();
+    ASSERT_EFI_ERROR (Status);
   }
 
   return EFI_SUCCESS;
@@ -826,4 +889,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..351a7810 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -9,68 +9,61 @@
 #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;
-
-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;
 } 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_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 +83,27 @@ 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.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
-  );
-
-/**
-  Parse DMAR DRHD table.
+  @return the VTd engine number.
 
-  @param[in]  VTdInfo           The VTd engine context information.
 **/
-VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                   *VTdInfo
+UINTN
+ParseDmarAcpiTableDrhd (
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   );
 
 /**
@@ -214,30 +200,7 @@ GetPciDataIndex (
   IN VTD_SOURCE_ID              SourceId
   );
 
-/**
-  Always enable the VTd page attribute for the device.
-
-  @param[in]  VTdInfo           The VTd engine context 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.
-  @param[in]  MemoryBase        The base of the memory.
-  @param[in]  MemoryLimit       The limit of the memory.
-  @param[in]  IoMmuAccess       The IOMMU access.
-
-  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT64                     MemoryBase,
-  IN UINT64                     MemoryLimit,
-  IN UINT64                     IoMmuAccess
-  );
-
 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..c94f4a85 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);
 
@@ -304,7 +309,7 @@ CreateContextEntry (
     RootEntry->Bits.ContextTablePointerHi  = (UINT32) RShiftU64 ((UINT64) (UINTN) Buffer, 32);
     RootEntry->Bits.Present = 1;
     Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
-    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;
+    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi);
 
     for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
       SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -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);
 
@@ -390,7 +399,7 @@ CreateExtContextEntry (
     ExtRootEntry->Bits.UpperContextTablePointerHi  = (UINT32) RShiftU64 (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
     ExtRootEntry->Bits.UpperPresent = 1;
     Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
-    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ;
+    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi);
 
     for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
       SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -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)) {
@@ -911,151 +923,3 @@ SetupTranslationTable (
   return EFI_SUCCESS;
 }
 
-/**
-  Find the VTd index by the Segment and SourceId.
-
-  @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.
-**/
-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
-  )
-{
-  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;
-
-  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 (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 (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;
-    }
-
-    return VtdIndex;
-  }
-
-  return (UINTN)-1;
-}
-
-/**
-  Always enable the VTd page attribute for the device.
-
-  @param[in]  VTdInfo           The VTd engine context 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.
-  @param[in]  MemoryBase        The base of the memory.
-  @param[in]  MemoryLimit       The limit of the memory.
-  @param[in]  IoMmuAccess       The IOMMU access.
-
-  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT64                     MemoryBase,
-  IN UINT64                     MemoryLimit,
-  IN UINT64                     IoMmuAccess
-  )
-{
-  EFI_STATUS Status;
-  UINTN                         VtdIndex;
-  VTD_EXT_CONTEXT_ENTRY         *ExtContextEntry;
-  VTD_CONTEXT_ENTRY             *ContextEntry;
-  VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
-  UINT64                        Pt;
-
-  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;
-    }
-
-    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;
-    }
-  }
-
-  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));
-  }
-
-  return EFI_SUCCESS;
-}
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 0/4] There are 4 patches for VTd drivers
  2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
                   ` (3 preceding siblings ...)
  2022-01-18  8:14 ` [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once Sheng Wei
@ 2022-01-18  8:30 ` Huang, Jenny
  4 siblings, 0 replies; 12+ messages in thread
From: Huang, Jenny @ 2022-01-18  8:30 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

Reviewed-by: Jenny Huang <jenny.huang@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 4:14 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 0/4] There are 4 patches for VTd drivers

[PATCH 1/4] IntelSiliconPkg/VTd: Fix typos [PATCH 2/4] IntelSiliconPkg/VTd: Update VTd register structs [PATCH 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode [PATCH 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.

Patch v2 update:
Fix build error in [PATCH 2/4] and [PATCH 4/4]

Patch v3 update:
Refine code for PEI 64 bit build compatible.
Change the condition for using Register-based Invalidation.

Patch v4 update:
[PATCH 4/4] Remove unused code.
[PATCH 4/4] Refine comments and vriable name.
[PATCH 4/4] Add empty pointer check.

Patch v5 update:
[PATCH 2/4] Add debug log

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>

Sheng Wei (4):
  IntelSiliconPkg/VTd: Fix typos
  IntelSiliconPkg/VTd: Update VTd register structs
  IntelSiliconPkg/VTd: Support VTd Abort DMA Mode
  IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.

 .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 545 +--------------------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 429 +++++++---------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 474 ++++++++++--------  .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 119 ++---  .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 215 ++------
 .../Feature/VTd/IntelVTdDxe/DmarAcpiTable.c        |  12 +-
 .../Feature/VTd/IntelVTdDxe/TranslationTable.c     |  22 +-
 .../Feature/VTd/IntelVTdDxe/VtdReg.c               |   7 +-
 .../Feature/VTd/IntelVTdPmrPei/DmarTable.c         |   6 +-
 .../IntelSiliconPkg/Include/IndustryStandard/Vtd.h |  34 +-
 10 files changed, 609 insertions(+), 1254 deletions(-)

--
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos
  2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
@ 2022-01-18  8:31   ` Huang, Jenny
  2022-01-19  8:26   ` Kowalewski, Robert
  1 sibling, 0 replies; 12+ messages in thread
From: Huang, Jenny @ 2022-01-18  8:31 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

Reviewed-by: Jenny Huang <jenny.huang@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 4:15 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos

It is DRHD(DMA Remapping Hardware Unit Definition).

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c  | 12 ++++++------  .../IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c  | 12 ++++++------
 .../IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c   |  6 +++---
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index 2154690d..e9c99d0a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTabl
+++ e.c
@@ -539,14 +539,14 @@ RegisterPciDevice (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdUnitInfo       The VTd engine unit information.
   @param[in]  DmarDrhd          The DRHD table.
 
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_UNIT_INFO              *VTdUnitInfo,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -581,10 +581,10 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
   } else {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; @@ -600,7 +600,7 @@ ProcessDhrd (
       return;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
       case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -708,7 +708,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], 
+ (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
       VtdIndex++;
 
       break;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
index 1ee290b7..75fbd53e 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTabl
+++ e.c
@@ -662,7 +662,7 @@ GetPciBusDeviceFunction (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
@@ -670,7 +670,7 @@ GetPciBusDeviceFunction (
   @retval EFI_SUCCESS The DRHD table is processed.
 **/
 EFI_STATUS
-ProcessDhrd (
+ProcessDrhd (
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -690,7 +690,7 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
 
     Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice);
     if (EFI_ERROR (Status)) {
@@ -698,7 +698,7 @@ ProcessDhrd (
     }
   } else {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1)); @@ -709,7 +709,7 @@ ProcessDhrd (
       return Status;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
     case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -877,7 +877,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < mVtdUnitNumber);
-      Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      Status = ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER 
+ *)DmarHeader);
       if (EFI_ERROR (Status)) {
         return Status;
       }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
index d920d136..1bb74f40 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable
+++ .c
@@ -356,14 +356,14 @@ GetVtdEngineNumber (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdInfo   The VTd engine context information.
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_INFO                   *VTdInfo,
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd @@ -415,7 +415,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      ProcessDrhd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER 
+ *)DmarHeader);
       VtdIndex++;
 
       break;
--
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos
  2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
  2022-01-18  8:31   ` Huang, Jenny
@ 2022-01-19  8:26   ` Kowalewski, Robert
  1 sibling, 0 replies; 12+ messages in thread
From: Kowalewski, Robert @ 2022-01-19  8:26 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Huang, Jenny

Reviewed-by: Robert Kowalewski <robert.kowalewski@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 9:15 AM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos

It is DRHD(DMA Remapping Hardware Unit Definition).

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c  | 12 ++++++------  .../IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c  | 12 ++++++------
 .../IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c   |  6 +++---
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index 2154690d..e9c99d0a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTabl
+++ e.c
@@ -539,14 +539,14 @@ RegisterPciDevice (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdUnitInfo       The VTd engine unit information.
   @param[in]  DmarDrhd          The DRHD table.
 
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_UNIT_INFO              *VTdUnitInfo,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -581,10 +581,10 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
   } else {
     VTdUnitInfo->PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0; @@ -600,7 +600,7 @@ ProcessDhrd (
       return;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
       case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -708,7 +708,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], 
+ (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
       VtdIndex++;
 
       break;
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
index 1ee290b7..75fbd53e 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/DmarAcpiTabl
+++ e.c
@@ -662,7 +662,7 @@ GetPciBusDeviceFunction (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
@@ -670,7 +670,7 @@ GetPciBusDeviceFunction (
   @retval EFI_SUCCESS The DRHD table is processed.
 **/
 EFI_STATUS
-ProcessDhrd (
+ProcessDrhd (
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
   )
@@ -690,7 +690,7 @@ ProcessDhrd (
 
   if ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0) {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = TRUE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: with INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: with INCLUDE ALL\n"));
 
     Status = ScanAllPciBus((VOID *)VtdIndex, DmarDrhd->SegmentNumber, ScanBusCallbackRegisterPciDevice);
     if (EFI_ERROR (Status)) {
@@ -698,7 +698,7 @@ ProcessDhrd (
     }
   } else {
     mVtdUnitInformation[VtdIndex].PciDeviceInfo.IncludeAllFlag = FALSE;
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: without INCLUDE ALL\n"));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: without INCLUDE ALL\n"));
   }
 
   DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1)); @@ -709,7 +709,7 @@ ProcessDhrd (
       return Status;
     }
 
-    DEBUG ((DEBUG_INFO,"  ProcessDhrd: "));
+    DEBUG ((DEBUG_INFO,"  ProcessDrhd: "));
     switch (DmarDevScopeEntry->Type) {
     case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
       DEBUG ((DEBUG_INFO,"PCI Endpoint")); @@ -877,7 +877,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < mVtdUnitNumber);
-      Status = ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      Status = ProcessDrhd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER 
+ *)DmarHeader);
       if (EFI_ERROR (Status)) {
         return Status;
       }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
index d920d136..1bb74f40 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable
+++ .c
@@ -356,14 +356,14 @@ GetVtdEngineNumber (  }
 
 /**
-  Process DMAR DHRD table.
+  Process DMAR DRHD table.
 
   @param[in]  VTdInfo   The VTd engine context information.
   @param[in]  VtdIndex  The index of VTd engine.
   @param[in]  DmarDrhd  The DRHD table.
 **/
 VOID
-ProcessDhrd (
+ProcessDrhd (
   IN VTD_INFO                   *VTdInfo,
   IN UINTN                      VtdIndex,
   IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd @@ -415,7 +415,7 @@ ParseDmarAcpiTableDrhd (
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
       ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      ProcessDrhd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER 
+ *)DmarHeader);
       VtdIndex++;
 
       break;
--
2.16.2.windows.1

---------------------------------------------------------------------
Intel Technology Poland sp. z o.o.
ul. Slowackiego 173 | 80-298 Gdansk | Sad Rejonowy Gdansk Polnoc | VII Wydzial Gospodarczy Krajowego Rejestru Sadowego - KRS 101882 | NIP 957-07-52-316 | Kapital zakladowy 200.000 PLN.
Ta wiadomosc wraz z zalacznikami jest przeznaczona dla okreslonego adresata i moze zawierac informacje poufne. W razie przypadkowego otrzymania tej wiadomosci, prosimy o powiadomienie nadawcy oraz trwale jej usuniecie; jakiekolwiek przegladanie lub rozpowszechnianie jest zabronione.
This e-mail and any attachments may contain confidential material for the sole use of the intended recipient(s). If you are not the intended recipient, please contact the sender and delete all copies; any review or distribution by others is strictly prohibited.


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs
  2022-01-18  8:14 ` [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs Sheng Wei
@ 2022-01-21  8:24   ` Huang, Jenny
  0 siblings, 0 replies; 12+ messages in thread
From: Huang, Jenny @ 2022-01-21  8:24 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

Reviewed-by: Jenny Huang <jenny.huang@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 4:15 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs

Update VTd register structs accroding to VTd spec ver 3.3

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     |  3 +-
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 23 +++++++++++----
 .../Feature/VTd/IntelVTdDxe/TranslationTable.c     | 22 ++++++++++++--
 .../Feature/VTd/IntelVTdDxe/VtdReg.c               |  7 +++--
 .../IntelSiliconPkg/Include/IndustryStandard/Vtd.h | 34 +++++++++++++++++-----
 5 files changed, 68 insertions(+), 21 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index c3a939c9..87ce9716 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -631,10 +631,8 @@ DumpVtdECapRegs (
   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, "    ECS    - 0x%x\n", ECapReg->Bits.ECS));
   DEBUG ((DEBUG_INFO, "    MTS    - 0x%x\n", ECapReg->Bits.MTS));
   DEBUG ((DEBUG_INFO, "    NEST   - 0x%x\n", ECapReg->Bits.NEST));
-  DEBUG ((DEBUG_INFO, "    DIS    - 0x%x\n", ECapReg->Bits.DIS));
   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));
@@ -642,6 +640,7 @@ DumpVtdECapRegs (
   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));
 }
 
 
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
index 6676b2a9..a309d566 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTable.c
@@ -884,13 +884,26 @@ SetupTranslationTable (
       return Status;
     }
 
-    if (VtdUnitInfo->ECapReg.Bits.ECS) {
-      DEBUG ((DEBUG_INFO, "CreateExtContextEntry - %d\n", Index));
-      Status = CreateExtContextEntry (VtdUnitInfo);
+    if (VtdUnitInfo->ECapReg.Bits.SMTS) {
+      if (VtdUnitInfo->ECapReg.Bits.DEP_24) {
+        DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));
+        ASSERT(FALSE);
+        Status = EFI_UNSUPPORTED;
+      } else {
+        Status = CreateExtContextEntry (VtdUnitInfo);
+      }
     } else {
-      DEBUG ((DEBUG_INFO, "CreateContextEntry - %d\n", Index));
-      Status = CreateContextEntry (VtdUnitInfo);
+      if (VtdUnitInfo->ECapReg.Bits.DEP_24) {
+        //
+        // To compatible with pervious VTd engine
+        // It was ECS(Extended Context Support) bit.
+        //
+        Status = CreateExtContextEntry (VtdUnitInfo);
+      } else {
+        Status = CreateContextEntry (VtdUnitInfo);
+      }
     }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
index ca5f65a8..48e38d56 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/TranslationTable.c
@@ -382,11 +382,27 @@ SetupTranslationTable (
 
   for (Index = 0; Index < mVtdUnitNumber; Index++) {
     DEBUG((DEBUG_INFO, "CreateContextEntry - %d\n", Index));
-    if (mVtdUnitInformation[Index].ECapReg.Bits.ECS) {
-      Status = CreateExtContextEntry (Index);
+
+    if (mVtdUnitInformation[Index].ECapReg.Bits.SMTS) {
+      if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {
+        DEBUG ((DEBUG_ERROR,"ECapReg.bit24 is not zero\n"));
+        ASSERT(FALSE);
+        Status = EFI_UNSUPPORTED;
+      } else {
+        Status = CreateExtContextEntry (Index);
+      }
     } else {
-      Status = CreateContextEntry (Index);
+      if (mVtdUnitInformation[Index].ECapReg.Bits.DEP_24) {
+        //
+        // To compatible with pervious VTd engine
+        // It was ECS(Extended Context Support) bit.
+        //
+        Status = CreateExtContextEntry (Index);
+      } else {
+        Status = CreateContextEntry (Index);
+      }
     }
+
     if (EFI_ERROR (Status)) {
       return Status;
     }
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index 1ce9c1c0..1aacd39a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -698,10 +698,8 @@ DumpVtdECapRegs (
   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, "    ECS    - 0x%x\n", ECapReg->Bits.ECS));
   DEBUG((DEBUG_INFO, "    MTS    - 0x%x\n", ECapReg->Bits.MTS));
   DEBUG((DEBUG_INFO, "    NEST   - 0x%x\n", ECapReg->Bits.NEST));
-  DEBUG((DEBUG_INFO, "    DIS    - 0x%x\n", ECapReg->Bits.DIS));
   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));
@@ -709,6 +707,8 @@ DumpVtdECapRegs (
   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, "    SMTS   - 0x%x\n", ECapReg->Bits.SMTS));
+  DEBUG((DEBUG_INFO, "    ADMS   - 0x%x\n", ECapReg->Bits.ADMS));
 }
 
 /**
@@ -769,9 +769,10 @@ DumpVtdRegs (
     DEBUG((DEBUG_INFO, "  FRCD_REG[%d] - 0x%016lx %016lx\n", Index, FrcdReg.Uint64[1], FrcdReg.Uint64[0]));
     if (FrcdReg.Uint64[1] != 0 || FrcdReg.Uint64[0] != 0) {
       DEBUG((DEBUG_INFO, "    Fault Info - 0x%016lx\n", VTD_64BITS_ADDRESS(FrcdReg.Bits.FILo, FrcdReg.Bits.FIHi)));
+      DEBUG((DEBUG_INFO, "    Fault Bit - %d\n", FrcdReg.Bits.F));
       SourceId.Uint16 = (UINT16)FrcdReg.Bits.SID;
       DEBUG((DEBUG_INFO, "    Source - B%02x D%02x F%02x\n", SourceId.Bits.Bus, SourceId.Bits.Device, SourceId.Bits.Function));
-      DEBUG((DEBUG_INFO, "    Type - %x (%a)\n", FrcdReg.Bits.T, FrcdReg.Bits.T ? "read" : "write"));
+      DEBUG((DEBUG_INFO, "    Type - 0x%02x\n", (FrcdReg.Bits.T1 << 1) | FrcdReg.Bits.T2));
       DEBUG((DEBUG_INFO, "    Reason - %x (Refer to VTd Spec, Appendix A)\n", FrcdReg.Bits.FR));
     }
   }
diff --git a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index a759ca10..32fbdd02 100644
--- a/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/Silicon/Intel/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -216,6 +216,7 @@ typedef union {
 #define   B_GSTS_REG_RTPS      BIT30
 #define   B_GSTS_REG_TE        BIT31
 #define R_RTADDR_REG     0x20
+#define   V_RTADDR_REG_TTM_ADM    (BIT11|BIT10)
 #define R_CCMD_REG       0x28
 #define   B_CCMD_REG_CIRG_MASK    (BIT62|BIT61)
 #define   V_CCMD_REG_CIRG_GLOBAL  BIT61
@@ -334,7 +335,10 @@ typedef union {
     UINT8         FL1GP:1; // First Level 1-GByte Page Support
     UINT8         Rsvd_57:2;
     UINT8         PI:1; // Posted Interrupts Support
-    UINT8         Rsvd_60:4;
+    UINT8         FL5LP:1; // First Level 5-level Paging Support
+    UINT8         Rsvd_61:1;
+    UINT8         ESIRTPS:1; // Enhanced Set Interrupt Remap Table Pointer Support
+    UINT8         ESRTPS:1; // Enhanced Set Root Table Pointer Support
   } Bits;
   UINT64     Uint64;
 } VTD_CAP_REG;
@@ -346,7 +350,7 @@ typedef union {
     UINT8         DT:1; // Device-TLB support
     UINT8         IR:1; // Interrupt Remapping support
     UINT8         EIM:1; // Extended Interrupt Mode
-    UINT8         Rsvd_5:1;
+    UINT8         DEP_5:1;
     UINT8         PT:1; // Pass Through
     UINT8         SC:1; // Snoop Control
 
@@ -354,11 +358,11 @@ typedef union {
     UINT16        Rsvd_18:2;
     UINT16        MHMV:4; // Maximum Handle Mask Value
 
-    UINT8         ECS:1; // Extended Context Support
+    UINT8         DEP_24:1;
     UINT8         MTS:1; // Memory Type Support
     UINT8         NEST:1; // Nested Translation Support
-    UINT8         DIS:1; // Deferred Invalidate Support
-    UINT8         PASID:1; // Process Address Space ID Support
+    UINT8         Rsvd_27:1;
+    UINT8         DEP_28:1;
     UINT8         PRS:1; // Page Request Support
     UINT8         ERS:1; // Execute Request Support
     UINT8         SRS:1; // Supervisor Request Support
@@ -367,7 +371,20 @@ typedef union {
     UINT32        NWFS:1; // No Write Flag Support
     UINT32        EAFS:1; // Extended Accessed Flag Support
     UINT32        PSS:5; // PASID Size Supported
-    UINT32        Rsvd_40:24;
+    UINT32        PASID:1; // Process Address Space ID Support
+    UINT32        DIT:1; // Device-TLB Invalidation Throttle
+    UINT32        PDS:1; // Page-request Drain Support
+    UINT32        SMTS:1; // Scalable Mode Translation Support
+    UINT32        VCS:1; // Virtual Command Support
+    UINT32        SLADS:1; // Second-Level Accessed Dirty Support
+    UINT32        SLTS:1; // Second-level Translation Support
+    UINT32        FLTS:1; // First-level Translation Support
+    UINT32        SMPWCS:1; // Scalable-Mode Page-walk Coherency Support
+    UINT32        RPS:1; // RID-PASID Support
+    UINT32        Rsvd_50:2;
+    UINT32        ADMS:1; // Abort DMA Mode Support
+    UINT32        RPRIVS:1; // RID_PRIV Support
+    UINT32        Rsvd_54:10;
   } Bits;
   UINT64     Uint64;
 } VTD_ECAP_REG;
@@ -379,7 +396,8 @@ typedef union {
     UINT32   FIHi:32;      // FaultInfo
 
     UINT32   SID:16;       // Source Identifier
-    UINT32   Rsvd_80:13;
+    UINT32   Rsvd_80:12;
+    UINT32   T2:1;         // Type bit2 (0: Write/Read, 1: Page/AtomicOp)
     UINT32   PRIV:1;       // Privilege Mode Requested
     UINT32   EXE:1;        // Execute Permission Requested
     UINT32   PP:1;         // PASID Present
@@ -387,7 +405,7 @@ typedef union {
     UINT32   FR:8;         // Fault Reason
     UINT32   PV:20;        // PASID Value
     UINT32   AT:2;         // Address Type
-    UINT32   T:1;          // Type (0: Write, 1: Read)
+    UINT32   T1:1;         // Type bit1 (0: Write/Page, 1: Read/AtomicOp)
     UINT32   F:1;          // Fault
   } Bits;
   UINT64     Uint64[2];
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
  2022-01-18  8:14 ` [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once Sheng Wei
@ 2022-01-21  8:35   ` Huang, Jenny
  2022-01-24  2:44     ` Sheng Wei
  0 siblings, 1 reply; 12+ messages in thread
From: Huang, Jenny @ 2022-01-21  8:35 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

Reviewed-by: Jenny Huang <jenny.huang@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 4:15 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 545 +--------------------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 433 +++++++---------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 474 ++++++++++--------
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 119 ++---
 .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
 5 files changed, 533 insertions(+), 1234 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
index e9c99d0a..acfbc4a8 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
 
 **/
@@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
   return;
 }
 
-/**
-  Dump DMAR RMRR table.
-
-  @param[in]  Rmrr              DMAR RMRR table
-**/
-VOID
-DumpDmarRmrr (
-  IN EFI_ACPI_DMAR_RMRR_HEADER  *Rmrr
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry;
-  INTN                                            RmrrLen;
-
-  if (Rmrr == NULL) {
-    return;
-  }
-
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    "  *       Reserved Memory Region Reporting Structure                        *\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n"
-    ));
-  DEBUG ((DEBUG_INFO,
-    (sizeof (UINTN) == sizeof (UINT64)) ?
-    "  RMRR address ........................................... 0x%016lx\n" :
-    "  RMRR address ........................................... 0x%08x\n",
-    Rmrr
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Type ................................................. 0x%04x\n",
-    Rmrr->Header.Type
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Length ............................................... 0x%04x\n",
-    Rmrr->Header.Length
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Segment Number ....................................... 0x%04x\n",
-    Rmrr->SegmentNumber
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
-    Rmrr->ReservedMemoryRegionBaseAddress
-    ));
-  DEBUG ((DEBUG_INFO,
-    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
-    Rmrr->ReservedMemoryRegionLimitAddress
-    ));
-
-  RmrrLen  = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
-  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
-  while (RmrrLen > 0) {
-    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
-    RmrrLen -= DmarDeviceScopeEntry->Length;
-    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
-  }
-
-  DEBUG ((DEBUG_INFO,
-    "  ***************************************************************************\n\n"
-    ));
-
-  return;
-}
-
 /**
   Dump DMAR DRHD table.
 
@@ -312,9 +245,6 @@ DumpAcpiDMAR (
     case EFI_ACPI_DMAR_TYPE_DRHD:
       DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
       break;
-    case EFI_ACPI_DMAR_TYPE_RMRR:
-      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
-      break;
     default:
       break;
     }
@@ -329,492 +259,43 @@ DumpAcpiDMAR (
   return;
 }
 
-/**
-  Get VTd engine number.
-
-  @param[in]  AcpiDmarTable     DMAR ACPI table
-
-  @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
-  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
-  )
-{
-  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
-  UINTN                                 VtdIndex;
-
-  VtdIndex = 0;
-  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1));
-  while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) {
-    switch (DmarHeader->Type) {
-    case EFI_ACPI_DMAR_TYPE_DRHD:
-      VtdIndex++;
-      break;
-    default:
-      break;
-    }
-    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
-  }
-  return VtdIndex ;
-}
-
-/**
-  Get PCI device information from DMAR DevScopeEntry.
-
-  @param[in]  Segment           The segment number.
-  @param[in]  DmarDevScopeEntry DMAR DevScopeEntry
-  @param[out] Bus               The bus number.
-  @param[out] Device            The device number.
-  @param[out] Function          The function number.
-
-  @retval EFI_SUCCESS  The PCI device information is returned.
-**/
-EFI_STATUS
-GetPciBusDeviceFunction (
-  IN  UINT16                                      Segment,
-  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry,
-  OUT UINT8                                       *Bus,
-  OUT UINT8                                       *Device,
-  OUT UINT8                                       *Function
-  )
-{
-  EFI_ACPI_DMAR_PCI_PATH                          *DmarPciPath;
-  UINT8                                           MyBus;
-  UINT8                                           MyDevice;
-  UINT8                                           MyFunction;
-
-  DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN) (DmarDevScopeEntry + 1));
-  MyBus = DmarDevScopeEntry->StartBusNumber;
-  MyDevice = DmarPciPath->Device;
-  MyFunction = DmarPciPath->Function;
-
-  switch (DmarDevScopeEntry->Type) {
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
-    while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) < (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
-      MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment, MyBus, MyDevice, MyFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
-      DmarPciPath ++;
-      MyDevice = DmarPciPath->Device;
-      MyFunction = DmarPciPath->Function;
-    }
-    break;
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
-  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
-    break;
-  }
-
-  *Bus = MyBus;
-  *Device = MyDevice;
-  *Function = MyFunction;
-
-  return EFI_SUCCESS;
-}
-
-/**
-  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.
-
-  @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.
-
-  @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.
-
-**/
-EFI_STATUS
-RegisterPciDevice (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT8                      DeviceType,
-  IN BOOLEAN                    CheckExist
-  )
-{
-  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"));
-
-    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;
-    }
-  }
-
-  return EFI_SUCCESS;
-}
-
-/**
-  Process DMAR DRHD table.
-
-  @param[in]  VTdUnitInfo       The VTd engine unit information.
-  @param[in]  DmarDrhd          The DRHD table.
-
-**/
-VOID
-ProcessDrhd (
-  IN VTD_UNIT_INFO              *VTdUnitInfo,
-  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
-  UINT8                                           Bus;
-  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"));
-  }
-
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
-  VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
-
-  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarDrhd + 1));
-  while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd->Header.Length) {
-
-    Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
-    if (EFI_ERROR (Status)) {
-      return;
-    }
-
-    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;
-    }
-    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);
-    if (EFI_ERROR (Status)) {
-      DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
-    }
-
-    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
-    ));
-
-  PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo->VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
-
-  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
-      ));
-  }
-}
-
 /**
   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.
 
 **/
 EFI_STATUS
 ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   )
 {
   EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
-  UINTN                                 VtdUnitNumber;
-  UINTN                                 VtdIndex;
-  VTD_INFO                              *VTdInfo;
-
-  VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
-  if (VtdUnitNumber == 0) {
-    return EFI_UNSUPPORTED;
-  }
-
-  VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) + (VtdUnitNumber - 1) * sizeof (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;
+  UINT32                                VtdIndex;
 
   VtdIndex = 0;
   DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) (AcpiDmarTable + 1));
+
   while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable->Header.Length) {
     switch (DmarHeader->Type) {
     case EFI_ACPI_DMAR_TYPE_DRHD:
-      ASSERT (VtdIndex < VtdUnitNumber);
-      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex], (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      if (Callback != NULL) {
+        Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
+      }
       VtdIndex++;
-
       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;
-}
-
-
-/**
-  Process DMAR RMRR table.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-  @param[in]  DmarRmrr          The RMRR table.
-
-**/
-VOID
-ProcessRmrr (
-  IN VTD_INFO                                     *VTdInfo,
-  IN EFI_ACPI_DMAR_RMRR_HEADER                    *DmarRmrr
-  )
-{
-  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDevScopeEntry;
-  UINT8                                           Bus;
-  UINT8                                           Device;
-  UINT8                                           Function;
-  EFI_STATUS                                      Status;
-  VTD_SOURCE_ID                                   SourceId;
-
-  DEBUG ((DEBUG_INFO,"  PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
-  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
-      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
-    return ;
-  }
-
-  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) (DmarRmrr + 1));
-  while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr->Header.Length) {
-    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;
-    }
-
-    Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber, DmarDevScopeEntry, &Bus, &Device, &Function);
-    if (EFI_ERROR (Status)) {
-      continue;
-    }
-
-    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));
-    }
-
-    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length);
-  }
-}
-
-/**
-  Parse DMAR DRHD table.
-
-  @param[in]  VTdInfo           The VTd engine context information.
-
-**/
-VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                           *VTdInfo
-  )
-{
-  EFI_ACPI_DMAR_HEADER                  *AcpiDmarTable;
-  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
 
-  AcpiDmarTable = (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);
-      break;
-    default:
-      break;
-    }
-    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN) DmarHeader + DmarHeader->Length);
-  }
+  return VtdIndex;
 }
 
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 63397a1a..0ed216bb 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..ac91eac3 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,114 @@ 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;
 
-    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;
+  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.
+
+  @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);
 }
 
 /**
-  Initializes the Intel VTd Info.
+  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 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 +481,103 @@ InitVTdInfo (
   VOID
   )
 {
-  EFI_STATUS                    Status;
-  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
-  VOID                          *Hob;
   VTD_INFO                      *VTdInfo;
-  UINT64                        EngineMask;
+  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
+  UINTN                         VtdUnitNumber;
+  VTD_UNIT_INFO                 *VtdUnitInfo;
+  EFI_STATUS                    Status;
+  UINTN                         NewUnitIndex;
+  UINTN                         PreviousUnitIndex;
 
-  Status = PeiServicesLocatePpi (
-             &gEdkiiVTdInfoPpiGuid,
-             0,
-             NULL,
-             (VOID **)&AcpiDmarTable
-             );
-  ASSERT_EFI_ERROR (Status);
+  VTdInfo = GetVTdInfoHob ();
+  ASSERT (VTdInfo != NULL);
 
-  DumpAcpiDMAR (AcpiDmarTable);
+  AcpiDmarTable = GetAcpiDmarTable ();
+  ASSERT (AcpiDmarTable != NULL);
 
   //
-  // Clear old VTdInfo Hob.
+  // Get VTd Unit Number
   //
-  Hob = GetFirstGuidHob (&mVTdInfoGuid);
-  if (Hob != NULL) {
-    DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
-
-    VTdInfo = GET_GUID_HOB_DATA(Hob);
-    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
-    EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
-
-    ReleaseVTdInfo (VTdInfo);
-    VTdInfo->VTdEngineCount = 0;
+  VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
+  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
 
-    ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
+  //
+  // Genrate a new Vtd Unit Info Table
+  //
+  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
+  // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
   //
-  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) {
+    //
+    // New Vtd Unit Info Table Loop
+    //
+    for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber; NewUnitIndex++) {
+      //
+      // Previous Vtd Unit Info Table Loop
+      //
+      for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo->VTdEngineCount; PreviousUnitIndex++) {
+        //
+        // Compare the new Vtd Unit with the previous VTd Unit
+        //
+        if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo->VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
+          DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n", VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
+          CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo->VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
+          VtdUnitInfo[NewUnitIndex].Done = TRUE;
+
+          break;
+        }
+      }
+    }
+  }
+  VTdInfo->AcpiDmarTable = AcpiDmarTable;
+  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
+  VTdInfo->VTdEngineCount = VtdUnitNumber;
+  VTdInfo->VtdUnitInfo = VtdUnitInfo;
 
   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;
+  EFI_ACPI_DMAR_HEADER      *AcpiDmarTable;
 
-  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;
-  }
-
-  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 +600,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 +611,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 +621,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 +671,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 +687,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);
@@ -619,10 +695,6 @@ InitVTdDmarForDma (
     return Status;
   }
 
-  // If there is RMRR memory, parse it here.
-  DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
-  ParseDmarAcpiTableRmrr (VTdInfo);
-
   DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
   Status = EnableVTdTranslationProtection(VTdInfo);
   if (EFI_ERROR (Status)) {
@@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
     //
 
     Status = InitDmaBuffer ();
-    ASSERT_EFI_ERROR(Status);
+    ASSERT_EFI_ERROR (Status);
+
+    //
+    // NOTE: We need reinit VTdInfo because previous information might be overriden.
+    //
+    Status = InitVTdInfo ();
+    ASSERT_EFI_ERROR (Status);
 
-    InitVTdDmarForDma ();
+    Status = InitVTdDmarForDma ();
+    ASSERT_EFI_ERROR (Status);
   }
 
   return EFI_SUCCESS;
@@ -826,4 +889,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..351a7810 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h
@@ -9,68 +9,61 @@
 #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;
-
-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;
 } 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_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 +83,27 @@ 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.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
-  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
-  );
-
-/**
-  Parse DMAR DRHD table.
+  @return the VTd engine number.
 
-  @param[in]  VTdInfo           The VTd engine context information.
 **/
-VOID
-ParseDmarAcpiTableRmrr (
-  IN VTD_INFO                   *VTdInfo
+UINTN
+ParseDmarAcpiTableDrhd (
+  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
+  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
+  IN VOID                               *Context
   );
 
 /**
@@ -214,30 +200,7 @@ GetPciDataIndex (
   IN VTD_SOURCE_ID              SourceId
   );
 
-/**
-  Always enable the VTd page attribute for the device.
-
-  @param[in]  VTdInfo           The VTd engine context 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.
-  @param[in]  MemoryBase        The base of the memory.
-  @param[in]  MemoryLimit       The limit of the memory.
-  @param[in]  IoMmuAccess       The IOMMU access.
-
-  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT64                     MemoryBase,
-  IN UINT64                     MemoryLimit,
-  IN UINT64                     IoMmuAccess
-  );
-
 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..c94f4a85 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);
 
@@ -304,7 +309,7 @@ CreateContextEntry (
     RootEntry->Bits.ContextTablePointerHi  = (UINT32) RShiftU64 ((UINT64) (UINTN) Buffer, 32);
     RootEntry->Bits.Present = 1;
     Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
-    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi) ;
+    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry->Bits.ContextTablePointerHi);
 
     for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
       SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -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);
 
@@ -390,7 +399,7 @@ CreateExtContextEntry (
     ExtRootEntry->Bits.UpperContextTablePointerHi  = (UINT32) RShiftU64 (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
     ExtRootEntry->Bits.UpperPresent = 1;
     Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
-    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi) ;
+    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN) VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo, ExtRootEntry->Bits.LowerContextTablePointerHi);
 
     for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER; ContextIndex++) {
       SourceId.Index.ContextIndex = (UINT8) ContextIndex;
@@ -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)) {
@@ -911,151 +923,3 @@ SetupTranslationTable (
   return EFI_SUCCESS;
 }
 
-/**
-  Find the VTd index by the Segment and SourceId.
-
-  @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.
-**/
-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
-  )
-{
-  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;
-
-  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 (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 (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;
-    }
-
-    return VtdIndex;
-  }
-
-  return (UINTN)-1;
-}
-
-/**
-  Always enable the VTd page attribute for the device.
-
-  @param[in]  VTdInfo           The VTd engine context 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.
-  @param[in]  MemoryBase        The base of the memory.
-  @param[in]  MemoryLimit       The limit of the memory.
-  @param[in]  IoMmuAccess       The IOMMU access.
-
-  @retval EFI_SUCCESS           The VTd entry is updated to always enable all DMA access for the specific device.
-**/
-EFI_STATUS
-EnableRmrrPageAttribute (
-  IN VTD_INFO                   *VTdInfo,
-  IN UINT16                     Segment,
-  IN VTD_SOURCE_ID              SourceId,
-  IN UINT64                     MemoryBase,
-  IN UINT64                     MemoryLimit,
-  IN UINT64                     IoMmuAccess
-  )
-{
-  EFI_STATUS Status;
-  UINTN                         VtdIndex;
-  VTD_EXT_CONTEXT_ENTRY         *ExtContextEntry;
-  VTD_CONTEXT_ENTRY             *ContextEntry;
-  VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
-  UINT64                        Pt;
-
-  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;
-    }
-
-    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;
-    }
-  }
-
-  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));
-  }
-
-  return EFI_SUCCESS;
-}
-- 
2.16.2.windows.1


^ permalink raw reply related	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode
  2022-01-18  8:14 ` [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
@ 2022-01-21  8:51   ` Huang, Jenny
  0 siblings, 0 replies; 12+ messages in thread
From: Huang, Jenny @ 2022-01-21  8:51 UTC (permalink / raw)
  To: Sheng, W, devel@edk2.groups.io
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

Reviewed-by: Jenny Huang <jenny.huang@intel.com>

-----Original Message-----
From: Sheng, W <w.sheng@intel.com> 
Sent: Tuesday, January 18, 2022 4:15 PM
To: devel@edk2.groups.io
Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode

If VTd ECAP_REG.ADMS bit is set, abort DMA mode is supported.
When VTd Abort DMA Mode is enabled, hardware will abort all DMA  operations without the need to set up a root-table with each  entry marked as not-present.

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

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>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Signed-off-by: Sheng Wei <w.sheng@intel.com>
---
 .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 43 +++++++++++++---------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index 87ce9716..63397a1a 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
+++ Dmar.c
@@ -384,7 +384,7 @@ InvalidateIOTLB (
   Enable DMAR translation inpre-mem phase.
 
   @param[in]  VtdUnitBaseAddress  The base address of the VTd engine.
-  @param[in]  RootEntryTable      The address of the VTd RootEntryTable.
+  @param[in]  RtaddrRegValue      The value of RTADDR_REG.
 
   @retval EFI_SUCCESS             DMAR translation is enabled.
   @retval EFI_DEVICE_ERROR        DMAR translation is not enabled.
@@ -392,15 +392,15 @@ InvalidateIOTLB (
 EFI_STATUS
 EnableDmarPreMem (
   IN UINTN                        VtdUnitBaseAddress,
-  IN UINTN                        RootEntryTable
+  IN UINTN                        RtaddrRegValue
   )
 {
   UINT32                          Reg32;
 
   DEBUG ((DEBUG_INFO, ">>>>>>EnableDmarPreMem() for engine [%x] \n", VtdUnitBaseAddress));
 
-  DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
-  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (UINTN) RootEntryTable);
+  DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%x \n", RtaddrRegValue));
+  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) 
+ RtaddrRegValue);
 
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP); @@ -662,18 +662,6 @@ EnableVTdTranslationProtectionAll (
 
   DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionAll - 0x%lx\n", EngineMask));
 
-  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;
-  }
-
   for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
     if ((EngineMask & LShiftU64(1, Index)) == 0) {
       continue;
@@ -686,7 +674,28 @@ EnableVTdTranslationProtectionAll (
     VTdInfo->VtdUnitInfo[Index].ECapReg.Uint64 = MmioRead64 (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress + R_ECAP_REG);
     DumpVtdECapRegs (&VTdInfo->VtdUnitInfo[Index].ECapReg);
 
-    EnableDmarPreMem (VTdInfo->VtdUnitInfo[Index].VtdUnitBaseAddress, (UINTN) *RootEntryTable);
+    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);
+    }
   }
 
   return;
--
2.16.2.windows.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once.
  2022-01-21  8:35   ` Huang, Jenny
@ 2022-01-24  2:44     ` Sheng Wei
  0 siblings, 0 replies; 12+ messages in thread
From: Sheng Wei @ 2022-01-24  2:44 UTC (permalink / raw)
  To: Ni, Ray, Huang, Jenny, devel@edk2.groups.io
  Cc: Chaganty, Rangasai V, Kowalewski, Robert

As the review comment form Ray, I will use a fixed MAX VTdUnit number in function VTdInfoNotify().
After that, it will no need to allocate memory at every function call of VTdInfoNotify().
I set the MAX VTd unit number to 42. The total memory usage will just smaller than 4k (1 page). And this number is enough for client and server projects.
I update to patch V6
@Ni, Ray Could you help review and merge the patch ?
Thank you
BR
Sheng Wei


> -----Original Message-----
> From: Huang, Jenny <jenny.huang@intel.com>
> Sent: 2022年1月21日 16:36
> To: Sheng, W <w.sheng@intel.com>; devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Kowalewski, Robert
> <robert.kowalewski@intel.com>
> Subject: RE: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA
> buffer once.
> 
> Reviewed-by: Jenny Huang <jenny.huang@intel.com>
> 
> -----Original Message-----
> From: Sheng, W <w.sheng@intel.com>
> Sent: Tuesday, January 18, 2022 4:15 PM
> To: devel@edk2.groups.io
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Huang, Jenny <jenny.huang@intel.com>;
> Kowalewski, Robert <robert.kowalewski@intel.com>
> Subject: [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer
> once.
> 
> 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>
> Reviewed-by: Jenny Huang <jenny.huang@intel.com>
> Signed-off-by: Sheng Wei <w.sheng@intel.com>
> ---
>  .../Feature/VTd/IntelVTdDmarPei/DmarTable.c        | 545 +--------------------
>  .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c     | 433 +++++++---------
>  .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.c  | 474 ++++++++++----
> ----
>  .../Feature/VTd/IntelVTdDmarPei/IntelVTdDmarPei.h  | 119 ++---
>  .../Feature/VTd/IntelVTdDmarPei/TranslationTable.c | 196 ++------
>  5 files changed, 533 insertions(+), 1234 deletions(-)
> 
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/DmarTable.c
> index e9c99d0a..acfbc4a8 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
> 
>  **/
> @@ -104,74 +105,6 @@ DumpDmarDeviceScopeEntry (
>    return;
>  }
> 
> -/**
> -  Dump DMAR RMRR table.
> -
> -  @param[in]  Rmrr              DMAR RMRR table
> -**/
> -VOID
> -DumpDmarRmrr (
> -  IN EFI_ACPI_DMAR_RMRR_HEADER  *Rmrr
> -  )
> -{
> -  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDeviceScopeEntry;
> -  INTN                                            RmrrLen;
> -
> -  if (Rmrr == NULL) {
> -    return;
> -  }
> -
> -  DEBUG ((DEBUG_INFO,
> -    "
> **********************************************************
> *****************\n"
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "  *       Reserved Memory Region Reporting Structure                        *\n"
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "
> **********************************************************
> *****************\n"
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    (sizeof (UINTN) == sizeof (UINT64)) ?
> -    "  RMRR address ........................................... 0x%016lx\n" :
> -    "  RMRR address ........................................... 0x%08x\n",
> -    Rmrr
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "    Type ................................................. 0x%04x\n",
> -    Rmrr->Header.Type
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "    Length ............................................... 0x%04x\n",
> -    Rmrr->Header.Length
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "    Segment Number ....................................... 0x%04x\n",
> -    Rmrr->SegmentNumber
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
> -    Rmrr->ReservedMemoryRegionBaseAddress
> -    ));
> -  DEBUG ((DEBUG_INFO,
> -    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
> -    Rmrr->ReservedMemoryRegionLimitAddress
> -    ));
> -
> -  RmrrLen  = Rmrr->Header.Length -
> sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
> -  DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) (Rmrr + 1);
> -  while (RmrrLen > 0) {
> -    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
> -    RmrrLen -= DmarDeviceScopeEntry->Length;
> -    DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
> -  }
> -
> -  DEBUG ((DEBUG_INFO,
> -    "
> **********************************************************
> *****************\n\n"
> -    ));
> -
> -  return;
> -}
> -
>  /**
>    Dump DMAR DRHD table.
> 
> @@ -312,9 +245,6 @@ DumpAcpiDMAR (
>      case EFI_ACPI_DMAR_TYPE_DRHD:
>        DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
>        break;
> -    case EFI_ACPI_DMAR_TYPE_RMRR:
> -      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *) DmarHeader);
> -      break;
>      default:
>        break;
>      }
> @@ -329,492 +259,43 @@ DumpAcpiDMAR (
>    return;
>  }
> 
> -/**
> -  Get VTd engine number.
> -
> -  @param[in]  AcpiDmarTable     DMAR ACPI table
> -
> -  @return the VTd engine number.
> -**/
> -UINTN
> -GetVtdEngineNumber (
> -  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
> -  )
> -{
> -  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
> -  UINTN                                 VtdIndex;
> -
> -  VtdIndex = 0;
> -  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> (AcpiDmarTable + 1));
> -  while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable-
> >Header.Length) {
> -    switch (DmarHeader->Type) {
> -    case EFI_ACPI_DMAR_TYPE_DRHD:
> -      VtdIndex++;
> -      break;
> -    default:
> -      break;
> -    }
> -    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> DmarHeader + DmarHeader->Length);
> -  }
> -  return VtdIndex ;
> -}
> -
> -/**
> -  Get PCI device information from DMAR DevScopeEntry.
> -
> -  @param[in]  Segment           The segment number.
> -  @param[in]  DmarDevScopeEntry DMAR DevScopeEntry
> -  @param[out] Bus               The bus number.
> -  @param[out] Device            The device number.
> -  @param[out] Function          The function number.
> -
> -  @retval EFI_SUCCESS  The PCI device information is returned.
> -**/
> -EFI_STATUS
> -GetPciBusDeviceFunction (
> -  IN  UINT16                                      Segment,
> -  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry,
> -  OUT UINT8                                       *Bus,
> -  OUT UINT8                                       *Device,
> -  OUT UINT8                                       *Function
> -  )
> -{
> -  EFI_ACPI_DMAR_PCI_PATH                          *DmarPciPath;
> -  UINT8                                           MyBus;
> -  UINT8                                           MyDevice;
> -  UINT8                                           MyFunction;
> -
> -  DmarPciPath = (EFI_ACPI_DMAR_PCI_PATH *) ((UINTN)
> (DmarDevScopeEntry + 1));
> -  MyBus = DmarDevScopeEntry->StartBusNumber;
> -  MyDevice = DmarPciPath->Device;
> -  MyFunction = DmarPciPath->Function;
> -
> -  switch (DmarDevScopeEntry->Type) {
> -  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
> -  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
> -    while ((UINTN) DmarPciPath + sizeof (EFI_ACPI_DMAR_PCI_PATH) <
> (UINTN) DmarDevScopeEntry + DmarDevScopeEntry->Length) {
> -      MyBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (Segment,
> MyBus, MyDevice, MyFunction,
> PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
> -      DmarPciPath ++;
> -      MyDevice = DmarPciPath->Device;
> -      MyFunction = DmarPciPath->Function;
> -    }
> -    break;
> -  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_IOAPIC:
> -  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_MSI_CAPABLE_HPET:
> -  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_ACPI_NAMESPACE_DEVICE:
> -    break;
> -  }
> -
> -  *Bus = MyBus;
> -  *Device = MyDevice;
> -  *Function = MyFunction;
> -
> -  return EFI_SUCCESS;
> -}
> -
> -/**
> -  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.
> -
> -  @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.
> -
> -  @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.
> -
> -**/
> -EFI_STATUS
> -RegisterPciDevice (
> -  IN VTD_UNIT_INFO              *VTdUnitInfo,
> -  IN UINT16                     Segment,
> -  IN VTD_SOURCE_ID              SourceId,
> -  IN UINT8                      DeviceType,
> -  IN BOOLEAN                    CheckExist
> -  )
> -{
> -  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"));
> -
> -    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;
> -    }
> -  }
> -
> -  return EFI_SUCCESS;
> -}
> -
> -/**
> -  Process DMAR DRHD table.
> -
> -  @param[in]  VTdUnitInfo       The VTd engine unit information.
> -  @param[in]  DmarDrhd          The DRHD table.
> -
> -**/
> -VOID
> -ProcessDrhd (
> -  IN VTD_UNIT_INFO              *VTdUnitInfo,
> -  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
> -  )
> -{
> -  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry;
> -  UINT8                                           Bus;
> -  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"));
> -  }
> -
> -  VTdUnitInfo->PciDeviceInfo.PciDeviceDataNumber = 0;
> -  VTdUnitInfo->PciDeviceInfo.PciDeviceDataMaxNumber = 0;
> -  VTdUnitInfo->PciDeviceInfo.PciDeviceDataPageSize = 0;
> -  VTdUnitInfo->PciDeviceInfo.PciDeviceData = 0;
> -
> -  DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> (DmarDrhd + 1));
> -  while ((UINTN)DmarDevScopeEntry < (UINTN) DmarDrhd + DmarDrhd-
> >Header.Length) {
> -
> -    Status = GetPciBusDeviceFunction (DmarDrhd->SegmentNumber,
> DmarDevScopeEntry, &Bus, &Device, &Function);
> -    if (EFI_ERROR (Status)) {
> -      return;
> -    }
> -
> -    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;
> -    }
> -    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);
> -    if (EFI_ERROR (Status)) {
> -      DEBUG ((DEBUG_ERROR,"RegisterPciDevice Failed !\n"));
> -    }
> -
> -    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
> -    ));
> -
> -  PciDeviceDataBase = (PEI_PCI_DEVICE_DATA *) (UINTN) VTdInfo-
> >VtdUnitInfo[VtdIndex].PciDeviceInfo.PciDeviceData;
> -
> -  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
> -      ));
> -  }
> -}
> -
>  /**
>    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.
> 
>  **/
>  EFI_STATUS
>  ParseDmarAcpiTableDrhd (
> -  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable
> +  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
> +  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
> +  IN VOID                               *Context
>    )
>  {
>    EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
> -  UINTN                                 VtdUnitNumber;
> -  UINTN                                 VtdIndex;
> -  VTD_INFO                              *VTdInfo;
> -
> -  VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
> -  if (VtdUnitNumber == 0) {
> -    return EFI_UNSUPPORTED;
> -  }
> -
> -  VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof (VTD_INFO) +
> (VtdUnitNumber - 1) * sizeof (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;
> +  UINT32                                VtdIndex;
> 
>    VtdIndex = 0;
>    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> (AcpiDmarTable + 1));
> +
>    while ((UINTN) DmarHeader < (UINTN) AcpiDmarTable + AcpiDmarTable-
> >Header.Length) {
>      switch (DmarHeader->Type) {
>      case EFI_ACPI_DMAR_TYPE_DRHD:
> -      ASSERT (VtdIndex < VtdUnitNumber);
> -      ProcessDrhd (&VTdInfo->VtdUnitInfo[VtdIndex],
> (EFI_ACPI_DMAR_DRHD_HEADER *) DmarHeader);
> +      if (Callback != NULL) {
> +        Callback (Context, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)
> DmarHeader);
> +      }
>        VtdIndex++;
> -
>        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;
> -}
> -
> -
> -/**
> -  Process DMAR RMRR table.
> -
> -  @param[in]  VTdInfo           The VTd engine context information.
> -  @param[in]  DmarRmrr          The RMRR table.
> -
> -**/
> -VOID
> -ProcessRmrr (
> -  IN VTD_INFO                                     *VTdInfo,
> -  IN EFI_ACPI_DMAR_RMRR_HEADER                    *DmarRmrr
> -  )
> -{
> -  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry;
> -  UINT8                                           Bus;
> -  UINT8                                           Device;
> -  UINT8                                           Function;
> -  EFI_STATUS                                      Status;
> -  VTD_SOURCE_ID                                   SourceId;
> -
> -  DEBUG ((DEBUG_INFO,"  PEI RMRR (Base 0x%016lx, Limit 0x%016lx)\n",
> DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr-
> >ReservedMemoryRegionLimitAddress));
> -
> -  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
> -      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
> -    return ;
> -  }
> -
> -  DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> (DmarRmrr + 1));
> -  while ((UINTN) DmarDevScopeEntry < (UINTN) DmarRmrr + DmarRmrr-
> >Header.Length) {
> -    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;
> -    }
> -
> -    Status = GetPciBusDeviceFunction (DmarRmrr->SegmentNumber,
> DmarDevScopeEntry, &Bus, &Device, &Function);
> -    if (EFI_ERROR (Status)) {
> -      continue;
> -    }
> -
> -    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));
> -    }
> -
> -    DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *) ((UINTN)
> DmarDevScopeEntry + DmarDevScopeEntry->Length);
> -  }
> -}
> -
> -/**
> -  Parse DMAR DRHD table.
> -
> -  @param[in]  VTdInfo           The VTd engine context information.
> -
> -**/
> -VOID
> -ParseDmarAcpiTableRmrr (
> -  IN VTD_INFO                           *VTdInfo
> -  )
> -{
> -  EFI_ACPI_DMAR_HEADER                  *AcpiDmarTable;
> -  EFI_ACPI_DMAR_STRUCTURE_HEADER        *DmarHeader;
> 
> -  AcpiDmarTable = (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);
> -      break;
> -    default:
> -      break;
> -    }
> -    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *) ((UINTN)
> DmarHeader + DmarHeader->Length);
> -  }
> +  return VtdIndex;
>  }
> 
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> index 63397a1a..0ed216bb 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/IntelVTdDmar
> Pei.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.c
> index a8f7bfee..ac91eac3 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.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,114 @@ 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;
> 
> -    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;
> +  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.
> +
> +  @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);
>  }
> 
>  /**
> -  Initializes the Intel VTd Info.
> +  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 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 +481,103 @@ InitVTdInfo (
>    VOID
>    )
>  {
> -  EFI_STATUS                    Status;
> -  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
> -  VOID                          *Hob;
>    VTD_INFO                      *VTdInfo;
> -  UINT64                        EngineMask;
> +  EFI_ACPI_DMAR_HEADER          *AcpiDmarTable;
> +  UINTN                         VtdUnitNumber;
> +  VTD_UNIT_INFO                 *VtdUnitInfo;
> +  EFI_STATUS                    Status;
> +  UINTN                         NewUnitIndex;
> +  UINTN                         PreviousUnitIndex;
> 
> -  Status = PeiServicesLocatePpi (
> -             &gEdkiiVTdInfoPpiGuid,
> -             0,
> -             NULL,
> -             (VOID **)&AcpiDmarTable
> -             );
> -  ASSERT_EFI_ERROR (Status);
> +  VTdInfo = GetVTdInfoHob ();
> +  ASSERT (VTdInfo != NULL);
> 
> -  DumpAcpiDMAR (AcpiDmarTable);
> +  AcpiDmarTable = GetAcpiDmarTable ();
> +  ASSERT (AcpiDmarTable != NULL);
> 
>    //
> -  // Clear old VTdInfo Hob.
> +  // Get VTd Unit Number
>    //
> -  Hob = GetFirstGuidHob (&mVTdInfoGuid);
> -  if (Hob != NULL) {
> -    DEBUG ((DEBUG_INFO, " Find Hob : mVTdInfoGuid - 0x%x\n", Hob));
> -
> -    VTdInfo = GET_GUID_HOB_DATA(Hob);
> -    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
> -    EnableVTdTranslationProtectionAll (VTdInfo, EngineMask);
> -
> -    ReleaseVTdInfo (VTdInfo);
> -    VTdInfo->VTdEngineCount = 0;
> +  VtdUnitNumber = ParseDmarAcpiTableDrhd (AcpiDmarTable, NULL, NULL);
> +  if (VtdUnitNumber == 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> 
> -    ZeroMem (&((EFI_HOB_GUID_TYPE *) Hob)->Name, sizeof (EFI_GUID));
> +  //
> +  // Genrate a new Vtd Unit Info Table
> +  //
> +  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
> +  // Parse the DMAR ACPI Table to the new Vtd Unit Info Table
>    //
> -  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) {
> +    //
> +    // New Vtd Unit Info Table Loop
> +    //
> +    for (NewUnitIndex = 0; NewUnitIndex < VtdUnitNumber;
> NewUnitIndex++) {
> +      //
> +      // Previous Vtd Unit Info Table Loop
> +      //
> +      for (PreviousUnitIndex = 0; PreviousUnitIndex < VTdInfo-
> >VTdEngineCount; PreviousUnitIndex++) {
> +        //
> +        // Compare the new Vtd Unit with the previous VTd Unit
> +        //
> +        if (VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress == VTdInfo-
> >VtdUnitInfo[PreviousUnitIndex].VtdUnitBaseAddress) {
> +          DEBUG ((DEBUG_INFO,"Find VTD [0x%08x] Exist\n",
> VtdUnitInfo[NewUnitIndex].VtdUnitBaseAddress));
> +          CopyMem (&VtdUnitInfo[NewUnitIndex], &VTdInfo-
> >VtdUnitInfo[PreviousUnitIndex], sizeof (VTD_UNIT_INFO));
> +          VtdUnitInfo[NewUnitIndex].Done = TRUE;
> +
> +          break;
> +        }
> +      }
> +    }
> +  }
> +  VTdInfo->AcpiDmarTable = AcpiDmarTable;
> +  VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
> +  VTdInfo->VTdEngineCount = VtdUnitNumber;
> +  VTdInfo->VtdUnitInfo = VtdUnitInfo;
> 
>    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;
> +  EFI_ACPI_DMAR_HEADER      *AcpiDmarTable;
> 
> -  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;
> -  }
> -
> -  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 +600,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 +611,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 +621,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 +671,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 +687,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);
> @@ -619,10 +695,6 @@ InitVTdDmarForDma (
>      return Status;
>    }
> 
> -  // If there is RMRR memory, parse it here.
> -  DEBUG ((DEBUG_INFO, "PeiParseDmarAcpiTableRmrr\n"));
> -  ParseDmarAcpiTableRmrr (VTdInfo);
> -
>    DEBUG ((DEBUG_INFO, "EnableVtdDmar\n"));
>    Status = EnableVTdTranslationProtection(VTdInfo);
>    if (EFI_ERROR (Status)) {
> @@ -668,21 +740,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 +794,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 +814,16 @@ VTdInfoNotify (
>      //
> 
>      Status = InitDmaBuffer ();
> -    ASSERT_EFI_ERROR(Status);
> +    ASSERT_EFI_ERROR (Status);
> +
> +    //
> +    // NOTE: We need reinit VTdInfo because previous information might be
> overriden.
> +    //
> +    Status = InitVTdInfo ();
> +    ASSERT_EFI_ERROR (Status);
> 
> -    InitVTdDmarForDma ();
> +    Status = InitVTdDmarForDma ();
> +    ASSERT_EFI_ERROR (Status);
>    }
> 
>    return EFI_SUCCESS;
> @@ -826,4 +889,3 @@ IntelVTdDmarInitialize (
> 
>    return EFI_SUCCESS;
>  }
> -
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> index e23a6c8e..351a7810 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar
> Pei.h
> @@ -9,68 +9,61 @@
>  #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;
> -
> -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;
>  } 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_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 +83,27 @@ 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.
> -**/
> -EFI_STATUS
> -ParseDmarAcpiTableDrhd (
> -  IN EFI_ACPI_DMAR_HEADER       *AcpiDmarTable
> -  );
> -
> -/**
> -  Parse DMAR DRHD table.
> +  @return the VTd engine number.
> 
> -  @param[in]  VTdInfo           The VTd engine context information.
>  **/
> -VOID
> -ParseDmarAcpiTableRmrr (
> -  IN VTD_INFO                   *VTdInfo
> +UINTN
> +ParseDmarAcpiTableDrhd (
> +  IN EFI_ACPI_DMAR_HEADER               *AcpiDmarTable,
> +  IN PROCESS_DRHD_CALLBACK_FUNC         Callback,
> +  IN VOID                               *Context
>    );
> 
>  /**
> @@ -214,30 +200,7 @@ GetPciDataIndex (
>    IN VTD_SOURCE_ID              SourceId
>    );
> 
> -/**
> -  Always enable the VTd page attribute for the device.
> -
> -  @param[in]  VTdInfo           The VTd engine context 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.
> -  @param[in]  MemoryBase        The base of the memory.
> -  @param[in]  MemoryLimit       The limit of the memory.
> -  @param[in]  IoMmuAccess       The IOMMU access.
> -
> -  @retval EFI_SUCCESS           The VTd entry is updated to always enable all
> DMA access for the specific device.
> -**/
> -EFI_STATUS
> -EnableRmrrPageAttribute (
> -  IN VTD_INFO                   *VTdInfo,
> -  IN UINT16                     Segment,
> -  IN VTD_SOURCE_ID              SourceId,
> -  IN UINT64                     MemoryBase,
> -  IN UINT64                     MemoryLimit,
> -  IN UINT64                     IoMmuAccess
> -  );
> -
>  extern EFI_GUID mVTdInfoGuid;
>  extern EFI_GUID mDmaBufferInfoGuid;
> 
>  #endif
> -
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> index a309d566..c94f4a85 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.c
> +++
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/TranslationTab
> le.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);
> 
> @@ -304,7 +309,7 @@ CreateContextEntry (
>      RootEntry->Bits.ContextTablePointerHi  = (UINT32) RShiftU64 ((UINT64)
> (UINTN) Buffer, 32);
>      RootEntry->Bits.Present = 1;
>      Buffer = (UINT8 *)Buffer + EFI_PAGES_TO_SIZE (ContextPages);
> -    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry-
> >Bits.ContextTablePointerHi) ;
> +    ContextEntryTable = (VTD_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS(RootEntry->Bits.ContextTablePointerLo, RootEntry-
> >Bits.ContextTablePointerHi);
> 
>      for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER;
> ContextIndex++) {
>        SourceId.Index.ContextIndex = (UINT8) ContextIndex;
> @@ -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);
> 
> @@ -390,7 +399,7 @@ CreateExtContextEntry (
>      ExtRootEntry->Bits.UpperContextTablePointerHi  = (UINT32) RShiftU64
> (RShiftU64 ((UINT64) (UINTN) Buffer, 12) + 1, 20);
>      ExtRootEntry->Bits.UpperPresent = 1;
>      Buffer = (UINT8 *) Buffer + EFI_PAGES_TO_SIZE (ContextPages);
> -    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo,
> ExtRootEntry->Bits.LowerContextTablePointerHi) ;
> +    ExtContextEntryTable = (VTD_EXT_CONTEXT_ENTRY *) (UINTN)
> VTD_64BITS_ADDRESS (ExtRootEntry->Bits.LowerContextTablePointerLo,
> ExtRootEntry->Bits.LowerContextTablePointerHi);
> 
>      for (ContextIndex = 0; ContextIndex < VTD_CONTEXT_ENTRY_NUMBER;
> ContextIndex++) {
>        SourceId.Index.ContextIndex = (UINT8) ContextIndex;
> @@ -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)) {
> @@ -911,151 +923,3 @@ SetupTranslationTable (
>    return EFI_SUCCESS;
>  }
> 
> -/**
> -  Find the VTd index by the Segment and SourceId.
> -
> -  @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.
> -**/
> -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
> -  )
> -{
> -  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;
> -
> -  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 (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 (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;
> -    }
> -
> -    return VtdIndex;
> -  }
> -
> -  return (UINTN)-1;
> -}
> -
> -/**
> -  Always enable the VTd page attribute for the device.
> -
> -  @param[in]  VTdInfo           The VTd engine context 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.
> -  @param[in]  MemoryBase        The base of the memory.
> -  @param[in]  MemoryLimit       The limit of the memory.
> -  @param[in]  IoMmuAccess       The IOMMU access.
> -
> -  @retval EFI_SUCCESS           The VTd entry is updated to always enable all
> DMA access for the specific device.
> -**/
> -EFI_STATUS
> -EnableRmrrPageAttribute (
> -  IN VTD_INFO                   *VTdInfo,
> -  IN UINT16                     Segment,
> -  IN VTD_SOURCE_ID              SourceId,
> -  IN UINT64                     MemoryBase,
> -  IN UINT64                     MemoryLimit,
> -  IN UINT64                     IoMmuAccess
> -  )
> -{
> -  EFI_STATUS Status;
> -  UINTN                         VtdIndex;
> -  VTD_EXT_CONTEXT_ENTRY         *ExtContextEntry;
> -  VTD_CONTEXT_ENTRY             *ContextEntry;
> -  VTD_SECOND_LEVEL_PAGING_ENTRY *SecondLevelPagingEntry;
> -  UINT64                        Pt;
> -
> -  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;
> -    }
> -
> -    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;
> -    }
> -  }
> -
> -  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));
> -  }
> -
> -  return EFI_SUCCESS;
> -}
> --
> 2.16.2.windows.1


^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2022-01-24  2:44 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-01-18  8:14 [PATCH v5 0/4] There are 4 patches for VTd drivers Sheng Wei
2022-01-18  8:14 ` [PATCH v5 1/4] IntelSiliconPkg/VTd: Fix typos Sheng Wei
2022-01-18  8:31   ` Huang, Jenny
2022-01-19  8:26   ` Kowalewski, Robert
2022-01-18  8:14 ` [PATCH v5 2/4] IntelSiliconPkg/VTd: Update VTd register structs Sheng Wei
2022-01-21  8:24   ` Huang, Jenny
2022-01-18  8:14 ` [PATCH v5 3/4] IntelSiliconPkg/VTd: Support VTd Abort DMA Mode Sheng Wei
2022-01-21  8:51   ` Huang, Jenny
2022-01-18  8:14 ` [PATCH v5 4/4] IntelSiliconPkg/VTd: Only generate PEI DMA buffer once Sheng Wei
2022-01-21  8:35   ` Huang, Jenny
2022-01-24  2:44     ` Sheng Wei
2022-01-18  8:30 ` [PATCH v5 0/4] There are 4 patches for VTd drivers Huang, Jenny

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox