]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
IntelSiliconPkg IntelVTdDxe: Fix DMA does not work issue
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmrPei.c
index d118b7ef26471d27fa62f5d1e98352db1538d232..63ba94d62b7eb27d9d09983226d64ccb0eab1753 100644 (file)
@@ -1,6 +1,6 @@
 /** @file\r
 \r
-  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
 \r
   This program and the accompanying materials are licensed and made available under\r
   the terms and conditions of the BSD License which accompanies this distribution.\r
 #include <Library/HobLib.h>\r
 #include <IndustryStandard/Vtd.h>\r
 #include <Ppi/IoMmu.h>\r
-#include <Ppi/VTdInfo.h>\r
+#include <Ppi/VtdInfo.h>\r
+#include <Ppi/MemoryDiscovered.h>\r
+#include <Ppi/EndOfPeiPhase.h>\r
 \r
 #include "IntelVTdPmrPei.h"\r
 \r
 #define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB\r
+#define  TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB\r
 \r
-EDKII_VTD_INFO_PPI                *mVTdInfoPpi;\r
-UINTN                             mDmaBufferBase;\r
-UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
-UINTN                             mDmaBufferCurrentTop;\r
-UINTN                             mDmaBufferCurrentBottom;\r
+EFI_GUID mVTdInfoGuid = {\r
+  0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }\r
+};\r
+\r
+EFI_GUID mDmaBufferInfoGuid = {\r
+  0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }\r
+};\r
+\r
+typedef struct {\r
+  UINTN                             DmaBufferBase;\r
+  UINTN                             DmaBufferSize;\r
+  UINTN                             DmaBufferCurrentTop;\r
+  UINTN                             DmaBufferCurrentBottom;\r
+} DMA_BUFFER_INFO;\r
 \r
 #define MAP_INFO_SIGNATURE  SIGNATURE_32 ('D', 'M', 'A', 'P')\r
 typedef struct {\r
@@ -48,15 +60,19 @@ typedef struct {
 \r
   PEI Memory Layout:\r
 \r
+              +------------------+ <=============== PHMR.Limit (+ alignment) (1 << (HostAddressWidth + 1))\r
+              |   Mem Resource   |\r
+              |                  |\r
+\r
               +------------------+ <------- EfiMemoryTop\r
               |   PEI allocated  |\r
-  =========== +==================+\r
+  =========== +==================+ <=============== PHMR.Base\r
        ^      |    Commom Buf    |\r
        |      |  --------------  |\r
   DMA Buffer  |   * DMA FREE *   |\r
        |      |  --------------  |\r
        V      |  Read/Write Buf  |\r
-  =========== +==================+\r
+  =========== +==================+ <=============== PLMR.Limit (+ alignment)\r
               |   PEI allocated  |\r
               |  --------------  | <------- EfiFreeMemoryTop\r
               |   * PEI FREE *   |\r
@@ -70,9 +86,11 @@ typedef struct {
               |   Mem Alloc Hob  |\r
               +------------------+\r
 \r
+              |                  |\r
+              |   Mem Resource   |\r
+              +------------------+ <=============== PLMR.Base (0)\r
 **/\r
 \r
-\r
 /**\r
   Set IOMMU attribute for a system memory.\r
 \r
@@ -138,8 +156,13 @@ PeiIoMmuMap (
   OUT    VOID                                       **Mapping\r
   )\r
 {\r
-  MAP_INFO   *MapInfo;\r
-  UINTN      Length;\r
+  MAP_INFO                    *MapInfo;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||\r
       Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {\r
@@ -149,18 +172,18 @@ PeiIoMmuMap (
   }\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = *NumberOfBytes + sizeof(MAP_INFO);\r
-  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+  if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
     DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));\r
     ASSERT (FALSE);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
-  *DeviceAddress = mDmaBufferCurrentBottom;\r
-  mDmaBufferCurrentBottom += Length;\r
+  *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;\r
+  DmaBufferInfo->DmaBufferCurrentBottom += Length;\r
 \r
   MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);\r
   MapInfo->Signature     = MAP_INFO_SIGNATURE;\r
@@ -205,16 +228,21 @@ PeiIoMmuUnmap (
   IN  VOID                                     *Mapping\r
   )\r
 {\r
-  MAP_INFO   *MapInfo;\r
-  UINTN      Length;\r
+  MAP_INFO                    *MapInfo;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   if (Mapping == NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   MapInfo = Mapping;\r
   ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);\r
@@ -235,8 +263,8 @@ PeiIoMmuUnmap (
   }\r
 \r
   Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);\r
-  if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
-    mDmaBufferCurrentBottom -= Length;\r
+  if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {\r
+    DmaBufferInfo->DmaBufferCurrentBottom -= Length;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -256,7 +284,7 @@ PeiIoMmuUnmap (
 \r
   @retval EFI_SUCCESS           The requested memory pages were allocated.\r
   @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are\r
-                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.\r
+                                MEMORY_WRITE_COMBINE, MEMORY_CACHED and DUAL_ADDRESS_CYCLE.\r
   @retval EFI_INVALID_PARAMETER One or more parameters are invalid.\r
   @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.\r
 \r
@@ -271,20 +299,25 @@ PeiIoMmuAllocateBuffer (
   IN     UINT64                                   Attributes\r
   )\r
 {\r
-  UINTN  Length;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = EFI_PAGES_TO_SIZE(Pages);\r
-  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {\r
+  if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {\r
     DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));\r
     ASSERT (FALSE);\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
-  *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);\r
-  mDmaBufferCurrentTop -= Length;\r
+  *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);\r
+  DmaBufferInfo->DmaBufferCurrentTop -= Length;\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));\r
   return EFI_SUCCESS;\r
@@ -310,15 +343,20 @@ PeiIoMmuFreeBuffer (
   IN  VOID                                     *HostAddress\r
   )\r
 {\r
-  UINTN  Length;\r
+  UINTN                       Length;\r
+  VOID                        *Hob;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
 \r
   DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));\r
+  DEBUG ((DEBUG_VERBOSE, "  DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));\r
 \r
   Length = EFI_PAGES_TO_SIZE(Pages);\r
-  if ((UINTN)HostAddress == mDmaBufferCurrentTop) {\r
-    mDmaBufferCurrentTop += Length;\r
+  if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {\r
+    DmaBufferInfo->DmaBufferCurrentTop += Length;\r
   }\r
 \r
   return EFI_SUCCESS;\r
@@ -339,225 +377,340 @@ CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
   (VOID *) &mIoMmuPpi\r
 };\r
 \r
-#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \\r
-                               EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \\r
-                               EFI_RESOURCE_ATTRIBUTE_TESTED | \\r
-                               EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \\r
-                               EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \\r
-                               EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \\r
-                               )\r
+/**\r
+  Initialize DMA protection.\r
+\r
+  @param VTdInfo        The VTd engine context information.\r
+  @param DmaBufferSize  the DMA buffer size\r
+  @param DmaBufferBase  the DMA buffer base\r
+\r
+  @retval EFI_SUCCESS           the DMA protection is initialized.\r
+  @retval EFI_OUT_OF_RESOURCES  no enough resource to initialize DMA protection.\r
+**/\r
+EFI_STATUS\r
+InitDmaProtection (\r
+  IN   VTD_INFO                    *VTdInfo,\r
+  IN   UINTN                       DmaBufferSize,\r
+  OUT  UINTN                       *DmaBufferBase\r
+  )\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINT32                      LowMemoryAlignment;\r
+  UINT64                      HighMemoryAlignment;\r
+  UINTN                       MemoryAlignment;\r
+  UINTN                       LowBottom;\r
+  UINTN                       LowTop;\r
+  UINTN                       HighBottom;\r
+  UINT64                      HighTop;\r
 \r
-#define TESTED_MEMORY_ATTRIBUTES      (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)\r
+  LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
+  HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);\r
+  if (LowMemoryAlignment < HighMemoryAlignment) {\r
+    MemoryAlignment = (UINTN)HighMemoryAlignment;\r
+  } else {\r
+    MemoryAlignment = LowMemoryAlignment;\r
+  }\r
+  ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));\r
+  *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);\r
+  ASSERT (*DmaBufferBase != 0);\r
+  if (*DmaBufferBase == 0) {\r
+    DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
 \r
-#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)\r
+  LowBottom = 0;\r
+  LowTop = *DmaBufferBase;\r
+  HighBottom = *DmaBufferBase + DmaBufferSize;\r
+  HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
 \r
-#define PRESENT_MEMORY_ATTRIBUTES     (EFI_RESOURCE_ATTRIBUTE_PRESENT)\r
+  Status = SetDmaProtectedRange (\r
+             VTdInfo,\r
+             VTdInfo->EngineMask,\r
+             (UINT32)LowBottom,\r
+             (UINT32)(LowTop - LowBottom),\r
+             HighBottom,\r
+             HighTop - HighBottom\r
+             );\r
 \r
-GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {\r
-  "Mem",\r
-  "MMIO",\r
-  "I/O",\r
-  "FD",\r
-  "MM Port I/O",\r
-  "Reserved Mem",\r
-  "Reserved I/O",\r
-};\r
+  if (EFI_ERROR(Status)) {\r
+    FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
-  Return the short name of resource type.\r
+  Initializes the Intel VTd Info.\r
 \r
-  @param Type  resource type.\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @return the short name of resource type.\r
 **/\r
-CHAR8 *\r
-ShortNameOfResourceType (\r
-  IN UINT32 Type\r
+EFI_STATUS\r
+InitVTdInfo (\r
+  VOID\r
   )\r
 {\r
-  if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {\r
-    return mResourceTypeShortName[Type];\r
-  } else {\r
-    return "Unknown";\r
+  EFI_STATUS                  Status;\r
+  EFI_ACPI_DMAR_HEADER        *AcpiDmarTable;\r
+  VOID                        *Hob;\r
+\r
+  Status = PeiServicesLocatePpi (\r
+             &gEdkiiVTdInfoPpiGuid,\r
+             0,\r
+             NULL,\r
+             (VOID **)&AcpiDmarTable\r
+             );\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  DumpAcpiDMAR (AcpiDmarTable);\r
+\r
+  //\r
+  // Clear old VTdInfo Hob.\r
+  //\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  if (Hob != NULL) {\r
+    ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));\r
   }\r
+\r
+  //\r
+  // Get DMAR information to local VTdInfo\r
+  //\r
+  Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.\r
+  //\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
-  Dump resource hob.\r
+  Initializes the Intel VTd PMR for all memory.\r
+\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @param HobList  the HOB list.\r
 **/\r
-VOID\r
-DumpResourceHob (\r
-  IN VOID                        *HobList\r
+EFI_STATUS\r
+InitVTdPmrForAll (\r
+  VOID\r
   )\r
 {\r
-  EFI_PEI_HOB_POINTERS        Hob;\r
-  EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
-\r
-  DEBUG ((DEBUG_VERBOSE, "Resource Descriptor HOBs\n"));\r
-  for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
-    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
-      ResourceHob = Hob.ResourceDescriptor;\r
-      DEBUG ((DEBUG_VERBOSE,\r
-        "  BA=%016lx  L=%016lx  Attr=%08x  ",\r
-        ResourceHob->PhysicalStart,\r
-        ResourceHob->ResourceLength,\r
-        ResourceHob->ResourceAttribute\r
-        ));\r
-      DEBUG ((DEBUG_VERBOSE, ShortNameOfResourceType(ResourceHob->ResourceType)));\r
-      switch (ResourceHob->ResourceType) {\r
-      case EFI_RESOURCE_SYSTEM_MEMORY:\r
-        if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) != 0) {\r
-          DEBUG ((DEBUG_VERBOSE, " (Persistent)"));\r
-        } else if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) != 0) {\r
-          DEBUG ((DEBUG_VERBOSE, " (MoreReliable)"));\r
-        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {\r
-          DEBUG ((DEBUG_VERBOSE, " (Tested)"));\r
-        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {\r
-          DEBUG ((DEBUG_VERBOSE, " (Init)"));\r
-        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {\r
-          DEBUG ((DEBUG_VERBOSE, " (Present)"));\r
-        } else {\r
-          DEBUG ((DEBUG_VERBOSE, " (Unknown)"));\r
-        }\r
-        break;\r
-      default:\r
-        break;\r
-      }\r
-      DEBUG ((DEBUG_VERBOSE, "\n"));\r
-    }\r
-  }\r
+  EFI_STATUS                  Status;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  UINTN                       LowBottom;\r
+  UINTN                       LowTop;\r
+  UINTN                       HighBottom;\r
+  UINT64                      HighTop;\r
+\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+  LowBottom = 0;\r
+  LowTop = 0;\r
+  HighBottom = 0;\r
+  HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth + 1);\r
+\r
+  Status = SetDmaProtectedRange (\r
+             VTdInfo,\r
+             VTdInfo->EngineMask,\r
+             (UINT32)LowBottom,\r
+             (UINT32)(LowTop - LowBottom),\r
+             HighBottom,\r
+             HighTop - HighBottom\r
+             );\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Dump PHIT hob.\r
+  Initializes the Intel VTd PMR for DMA buffer.\r
+\r
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.\r
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.\r
 \r
-  @param HobList  the HOB list.\r
 **/\r
-VOID\r
-DumpPhitHob (\r
-  IN VOID                        *HobList\r
+EFI_STATUS\r
+InitVTdPmrForDma (\r
+  VOID\r
   )\r
 {\r
-  EFI_HOB_HANDOFF_INFO_TABLE  *PhitHob;\r
-\r
-  PhitHob = HobList;\r
-  ASSERT(GET_HOB_TYPE(HobList) == EFI_HOB_TYPE_HANDOFF);\r
-  DEBUG ((DEBUG_VERBOSE, "PHIT HOB\n"));\r
-  DEBUG ((DEBUG_VERBOSE, "  PhitHob             - 0x%x\n", PhitHob));\r
-  DEBUG ((DEBUG_VERBOSE, "  BootMode            - 0x%x\n", PhitHob->BootMode));\r
-  DEBUG ((DEBUG_VERBOSE, "  EfiMemoryTop        - 0x%016lx\n", PhitHob->EfiMemoryTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  EfiMemoryBottom     - 0x%016lx\n", PhitHob->EfiMemoryBottom));\r
-  DEBUG ((DEBUG_VERBOSE, "  EfiFreeMemoryTop    - 0x%016lx\n", PhitHob->EfiFreeMemoryTop));\r
-  DEBUG ((DEBUG_VERBOSE, "  EfiFreeMemoryBottom - 0x%016lx\n", PhitHob->EfiFreeMemoryBottom));\r
-  DEBUG ((DEBUG_VERBOSE, "  EfiEndOfHobList     - 0x%lx\n", PhitHob->EfiEndOfHobList));\r
+  EFI_STATUS                  Status;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+  VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+  //\r
+  // If there is RMRR memory, parse it here.\r
+  //\r
+  ParseDmarAcpiTableRmrr (VTdInfo);\r
+\r
+  Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);\r
+  DmaBufferInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));\r
+  //\r
+  // Find a pre-memory in resource hob as DMA buffer\r
+  // Mark PEI memory to be DMA protected.\r
+  //\r
+  Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);\r
+  if (EFI_ERROR(Status)) {\r
+    return Status;\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));\r
+\r
+  DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;\r
+  DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;\r
+\r
+  //\r
+  // Install PPI.\r
+  //\r
+  Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
+  ASSERT_EFI_ERROR(Status);\r
+\r
+  return Status;\r
 }\r
 \r
 /**\r
-  Get the highest memory.\r
+  This function handles S3 resume task at the end of PEI\r
 \r
-  @param HobList  the HOB list.\r
+  @param[in] PeiServices    Pointer to PEI Services Table.\r
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that\r
+                            caused this function to execute.\r
+  @param[in] Ppi            Pointer to the PPI data associated with this function.\r
 \r
-  @return the highest memory.\r
+  @retval EFI_STATUS        Always return EFI_SUCCESS\r
 **/\r
-UINT64\r
-GetTopMemory (\r
-  IN VOID                        *HobList\r
+EFI_STATUS\r
+EFIAPI\r
+S3EndOfPeiNotify(\r
+  IN EFI_PEI_SERVICES          **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+  IN VOID                      *Ppi\r
   )\r
 {\r
-  EFI_PEI_HOB_POINTERS        Hob;\r
-  EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
-  UINT64                      TopMemory;\r
-  UINT64                      ResourceTop;\r
-\r
-  TopMemory = 0;\r
-  for (Hob.Raw = HobList; !END_OF_HOB_LIST (Hob); Hob.Raw = GET_NEXT_HOB (Hob)) {\r
-    if (GET_HOB_TYPE (Hob) == EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) {\r
-      ResourceHob = Hob.ResourceDescriptor;\r
-      switch (ResourceHob->ResourceType) {\r
-      case EFI_RESOURCE_SYSTEM_MEMORY:\r
-        ResourceTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;\r
-        if (TopMemory < ResourceTop) {\r
-          TopMemory = ResourceTop;\r
-        }\r
-        break;\r
-      default:\r
-        break;\r
-      }\r
-      DEBUG ((DEBUG_VERBOSE, "\n"));\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  UINT64                      EngineMask;\r
+\r
+  DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));\r
+\r
+  if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {\r
+    Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+    if (Hob == NULL) {\r
+      return EFI_SUCCESS;\r
     }\r
+    VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+    EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;\r
+    DisableDmaProtection (VTdInfo, EngineMask);\r
   }\r
-  return TopMemory;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEfiEndOfPeiSignalPpiGuid,\r
+  S3EndOfPeiNotify\r
+};\r
+\r
 /**\r
-  Initialize DMA protection.\r
+  This function handles VTd engine setup\r
 \r
-  @param DmaBufferSize  the DMA buffer size\r
-  @param DmaBufferBase  the DMA buffer base\r
+  @param[in] PeiServices    Pointer to PEI Services Table.\r
+  @param[in] NotifyDesc     Pointer to the descriptor for the Notification event that\r
+                            caused this function to execute.\r
+  @param[in] Ppi            Pointer to the PPI data associated with this function.\r
 \r
-  @retval EFI_SUCCESS           the DMA protection is initialized.\r
-  @retval EFI_OUT_OF_RESOURCES  no enough resource to initialize DMA protection.\r
+  @retval EFI_STATUS        Always return EFI_SUCCESS\r
 **/\r
 EFI_STATUS\r
-InitDmaProtection (\r
-  IN   UINTN  DmaBufferSize,\r
-  OUT  UINTN  *DmaBufferBase\r
+EFIAPI\r
+VTdInfoNotify (\r
+  IN EFI_PEI_SERVICES          **PeiServices,\r
+  IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,\r
+  IN VOID                      *Ppi\r
   )\r
 {\r
   EFI_STATUS                  Status;\r
-  VOID                        *HobList;\r
-  EFI_HOB_HANDOFF_INFO_TABLE  *PhitHob;\r
-  UINT32                      LowMemoryAlignment;\r
-  UINT64                      HighMemoryAlignment;\r
-  UINTN                       MemoryAlignment;\r
-  UINTN                       LowBottom;\r
-  UINTN                       LowTop;\r
-  UINTN                       HighBottom;\r
-  UINT64                      HighTop;\r
-\r
-  HobList = GetHobList ();\r
-  DumpPhitHob (HobList);\r
-  DumpResourceHob (HobList);\r
+  VOID                        *MemoryDiscovered;\r
+  UINT64                      EnabledEngineMask;\r
+  VOID                        *Hob;\r
+  VTD_INFO                    *VTdInfo;\r
+  BOOLEAN                     MemoryInitialized;\r
 \r
-  PhitHob = HobList;\r
+  DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));\r
 \r
-  ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);\r
-\r
-  LowMemoryAlignment = GetLowMemoryAlignment ();\r
-  HighMemoryAlignment = GetHighMemoryAlignment ();\r
-  if (LowMemoryAlignment < HighMemoryAlignment) {\r
-    MemoryAlignment = (UINTN)HighMemoryAlignment;\r
-  } else {\r
-    MemoryAlignment = LowMemoryAlignment;\r
-  }\r
-  ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));\r
-  *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);\r
-  if (*DmaBufferBase == 0) {\r
-    DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));\r
-    return EFI_OUT_OF_RESOURCES;\r
+  //\r
+  // Check if memory is initialized.\r
+  //\r
+  MemoryInitialized = FALSE;\r
+  Status = PeiServicesLocatePpi (\r
+             &gEfiPeiMemoryDiscoveredPpiGuid,\r
+             0,\r
+             NULL,\r
+             &MemoryDiscovered\r
+             );\r
+  if (!EFI_ERROR(Status)) {\r
+    MemoryInitialized = TRUE;\r
   }\r
 \r
-  LowBottom = 0;\r
-  LowTop = *DmaBufferBase;\r
-  HighBottom = *DmaBufferBase + DmaBufferSize;\r
-  HighTop = GetTopMemory (HobList);\r
+  DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));\r
 \r
-  Status = SetDmaProtectedRange (\r
-               (UINT32)LowBottom,\r
-               (UINT32)(LowTop - LowBottom),\r
-               HighBottom,\r
-               HighTop - HighBottom\r
-               );\r
+  if (!MemoryInitialized) {\r
+    //\r
+    // If the memory is not initialized,\r
+    // Protect all system memory\r
+    //\r
+    InitVTdInfo ();\r
+    InitVTdPmrForAll ();\r
+  } else {\r
+    //\r
+    // If the memory is initialized,\r
+    // Allocate DMA buffer and protect rest system memory\r
+    //\r
+\r
+    //\r
+    // NOTE: We need reinit VTdInfo because previous information might be overriden.\r
+    //\r
+    InitVTdInfo ();\r
+\r
+    Hob = GetFirstGuidHob (&mVTdInfoGuid);\r
+    VTdInfo = GET_GUID_HOB_DATA(Hob);\r
+\r
+    //\r
+    // NOTE: We need check if PMR is enabled or not.\r
+    //\r
+    EnabledEngineMask = GetDmaProtectionEnabledEngineMask (VTdInfo, VTdInfo->EngineMask);\r
+    if (EnabledEngineMask != 0) {\r
+      EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+      DisableDmaProtection (VTdInfo, EnabledEngineMask);\r
+    }\r
+    InitVTdPmrForDma ();\r
+    if (EnabledEngineMask != 0) {\r
+      DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask);\r
+    }\r
 \r
-  if (EFI_ERROR(Status)) {\r
-    FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));\r
   }\r
 \r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {\r
+  (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),\r
+  &gEdkiiVTdInfoPpiGuid,\r
+  VTdInfoNotify\r
+};\r
+\r
 /**\r
   Initializes the Intel VTd PMR PEIM.\r
 \r
@@ -576,40 +729,41 @@ IntelVTdPmrInitialize (
   )\r
 {\r
   EFI_STATUS                  Status;\r
+  EFI_BOOT_MODE               BootMode;\r
+  DMA_BUFFER_INFO             *DmaBufferInfo;\r
+\r
+  DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));\r
 \r
   if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  Status = PeiServicesLocatePpi (\r
-             &gEdkiiVTdInfoPpiGuid,\r
-             0,\r
-             NULL,\r
-             (VOID **)&mVTdInfoPpi\r
-             );\r
-  ASSERT_EFI_ERROR(Status);\r
-\r
-  //\r
-  // Find a pre-memory in resource hob as DMA buffer\r
-  // Mark PEI memory to be DMA protected.\r
-  //\r
-  Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);\r
-  if (EFI_ERROR(Status)) {\r
-    return Status;\r
+  DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));\r
+  ASSERT(DmaBufferInfo != NULL);\r
+  if (DmaBufferInfo == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
   }\r
+  ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));\r
 \r
-  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));\r
-  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));\r
+  PeiServicesGetBootMode (&BootMode);\r
+\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
+    DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;\r
+  } else {\r
+    DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;\r
+  }\r
 \r
-  mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;\r
-  mDmaBufferCurrentBottom = mDmaBufferBase;\r
+  Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);\r
+  ASSERT_EFI_ERROR (Status);\r
 \r
   //\r
-  // Install PPI.\r
+  // Register EndOfPei Notify for S3\r
   //\r
-  Status = PeiServicesInstallPpi (&mIoMmuPpiList);\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (BootMode == BOOT_ON_S3_RESUME) {\r
+    Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
 \r
-  return Status;\r
+  return EFI_SUCCESS;\r
 }\r
 \r