public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI
@ 2017-09-17  6:06 Jiewen Yao
  2017-09-17  6:06 ` [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table Jiewen Yao
                   ` (3 more replies)
  0 siblings, 4 replies; 10+ messages in thread
From: Jiewen Yao @ 2017-09-17  6:06 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

We notice that there is real usage in PEI to show
the graphic output.
The Integrated Graphic Device is blocked by current
IntelVTdPei because the DMA buffer is fully controlled
by VTd PEIM. The UMA is not allowed.

In DXE phase, the UMA is reported via RMRR table.

As such, we need similar way in PEI to let VTd PEI
get the RMRR information.

This series patch resolves this problem.

We also updated sample driver to show how to get the RMRR information.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>

Jiewen Yao (3):
  IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
  IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  IntelSiliconPkg/VTdInfoSample: Add RMRR table.

 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c                          |  52 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c                       | 581 +++++++++++++++++++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h                       |  20 +-
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 156 +++++-
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   3 +
 IntelSiliconPkg/Include/Ppi/VtdInfo.h                                             |  26 +-
 6 files changed, 788 insertions(+), 50 deletions(-)

-- 
2.7.4.windows.1



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

* [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
  2017-09-17  6:06 [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Jiewen Yao
@ 2017-09-17  6:06 ` Jiewen Yao
  2017-09-20  6:30   ` Zeng, Star
  2017-09-17  6:06 ` [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table Jiewen Yao
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 10+ messages in thread
From: Jiewen Yao @ 2017-09-17  6:06 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

We notice that there is real usage in PEI to show
the graphic output. As such we need report RMRR table
in PEI to let VTdPmrPei driver skip the IGD UMA region.

Now the VTD_INFO PPI uses the same DMAR data structure.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Include/Ppi/VtdInfo.h | 26 +++++++++++---------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/IntelSiliconPkg/Include/Ppi/VtdInfo.h b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
index e8be63f..a0a6f9c 100644
--- a/IntelSiliconPkg/Include/Ppi/VtdInfo.h
+++ b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
@@ -17,22 +17,26 @@
 #ifndef __VTD_INFO_PPI_H__
 #define __VTD_INFO_PPI_H__
 
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/DmaRemappingReportingTable.h>
+
 #define EDKII_VTD_INFO_PPI_GUID \
     { \
       0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } \
     }
 
-typedef struct _EDKII_VTD_INFO_PPI  EDKII_VTD_INFO_PPI;
-
-#define EDKII_VTD_INFO_PPI_REVISION 0x00010000
-
-struct _EDKII_VTD_INFO_PPI {
-  UINT64                                  Revision;
-  UINT8                                   HostAddressWidth;
-  UINT8                                   Reserved[3];
-  UINT32                                  VTdEngineCount;
-  UINT64                                  VTdEngineAddress[1];
-};
+//
+// VTD info PPI just use same data structure as DMAR table.
+//
+// The reported information must include what is needed in PEI phase, e.g.
+//   the VTd engine (such as DRHD)
+//   the reserved DMA address in PEI for eary graphic (such as RMRR for graphic UMA)
+//
+// The reported information can be and might be a subset of full DMAR table, e.g.
+//   if some data is not avaiable (such as ANDD),
+//   if some data is not needed (such as RMRR for legacy USB).
+//
+typedef EFI_ACPI_DMAR_HEADER EDKII_VTD_INFO_PPI;
 
 extern EFI_GUID gEdkiiVTdInfoPpiGuid;
 
-- 
2.7.4.windows.1



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

* [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  2017-09-17  6:06 [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Jiewen Yao
  2017-09-17  6:06 ` [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table Jiewen Yao
@ 2017-09-17  6:06 ` Jiewen Yao
  2017-09-20  6:29   ` Zeng, Star
  2017-09-17  6:06 ` [PATCH 3/3] IntelSiliconPkg/VTdInfoSample: Add " Jiewen Yao
  2017-09-20  6:30 ` [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Zeng, Star
  3 siblings, 1 reply; 10+ messages in thread
From: Jiewen Yao @ 2017-09-17  6:06 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

In order to support PEI graphic, we let VTdPmrPei driver
parse DMAR table RMRR entry and allow the UMA access.

If a system has no PEI IGD, no RMRR is needed. The behavior
is unchanged.

If a system has PEI IGD, it must report RMRR in PEI phase.
The PeiVTdPrm will program the IGD VTd engine to skip the
RMRR region, and program the reset PCI VTd engine to skip
the another DMA buffer allocated in PEI phase for other
device driver.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c    |  52 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 581 +++++++++++++++++++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h |  20 +-
 3 files changed, 624 insertions(+), 29 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
index ef08e29..be841aa 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
@@ -22,7 +22,7 @@
 
 #include "IntelVTdPmrPei.h"
 
-extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+extern VTD_INFO                *mVTdInfo;
 
 /**
   Get protected low memory alignment.
@@ -60,7 +60,7 @@ GetPhmrAlignment (
   UINT64        Data64;
   UINT8         HostAddressWidth;
 
-  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
+  HostAddressWidth = mVTdInfo->HostAddressWidth;
 
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
   Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
@@ -73,11 +73,13 @@ GetPhmrAlignment (
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -85,8 +87,11 @@ GetLowMemoryAlignment (
   UINT32        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -97,11 +102,13 @@ GetLowMemoryAlignment (
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -109,8 +116,11 @@ GetHighMemoryAlignment (
   UINT64        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -246,6 +256,7 @@ SetPmrRegion (
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -256,6 +267,7 @@ SetPmrRegion (
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -265,12 +277,15 @@ SetDmaProtectedRange (
   UINTN       Index;
   EFI_STATUS  Status;
 
-  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
+  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     Status = SetPmrRegion (
-               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
+               (UINTN)mVTdInfo->VTdEngineAddress[Index],
                LowMemoryBase,
                LowMemoryLength,
                HighMemoryBase,
@@ -279,7 +294,7 @@ SetDmaProtectedRange (
     if (EFI_ERROR(Status)) {
       return Status;
     }
-    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
@@ -291,11 +306,13 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN       Index;
@@ -303,8 +320,11 @@ DisableDmaProtection (
 
   DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
index d118b7e..063e8cd 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -29,7 +29,9 @@
 
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB
 
-EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;
+VTD_INFO                          *mVTdInfo;
+UINT64                            mEngineMask;
 UINTN                             mDmaBufferBase;
 UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
 UINTN                             mDmaBufferCurrentTop;
@@ -48,15 +50,19 @@ typedef struct {
 
   PEI Memory Layout:
 
+              +------------------+ <=============== PHMR.Limit (Top of memory)
+              |   Mem Resource   |
+              |                  |
+
               +------------------+ <------- EfiMemoryTop
               |   PEI allocated  |
-  =========== +==================+
+  =========== +==================+ <=============== PHMR.Base
        ^      |    Commom Buf    |
        |      |  --------------  |
   DMA Buffer  |   * DMA FREE *   |
        |      |  --------------  |
        V      |  Read/Write Buf  |
-  =========== +==================+
+  =========== +==================+ <=============== PLMR.Limit
               |   PEI allocated  |
               |  --------------  | <------- EfiFreeMemoryTop
               |   * PEI FREE *   |
@@ -70,6 +76,9 @@ typedef struct {
               |   Mem Alloc Hob  |
               +------------------+
 
+              |                  |
+              |   Mem Resource   |
+              +------------------+ <=============== PLMR.Base (0)
 **/
 
 
@@ -457,20 +466,21 @@ DumpPhitHob (
 /**
   Get the highest memory.
 
-  @param HobList  the HOB list.
-
   @return the highest memory.
 **/
 UINT64
 GetTopMemory (
-  IN VOID                        *HobList
+  VOID
   )
 {
+  VOID                        *HobList;
   EFI_PEI_HOB_POINTERS        Hob;
   EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
   UINT64                      TopMemory;
   UINT64                      ResourceTop;
 
+  HobList = GetHobList ();
+
   TopMemory = 0;
   for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {
@@ -525,8 +535,8 @@ InitDmaProtection (
 
   ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
 
-  LowMemoryAlignment = GetLowMemoryAlignment ();
-  HighMemoryAlignment = GetHighMemoryAlignment ();
+  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
+  HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
   if (LowMemoryAlignment < HighMemoryAlignment) {
     MemoryAlignment = (UINTN)HighMemoryAlignment;
   } else {
@@ -542,9 +552,10 @@ InitDmaProtection (
   LowBottom = 0;
   LowTop = *DmaBufferBase;
   HighBottom = *DmaBufferBase + DmaBufferSize;
-  HighTop = GetTopMemory (HobList);
+  HighTop = GetTopMemory ();
 
   Status = SetDmaProtectedRange (
+               mEngineMask,
                (UINT32)LowBottom,
                (UINT32)(LowTop - LowBottom),
                HighBottom,
@@ -559,6 +570,541 @@ InitDmaProtection (
 }
 
 /**
+  Dump DMAR DeviceScopeEntry.
+
+  @param[in]  DmarDeviceScopeEntry  DMAR DeviceScopeEntry
+**/
+VOID
+DumpDmarDeviceScopeEntry (
+  IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry
+  )
+{
+  UINTN   PciPathNumber;
+  UINTN   PciPathIndex;
+  EFI_ACPI_DMAR_PCI_PATH  *PciPath;
+
+  if (DmarDeviceScopeEntry == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *       DMA-Remapping Device Scope Entry Structure                      *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "    DMAR Device Scope Entry address ...................... 0x%016lx\n" :
+    "    DMAR Device Scope Entry address ...................... 0x%08x\n",
+    DmarDeviceScopeEntry
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Device Scope Entry Type ............................ 0x%02x\n",
+    DmarDeviceScopeEntry->Type
+    ));
+  switch (DmarDeviceScopeEntry->Type) {
+  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Endpoint Device\n"
+      ));
+    break;
+  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Sub-hierachy\n"
+      ));
+    break;
+  default:
+    break;
+  }
+  DEBUG ((DEBUG_INFO,
+    "      Length ............................................. 0x%02x\n",
+    DmarDeviceScopeEntry->Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Enumeration ID ..................................... 0x%02x\n",
+    DmarDeviceScopeEntry->EnumerationId
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Starting Bus Number ................................ 0x%02x\n",
+    DmarDeviceScopeEntry->StartBusNumber
+    ));
+
+  PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
+  PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
+  for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
+    DEBUG ((DEBUG_INFO,
+      "      Device ............................................. 0x%02x\n",
+      PciPath[PciPathIndex].Device
+      ));
+    DEBUG ((DEBUG_INFO,
+      "      Function ........................................... 0x%02x\n",
+      PciPath[PciPathIndex].Function
+      ));
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR RMRR table.
+
+  @param[in]  Rmrr  DMAR RMRR table
+**/
+VOID
+DumpDmarRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    RmrrLen;
+
+  if (Rmrr == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       Reserved Memory Region Reporting Structure                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  RMRR address ........................................... 0x%016lx\n" :
+    "  RMRR address ........................................... 0x%08x\n",
+    Rmrr
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Rmrr->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Rmrr->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Rmrr->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionBaseAddress
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionLimitAddress
+    ));
+
+  RmrrLen  = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
+  while (RmrrLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    RmrrLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR DRHD table.
+
+  @param[in]  Drhd  DMAR DRHD table
+**/
+VOID
+DumpDmarDrhd (
+  IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    DrhdLen;
+
+  if (Drhd == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       DMA-Remapping Hardware Definition Structure                       *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  DRHD address ........................................... 0x%016lx\n" :
+    "  DRHD address ........................................... 0x%08x\n",
+    Drhd
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Drhd->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Drhd->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Drhd->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INCLUDE_PCI_ALL .................................... 0x%02x\n",
+    Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Drhd->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Register Base Address ................................ 0x%016lx\n",
+    Drhd->RegisterBaseAddress
+    ));
+
+  DrhdLen  = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
+  while (DrhdLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    DrhdLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR ACPI table.
+
+  @param[in]  Dmar  DMAR ACPI table
+**/
+VOID
+DumpAcpiDMAR (
+  IN EFI_ACPI_DMAR_HEADER  *Dmar
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+  INTN                  DmarLen;
+
+  if (Dmar == NULL) {
+    return;
+  }
+
+  //
+  // Dump Dmar table
+  //
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*         DMAR Table                                                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "DMAR address ............................................. 0x%016lx\n" :
+    "DMAR address ............................................. 0x%08x\n",
+    Dmar
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    "  Table Contents:\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Host Address Width ................................... 0x%02x\n",
+    Dmar->HostAddressWidth
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Dmar->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INTR_REMAP ......................................... 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
+    ));
+
+  DmarLen  = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
+  while (DmarLen > 0) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      break;
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarLen -= DmarHeader->Length;
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Get VTd engine number.
+
+  @return the VTd engine number.
+**/
+UINTN
+GetVtdEngineNumber (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      VtdIndex++;
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+  }
+  return VtdIndex ;
+}
+
+/**
+  Process DMAR DHRD table.
+
+  @param[in]  VtdIndex  The index of VTd engine.
+  @param[in]  DmarDrhd  The DRHD table.
+**/
+VOID
+ProcessDhrd (
+  IN UINTN                      VtdIndex,
+  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  )
+{
+  DEBUG ((DEBUG_INFO,"  VTD (%d) BaseAddress -  0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
+  mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
+}
+
+/**
+  Parse DMAR DRHD table.
+
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
+**/
+EFI_STATUS
+ParseDmarAcpiTableDrhd (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdUnitNumber;
+  UINTN                                             VtdIndex;
+
+  VtdUnitNumber = GetVtdEngineNumber ();
+  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
+  if (mVTdInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
+  mVTdInfo->VTdEngineCount   = VtdUnitNumber;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      ASSERT (VtdIndex < VtdUnitNumber);
+      ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      VtdIndex++;
+
+      break;
+
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+  }
+  ASSERT (VtdIndex == VtdUnitNumber);
+
+  //
+  // Initialize the engine mask to all.
+  //
+  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the VTd engine index according to the Segment and DevScopeEntry.
+
+  @param Segment         The segment of the VTd engine
+  @param DevScopeEntry   The DevScopeEntry of the VTd engine
+
+  @return The VTd engine index according to the Segment and DevScopeEntry.
+  @retval -1  The VTd engine is not found.
+**/
+UINTN
+GetVTdEngineFromDevScopeEntry (
+  IN  UINT16                                      Segment,
+  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+  EFI_ACPI_DMAR_DRHD_HEADER                         *DmarDrhd;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *ThisDevScopeEntry;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
+      if (DmarDrhd->SegmentNumber != Segment) {
+        // Mismatch
+        break;
+      }
+      if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
+          ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
+        // No DevScopeEntry
+        // Do not handle PCI_ALL
+        break;
+      }
+      ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
+      while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
+        if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
+            (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
+          return VtdIndex;
+        }
+        ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
+      }
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+  }
+  return (UINTN)-1;
+}
+
+/**
+  Process DMAR RMRR table.
+
+  @param[in]  DmarRmrr  The RMRR table.
+**/
+VOID
+ProcessRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER  *DmarRmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDevScopeEntry;
+  UINTN                                             VTdIndex;
+  UINT64                                            RmrrMask;
+  UINTN                                             LowBottom;
+  UINTN                                             LowTop;
+  UINTN                                             HighBottom;
+  UINT64                                            HighTop;
+
+  DEBUG ((DEBUG_INFO,"  RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
+
+  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
+      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
+    return ;
+  }
+
+  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));
+  while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
+    ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
+
+    VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
+    if (VTdIndex != (UINTN)-1) {
+      RmrrMask = LShiftU64 (1, VTdIndex);
+
+      LowBottom = 0;
+      LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
+      HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
+      HighTop = GetTopMemory ();
+
+      SetDmaProtectedRange (
+        RmrrMask,
+        0,
+        (UINT32)(LowTop - LowBottom),
+        HighBottom,
+        HighTop - HighBottom
+        );
+
+      //
+      // Remove the engine from the engine mask.
+      // The assumption is that any other PEI driver does not access
+      // the device covered by this engine.
+      //
+      mEngineMask = mEngineMask & (~RmrrMask);
+    }
+
+    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+  }
+}
+
+/**
+  Parse DMAR DRHD table.
+**/
+VOID
+ParseDmarAcpiTableRmrr (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
+  }
+}
+
+/**
   Initializes the Intel VTd PMR PEIM.
 
   @param  FileHandle  Handle of the file being invoked.
@@ -585,10 +1131,25 @@ IntelVTdPmrInitialize (
              &gEdkiiVTdInfoPpiGuid,
              0,
              NULL,
-             (VOID **)&mVTdInfoPpi
+             (VOID **)&mAcpiDmarTable
              );
   ASSERT_EFI_ERROR(Status);
 
+  DumpAcpiDMAR (mAcpiDmarTable);
+
+  //
+  // Get DMAR information to local VTdInfo
+  //
+  Status = ParseDmarAcpiTableDrhd ();
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // If there is RMRR memory, parse it here.
+  //
+  ParseDmarAcpiTableRmrr ();
+
   //
   // Find a pre-memory in resource hob as DMA buffer
   // Mark PEI memory to be DMA protected.
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
index aa5926a7..720f5d4 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -15,9 +15,16 @@
 #ifndef __DMA_ACCESS_LIB_H__
 #define __DMA_ACCESS_LIB_H__
 
+typedef struct {
+  UINT8                                   HostAddressWidth;
+  UINTN                                   VTdEngineCount;
+  UINT64                                  VTdEngineAddress[1];
+} VTD_INFO;
+
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -28,6 +35,7 @@
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -37,31 +45,37 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 #endif
-- 
2.7.4.windows.1



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

* [PATCH 3/3] IntelSiliconPkg/VTdInfoSample: Add RMRR table.
  2017-09-17  6:06 [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Jiewen Yao
  2017-09-17  6:06 ` [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table Jiewen Yao
  2017-09-17  6:06 ` [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table Jiewen Yao
@ 2017-09-17  6:06 ` Jiewen Yao
  2017-09-20  6:30 ` [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Zeng, Star
  3 siblings, 0 replies; 10+ messages in thread
From: Jiewen Yao @ 2017-09-17  6:06 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Let system report RMRR table for the platform support
PEI graphic.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 156 ++++++++++++++++++--
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   3 +
 2 files changed, 149 insertions(+), 10 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index c79398f..423e2f1 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
@@ -18,21 +18,111 @@
 
 #include <Library/PeiServicesLib.h>
 #include <Library/DebugLib.h>
+#include <Library/PciLib.h>
+#include <Library/IoLib.h>
+
+#define R_SA_MCHBAR               (0x48)
+#define R_SA_GGC                  (0x50)
+#define N_SKL_SA_GGC_GGMS_OFFSET  (0x6)
+#define B_SKL_SA_GGC_GGMS_MASK    (0xc0)
+#define N_SKL_SA_GGC_GMS_OFFSET   (0x8)
+#define B_SKL_SA_GGC_GMS_MASK     (0xff00)
+#define V_SKL_SA_GGC_GGMS_8MB     3
+#define R_SA_TOLUD                (0xbc)
+
+#define R_SA_MCHBAR_VTD1_OFFSET  0x5400  ///< HW UNIT for IGD
+#define R_SA_MCHBAR_VTD2_OFFSET  0x5410  ///< HW UNIT for all other - PEG, USB, SATA etc
 
 typedef struct {
-  UINT64                                  Revision;
-  UINT8                                   HostAddressWidth;
-  UINT8                                   Reserved[3];
-  UINT32                                  VTdEngineCount;
-  UINT64                                  VTdEngineAddress[2];
+  EFI_ACPI_DMAR_HEADER                         DmarHeader;
+  //
+  // VTd engine 1 - integrated graphic
+  //
+  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd1;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER  Drhd11;
+  EFI_ACPI_DMAR_PCI_PATH                       Drhd111;
+  //
+  // VTd engine 2 - all rest
+  //
+  EFI_ACPI_DMAR_DRHD_HEADER                    Drhd2;
+  //
+  // RMRR 1 - integrated graphic
+  //
+  EFI_ACPI_DMAR_RMRR_HEADER                    Rmrr1;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER  Rmrr11;
+  EFI_ACPI_DMAR_PCI_PATH                       Rmrr111;
 } MY_VTD_INFO_PPI;
 
 MY_VTD_INFO_PPI  mPlatformVTdSample = {
-  EDKII_VTD_INFO_PPI_REVISION,
-  0x26,
-  {0},
-  2,
-  {0xFED90000, 0xFED91000},
+  { // DmarHeader
+    { // Header
+      EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+      sizeof(MY_VTD_INFO_PPI),
+      EFI_ACPI_DMAR_REVISION,
+    },
+    0x26, // HostAddressWidth
+  },
+
+  { // Drhd1
+    { // Header
+      EFI_ACPI_DMAR_TYPE_DRHD,
+      sizeof(EFI_ACPI_DMAR_DRHD_HEADER) +
+        sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
+        sizeof(EFI_ACPI_DMAR_PCI_PATH)
+    },
+    0, // Flags
+    0, // Reserved
+    0, // SegmentNumber
+    0xFED90000 // RegisterBaseAddress -- TO BE PATCHED
+  },
+  { // Drhd11
+    EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,
+    sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
+      sizeof(EFI_ACPI_DMAR_PCI_PATH),
+    0, // Reserved2
+    0, // EnumerationId
+    0  // StartBusNumber
+  },
+  { // Drhd111
+    2,  // Device
+    0   // Function
+  },
+
+  { // Drhd2
+    { // Header
+      EFI_ACPI_DMAR_TYPE_DRHD,
+      sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+    },
+    EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+    0, // Reserved
+    0, // SegmentNumber
+    0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+  },
+
+  { // Rmrr1
+    { // Header
+      EFI_ACPI_DMAR_TYPE_RMRR,
+      sizeof(EFI_ACPI_DMAR_RMRR_HEADER) +
+        sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
+        sizeof(EFI_ACPI_DMAR_PCI_PATH)
+    },
+    {0}, // Reserved
+    0, // SegmentNumber
+    0x0, // ReservedMemoryRegionBaseAddress -- TO BE PATCHED
+    0x0 // ReservedMemoryRegionLimitAddress -- TO BE PATCHED
+  },
+  { // Rmrr11
+    EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT,
+    sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER) +
+      sizeof(EFI_ACPI_DMAR_PCI_PATH),
+    0, // Reserved2
+    0, // EnumerationId
+    0  // StartBusNumber
+  },
+  { // Rmrr111
+    2,  // Device
+    0   // Function
+  },
 };
 
 EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
@@ -42,6 +132,50 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
 };
 
 /**
+  Patch Graphic UMA address in RMRR and base address.
+**/
+VOID
+PatchDmar (
+  VOID
+  )
+{
+  UINT32              MchBar;
+  UINT16              IgdMode;
+  UINT16              GttMode;
+  UINT32              IgdMemSize;
+  UINT32              GttMemSize;
+
+  ///
+  /// Calculate IGD memsize
+  ///
+  IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+  if (IgdMode < 0xF0) {
+    IgdMemSize = IgdMode * 32 * (1024) * (1024);
+  } else {
+    IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+  }
+
+  ///
+  /// Calculate GTT mem size
+  ///
+  GttMemSize = 0;
+  GttMode = PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+  if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+    GttMemSize = (1 << GttMode) * (1024) * (1024);
+  }
+
+  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress  = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+  mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+
+  ///
+  /// Update DRHD structures of DmarTable
+  ///
+  MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+  mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+  mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+}
+
+/**
   Platform VTd Info sample driver.
 
   @param[in] FileHandle  Handle of the file being invoked.
@@ -58,6 +192,8 @@ PlatformVTdInfoSampleInitialize (
 {
   EFI_STATUS  Status;
 
+  PatchDmar ();
+
   Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
   ASSERT_EFI_ERROR (Status);
 
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index fe12821..96adb70 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
@@ -39,6 +39,9 @@
 [LibraryClasses]
   PeimEntryPoint
   PeiServicesLib
+  DebugLib
+  PciLib
+  IoLib
 
 [Ppis]
   gEdkiiVTdInfoPpiGuid         ## PRODUCES
-- 
2.7.4.windows.1



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

* Re: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  2017-09-17  6:06 ` [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table Jiewen Yao
@ 2017-09-20  6:29   ` Zeng, Star
  2017-09-20  6:29     ` Zeng, Star
  0 siblings, 1 reply; 10+ messages in thread
From: Zeng, Star @ 2017-09-20  6:29 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

The typo "reset" in commit log? Should it be "reset"?

Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Sunday, September 17, 2017 2:07 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.

In order to support PEI graphic, we let VTdPmrPei driver parse DMAR table RMRR entry and allow the UMA access.

If a system has no PEI IGD, no RMRR is needed. The behavior is unchanged.

If a system has PEI IGD, it must report RMRR in PEI phase.
The PeiVTdPrm will program the IGD VTd engine to skip the RMRR region, and program the reset PCI VTd engine to skip the another DMA buffer allocated in PEI phase for other device driver.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c    |  52 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 581 +++++++++++++++++++-  IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h |  20 +-
 3 files changed, 624 insertions(+), 29 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
index ef08e29..be841aa 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
@@ -22,7 +22,7 @@
 
 #include "IntelVTdPmrPei.h"
 
-extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+extern VTD_INFO                *mVTdInfo;
 
 /**
   Get protected low memory alignment.
@@ -60,7 +60,7 @@ GetPhmrAlignment (
   UINT64        Data64;
   UINT8         HostAddressWidth;
 
-  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
+  HostAddressWidth = mVTdInfo->HostAddressWidth;
 
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
   Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG); @@ -73,11 +73,13 @@ GetPhmrAlignment (
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -85,8 +87,11 @@ GetLowMemoryAlignment (
   UINT32        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPlmrAlignment 
+ ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -97,11 +102,13 @@ GetLowMemoryAlignment (
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -109,8 +116,11 @@ GetHighMemoryAlignment (
   UINT64        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPhmrAlignment 
+ ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -246,6 +256,7 @@ SetPmrRegion (
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -256,6 +267,7 @@ SetPmrRegion (
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -265,12 +277,15 @@ SetDmaProtectedRange (
   UINTN       Index;
   EFI_STATUS  Status;
 
-  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
+  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] 
+ [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, 
+ HighMemoryBase, HighMemoryLength));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     Status = SetPmrRegion (
-               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
+               (UINTN)mVTdInfo->VTdEngineAddress[Index],
                LowMemoryBase,
                LowMemoryLength,
                HighMemoryBase,
@@ -279,7 +294,7 @@ SetDmaProtectedRange (
     if (EFI_ERROR(Status)) {
       return Status;
     }
-    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
@@ -291,11 +306,13 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN       Index;
@@ -303,8 +320,11 @@ DisableDmaProtection (
 
   DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
index d118b7e..063e8cd 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -29,7 +29,9 @@
 
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB
 
-EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;
+VTD_INFO                          *mVTdInfo;
+UINT64                            mEngineMask;
 UINTN                             mDmaBufferBase;
 UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
 UINTN                             mDmaBufferCurrentTop;
@@ -48,15 +50,19 @@ typedef struct {
 
   PEI Memory Layout:
 
+              +------------------+ <=============== PHMR.Limit (Top of memory)
+              |   Mem Resource   |
+              |                  |
+
               +------------------+ <------- EfiMemoryTop
               |   PEI allocated  |
-  =========== +==================+
+  =========== +==================+ <=============== PHMR.Base
        ^      |    Commom Buf    |
        |      |  --------------  |
   DMA Buffer  |   * DMA FREE *   |
        |      |  --------------  |
        V      |  Read/Write Buf  |
-  =========== +==================+
+  =========== +==================+ <=============== PLMR.Limit
               |   PEI allocated  |
               |  --------------  | <------- EfiFreeMemoryTop
               |   * PEI FREE *   |
@@ -70,6 +76,9 @@ typedef struct {
               |   Mem Alloc Hob  |
               +------------------+
 
+              |                  |
+              |   Mem Resource   |
+              +------------------+ <=============== PLMR.Base (0)
 **/
 
 
@@ -457,20 +466,21 @@ DumpPhitHob (
 /**
   Get the highest memory.
 
-  @param HobList  the HOB list.
-
   @return the highest memory.
 **/
 UINT64
 GetTopMemory (
-  IN VOID                        *HobList
+  VOID
   )
 {
+  VOID                        *HobList;
   EFI_PEI_HOB_POINTERS        Hob;
   EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
   UINT64                      TopMemory;
   UINT64                      ResourceTop;
 
+  HobList = GetHobList ();
+
   TopMemory = 0;
   for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { @@ -525,8 +535,8 @@ InitDmaProtection (
 
   ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
 
-  LowMemoryAlignment = GetLowMemoryAlignment ();
-  HighMemoryAlignment = GetHighMemoryAlignment ();
+  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);  
+ HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
   if (LowMemoryAlignment < HighMemoryAlignment) {
     MemoryAlignment = (UINTN)HighMemoryAlignment;
   } else {
@@ -542,9 +552,10 @@ InitDmaProtection (
   LowBottom = 0;
   LowTop = *DmaBufferBase;
   HighBottom = *DmaBufferBase + DmaBufferSize;
-  HighTop = GetTopMemory (HobList);
+  HighTop = GetTopMemory ();
 
   Status = SetDmaProtectedRange (
+               mEngineMask,
                (UINT32)LowBottom,
                (UINT32)(LowTop - LowBottom),
                HighBottom,
@@ -559,6 +570,541 @@ InitDmaProtection (  }
 
 /**
+  Dump DMAR DeviceScopeEntry.
+
+  @param[in]  DmarDeviceScopeEntry  DMAR DeviceScopeEntry **/ VOID 
+DumpDmarDeviceScopeEntry (
+  IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry
+  )
+{
+  UINTN   PciPathNumber;
+  UINTN   PciPathIndex;
+  EFI_ACPI_DMAR_PCI_PATH  *PciPath;
+
+  if (DmarDeviceScopeEntry == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *       DMA-Remapping Device Scope Entry Structure                      *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "    DMAR Device Scope Entry address ...................... 0x%016lx\n" :
+    "    DMAR Device Scope Entry address ...................... 0x%08x\n",
+    DmarDeviceScopeEntry
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Device Scope Entry Type ............................ 0x%02x\n",
+    DmarDeviceScopeEntry->Type
+    ));
+  switch (DmarDeviceScopeEntry->Type) {  case 
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Endpoint Device\n"
+      ));
+    break;
+  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Sub-hierachy\n"
+      ));
+    break;
+  default:
+    break;
+  }
+  DEBUG ((DEBUG_INFO,
+    "      Length ............................................. 0x%02x\n",
+    DmarDeviceScopeEntry->Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Enumeration ID ..................................... 0x%02x\n",
+    DmarDeviceScopeEntry->EnumerationId
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Starting Bus Number ................................ 0x%02x\n",
+    DmarDeviceScopeEntry->StartBusNumber
+    ));
+
+  PciPathNumber = (DmarDeviceScopeEntry->Length - 
+ sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / 
+ sizeof(EFI_ACPI_DMAR_PCI_PATH);  PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);  for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
+    DEBUG ((DEBUG_INFO,
+      "      Device ............................................. 0x%02x\n",
+      PciPath[PciPathIndex].Device
+      ));
+    DEBUG ((DEBUG_INFO,
+      "      Function ........................................... 0x%02x\n",
+      PciPath[PciPathIndex].Function
+      ));
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR RMRR table.
+
+  @param[in]  Rmrr  DMAR RMRR table
+**/
+VOID
+DumpDmarRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    RmrrLen;
+
+  if (Rmrr == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       Reserved Memory Region Reporting Structure                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  RMRR address ........................................... 0x%016lx\n" :
+    "  RMRR address ........................................... 0x%08x\n",
+    Rmrr
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Rmrr->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Rmrr->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Rmrr->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionBaseAddress
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionLimitAddress
+    ));
+
+  RmrrLen  = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)(Rmrr + 1);  while (RmrrLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    RmrrLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR DRHD table.
+
+  @param[in]  Drhd  DMAR DRHD table
+**/
+VOID
+DumpDmarDrhd (
+  IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    DrhdLen;
+
+  if (Drhd == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       DMA-Remapping Hardware Definition Structure                       *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  DRHD address ........................................... 0x%016lx\n" :
+    "  DRHD address ........................................... 0x%08x\n",
+    Drhd
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Drhd->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Drhd->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Drhd->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INCLUDE_PCI_ALL .................................... 0x%02x\n",
+    Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Drhd->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Register Base Address ................................ 0x%016lx\n",
+    Drhd->RegisterBaseAddress
+    ));
+
+  DrhdLen  = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)(Drhd + 1);  while (DrhdLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    DrhdLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR ACPI table.
+
+  @param[in]  Dmar  DMAR ACPI table
+**/
+VOID
+DumpAcpiDMAR (
+  IN EFI_ACPI_DMAR_HEADER  *Dmar
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+  INTN                  DmarLen;
+
+  if (Dmar == NULL) {
+    return;
+  }
+
+  //
+  // Dump Dmar table
+  //
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*         DMAR Table                                                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "DMAR address ............................................. 0x%016lx\n" :
+    "DMAR address ............................................. 0x%08x\n",
+    Dmar
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    "  Table Contents:\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Host Address Width ................................... 0x%02x\n",
+    Dmar->HostAddressWidth
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Dmar->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INTR_REMAP ......................................... 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
+    ));
+
+  DmarLen  = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);  
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);  while 
+ (DmarLen > 0) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      break;
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarLen -= DmarHeader->Length;
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+ DmarHeader->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Get VTd engine number.
+
+  @return the VTd engine number.
+**/
+UINTN
+GetVtdEngineNumber (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      VtdIndex++;
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+  return VtdIndex ;
+}
+
+/**
+  Process DMAR DHRD table.
+
+  @param[in]  VtdIndex  The index of VTd engine.
+  @param[in]  DmarDrhd  The DRHD table.
+**/
+VOID
+ProcessDhrd (
+  IN UINTN                      VtdIndex,
+  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  )
+{
+  DEBUG ((DEBUG_INFO,"  VTD (%d) BaseAddress -  0x%016lx\n", VtdIndex, 
+DmarDrhd->RegisterBaseAddress));
+  mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress; 
+}
+
+/**
+  Parse DMAR DRHD table.
+
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
+**/
+EFI_STATUS
+ParseDmarAcpiTableDrhd (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdUnitNumber;
+  UINTN                                             VtdIndex;
+
+  VtdUnitNumber = GetVtdEngineNumber ();  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * 
+ sizeof(UINT64));  if (mVTdInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
+  mVTdInfo->VTdEngineCount   = VtdUnitNumber;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+ *)((UINTN)(mAcpiDmarTable + 1));  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      ASSERT (VtdIndex < VtdUnitNumber);
+      ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      VtdIndex++;
+
+      break;
+
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+ DmarHeader->Length);  }  ASSERT (VtdIndex == VtdUnitNumber);
+
+  //
+  // Initialize the engine mask to all.
+  //
+  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the VTd engine index according to the Segment and DevScopeEntry.
+
+  @param Segment         The segment of the VTd engine
+  @param DevScopeEntry   The DevScopeEntry of the VTd engine
+
+  @return The VTd engine index according to the Segment and DevScopeEntry.
+  @retval -1  The VTd engine is not found.
+**/
+UINTN
+GetVTdEngineFromDevScopeEntry (
+  IN  UINT16                                      Segment,
+  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+  EFI_ACPI_DMAR_DRHD_HEADER                         *DmarDrhd;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *ThisDevScopeEntry;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
+      if (DmarDrhd->SegmentNumber != Segment) {
+        // Mismatch
+        break;
+      }
+      if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
+          ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
+        // No DevScopeEntry
+        // Do not handle PCI_ALL
+        break;
+      }
+      ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
+      while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
+        if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
+            (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
+          return VtdIndex;
+        }
+        ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
+      }
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+  return (UINTN)-1;
+}
+
+/**
+  Process DMAR RMRR table.
+
+  @param[in]  DmarRmrr  The RMRR table.
+**/
+VOID
+ProcessRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER  *DmarRmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDevScopeEntry;
+  UINTN                                             VTdIndex;
+  UINT64                                            RmrrMask;
+  UINTN                                             LowBottom;
+  UINTN                                             LowTop;
+  UINTN                                             HighBottom;
+  UINT64                                            HighTop;
+
+  DEBUG ((DEBUG_INFO,"  RMRR (Base 0x%016lx, Limit 0x%016lx)\n", 
+ DmarRmrr->ReservedMemoryRegionBaseAddress, 
+ DmarRmrr->ReservedMemoryRegionLimitAddress));
+
+  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
+      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
+    return ;
+  }
+
+  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)((UINTN)(DmarRmrr + 1));  while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
+    ASSERT (DmarDevScopeEntry->Type == 
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
+
+    VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
+    if (VTdIndex != (UINTN)-1) {
+      RmrrMask = LShiftU64 (1, VTdIndex);
+
+      LowBottom = 0;
+      LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
+      HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
+      HighTop = GetTopMemory ();
+
+      SetDmaProtectedRange (
+        RmrrMask,
+        0,
+        (UINT32)(LowTop - LowBottom),
+        HighBottom,
+        HighTop - HighBottom
+        );
+
+      //
+      // Remove the engine from the engine mask.
+      // The assumption is that any other PEI driver does not access
+      // the device covered by this engine.
+      //
+      mEngineMask = mEngineMask & (~RmrrMask);
+    }
+
+    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+*)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+  }
+}
+
+/**
+  Parse DMAR DRHD table.
+**/
+VOID
+ParseDmarAcpiTableRmrr (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+}
+
+/**
   Initializes the Intel VTd PMR PEIM.
 
   @param  FileHandle  Handle of the file being invoked.
@@ -585,10 +1131,25 @@ IntelVTdPmrInitialize (
              &gEdkiiVTdInfoPpiGuid,
              0,
              NULL,
-             (VOID **)&mVTdInfoPpi
+             (VOID **)&mAcpiDmarTable
              );
   ASSERT_EFI_ERROR(Status);
 
+  DumpAcpiDMAR (mAcpiDmarTable);
+
+  //
+  // Get DMAR information to local VTdInfo  //  Status = 
+ ParseDmarAcpiTableDrhd ();  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // If there is RMRR memory, parse it here.
+  //
+  ParseDmarAcpiTableRmrr ();
+
   //
   // Find a pre-memory in resource hob as DMA buffer
   // Mark PEI memory to be DMA protected.
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
index aa5926a7..720f5d4 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -15,9 +15,16 @@
 #ifndef __DMA_ACCESS_LIB_H__
 #define __DMA_ACCESS_LIB_H__
 
+typedef struct {
+  UINT8                                   HostAddressWidth;
+  UINTN                                   VTdEngineCount;
+  UINT64                                  VTdEngineAddress[1];
+} VTD_INFO;
+
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -28,6 +35,7 @@
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -37,31 +45,37 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 #endif
--
2.7.4.windows.1



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

* Re: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  2017-09-20  6:29   ` Zeng, Star
@ 2017-09-20  6:29     ` Zeng, Star
  2017-09-20  6:33       ` Yao, Jiewen
  0 siblings, 1 reply; 10+ messages in thread
From: Zeng, Star @ 2017-09-20  6:29 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Sorry, should it be "rest"?

-----Original Message-----
From: Zeng, Star 
Sent: Wednesday, September 20, 2017 2:29 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.

The typo "reset" in commit log? Should it be "reset"?

Thanks,
Star
-----Original Message-----
From: Yao, Jiewen
Sent: Sunday, September 17, 2017 2:07 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.

In order to support PEI graphic, we let VTdPmrPei driver parse DMAR table RMRR entry and allow the UMA access.

If a system has no PEI IGD, no RMRR is needed. The behavior is unchanged.

If a system has PEI IGD, it must report RMRR in PEI phase.
The PeiVTdPrm will program the IGD VTd engine to skip the RMRR region, and program the reset PCI VTd engine to skip the another DMA buffer allocated in PEI phase for other device driver.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c    |  52 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 581 +++++++++++++++++++-  IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h |  20 +-
 3 files changed, 624 insertions(+), 29 deletions(-)

diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
index ef08e29..be841aa 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
@@ -22,7 +22,7 @@
 
 #include "IntelVTdPmrPei.h"
 
-extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+extern VTD_INFO                *mVTdInfo;
 
 /**
   Get protected low memory alignment.
@@ -60,7 +60,7 @@ GetPhmrAlignment (
   UINT64        Data64;
   UINT8         HostAddressWidth;
 
-  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
+  HostAddressWidth = mVTdInfo->HostAddressWidth;
 
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
   Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG); @@ -73,11 +73,13 @@ GetPhmrAlignment (
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -85,8 +87,11 @@ GetLowMemoryAlignment (
   UINT32        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPlmrAlignment
+ ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -97,11 +102,13 @@ GetLowMemoryAlignment (
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN         Index;
@@ -109,8 +116,11 @@ GetHighMemoryAlignment (
   UINT64        FinalAlignment;
 
   FinalAlignment = 0;
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Alignment = GetPhmrAlignment
+ ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (FinalAlignment < Alignment) {
       FinalAlignment = Alignment;
     }
@@ -246,6 +256,7 @@ SetPmrRegion (
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -256,6 +267,7 @@ SetPmrRegion (
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -265,12 +277,15 @@ SetDmaProtectedRange (
   UINTN       Index;
   EFI_STATUS  Status;
 
-  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
+  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] 
+ [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, 
+ HighMemoryBase, HighMemoryLength));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     Status = SetPmrRegion (
-               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
+               (UINTN)mVTdInfo->VTdEngineAddress[Index],
                LowMemoryBase,
                LowMemoryLength,
                HighMemoryBase,
@@ -279,7 +294,7 @@ SetDmaProtectedRange (
     if (EFI_ERROR(Status)) {
       return Status;
     }
-    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
@@ -291,11 +306,13 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   )
 {
   UINTN       Index;
@@ -303,8 +320,11 @@ DisableDmaProtection (
 
   DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
 
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
-    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {
+      continue;
+    }
+    Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
     if (EFI_ERROR(Status)) {
       return Status;
     }
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
index d118b7e..063e8cd 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -29,7 +29,9 @@
 
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB
 
-EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;
+VTD_INFO                          *mVTdInfo;
+UINT64                            mEngineMask;
 UINTN                             mDmaBufferBase;
 UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
 UINTN                             mDmaBufferCurrentTop;
@@ -48,15 +50,19 @@ typedef struct {
 
   PEI Memory Layout:
 
+              +------------------+ <=============== PHMR.Limit (Top of memory)
+              |   Mem Resource   |
+              |                  |
+
               +------------------+ <------- EfiMemoryTop
               |   PEI allocated  |
-  =========== +==================+
+  =========== +==================+ <=============== PHMR.Base
        ^      |    Commom Buf    |
        |      |  --------------  |
   DMA Buffer  |   * DMA FREE *   |
        |      |  --------------  |
        V      |  Read/Write Buf  |
-  =========== +==================+
+  =========== +==================+ <=============== PLMR.Limit
               |   PEI allocated  |
               |  --------------  | <------- EfiFreeMemoryTop
               |   * PEI FREE *   |
@@ -70,6 +76,9 @@ typedef struct {
               |   Mem Alloc Hob  |
               +------------------+
 
+              |                  |
+              |   Mem Resource   |
+              +------------------+ <=============== PLMR.Base (0)
 **/
 
 
@@ -457,20 +466,21 @@ DumpPhitHob (
 /**
   Get the highest memory.
 
-  @param HobList  the HOB list.
-
   @return the highest memory.
 **/
 UINT64
 GetTopMemory (
-  IN VOID                        *HobList
+  VOID
   )
 {
+  VOID                        *HobList;
   EFI_PEI_HOB_POINTERS        Hob;
   EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
   UINT64                      TopMemory;
   UINT64                      ResourceTop;
 
+  HobList = GetHobList ();
+
   TopMemory = 0;
   for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {
     if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { @@ -525,8 +535,8 @@ InitDmaProtection (
 
   ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
 
-  LowMemoryAlignment = GetLowMemoryAlignment ();
-  HighMemoryAlignment = GetHighMemoryAlignment ();
+  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask); 
+ HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
   if (LowMemoryAlignment < HighMemoryAlignment) {
     MemoryAlignment = (UINTN)HighMemoryAlignment;
   } else {
@@ -542,9 +552,10 @@ InitDmaProtection (
   LowBottom = 0;
   LowTop = *DmaBufferBase;
   HighBottom = *DmaBufferBase + DmaBufferSize;
-  HighTop = GetTopMemory (HobList);
+  HighTop = GetTopMemory ();
 
   Status = SetDmaProtectedRange (
+               mEngineMask,
                (UINT32)LowBottom,
                (UINT32)(LowTop - LowBottom),
                HighBottom,
@@ -559,6 +570,541 @@ InitDmaProtection (  }
 
 /**
+  Dump DMAR DeviceScopeEntry.
+
+  @param[in]  DmarDeviceScopeEntry  DMAR DeviceScopeEntry **/ VOID 
+DumpDmarDeviceScopeEntry (
+  IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER     *DmarDeviceScopeEntry
+  )
+{
+  UINTN   PciPathNumber;
+  UINTN   PciPathIndex;
+  EFI_ACPI_DMAR_PCI_PATH  *PciPath;
+
+  if (DmarDeviceScopeEntry == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *       DMA-Remapping Device Scope Entry Structure                      *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "    DMAR Device Scope Entry address ...................... 0x%016lx\n" :
+    "    DMAR Device Scope Entry address ...................... 0x%08x\n",
+    DmarDeviceScopeEntry
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Device Scope Entry Type ............................ 0x%02x\n",
+    DmarDeviceScopeEntry->Type
+    ));
+  switch (DmarDeviceScopeEntry->Type) {  case
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Endpoint Device\n"
+      ));
+    break;
+  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
+    DEBUG ((DEBUG_INFO,
+      "        PCI Sub-hierachy\n"
+      ));
+    break;
+  default:
+    break;
+  }
+  DEBUG ((DEBUG_INFO,
+    "      Length ............................................. 0x%02x\n",
+    DmarDeviceScopeEntry->Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Enumeration ID ..................................... 0x%02x\n",
+    DmarDeviceScopeEntry->EnumerationId
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      Starting Bus Number ................................ 0x%02x\n",
+    DmarDeviceScopeEntry->StartBusNumber
+    ));
+
+  PciPathNumber = (DmarDeviceScopeEntry->Length -
+ sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / 
+ sizeof(EFI_ACPI_DMAR_PCI_PATH);  PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);  for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
+    DEBUG ((DEBUG_INFO,
+      "      Device ............................................. 0x%02x\n",
+      PciPath[PciPathIndex].Device
+      ));
+    DEBUG ((DEBUG_INFO,
+      "      Function ........................................... 0x%02x\n",
+      PciPath[PciPathIndex].Function
+      ));
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "    *************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR RMRR table.
+
+  @param[in]  Rmrr  DMAR RMRR table
+**/
+VOID
+DumpDmarRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    RmrrLen;
+
+  if (Rmrr == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       Reserved Memory Region Reporting Structure                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  RMRR address ........................................... 0x%016lx\n" :
+    "  RMRR address ........................................... 0x%08x\n",
+    Rmrr
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Rmrr->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Rmrr->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Rmrr->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionBaseAddress
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
+    Rmrr->ReservedMemoryRegionLimitAddress
+    ));
+
+  RmrrLen  = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
+ *)(Rmrr + 1);  while (RmrrLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    RmrrLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
+ *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR DRHD table.
+
+  @param[in]  Drhd  DMAR DRHD table
+**/
+VOID
+DumpDmarDrhd (
+  IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDeviceScopeEntry;
+  INTN                                    DrhdLen;
+
+  if (Drhd == NULL) {
+    return;
+  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  *       DMA-Remapping Hardware Definition Structure                       *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "  DRHD address ........................................... 0x%016lx\n" :
+    "  DRHD address ........................................... 0x%08x\n",
+    Drhd
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Type ................................................. 0x%04x\n",
+    Drhd->Header.Type
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Length ............................................... 0x%04x\n",
+    Drhd->Header.Length
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Drhd->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INCLUDE_PCI_ALL .................................... 0x%02x\n",
+    Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Segment Number ....................................... 0x%04x\n",
+    Drhd->SegmentNumber
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Register Base Address ................................ 0x%016lx\n",
+    Drhd->RegisterBaseAddress
+    ));
+
+  DrhdLen  = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
+  DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
+ *)(Drhd + 1);  while (DrhdLen > 0) {
+    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
+    DrhdLen -= DmarDeviceScopeEntry->Length;
+    DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
+ *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "  ***************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Dump DMAR ACPI table.
+
+  @param[in]  Dmar  DMAR ACPI table
+**/
+VOID
+DumpAcpiDMAR (
+  IN EFI_ACPI_DMAR_HEADER  *Dmar
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
+  INTN                  DmarLen;
+
+  if (Dmar == NULL) {
+    return;
+  }
+
+  //
+  // Dump Dmar table
+  //
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*         DMAR Table                                                        *\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n"
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    (sizeof(UINTN) == sizeof(UINT64)) ?
+    "DMAR address ............................................. 0x%016lx\n" :
+    "DMAR address ............................................. 0x%08x\n",
+    Dmar
+    ));
+
+  DEBUG ((DEBUG_INFO,
+    "  Table Contents:\n"
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Host Address Width ................................... 0x%02x\n",
+    Dmar->HostAddressWidth
+    ));
+  DEBUG ((DEBUG_INFO,
+    "    Flags ................................................ 0x%02x\n",
+    Dmar->Flags
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      INTR_REMAP ......................................... 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
+    ));
+  DEBUG ((DEBUG_INFO,
+    "      X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
+    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
+    ));
+
+  DmarLen  = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER); 
+ DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);  while 
+ (DmarLen > 0) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      break;
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarLen -= DmarHeader->Length;
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader +
+ DmarHeader->Length);  }
+
+  DEBUG ((DEBUG_INFO,
+    "*****************************************************************************\n\n"
+    ));
+
+  return;
+}
+
+/**
+  Get VTd engine number.
+
+  @return the VTd engine number.
+**/
+UINTN
+GetVtdEngineNumber (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      VtdIndex++;
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+  return VtdIndex ;
+}
+
+/**
+  Process DMAR DHRD table.
+
+  @param[in]  VtdIndex  The index of VTd engine.
+  @param[in]  DmarDrhd  The DRHD table.
+**/
+VOID
+ProcessDhrd (
+  IN UINTN                      VtdIndex,
+  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
+  )
+{
+  DEBUG ((DEBUG_INFO,"  VTD (%d) BaseAddress -  0x%016lx\n", VtdIndex, 
+DmarDrhd->RegisterBaseAddress));
+  mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress; 
+}
+
+/**
+  Parse DMAR DRHD table.
+
+  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
+**/
+EFI_STATUS
+ParseDmarAcpiTableDrhd (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdUnitNumber;
+  UINTN                                             VtdIndex;
+
+  VtdUnitNumber = GetVtdEngineNumber ();  if (VtdUnitNumber == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * 
+ sizeof(UINT64));  if (mVTdInfo == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+  mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
+  mVTdInfo->VTdEngineCount   = VtdUnitNumber;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+ *)((UINTN)(mAcpiDmarTable + 1));  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      ASSERT (VtdIndex < VtdUnitNumber);
+      ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
+      VtdIndex++;
+
+      break;
+
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+ DmarHeader->Length);  }  ASSERT (VtdIndex == VtdUnitNumber);
+
+  //
+  // Initialize the engine mask to all.
+  //
+  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Return the VTd engine index according to the Segment and DevScopeEntry.
+
+  @param Segment         The segment of the VTd engine
+  @param DevScopeEntry   The DevScopeEntry of the VTd engine
+
+  @return The VTd engine index according to the Segment and DevScopeEntry.
+  @retval -1  The VTd engine is not found.
+**/
+UINTN
+GetVTdEngineFromDevScopeEntry (
+  IN  UINT16                                      Segment,
+  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+  UINTN                                             VtdIndex;
+  EFI_ACPI_DMAR_DRHD_HEADER                         *DmarDrhd;
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *ThisDevScopeEntry;
+
+  VtdIndex = 0;
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_DRHD:
+      DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
+      if (DmarDrhd->SegmentNumber != Segment) {
+        // Mismatch
+        break;
+      }
+      if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
+          ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
+        // No DevScopeEntry
+        // Do not handle PCI_ALL
+        break;
+      }
+      ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
+      while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
+        if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
+            (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
+          return VtdIndex;
+        }
+        ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
+      }
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+  return (UINTN)-1;
+}
+
+/**
+  Process DMAR RMRR table.
+
+  @param[in]  DmarRmrr  The RMRR table.
+**/
+VOID
+ProcessRmrr (
+  IN EFI_ACPI_DMAR_RMRR_HEADER  *DmarRmrr
+  )
+{
+  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER       *DmarDevScopeEntry;
+  UINTN                                             VTdIndex;
+  UINT64                                            RmrrMask;
+  UINTN                                             LowBottom;
+  UINTN                                             LowTop;
+  UINTN                                             HighBottom;
+  UINT64                                            HighTop;
+
+  DEBUG ((DEBUG_INFO,"  RMRR (Base 0x%016lx, Limit 0x%016lx)\n", 
+ DmarRmrr->ReservedMemoryRegionBaseAddress, 
+ DmarRmrr->ReservedMemoryRegionLimitAddress));
+
+  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
+      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
+    return ;
+  }
+
+  DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+ *)((UINTN)(DmarRmrr + 1));  while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
+    ASSERT (DmarDevScopeEntry->Type == 
+ EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
+
+    VTdIndex = GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
+    if (VTdIndex != (UINTN)-1) {
+      RmrrMask = LShiftU64 (1, VTdIndex);
+
+      LowBottom = 0;
+      LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
+      HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
+      HighTop = GetTopMemory ();
+
+      SetDmaProtectedRange (
+        RmrrMask,
+        0,
+        (UINT32)(LowTop - LowBottom),
+        HighBottom,
+        HighTop - HighBottom
+        );
+
+      //
+      // Remove the engine from the engine mask.
+      // The assumption is that any other PEI driver does not access
+      // the device covered by this engine.
+      //
+      mEngineMask = mEngineMask & (~RmrrMask);
+    }
+
+    DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER 
+*)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+  }
+}
+
+/**
+  Parse DMAR DRHD table.
+**/
+VOID
+ParseDmarAcpiTableRmrr (
+  VOID
+  )
+{
+  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
+
+  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER 
+*)((UINTN)(mAcpiDmarTable + 1));
+  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
+    switch (DmarHeader->Type) {
+    case EFI_ACPI_DMAR_TYPE_RMRR:
+      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
+      break;
+    default:
+      break;
+    }
+    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + 
+DmarHeader->Length);
+  }
+}
+
+/**
   Initializes the Intel VTd PMR PEIM.
 
   @param  FileHandle  Handle of the file being invoked.
@@ -585,10 +1131,25 @@ IntelVTdPmrInitialize (
              &gEdkiiVTdInfoPpiGuid,
              0,
              NULL,
-             (VOID **)&mVTdInfoPpi
+             (VOID **)&mAcpiDmarTable
              );
   ASSERT_EFI_ERROR(Status);
 
+  DumpAcpiDMAR (mAcpiDmarTable);
+
+  //
+  // Get DMAR information to local VTdInfo  //  Status = 
+ ParseDmarAcpiTableDrhd ();  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  //
+  // If there is RMRR memory, parse it here.
+  //
+  ParseDmarAcpiTableRmrr ();
+
   //
   // Find a pre-memory in resource hob as DMA buffer
   // Mark PEI memory to be DMA protected.
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
index aa5926a7..720f5d4 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -15,9 +15,16 @@
 #ifndef __DMA_ACCESS_LIB_H__
 #define __DMA_ACCESS_LIB_H__
 
+typedef struct {
+  UINT8                                   HostAddressWidth;
+  UINTN                                   VTdEngineCount;
+  UINT64                                  VTdEngineAddress[1];
+} VTD_INFO;
+
 /**
   Set DMA protected region.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
   @param LowMemoryBase      The protected low memory region base.
   @param LowMemoryLength    The protected low memory region length.
   @param HighMemoryBase     The protected high memory region base.
@@ -28,6 +35,7 @@
 **/
 EFI_STATUS
 SetDmaProtectedRange (
+  IN UINT64        EngineMask,
   IN UINT32        LowMemoryBase,
   IN UINT32        LowMemoryLength,
   IN UINT64        HighMemoryBase,
@@ -37,31 +45,37 @@ SetDmaProtectedRange (
 /**
   Diable DMA protection.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @retval DMA protection is disabled.
 **/
 EFI_STATUS
 DisableDmaProtection (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected low memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected low memory alignment.
 **/
 UINT32
 GetLowMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 /**
   Get protected high memory alignment.
 
+  @param EngineMask         The mask of the VTd engine to be accessed.
+
   @return protected high memory alignment.
 **/
 UINT64
 GetHighMemoryAlignment (
-  VOID
+  IN UINT64        EngineMask
   );
 
 #endif
--
2.7.4.windows.1



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

* Re: [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
  2017-09-17  6:06 ` [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table Jiewen Yao
@ 2017-09-20  6:30   ` Zeng, Star
  2017-09-20  6:33     ` Yao, Jiewen
  0 siblings, 1 reply; 10+ messages in thread
From: Zeng, Star @ 2017-09-20  6:30 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

I think we'd better to add #include <IndustryStandard/Acpi.h> in DmaRemappingReportingTable.h, but not VtdInfo.h.

Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Sunday, September 17, 2017 2:07 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.

We notice that there is real usage in PEI to show the graphic output. As such we need report RMRR table in PEI to let VTdPmrPei driver skip the IGD UMA region.

Now the VTD_INFO PPI uses the same DMAR data structure.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/Include/Ppi/VtdInfo.h | 26 +++++++++++---------
 1 file changed, 15 insertions(+), 11 deletions(-)

diff --git a/IntelSiliconPkg/Include/Ppi/VtdInfo.h b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
index e8be63f..a0a6f9c 100644
--- a/IntelSiliconPkg/Include/Ppi/VtdInfo.h
+++ b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
@@ -17,22 +17,26 @@
 #ifndef __VTD_INFO_PPI_H__
 #define __VTD_INFO_PPI_H__
 
+#include <IndustryStandard/Acpi.h>
+#include <IndustryStandard/DmaRemappingReportingTable.h>
+
 #define EDKII_VTD_INFO_PPI_GUID \
     { \
       0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } \
     }
 
-typedef struct _EDKII_VTD_INFO_PPI  EDKII_VTD_INFO_PPI;
-
-#define EDKII_VTD_INFO_PPI_REVISION 0x00010000
-
-struct _EDKII_VTD_INFO_PPI {
-  UINT64                                  Revision;
-  UINT8                                   HostAddressWidth;
-  UINT8                                   Reserved[3];
-  UINT32                                  VTdEngineCount;
-  UINT64                                  VTdEngineAddress[1];
-};
+//
+// VTD info PPI just use same data structure as DMAR table.
+//
+// The reported information must include what is needed in PEI phase, e.g.
+//   the VTd engine (such as DRHD)
+//   the reserved DMA address in PEI for eary graphic (such as RMRR for graphic UMA)
+//
+// The reported information can be and might be a subset of full DMAR table, e.g.
+//   if some data is not avaiable (such as ANDD),
+//   if some data is not needed (such as RMRR for legacy USB).
+//
+typedef EFI_ACPI_DMAR_HEADER EDKII_VTD_INFO_PPI;
 
 extern EFI_GUID gEdkiiVTdInfoPpiGuid;
 
--
2.7.4.windows.1



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

* Re: [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI
  2017-09-17  6:06 [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Jiewen Yao
                   ` (2 preceding siblings ...)
  2017-09-17  6:06 ` [PATCH 3/3] IntelSiliconPkg/VTdInfoSample: Add " Jiewen Yao
@ 2017-09-20  6:30 ` Zeng, Star
  3 siblings, 0 replies; 10+ messages in thread
From: Zeng, Star @ 2017-09-20  6:30 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Minor comments added for separated patches, with that fixed, Reviewed-by: Star Zeng <star.zeng@intel.com>


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Sunday, September 17, 2017 2:07 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI

We notice that there is real usage in PEI to show the graphic output.
The Integrated Graphic Device is blocked by current IntelVTdPei because the DMA buffer is fully controlled by VTd PEIM. The UMA is not allowed.

In DXE phase, the UMA is reported via RMRR table.

As such, we need similar way in PEI to let VTd PEI get the RMRR information.

This series patch resolves this problem.

We also updated sample driver to show how to get the RMRR information.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>

Jiewen Yao (3):
  IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
  IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  IntelSiliconPkg/VTdInfoSample: Add RMRR table.

 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c                          |  52 +-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c                       | 581 +++++++++++++++++++-
 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h                       |  20 +-
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c   | 156 +++++-
 IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf |   3 +
 IntelSiliconPkg/Include/Ppi/VtdInfo.h                                             |  26 +-
 6 files changed, 788 insertions(+), 50 deletions(-)

--
2.7.4.windows.1



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

* Re: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
  2017-09-20  6:29     ` Zeng, Star
@ 2017-09-20  6:33       ` Yao, Jiewen
  0 siblings, 0 replies; 10+ messages in thread
From: Yao, Jiewen @ 2017-09-20  6:33 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

Yes, Typo. will be fixed.

> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, September 20, 2017 2:30 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
> 
> Sorry, should it be "rest"?
> 
> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, September 20, 2017 2:29 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
> 
> The typo "reset" in commit log? Should it be "reset"?
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Sunday, September 17, 2017 2:07 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table.
> 
> In order to support PEI graphic, we let VTdPmrPei driver parse DMAR table RMRR
> entry and allow the UMA access.
> 
> If a system has no PEI IGD, no RMRR is needed. The behavior is unchanged.
> 
> If a system has PEI IGD, it must report RMRR in PEI phase.
> The PeiVTdPrm will program the IGD VTd engine to skip the RMRR region, and
> program the reset PCI VTd engine to skip the another DMA buffer allocated in PEI
> phase for other device driver.
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c    |  52 +-
>  IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 581
> +++++++++++++++++++-
> IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h |  20 +-
>  3 files changed, 624 insertions(+), 29 deletions(-)
> 
> diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
> b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
> index ef08e29..be841aa 100644
> --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
> +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
> @@ -22,7 +22,7 @@
> 
>  #include "IntelVTdPmrPei.h"
> 
> -extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
> +extern VTD_INFO                *mVTdInfo;
> 
>  /**
>    Get protected low memory alignment.
> @@ -60,7 +60,7 @@ GetPhmrAlignment (
>    UINT64        Data64;
>    UINT8         HostAddressWidth;
> 
> -  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
> +  HostAddressWidth = mVTdInfo->HostAddressWidth;
> 
>    MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG,
> 0xFFFFFFFFFFFFFFFF);
>    Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
> @@ -73,11 +73,13 @@ GetPhmrAlignment (
>  /**
>    Get protected low memory alignment.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @return protected low memory alignment.
>  **/
>  UINT32
>  GetLowMemoryAlignment (
> -  VOID
> +  IN UINT64        EngineMask
>    )
>  {
>    UINTN         Index;
> @@ -85,8 +87,11 @@ GetLowMemoryAlignment (
>    UINT32        FinalAlignment;
> 
>    FinalAlignment = 0;
> -  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
> -    Alignment = GetPlmrAlignment
> ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
> +  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
> +    if ((EngineMask & LShiftU64(1, Index)) == 0) {
> +      continue;
> +    }
> +    Alignment = GetPlmrAlignment
> + ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
>      if (FinalAlignment < Alignment) {
>        FinalAlignment = Alignment;
>      }
> @@ -97,11 +102,13 @@ GetLowMemoryAlignment (
>  /**
>    Get protected high memory alignment.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @return protected high memory alignment.
>  **/
>  UINT64
>  GetHighMemoryAlignment (
> -  VOID
> +  IN UINT64        EngineMask
>    )
>  {
>    UINTN         Index;
> @@ -109,8 +116,11 @@ GetHighMemoryAlignment (
>    UINT64        FinalAlignment;
> 
>    FinalAlignment = 0;
> -  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
> -    Alignment = GetPhmrAlignment
> ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
> +  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
> +    if ((EngineMask & LShiftU64(1, Index)) == 0) {
> +      continue;
> +    }
> +    Alignment = GetPhmrAlignment
> + ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
>      if (FinalAlignment < Alignment) {
>        FinalAlignment = Alignment;
>      }
> @@ -246,6 +256,7 @@ SetPmrRegion (
>  /**
>    Set DMA protected region.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
>    @param LowMemoryBase      The protected low memory region base.
>    @param LowMemoryLength    The protected low memory region length.
>    @param HighMemoryBase     The protected high memory region base.
> @@ -256,6 +267,7 @@ SetPmrRegion (
>  **/
>  EFI_STATUS
>  SetDmaProtectedRange (
> +  IN UINT64        EngineMask,
>    IN UINT32        LowMemoryBase,
>    IN UINT32        LowMemoryLength,
>    IN UINT64        HighMemoryBase,
> @@ -265,12 +277,15 @@ SetDmaProtectedRange (
>    UINTN       Index;
>    EFI_STATUS  Status;
> 
> -  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx,
> 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase,
> HighMemoryLength));
> +  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x]
> + [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength,
> + HighMemoryBase, HighMemoryLength));
> 
> -  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
> -    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
> +  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
> +    if ((EngineMask & LShiftU64(1, Index)) == 0) {
> +      continue;
> +    }
> +    DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
>      Status = SetPmrRegion (
> -               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
> +               (UINTN)mVTdInfo->VTdEngineAddress[Index],
>                 LowMemoryBase,
>                 LowMemoryLength,
>                 HighMemoryBase,
> @@ -279,7 +294,7 @@ SetDmaProtectedRange (
>      if (EFI_ERROR(Status)) {
>        return Status;
>      }
> -    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
> +    Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
>      if (EFI_ERROR(Status)) {
>        return Status;
>      }
> @@ -291,11 +306,13 @@ SetDmaProtectedRange (
>  /**
>    Diable DMA protection.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @retval DMA protection is disabled.
>  **/
>  EFI_STATUS
>  DisableDmaProtection (
> -  VOID
> +  IN UINT64        EngineMask
>    )
>  {
>    UINTN       Index;
> @@ -303,8 +320,11 @@ DisableDmaProtection (
> 
>    DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
> 
> -  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
> -    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
> +  for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
> +    if ((EngineMask & LShiftU64(1, Index)) == 0) {
> +      continue;
> +    }
> +    Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
>      if (EFI_ERROR(Status)) {
>        return Status;
>      }
> diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
> b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
> index d118b7e..063e8cd 100644
> --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
> +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
> @@ -29,7 +29,9 @@
> 
>  #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB
> 
> -EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
> +EFI_ACPI_DMAR_HEADER              *mAcpiDmarTable;
> +VTD_INFO                          *mVTdInfo;
> +UINT64                            mEngineMask;
>  UINTN                             mDmaBufferBase;
>  UINTN                             mDmaBufferSize =
> TOTAL_DMA_BUFFER_SIZE;
>  UINTN                             mDmaBufferCurrentTop;
> @@ -48,15 +50,19 @@ typedef struct {
> 
>    PEI Memory Layout:
> 
> +              +------------------+ <=============== PHMR.Limit (Top of
> memory)
> +              |   Mem Resource   |
> +              |                  |
> +
>                +------------------+ <------- EfiMemoryTop
>                |   PEI allocated  |
> -  =========== +==================+
> +  =========== +==================+ <=============== PHMR.Base
>         ^      |    Commom Buf    |
>         |      |  --------------  |
>    DMA Buffer  |   * DMA FREE *   |
>         |      |  --------------  |
>         V      |  Read/Write Buf  |
> -  =========== +==================+
> +  =========== +==================+ <=============== PLMR.Limit
>                |   PEI allocated  |
>                |  --------------  | <------- EfiFreeMemoryTop
>                |   * PEI FREE *   |
> @@ -70,6 +76,9 @@ typedef struct {
>                |   Mem Alloc Hob  |
>                +------------------+
> 
> +              |                  |
> +              |   Mem Resource   |
> +              +------------------+ <=============== PLMR.Base (0)
>  **/
> 
> 
> @@ -457,20 +466,21 @@ DumpPhitHob (
>  /**
>    Get the highest memory.
> 
> -  @param HobList  the HOB list.
> -
>    @return the highest memory.
>  **/
>  UINT64
>  GetTopMemory (
> -  IN VOID                        *HobList
> +  VOID
>    )
>  {
> +  VOID                        *HobList;
>    EFI_PEI_HOB_POINTERS        Hob;
>    EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
>    UINT64                      TopMemory;
>    UINT64                      ResourceTop;
> 
> +  HobList = GetHobList ();
> +
>    TopMemory = 0;
>    for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw =
> GET_NEXT_HOB (Hob)) {
>      if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR)
> { @@ -525,8 +535,8 @@ InitDmaProtection (
> 
>    ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
> 
> -  LowMemoryAlignment = GetLowMemoryAlignment ();
> -  HighMemoryAlignment = GetHighMemoryAlignment ();
> +  LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
> + HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
>    if (LowMemoryAlignment < HighMemoryAlignment) {
>      MemoryAlignment = (UINTN)HighMemoryAlignment;
>    } else {
> @@ -542,9 +552,10 @@ InitDmaProtection (
>    LowBottom = 0;
>    LowTop = *DmaBufferBase;
>    HighBottom = *DmaBufferBase + DmaBufferSize;
> -  HighTop = GetTopMemory (HobList);
> +  HighTop = GetTopMemory ();
> 
>    Status = SetDmaProtectedRange (
> +               mEngineMask,
>                 (UINT32)LowBottom,
>                 (UINT32)(LowTop - LowBottom),
>                 HighBottom,
> @@ -559,6 +570,541 @@ InitDmaProtection (  }
> 
>  /**
> +  Dump DMAR DeviceScopeEntry.
> +
> +  @param[in]  DmarDeviceScopeEntry  DMAR DeviceScopeEntry **/ VOID
> +DumpDmarDeviceScopeEntry (
> +  IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDeviceScopeEntry
> +  )
> +{
> +  UINTN   PciPathNumber;
> +  UINTN   PciPathIndex;
> +  EFI_ACPI_DMAR_PCI_PATH  *PciPath;
> +
> +  if (DmarDeviceScopeEntry == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> ************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    *       DMA-Remapping Device Scope Entry Structure
> *\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> ************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    (sizeof(UINTN) == sizeof(UINT64)) ?
> +    "    DMAR Device Scope Entry address ...................... 0x%016lx\n" :
> +    "    DMAR Device Scope Entry address ...................... 0x%08x\n",
> +    DmarDeviceScopeEntry
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      Device Scope Entry Type ............................ 0x%02x\n",
> +    DmarDeviceScopeEntry->Type
> +    ));
> +  switch (DmarDeviceScopeEntry->Type) {  case
> + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
> +    DEBUG ((DEBUG_INFO,
> +      "        PCI Endpoint Device\n"
> +      ));
> +    break;
> +  case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
> +    DEBUG ((DEBUG_INFO,
> +      "        PCI Sub-hierachy\n"
> +      ));
> +    break;
> +  default:
> +    break;
> +  }
> +  DEBUG ((DEBUG_INFO,
> +    "      Length ............................................. 0x%02x\n",
> +    DmarDeviceScopeEntry->Length
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      Enumeration ID ..................................... 0x%02x\n",
> +    DmarDeviceScopeEntry->EnumerationId
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      Starting Bus Number ................................ 0x%02x\n",
> +    DmarDeviceScopeEntry->StartBusNumber
> +    ));
> +
> +  PciPathNumber = (DmarDeviceScopeEntry->Length -
> + sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) /
> + sizeof(EFI_ACPI_DMAR_PCI_PATH);  PciPath = (EFI_ACPI_DMAR_PCI_PATH
> *)(DmarDeviceScopeEntry + 1);  for (PciPathIndex = 0; PciPathIndex <
> PciPathNumber; PciPathIndex++) {
> +    DEBUG ((DEBUG_INFO,
> +      "      Device ............................................. 0x%02x\n",
> +      PciPath[PciPathIndex].Device
> +      ));
> +    DEBUG ((DEBUG_INFO,
> +      "      Function ........................................... 0x%02x\n",
> +      PciPath[PciPathIndex].Function
> +      ));
> +  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> ************\n\n"
> +    ));
> +
> +  return;
> +}
> +
> +/**
> +  Dump DMAR RMRR table.
> +
> +  @param[in]  Rmrr  DMAR RMRR table
> +**/
> +VOID
> +DumpDmarRmrr (
> +  IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
> +  )
> +{
> +  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDeviceScopeEntry;
> +  INTN                                    RmrrLen;
> +
> +  if (Rmrr == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "  *       Reserved Memory Region Reporting Structure
> *\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    (sizeof(UINTN) == sizeof(UINT64)) ?
> +    "  RMRR address ........................................... 0x%016lx\n" :
> +    "  RMRR address ........................................... 0x%08x\n",
> +    Rmrr
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Type ................................................. 0x%04x\n",
> +    Rmrr->Header.Type
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Length ............................................... 0x%04x\n",
> +    Rmrr->Header.Length
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Segment Number ....................................... 0x%04x\n",
> +    Rmrr->SegmentNumber
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Reserved Memory Region Base Address .................. 0x%016lx\n",
> +    Rmrr->ReservedMemoryRegionBaseAddress
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Reserved Memory Region Limit Address ................. 0x%016lx\n",
> +    Rmrr->ReservedMemoryRegionLimitAddress
> +    ));
> +
> +  RmrrLen  = Rmrr->Header.Length -
> sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
> +  DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> + *)(Rmrr + 1);  while (RmrrLen > 0) {
> +    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
> +    RmrrLen -= DmarDeviceScopeEntry->Length;
> +    DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> + *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n\n"
> +    ));
> +
> +  return;
> +}
> +
> +/**
> +  Dump DMAR DRHD table.
> +
> +  @param[in]  Drhd  DMAR DRHD table
> +**/
> +VOID
> +DumpDmarDrhd (
> +  IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
> +  )
> +{
> +  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDeviceScopeEntry;
> +  INTN                                    DrhdLen;
> +
> +  if (Drhd == NULL) {
> +    return;
> +  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "  *       DMA-Remapping Hardware Definition Structure
> *\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    (sizeof(UINTN) == sizeof(UINT64)) ?
> +    "  DRHD address ........................................... 0x%016lx\n" :
> +    "  DRHD address ........................................... 0x%08x\n",
> +    Drhd
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Type ................................................. 0x%04x\n",
> +    Drhd->Header.Type
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Length ............................................... 0x%04x\n",
> +    Drhd->Header.Length
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Flags ................................................ 0x%02x\n",
> +    Drhd->Flags
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      INCLUDE_PCI_ALL .................................... 0x%02x\n",
> +    Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Segment Number ....................................... 0x%04x\n",
> +    Drhd->SegmentNumber
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Register Base Address ................................ 0x%016lx\n",
> +    Drhd->RegisterBaseAddress
> +    ));
> +
> +  DrhdLen  = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
> +  DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> + *)(Drhd + 1);  while (DrhdLen > 0) {
> +    DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
> +    DrhdLen -= DmarDeviceScopeEntry->Length;
> +    DmarDeviceScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> + *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);  }
> +
> +  DEBUG ((DEBUG_INFO,
> +    "
> *************************************************************
> **************\n\n"
> +    ));
> +
> +  return;
> +}
> +
> +/**
> +  Dump DMAR ACPI table.
> +
> +  @param[in]  Dmar  DMAR ACPI table
> +**/
> +VOID
> +DumpAcpiDMAR (
> +  IN EFI_ACPI_DMAR_HEADER  *Dmar
> +  )
> +{
> +  EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
> +  INTN                  DmarLen;
> +
> +  if (Dmar == NULL) {
> +    return;
> +  }
> +
> +  //
> +  // Dump Dmar table
> +  //
> +  DEBUG ((DEBUG_INFO,
> +
> "*************************************************************
> ****************\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "*         DMAR Table
> *\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +
> "*************************************************************
> ****************\n"
> +    ));
> +
> +  DEBUG ((DEBUG_INFO,
> +    (sizeof(UINTN) == sizeof(UINT64)) ?
> +    "DMAR address ............................................. 0x%016lx\n" :
> +    "DMAR address ............................................. 0x%08x\n",
> +    Dmar
> +    ));
> +
> +  DEBUG ((DEBUG_INFO,
> +    "  Table Contents:\n"
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Host Address Width ................................... 0x%02x\n",
> +    Dmar->HostAddressWidth
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "    Flags ................................................ 0x%02x\n",
> +    Dmar->Flags
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      INTR_REMAP ......................................... 0x%02x\n",
> +    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
> +    ));
> +  DEBUG ((DEBUG_INFO,
> +    "      X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
> +    Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
> +    ));
> +
> +  DmarLen  = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
> + DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);  while
> + (DmarLen > 0) {
> +    switch (DmarHeader->Type) {
> +    case EFI_ACPI_DMAR_TYPE_DRHD:
> +      DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
> +      break;
> +    case EFI_ACPI_DMAR_TYPE_RMRR:
> +      DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
> +      break;
> +    default:
> +      break;
> +    }
> +    DmarLen -= DmarHeader->Length;
> +    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> *)((UINTN)DmarHeader +
> + DmarHeader->Length);  }
> +
> +  DEBUG ((DEBUG_INFO,
> +
> "*************************************************************
> ****************\n\n"
> +    ));
> +
> +  return;
> +}
> +
> +/**
> +  Get VTd engine number.
> +
> +  @return the VTd engine number.
> +**/
> +UINTN
> +GetVtdEngineNumber (
> +  VOID
> +  )
> +{
> +  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
> +  UINTN                                             VtdIndex;
> +
> +  VtdIndex = 0;
> +  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> +*)((UINTN)(mAcpiDmarTable + 1));
> +  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable +
> mAcpiDmarTable->Header.Length) {
> +    switch (DmarHeader->Type) {
> +    case EFI_ACPI_DMAR_TYPE_DRHD:
> +      VtdIndex++;
> +      break;
> +    default:
> +      break;
> +    }
> +    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> *)((UINTN)DmarHeader +
> +DmarHeader->Length);
> +  }
> +  return VtdIndex ;
> +}
> +
> +/**
> +  Process DMAR DHRD table.
> +
> +  @param[in]  VtdIndex  The index of VTd engine.
> +  @param[in]  DmarDrhd  The DRHD table.
> +**/
> +VOID
> +ProcessDhrd (
> +  IN UINTN                      VtdIndex,
> +  IN EFI_ACPI_DMAR_DRHD_HEADER  *DmarDrhd
> +  )
> +{
> +  DEBUG ((DEBUG_INFO,"  VTD (%d) BaseAddress -  0x%016lx\n", VtdIndex,
> +DmarDrhd->RegisterBaseAddress));
> +  mVTdInfo->VTdEngineAddress[VtdIndex] =
> DmarDrhd->RegisterBaseAddress;
> +}
> +
> +/**
> +  Parse DMAR DRHD table.
> +
> +  @return EFI_SUCCESS  The DMAR DRHD table is parsed.
> +**/
> +EFI_STATUS
> +ParseDmarAcpiTableDrhd (
> +  VOID
> +  )
> +{
> +  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
> +  UINTN                                             VtdUnitNumber;
> +  UINTN                                             VtdIndex;
> +
> +  VtdUnitNumber = GetVtdEngineNumber ();  if (VtdUnitNumber == 0) {
> +    return EFI_UNSUPPORTED;
> +  }
> +
> +  mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) *
> + sizeof(UINT64));  if (mVTdInfo == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +  mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
> +  mVTdInfo->VTdEngineCount   = VtdUnitNumber;
> +
> +  VtdIndex = 0;
> +  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> + *)((UINTN)(mAcpiDmarTable + 1));  while ((UINTN)DmarHeader <
> (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
> +    switch (DmarHeader->Type) {
> +    case EFI_ACPI_DMAR_TYPE_DRHD:
> +      ASSERT (VtdIndex < VtdUnitNumber);
> +      ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER
> *)DmarHeader);
> +      VtdIndex++;
> +
> +      break;
> +
> +    default:
> +      break;
> +    }
> +    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> *)((UINTN)DmarHeader +
> + DmarHeader->Length);  }  ASSERT (VtdIndex == VtdUnitNumber);
> +
> +  //
> +  // Initialize the engine mask to all.
> +  //
> +  mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
> +
> +  return EFI_SUCCESS;
> +}
> +
> +/**
> +  Return the VTd engine index according to the Segment and DevScopeEntry.
> +
> +  @param Segment         The segment of the VTd engine
> +  @param DevScopeEntry   The DevScopeEntry of the VTd engine
> +
> +  @return The VTd engine index according to the Segment and DevScopeEntry.
> +  @retval -1  The VTd engine is not found.
> +**/
> +UINTN
> +GetVTdEngineFromDevScopeEntry (
> +  IN  UINT16                                      Segment,
> +  IN  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
> +  )
> +{
> +  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
> +  UINTN                                             VtdIndex;
> +  EFI_ACPI_DMAR_DRHD_HEADER                         *DmarDrhd;
> +  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *ThisDevScopeEntry;
> +
> +  VtdIndex = 0;
> +  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> +*)((UINTN)(mAcpiDmarTable + 1));
> +  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable +
> mAcpiDmarTable->Header.Length) {
> +    switch (DmarHeader->Type) {
> +    case EFI_ACPI_DMAR_TYPE_DRHD:
> +      DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
> +      if (DmarDrhd->SegmentNumber != Segment) {
> +        // Mismatch
> +        break;
> +      }
> +      if ((DmarDrhd->Header.Length ==
> sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
> +          ((DmarDrhd->Flags &
> EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
> +        // No DevScopeEntry
> +        // Do not handle PCI_ALL
> +        break;
> +      }
> +      ThisDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd +
> 1));
> +      while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd +
> DmarDrhd->Header.Length) {
> +        if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
> +            (CompareMem (ThisDevScopeEntry, DevScopeEntry,
> DevScopeEntry->Length) == 0)) {
> +          return VtdIndex;
> +        }
> +        ThisDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
> +      }
> +      break;
> +    default:
> +      break;
> +    }
> +    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> *)((UINTN)DmarHeader +
> +DmarHeader->Length);
> +  }
> +  return (UINTN)-1;
> +}
> +
> +/**
> +  Process DMAR RMRR table.
> +
> +  @param[in]  DmarRmrr  The RMRR table.
> +**/
> +VOID
> +ProcessRmrr (
> +  IN EFI_ACPI_DMAR_RMRR_HEADER  *DmarRmrr
> +  )
> +{
> +  EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> *DmarDevScopeEntry;
> +  UINTN                                             VTdIndex;
> +  UINT64                                            RmrrMask;
> +  UINTN                                             LowBottom;
> +  UINTN                                             LowTop;
> +  UINTN                                             HighBottom;
> +  UINT64                                            HighTop;
> +
> +  DEBUG ((DEBUG_INFO,"  RMRR (Base 0x%016lx, Limit 0x%016lx)\n",
> + DmarRmrr->ReservedMemoryRegionBaseAddress,
> + DmarRmrr->ReservedMemoryRegionLimitAddress));
> +
> +  if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
> +      (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
> +    return ;
> +  }
> +
> +  DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> + *)((UINTN)(DmarRmrr + 1));  while ((UINTN)DmarDevScopeEntry <
> (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
> +    ASSERT (DmarDevScopeEntry->Type ==
> + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
> +
> +    VTdIndex = GetVTdEngineFromDevScopeEntry
> (DmarRmrr->SegmentNumber, DmarDevScopeEntry);
> +    if (VTdIndex != (UINTN)-1) {
> +      RmrrMask = LShiftU64 (1, VTdIndex);
> +
> +      LowBottom = 0;
> +      LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
> +      HighBottom =
> (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
> +      HighTop = GetTopMemory ();
> +
> +      SetDmaProtectedRange (
> +        RmrrMask,
> +        0,
> +        (UINT32)(LowTop - LowBottom),
> +        HighBottom,
> +        HighTop - HighBottom
> +        );
> +
> +      //
> +      // Remove the engine from the engine mask.
> +      // The assumption is that any other PEI driver does not access
> +      // the device covered by this engine.
> +      //
> +      mEngineMask = mEngineMask & (~RmrrMask);
> +    }
> +
> +    DmarDevScopeEntry =
> (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER
> +*)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
> +  }
> +}
> +
> +/**
> +  Parse DMAR DRHD table.
> +**/
> +VOID
> +ParseDmarAcpiTableRmrr (
> +  VOID
> +  )
> +{
> +  EFI_ACPI_DMAR_STRUCTURE_HEADER                    *DmarHeader;
> +
> +  DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> +*)((UINTN)(mAcpiDmarTable + 1));
> +  while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable +
> mAcpiDmarTable->Header.Length) {
> +    switch (DmarHeader->Type) {
> +    case EFI_ACPI_DMAR_TYPE_RMRR:
> +      ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
> +      break;
> +    default:
> +      break;
> +    }
> +    DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER
> *)((UINTN)DmarHeader +
> +DmarHeader->Length);
> +  }
> +}
> +
> +/**
>    Initializes the Intel VTd PMR PEIM.
> 
>    @param  FileHandle  Handle of the file being invoked.
> @@ -585,10 +1131,25 @@ IntelVTdPmrInitialize (
>               &gEdkiiVTdInfoPpiGuid,
>               0,
>               NULL,
> -             (VOID **)&mVTdInfoPpi
> +             (VOID **)&mAcpiDmarTable
>               );
>    ASSERT_EFI_ERROR(Status);
> 
> +  DumpAcpiDMAR (mAcpiDmarTable);
> +
> +  //
> +  // Get DMAR information to local VTdInfo  //  Status =
> + ParseDmarAcpiTableDrhd ();  if (EFI_ERROR(Status)) {
> +    return Status;
> +  }
> +
> +  //
> +  // If there is RMRR memory, parse it here.
> +  //
> +  ParseDmarAcpiTableRmrr ();
> +
>    //
>    // Find a pre-memory in resource hob as DMA buffer
>    // Mark PEI memory to be DMA protected.
> diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
> b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
> index aa5926a7..720f5d4 100644
> --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
> +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
> @@ -15,9 +15,16 @@
>  #ifndef __DMA_ACCESS_LIB_H__
>  #define __DMA_ACCESS_LIB_H__
> 
> +typedef struct {
> +  UINT8                                   HostAddressWidth;
> +  UINTN                                   VTdEngineCount;
> +  UINT64                                  VTdEngineAddress[1];
> +} VTD_INFO;
> +
>  /**
>    Set DMA protected region.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
>    @param LowMemoryBase      The protected low memory region base.
>    @param LowMemoryLength    The protected low memory region length.
>    @param HighMemoryBase     The protected high memory region base.
> @@ -28,6 +35,7 @@
>  **/
>  EFI_STATUS
>  SetDmaProtectedRange (
> +  IN UINT64        EngineMask,
>    IN UINT32        LowMemoryBase,
>    IN UINT32        LowMemoryLength,
>    IN UINT64        HighMemoryBase,
> @@ -37,31 +45,37 @@ SetDmaProtectedRange (
>  /**
>    Diable DMA protection.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @retval DMA protection is disabled.
>  **/
>  EFI_STATUS
>  DisableDmaProtection (
> -  VOID
> +  IN UINT64        EngineMask
>    );
> 
>  /**
>    Get protected low memory alignment.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @return protected low memory alignment.
>  **/
>  UINT32
>  GetLowMemoryAlignment (
> -  VOID
> +  IN UINT64        EngineMask
>    );
> 
>  /**
>    Get protected high memory alignment.
> 
> +  @param EngineMask         The mask of the VTd engine to be accessed.
> +
>    @return protected high memory alignment.
>  **/
>  UINT64
>  GetHighMemoryAlignment (
> -  VOID
> +  IN UINT64        EngineMask
>    );
> 
>  #endif
> --
> 2.7.4.windows.1



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

* Re: [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
  2017-09-20  6:30   ` Zeng, Star
@ 2017-09-20  6:33     ` Yao, Jiewen
  0 siblings, 0 replies; 10+ messages in thread
From: Yao, Jiewen @ 2017-09-20  6:33 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

Agree!

> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, September 20, 2017 2:30 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
> 
> I think we'd better to add #include <IndustryStandard/Acpi.h> in
> DmaRemappingReportingTable.h, but not VtdInfo.h.
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Sunday, September 17, 2017 2:07 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table.
> 
> We notice that there is real usage in PEI to show the graphic output. As such we
> need report RMRR table in PEI to let VTdPmrPei driver skip the IGD UMA region.
> 
> Now the VTD_INFO PPI uses the same DMAR data structure.
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  IntelSiliconPkg/Include/Ppi/VtdInfo.h | 26 +++++++++++---------
>  1 file changed, 15 insertions(+), 11 deletions(-)
> 
> diff --git a/IntelSiliconPkg/Include/Ppi/VtdInfo.h
> b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
> index e8be63f..a0a6f9c 100644
> --- a/IntelSiliconPkg/Include/Ppi/VtdInfo.h
> +++ b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
> @@ -17,22 +17,26 @@
>  #ifndef __VTD_INFO_PPI_H__
>  #define __VTD_INFO_PPI_H__
> 
> +#include <IndustryStandard/Acpi.h>
> +#include <IndustryStandard/DmaRemappingReportingTable.h>
> +
>  #define EDKII_VTD_INFO_PPI_GUID \
>      { \
>        0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68,
> 0x4a } \
>      }
> 
> -typedef struct _EDKII_VTD_INFO_PPI  EDKII_VTD_INFO_PPI;
> -
> -#define EDKII_VTD_INFO_PPI_REVISION 0x00010000
> -
> -struct _EDKII_VTD_INFO_PPI {
> -  UINT64                                  Revision;
> -  UINT8                                   HostAddressWidth;
> -  UINT8                                   Reserved[3];
> -  UINT32                                  VTdEngineCount;
> -  UINT64                                  VTdEngineAddress[1];
> -};
> +//
> +// VTD info PPI just use same data structure as DMAR table.
> +//
> +// The reported information must include what is needed in PEI phase, e.g.
> +//   the VTd engine (such as DRHD)
> +//   the reserved DMA address in PEI for eary graphic (such as RMRR for
> graphic UMA)
> +//
> +// The reported information can be and might be a subset of full DMAR table,
> e.g.
> +//   if some data is not avaiable (such as ANDD),
> +//   if some data is not needed (such as RMRR for legacy USB).
> +//
> +typedef EFI_ACPI_DMAR_HEADER EDKII_VTD_INFO_PPI;
> 
>  extern EFI_GUID gEdkiiVTdInfoPpiGuid;
> 
> --
> 2.7.4.windows.1



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

end of thread, other threads:[~2017-09-20  6:30 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-17  6:06 [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Jiewen Yao
2017-09-17  6:06 ` [PATCH 1/3] IntelSiliconPkg/VTdInfoPpi: Let it follow DMAR table Jiewen Yao
2017-09-20  6:30   ` Zeng, Star
2017-09-20  6:33     ` Yao, Jiewen
2017-09-17  6:06 ` [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table Jiewen Yao
2017-09-20  6:29   ` Zeng, Star
2017-09-20  6:29     ` Zeng, Star
2017-09-20  6:33       ` Yao, Jiewen
2017-09-17  6:06 ` [PATCH 3/3] IntelSiliconPkg/VTdInfoSample: Add " Jiewen Yao
2017-09-20  6:30 ` [PATCH 0/3] IntelSiliconPkg/InteVTdPei: Add RMRR support in PEI Zeng, Star

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