public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH 00/11] Add IOMMU PEI support.
@ 2017-09-08 15:03 Jiewen Yao
  2017-09-08 15:03 ` [PATCH 01/11] MdeModulePkg/Include: Add IOMMU_PPI Jiewen Yao
                   ` (11 more replies)
  0 siblings, 12 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel

This series patch added IOMMU PEI support.
It is also posted to https://github.com/jyao1/edk2/tree/IoMmuPpi.

1) Patch 1 and 2 add EDKII_IOMMU_PPI.
It is similar to EDKII_IOMMU_PROTOCOL.

2) Patch 3 and 4 add Intel VTD PMR register support
for DXE phase IntelVTdDxe.
This is to prepare handle PMR usage in PEI phase.

3) Patch 5 and 6 add EDKII_VTD_INFO_PPI.
This PPI is to provide Intel VTD information in PEI.
In DXE, the VTd driver can get VTD info from ACPI DMAR table.
But in PEI, there is no way to get VTD info before.
VTD_INFO_PPI is added to resolve the problem.

4) Patch 7 and 8 add IntelVTdPmrPei driver.
This driver consumes EDKII_VTD_INFO_PPI and produces IOMMU_PPI.
It enables VTD PMR register to provide DMA protection.
The PMR based DMA protection is a simple solution to
mark 2 regions can be DMA protected.
The IntelVTdPmrPei allocates a small chunk buffer for DMA
and protect the rest memory.

5) Patch 9 and 10 add a sample VTdInfo PEI driver.
It provides a sample to show how to report VTd info in PEI phase.

6) Patch 11 updates XhciPei driver to consume IOMMU_PPI.
If the IOMMU_PPI is present, XhciPei will use IOMMU_PPI to
allocate DMA buffer. Or the XhciPei will still use old way -
PeiServiceAllocatePage to allocate DRAM as DMA buffer.
This is the first PEI device driver consuming IOMMU_PPI to
show the concept. The rest PEI device drivers will be
updated in separated patches.


This series patch is validated on Intel Kabylake Platform.
1) We can use XHCI to do file transfer in PEI phase,
2) We can still use XHCI in DXE phase, such as shell environment.
3) If the device driver does not consume IOMMU_PPI, the DMA fails.

Jiewen Yao (11):
  MdeModulePkg/Include: Add IOMMU_PPI.
  MdeModulePkg/Dec: Add IOMMU_PPI GUID.
  IntelSiliconPkg/Vtd.h: Add definition for PMR.
  IntelSiliconPkg/VTdDxe: Disable PMR
  IntelSiliconPkg/include: Add VTD_INFO PPI.
  IntelSiliconPkg/dec: Add VTD_INFO PPI GUID
  IntelSiliconPkg: Add IntelVTdPmrPei.
  IntelSiliconPkg/dsc: Add IntelVTdPmrPeim.
  IntelSiliconPkg: Add PlatformVTdInfoSamplePei.
  IntelSiliconPkg/dsc: Add PlatformVTdInfoSamplePei.
  MdeModulePkg/XhciPei: Support IoMmu.

 IntelSiliconPkg/Include/IndustryStandard/Vtd.h                             |   6 +
 IntelSiliconPkg/Include/Ppi/VtdInfo.h                                      |  40 ++
 IntelSiliconPkg/IntelSiliconPkg.dec                                        |   3 +
 IntelSiliconPkg/IntelSiliconPkg.dsc                                        |  10 +
 IntelSiliconPkg/IntelVTdDxe/VtdReg.c                                       |  51 +-
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c                               | 314 ++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c                            | 615 ++++++++++++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h                            |  68 +++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf                          |  59 ++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni                          |  20 +
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni                     |  20 +
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c        |  65 +++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf      |  51 ++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni      |  20 +
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni |  20 +
 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c                                      | 249 ++++++++
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c                                    |  55 +-
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h                                    |   9 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c                                     |  55 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h                                     | 107 ++++
 MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf                                   |   3 +
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c                                   |  47 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h                                   |   1 +
 MdeModulePkg/Include/Ppi/IoMmu.h                                           | 196 +++++++
 MdeModulePkg/MdeModulePkg.dec                                              |   3 +
 25 files changed, 2052 insertions(+), 35 deletions(-)
 create mode 100644 IntelSiliconPkg/Include/Ppi/VtdInfo.h
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
 create mode 100644 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
 create mode 100644 MdeModulePkg/Include/Ppi/IoMmu.h

-- 
2.7.4.windows.1



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

* [PATCH 01/11] MdeModulePkg/Include: Add IOMMU_PPI.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 02/11] MdeModulePkg/Dec: Add IOMMU_PPI GUID Jiewen Yao
                   ` (10 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

This IOMMU_PPI is to provide IOMMU abstraction in PEI.

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

diff --git a/MdeModulePkg/Include/Ppi/IoMmu.h b/MdeModulePkg/Include/Ppi/IoMmu.h
new file mode 100644
index 0000000..5303d68
--- /dev/null
+++ b/MdeModulePkg/Include/Ppi/IoMmu.h
@@ -0,0 +1,196 @@
+/** @file
+  PEI IOMMU PPI.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials are licensed and made available under
+the terms and conditions of the BSD License that accompanies this distribution.
+The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php.
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef __PEI_IOMMU_H__
+#define __PEI_IOMMU_H__
+
+//
+// for EFI_ALLOCATE_TYPE
+//
+#include <Uefi.h>
+
+//
+// Include protocol for common definition
+//   EDKII_IOMMU_ACCESS_xxx
+//   EDKII_IOMMU_OPERATION
+//
+#include <Protocol/IoMmu.h>
+
+//
+// IOMMU Ppi GUID value
+//
+#define EDKII_IOMMU_PPI_GUID \
+    { \
+      0x70b0af26, 0xf847, 0x4bb6, { 0xaa, 0xb9, 0xcd, 0xe8, 0x4f, 0xc6, 0x14, 0x31 } \
+    }
+
+//
+// Forward reference for pure ANSI compatability
+//
+typedef struct _EDKII_IOMMU_PPI  EDKII_IOMMU_PPI;
+
+//
+// Revision The revision to which the IOMMU interface adheres.
+//          All future revisions must be backwards compatible.
+//          If a future version is not back wards compatible it is not the same GUID.
+//
+#define EDKII_IOMMU_PPI_REVISION 0x00010000
+
+/**
+  Set IOMMU attribute for a system memory.
+
+  If the IOMMU PPI exists, the system memory cannot be used
+  for DMA by default.
+
+  When a device requests a DMA access for a system memory,
+  the device driver need use SetAttribute() to update the IOMMU
+  attribute to request DMA access (read and/or write).
+
+  @param[in]  This              The PPI instance pointer.
+  @param[in]  Mapping           The mapping value returned from Map().
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination of access.
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported by the IOMMU.
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range specified by Mapping.
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to modify the IOMMU access.
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while attempting the operation.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_PEI_IOMMU_SET_ATTRIBUTE)(
+  IN EDKII_IOMMU_PPI       *This,
+  IN VOID                  *Mapping,
+  IN UINT64                IoMmuAccess
+  );
+
+/**
+  Provides the controller-specific addresses required to access system memory from a
+  DMA bus master.
+
+  @param  This                  The PPI instance pointer.
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_PEI_IOMMU_MAP)(
+  IN     EDKII_IOMMU_PPI                            *This,
+  IN     EDKII_IOMMU_OPERATION                      Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  );
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  The PPI instance pointer.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_PEI_IOMMU_UNMAP)(
+  IN  EDKII_IOMMU_PPI                          *This,
+  IN  VOID                                     *Mapping
+  );
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  The PPI instance pointer.
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
+                                EfiRuntimeServicesData.
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory address of the
+                                allocated range.
+  @param  Attributes            The requested bit mask of attributes for the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_PEI_IOMMU_ALLOCATE_BUFFER)(
+  IN     EDKII_IOMMU_PPI                          *This,
+  IN     EFI_MEMORY_TYPE                          MemoryType,
+  IN     UINTN                                    Pages,
+  IN OUT VOID                                     **HostAddress,
+  IN     UINT64                                   Attributes
+  );
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  The protocol instance pointer.
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EDKII_PEI_IOMMU_FREE_BUFFER)(
+  IN  EDKII_IOMMU_PPI                          *This,
+  IN  UINTN                                    Pages,
+  IN  VOID                                     *HostAddress
+  );
+
+///
+/// IOMMU PPI structure.
+///
+struct _EDKII_IOMMU_PPI {
+  UINT64                              Revision;
+  EDKII_PEI_IOMMU_SET_ATTRIBUTE       SetAttribute;
+  EDKII_PEI_IOMMU_MAP                 Map;
+  EDKII_PEI_IOMMU_UNMAP               Unmap;
+  EDKII_PEI_IOMMU_ALLOCATE_BUFFER     AllocateBuffer;
+  EDKII_PEI_IOMMU_FREE_BUFFER         FreeBuffer;
+};
+
+///
+/// IOMMU PPI GUID variable.
+///
+extern EFI_GUID gEdkiiIoMmuPpiGuid;
+
+#endif
-- 
2.7.4.windows.1



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

* [PATCH 02/11] MdeModulePkg/Dec: Add IOMMU_PPI GUID.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
  2017-09-08 15:03 ` [PATCH 01/11] MdeModulePkg/Include: Add IOMMU_PPI Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 03/11] IntelSiliconPkg/Vtd.h: Add definition for PMR Jiewen Yao
                   ` (9 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/MdeModulePkg.dec | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/MdeModulePkg/MdeModulePkg.dec b/MdeModulePkg/MdeModulePkg.dec
index 593bff3..403a66a 100644
--- a/MdeModulePkg/MdeModulePkg.dec
+++ b/MdeModulePkg/MdeModulePkg.dec
@@ -431,6 +431,9 @@
   ## Include/Ppi/SdMmcHostController.h
   gEdkiiPeiSdMmcHostControllerPpiGuid = { 0xb30dfeed, 0x947f, 0x4396, { 0xb1, 0x5a, 0xdf, 0xbd, 0xb9, 0x16, 0xdc, 0x24 }}
 
+  ## Include/Ppi/IoMmu.h
+  gEdkiiIoMmuPpiGuid = { 0x70b0af26, 0xf847, 0x4bb6, { 0xaa, 0xb9, 0xcd, 0xe8, 0x4f, 0xc6, 0x14, 0x31 } }
+
 [Protocols]
   ## Load File protocol provides capability to load and unload EFI image into memory and execute it.
   #  Include/Protocol/LoadPe32Image.h
-- 
2.7.4.windows.1



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

* [PATCH 03/11] IntelSiliconPkg/Vtd.h: Add definition for PMR.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
  2017-09-08 15:03 ` [PATCH 01/11] MdeModulePkg/Include: Add IOMMU_PPI Jiewen Yao
  2017-09-08 15:03 ` [PATCH 02/11] MdeModulePkg/Dec: Add IOMMU_PPI GUID Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR Jiewen Yao
                   ` (8 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Add missing PMR definition in VTd spec.

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/IndustryStandard/Vtd.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/IntelSiliconPkg/Include/IndustryStandard/Vtd.h b/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
index 3b7012c..cfead61 100644
--- a/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
+++ b/IntelSiliconPkg/Include/IndustryStandard/Vtd.h
@@ -247,6 +247,12 @@ typedef union {
 
 #define R_FRCD_REG       0x00 // + FRO
 
+#define R_PMEN_ENABLE_REG         0x64
+#define R_PMEN_LOW_BASE_REG       0x68
+#define R_PMEN_LOW_LIMITE_REG     0x6C
+#define R_PMEN_HIGH_BASE_REG      0x70
+#define R_PMEN_HIGH_LIMITE_REG    0x78
+
 typedef union {
   struct {
     UINT8         ND:3; // Number of domains supported
-- 
2.7.4.windows.1



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

* [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (2 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 03/11] IntelSiliconPkg/Vtd.h: Add definition for PMR Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-14  5:35   ` Zeng, Star
  2017-09-08 15:03 ` [PATCH 05/11] IntelSiliconPkg/include: Add VTD_INFO PPI Jiewen Yao
                   ` (7 subsequent siblings)
  11 siblings, 1 reply; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

When VTd translation is enabled, PMR can be disable.
Or the DMA will be blocked by PMR.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelVTdDxe/VtdReg.c | 51 +++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
index 7402d81..1404af7 100644
--- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
+++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
@@ -196,6 +196,39 @@ PrepareVtdConfig (
 }
 
 /**
+  Disable PMR in all VTd engine.
+**/
+VOID
+DisablePmr (
+  VOID
+  )
+{
+  UINT32        Reg32;
+  VTD_CAP_REG   CapReg;
+  UINTN         Index;
+
+  DEBUG ((DEBUG_INFO,"DisablePmr\n"));
+  for (Index = 0; Index < mVtdUnitNumber; Index++) {
+    CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
+    if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+      continue ;
+    }
+
+    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+    if ((Reg32 & BIT0) != 0) {
+      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
+      do {
+        Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+      } while((Reg32 & BIT0) != 0);
+      DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
+    } else {
+      DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
+    }
+  }
+  return ;
+}
+
+/**
   Enable DMAR translation.
 
   @retval EFI_SUCCESS           DMAR translation is enabled.
@@ -259,6 +292,11 @@ EnableDmar (
     DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
   }
 
+  //
+  // Need disable PMR, since we already setup translation table.
+  //
+  DisablePmr ();
+
   mVtdEnabled = TRUE;
 
   return EFI_SUCCESS;
@@ -502,7 +540,7 @@ DumpVtdIfError (
     for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
       FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
       FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
-      if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
+      if (FrcdReg.Bits.F != 0) {
         HasError = TRUE;
       }
     }
@@ -511,6 +549,17 @@ DumpVtdIfError (
       DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
       DumpVtdRegs (Num);
       DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
+      //
+      // Clear
+      //
+      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
+        FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
+        if (FrcdReg.Bits.F != 0) {
+          FrcdReg.Bits.F = 0;
+          MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);
+        }
+        MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));
+      }
     }
   }
 }
-- 
2.7.4.windows.1



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

* [PATCH 05/11] IntelSiliconPkg/include: Add VTD_INFO PPI.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (3 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 06/11] IntelSiliconPkg/dec: Add VTD_INFO PPI GUID Jiewen Yao
                   ` (6 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

This VTD_INFO_PPI is to provide VTD information in PEI.
As such, we can have a generic VTd driver.

It is a lightweight version DMAR table, but it does
not contain PCI device information.

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 | 40 ++++++++++++++++++++
 1 file changed, 40 insertions(+)

diff --git a/IntelSiliconPkg/Include/Ppi/VtdInfo.h b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
new file mode 100644
index 0000000..e8be63f
--- /dev/null
+++ b/IntelSiliconPkg/Include/Ppi/VtdInfo.h
@@ -0,0 +1,40 @@
+/** @file
+  The definition for VTD information PPI.
+
+  This is a lightweight VTd information report in PEI phase.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __VTD_INFO_PPI_H__
+#define __VTD_INFO_PPI_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];
+};
+
+extern EFI_GUID gEdkiiVTdInfoPpiGuid;
+
+#endif
+
-- 
2.7.4.windows.1



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

* [PATCH 06/11] IntelSiliconPkg/dec: Add VTD_INFO PPI GUID
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (4 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 05/11] IntelSiliconPkg/include: Add VTD_INFO PPI Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 07/11] IntelSiliconPkg: Add IntelVTdPmrPei Jiewen Yao
                   ` (5 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelSiliconPkg.dec | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/IntelSiliconPkg/IntelSiliconPkg.dec b/IntelSiliconPkg/IntelSiliconPkg.dec
index 2fc6379..941380a 100644
--- a/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -33,6 +33,9 @@
   # Generic DXE Library / Driver can locate HOB(s) and add SMBIOS records into SMBIOS table
   gIntelSmbiosDataHobGuid         = { 0x798e722e, 0x15b2, 0x4e13, { 0x8a, 0xe9, 0x6b, 0xa3, 0x0f, 0xf7, 0xf1, 0x67 }}
 
+[Ppis]
+  gEdkiiVTdInfoPpiGuid = { 0x8a59fcb3, 0xf191, 0x400c, { 0x97, 0x67, 0x67, 0xaf, 0x2b, 0x25, 0x68, 0x4a } }
+
 [Protocols]
   gEdkiiPlatformVTdPolicyProtocolGuid = { 0x3d17e448, 0x466, 0x4e20, { 0x99, 0x9f, 0xb2, 0xe1, 0x34, 0x88, 0xee, 0x22 }}
 
-- 
2.7.4.windows.1



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

* [PATCH 07/11] IntelSiliconPkg: Add IntelVTdPmrPei.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (5 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 06/11] IntelSiliconPkg/dec: Add VTD_INFO PPI GUID Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 08/11] IntelSiliconPkg/dsc: Add IntelVTdPmrPeim Jiewen Yao
                   ` (4 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

This PEIM is to produce IOMMU_PPI, so that PEI device
driver can have better DAM management.

This PEIM will setup VTD PMR register to protect
most DRAM. It allocates a big chunk DMA buffer in
the entrypoint, and only use this buffer for DMA.
Any other region is DMA protected.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c           | 314 ++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c        | 615 ++++++++++++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h        |  68 +++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf      |  59 ++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni      |  20 +
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni |  20 +
 6 files changed, 1096 insertions(+)

diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
new file mode 100644
index 0000000..ef08e29
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
@@ -0,0 +1,314 @@
+/** @file
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License which accompanies this distribution.
+  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <IndustryStandard/Vtd.h>
+#include <Ppi/VTdInfo.h>
+
+#include "IntelVTdPmrPei.h"
+
+extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+
+/**
+  Get protected low memory alignment.
+
+  @param VtdUnitBaseAddress The base address of the VTd engine.
+
+  @return protected low memory alignment.
+**/
+UINT32
+GetPlmrAlignment (
+  IN UINTN         VtdUnitBaseAddress
+  )
+{
+  UINT32        Data32;
+
+  MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, 0xFFFFFFFF);
+  Data32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG);
+  Data32 = ~Data32 + 1;
+
+  return Data32;
+}
+
+/**
+  Get protected high memory alignment.
+
+  @param VtdUnitBaseAddress The base address of the VTd engine.
+
+  @return protected high memory alignment.
+**/
+UINT64
+GetPhmrAlignment (
+  IN UINTN         VtdUnitBaseAddress
+  )
+{
+  UINT64        Data64;
+  UINT8         HostAddressWidth;
+
+  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;
+
+  MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
+  Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
+  Data64 = ~Data64 + 1;
+  Data64 = Data64 & (LShiftU64 (1, HostAddressWidth) - 1);
+
+  return Data64;
+}
+
+/**
+  Get protected low memory alignment.
+
+  @return protected low memory alignment.
+**/
+UINT32
+GetLowMemoryAlignment (
+  VOID
+  )
+{
+  UINTN         Index;
+  UINT32        Alignment;
+  UINT32        FinalAlignment;
+
+  FinalAlignment = 0;
+  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
+    Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    if (FinalAlignment < Alignment) {
+      FinalAlignment = Alignment;
+    }
+  }
+  return FinalAlignment;
+}
+
+/**
+  Get protected high memory alignment.
+
+  @return protected high memory alignment.
+**/
+UINT64
+GetHighMemoryAlignment (
+  VOID
+  )
+{
+  UINTN         Index;
+  UINT64        Alignment;
+  UINT64        FinalAlignment;
+
+  FinalAlignment = 0;
+  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
+    Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    if (FinalAlignment < Alignment) {
+      FinalAlignment = Alignment;
+    }
+  }
+  return FinalAlignment;
+}
+
+/**
+  Enable PMR in the VTd engine.
+
+  @param VtdUnitBaseAddress The base address of the VTd engine.
+
+  @retval EFI_SUCCESS      The PMR is enabled.
+  @retval EFI_UNSUPPORTED  The PMR is not supported.
+**/
+EFI_STATUS
+EnablePmr (
+  IN UINTN         VtdUnitBaseAddress
+  )
+{
+  UINT32        Reg32;
+  VTD_CAP_REG   CapReg;
+
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+  if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+  if ((Reg32 & BIT0) == 0) {
+    MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
+    do {
+      Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+    } while((Reg32 & BIT0) == 0);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Disable PMR in the VTd engine.
+
+  @param VtdUnitBaseAddress The base address of the VTd engine.
+
+  @retval EFI_SUCCESS      The PMR is disabled.
+  @retval EFI_UNSUPPORTED  The PMR is not supported.
+**/
+EFI_STATUS
+DisablePmr (
+  IN UINTN         VtdUnitBaseAddress
+  )
+{
+  UINT32        Reg32;
+  VTD_CAP_REG   CapReg;
+
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+  if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+  if ((Reg32 & BIT0) != 0) {
+    MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
+    do {
+      Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+    } while((Reg32 & BIT0) != 0);
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set PMR region in the VTd engine.
+
+  @param VtdUnitBaseAddress The base address of the VTd engine.
+  @param LowMemoryBase      The protected low memory region base.
+  @param LowMemoryLength    The protected low memory region length.
+  @param HighMemoryBase     The protected high memory region base.
+  @param HighMemoryLength   The protected high memory region length.
+
+  @retval EFI_SUCCESS      The PMR is set to protected region.
+  @retval EFI_UNSUPPORTED  The PMR is not supported.
+**/
+EFI_STATUS
+SetPmrRegion (
+  IN UINTN         VtdUnitBaseAddress,
+  IN UINT32        LowMemoryBase,
+  IN UINT32        LowMemoryLength,
+  IN UINT64        HighMemoryBase,
+  IN UINT64        HighMemoryLength
+  )
+{
+  VTD_CAP_REG   CapReg;
+  UINT32        PlmrAlignment;
+  UINT64        PhmrAlignment;
+
+  DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));
+
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
+  if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+    DEBUG ((DEBUG_ERROR, "PLMR/PHMR unsupported\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);
+  DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
+  PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);
+  DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
+
+  if ((LowMemoryBase    != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
+      (LowMemoryLength  != ALIGN_VALUE(LowMemoryLength, PlmrAlignment)) ||
+      (HighMemoryBase   != ALIGN_VALUE(HighMemoryBase, PhmrAlignment)) ||
+      (HighMemoryLength != ALIGN_VALUE(HighMemoryLength, PhmrAlignment))) {
+    DEBUG ((DEBUG_ERROR, "PLMR/PHMR alignment issue\n"));
+    return EFI_UNSUPPORTED;
+  }
+
+  if (LowMemoryBase == 0 && LowMemoryLength == 0) {
+    LowMemoryBase = 0xFFFFFFFF;
+  }
+  if (HighMemoryBase == 0 && HighMemoryLength == 0) {
+    HighMemoryBase = 0xFFFFFFFFFFFFFFFF;
+  }
+
+  MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG,    LowMemoryBase);
+  MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG,  LowMemoryBase + LowMemoryLength - 1);
+  MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG,   HighMemoryBase);
+  MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Set DMA protected region.
+
+  @param LowMemoryBase      The protected low memory region base.
+  @param LowMemoryLength    The protected low memory region length.
+  @param HighMemoryBase     The protected high memory region base.
+  @param HighMemoryLength   The protected high memory region length.
+
+  @retval EFI_SUCCESS      The DMA protection is set.
+  @retval EFI_UNSUPPORTED  The DMA protection is not set.
+**/
+EFI_STATUS
+SetDmaProtectedRange (
+  IN UINT32        LowMemoryBase,
+  IN UINT32        LowMemoryLength,
+  IN UINT64        HighMemoryBase,
+  IN UINT64        HighMemoryLength
+  )
+{
+  UINTN       Index;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
+
+  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
+    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    Status = SetPmrRegion (
+               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],
+               LowMemoryBase,
+               LowMemoryLength,
+               HighMemoryBase,
+               HighMemoryLength
+               );
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Diable DMA protection.
+
+  @retval DMA protection is disabled.
+**/
+EFI_STATUS
+DisableDmaProtection (
+  VOID
+  )
+{
+  UINTN       Index;
+  EFI_STATUS  Status;
+
+  DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
+
+  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {
+    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);
+    if (EFI_ERROR(Status)) {
+      return Status;
+    }
+  }
+
+  return EFI_SUCCESS;
+}
diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
new file mode 100644
index 0000000..d118b7e
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -0,0 +1,615 @@
+/** @file
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+
+  This program and the accompanying materials are licensed and made available under
+  the terms and conditions of the BSD License which accompanies this distribution.
+  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <PiPei.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/IoLib.h>
+#include <Library/DebugLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/HobLib.h>
+#include <IndustryStandard/Vtd.h>
+#include <Ppi/IoMmu.h>
+#include <Ppi/VTdInfo.h>
+
+#include "IntelVTdPmrPei.h"
+
+#define  TOTAL_DMA_BUFFER_SIZE    SIZE_4MB
+
+EDKII_VTD_INFO_PPI                *mVTdInfoPpi;
+UINTN                             mDmaBufferBase;
+UINTN                             mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
+UINTN                             mDmaBufferCurrentTop;
+UINTN                             mDmaBufferCurrentBottom;
+
+#define MAP_INFO_SIGNATURE  SIGNATURE_32 ('D', 'M', 'A', 'P')
+typedef struct {
+  UINT32                                    Signature;
+  EDKII_IOMMU_OPERATION                     Operation;
+  UINTN                                     NumberOfBytes;
+  EFI_PHYSICAL_ADDRESS                      HostAddress;
+  EFI_PHYSICAL_ADDRESS                      DeviceAddress;
+} MAP_INFO;
+
+/**
+
+  PEI Memory Layout:
+
+              +------------------+ <------- EfiMemoryTop
+              |   PEI allocated  |
+  =========== +==================+
+       ^      |    Commom Buf    |
+       |      |  --------------  |
+  DMA Buffer  |   * DMA FREE *   |
+       |      |  --------------  |
+       V      |  Read/Write Buf  |
+  =========== +==================+
+              |   PEI allocated  |
+              |  --------------  | <------- EfiFreeMemoryTop
+              |   * PEI FREE *   |
+              |  --------------  | <------- EfiFreeMemoryBottom
+              |       hob        |
+              |  --------------  |
+              |      Stack       |
+              +------------------+ <------- EfiMemoryBottom / Stack Bottom
+
+              +------------------+
+              |   Mem Alloc Hob  |
+              +------------------+
+
+**/
+
+
+/**
+  Set IOMMU attribute for a system memory.
+
+  If the IOMMU PPI exists, the system memory cannot be used
+  for DMA by default.
+
+  When a device requests a DMA access for a system memory,
+  the device driver need use SetAttribute() to update the IOMMU
+  attribute to request DMA access (read and/or write).
+
+  @param[in]  This              The PPI instance pointer.
+  @param[in]  Mapping           The mapping value returned from Map().
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination of access.
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported by the IOMMU.
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range specified by Mapping.
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to modify the IOMMU access.
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while attempting the operation.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiIoMmuSetAttribute (
+  IN EDKII_IOMMU_PPI       *This,
+  IN VOID                  *Mapping,
+  IN UINT64                IoMmuAccess
+  )
+{
+  return EFI_SUCCESS;
+}
+
+/**
+  Provides the controller-specific addresses required to access system memory from a
+  DMA bus master.
+
+  @param  This                  The PPI instance pointer.
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiIoMmuMap (
+  IN     EDKII_IOMMU_PPI                            *This,
+  IN     EDKII_IOMMU_OPERATION                      Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+{
+  MAP_INFO   *MapInfo;
+  UINTN      Length;
+
+  if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
+      Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
+    *DeviceAddress = (UINTN)HostAddress;
+    *Mapping = 0;
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+
+  Length = *NumberOfBytes + sizeof(MAP_INFO);
+  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+    DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  *DeviceAddress = mDmaBufferCurrentBottom;
+  mDmaBufferCurrentBottom += Length;
+
+  MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
+  MapInfo->Signature     = MAP_INFO_SIGNATURE;
+  MapInfo->Operation     = Operation;
+  MapInfo->NumberOfBytes = *NumberOfBytes;
+  MapInfo->HostAddress   = (UINTN)HostAddress;
+  MapInfo->DeviceAddress = *DeviceAddress;
+  *Mapping = MapInfo;
+  DEBUG ((DEBUG_VERBOSE, "  Op(%x):DeviceAddress - %x, Mapping - %x\n", Operation, (UINTN)*DeviceAddress, MapInfo));
+
+  //
+  // If this is a read operation from the Bus Master's point of view,
+  // then copy the contents of the real buffer into the mapped buffer
+  // so the Bus Master can read the contents of the real buffer.
+  //
+  if (Operation == EdkiiIoMmuOperationBusMasterRead ||
+      Operation == EdkiiIoMmuOperationBusMasterRead64) {
+    CopyMem (
+      (VOID *) (UINTN) MapInfo->DeviceAddress,
+      (VOID *) (UINTN) MapInfo->HostAddress,
+      MapInfo->NumberOfBytes
+      );
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  The PPI instance pointer.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+**/
+EFI_STATUS
+EFIAPI
+PeiIoMmuUnmap (
+  IN  EDKII_IOMMU_PPI                          *This,
+  IN  VOID                                     *Mapping
+  )
+{
+  MAP_INFO   *MapInfo;
+  UINTN      Length;
+
+  if (Mapping == NULL) {
+    return EFI_SUCCESS;
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+
+  MapInfo = Mapping;
+  ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
+  DEBUG ((DEBUG_VERBOSE, "  Op(%x):DeviceAddress - %x, NumberOfBytes - %x\n", MapInfo->Operation, (UINTN)MapInfo->DeviceAddress, MapInfo->NumberOfBytes));
+
+  //
+  // If this is a write operation from the Bus Master's point of view,
+  // then copy the contents of the mapped buffer into the real buffer
+  // so the processor can read the contents of the real buffer.
+  //
+  if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
+      MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
+    CopyMem (
+      (VOID *) (UINTN) MapInfo->HostAddress,
+      (VOID *) (UINTN) MapInfo->DeviceAddress,
+      MapInfo->NumberOfBytes
+      );
+  }
+
+  Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
+  if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
+    mDmaBufferCurrentBottom -= Length;
+  }
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  The PPI instance pointer.
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData or
+                                EfiRuntimeServicesData.
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory address of the
+                                allocated range.
+  @param  Attributes            The requested bit mask of attributes for the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+PeiIoMmuAllocateBuffer (
+  IN     EDKII_IOMMU_PPI                          *This,
+  IN     EFI_MEMORY_TYPE                          MemoryType,
+  IN     UINTN                                    Pages,
+  IN OUT VOID                                     **HostAddress,
+  IN     UINT64                                   Attributes
+  )
+{
+  UINTN  Length;
+
+  DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+
+  Length = EFI_PAGES_TO_SIZE(Pages);
+  if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+    DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
+    ASSERT (FALSE);
+    return EFI_OUT_OF_RESOURCES;
+  }
+  *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
+  mDmaBufferCurrentTop -= Length;
+
+  DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
+  return EFI_SUCCESS;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  The PPI instance pointer.
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+PeiIoMmuFreeBuffer (
+  IN  EDKII_IOMMU_PPI                          *This,
+  IN  UINTN                                    Pages,
+  IN  VOID                                     *HostAddress
+  )
+{
+  UINTN  Length;
+
+  DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
+  DEBUG ((DEBUG_VERBOSE, "  mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+
+  Length = EFI_PAGES_TO_SIZE(Pages);
+  if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
+    mDmaBufferCurrentTop += Length;
+  }
+
+  return EFI_SUCCESS;
+}
+
+EDKII_IOMMU_PPI mIoMmuPpi = {
+  EDKII_IOMMU_PPI_REVISION,
+  PeiIoMmuSetAttribute,
+  PeiIoMmuMap,
+  PeiIoMmuUnmap,
+  PeiIoMmuAllocateBuffer,
+  PeiIoMmuFreeBuffer,
+};
+
+CONST EFI_PEI_PPI_DESCRIPTOR mIoMmuPpiList = {
+  EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
+  &gEdkiiIoMmuPpiGuid,
+  (VOID *) &mIoMmuPpi
+};
+
+#define MEMORY_ATTRIBUTE_MASK (EFI_RESOURCE_ATTRIBUTE_PRESENT | \
+                               EFI_RESOURCE_ATTRIBUTE_INITIALIZED | \
+                               EFI_RESOURCE_ATTRIBUTE_TESTED | \
+                               EFI_RESOURCE_ATTRIBUTE_16_BIT_IO | \
+                               EFI_RESOURCE_ATTRIBUTE_32_BIT_IO | \
+                               EFI_RESOURCE_ATTRIBUTE_64_BIT_IO \
+                               )
+
+#define TESTED_MEMORY_ATTRIBUTES      (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED | EFI_RESOURCE_ATTRIBUTE_TESTED)
+
+#define INITIALIZED_MEMORY_ATTRIBUTES (EFI_RESOURCE_ATTRIBUTE_PRESENT | EFI_RESOURCE_ATTRIBUTE_INITIALIZED)
+
+#define PRESENT_MEMORY_ATTRIBUTES     (EFI_RESOURCE_ATTRIBUTE_PRESENT)
+
+GLOBAL_REMOVE_IF_UNREFERENCED CHAR8 *mResourceTypeShortName[] = {
+  "Mem",
+  "MMIO",
+  "I/O",
+  "FD",
+  "MM Port I/O",
+  "Reserved Mem",
+  "Reserved I/O",
+};
+
+/**
+  Return the short name of resource type.
+
+  @param Type  resource type.
+
+  @return the short name of resource type.
+**/
+CHAR8 *
+ShortNameOfResourceType (
+  IN UINT32 Type
+  )
+{
+  if (Type < sizeof(mResourceTypeShortName) / sizeof(mResourceTypeShortName[0])) {
+    return mResourceTypeShortName[Type];
+  } else {
+    return "Unknown";
+  }
+}
+
+/**
+  Dump resource hob.
+
+  @param HobList  the HOB list.
+**/
+VOID
+DumpResourceHob (
+  IN VOID                        *HobList
+  )
+{
+  EFI_PEI_HOB_POINTERS        Hob;
+  EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+
+  DEBUG ((DEBUG_VERBOSE, "Resource Descriptor HOBs\n"));
+  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) {
+      ResourceHob = Hob.ResourceDescriptor;
+      DEBUG ((DEBUG_VERBOSE,
+        "  BA=%016lx  L=%016lx  Attr=%08x  ",
+        ResourceHob->PhysicalStart,
+        ResourceHob->ResourceLength,
+        ResourceHob->ResourceAttribute
+        ));
+      DEBUG ((DEBUG_VERBOSE, ShortNameOfResourceType(ResourceHob->ResourceType)));
+      switch (ResourceHob->ResourceType) {
+      case EFI_RESOURCE_SYSTEM_MEMORY:
+        if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_PERSISTENT) != 0) {
+          DEBUG ((DEBUG_VERBOSE, " (Persistent)"));
+        } else if ((ResourceHob->ResourceAttribute & EFI_RESOURCE_ATTRIBUTE_MORE_RELIABLE) != 0) {
+          DEBUG ((DEBUG_VERBOSE, " (MoreReliable)"));
+        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == TESTED_MEMORY_ATTRIBUTES) {
+          DEBUG ((DEBUG_VERBOSE, " (Tested)"));
+        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == INITIALIZED_MEMORY_ATTRIBUTES) {
+          DEBUG ((DEBUG_VERBOSE, " (Init)"));
+        } else if ((ResourceHob->ResourceAttribute & MEMORY_ATTRIBUTE_MASK) == PRESENT_MEMORY_ATTRIBUTES) {
+          DEBUG ((DEBUG_VERBOSE, " (Present)"));
+        } else {
+          DEBUG ((DEBUG_VERBOSE, " (Unknown)"));
+        }
+        break;
+      default:
+        break;
+      }
+      DEBUG ((DEBUG_VERBOSE, "\n"));
+    }
+  }
+}
+
+/**
+  Dump PHIT hob.
+
+  @param HobList  the HOB list.
+**/
+VOID
+DumpPhitHob (
+  IN VOID                        *HobList
+  )
+{
+  EFI_HOB_HANDOFF_INFO_TABLE  *PhitHob;
+
+  PhitHob = HobList;
+  ASSERT(GET_HOB_TYPE(HobList) == EFI_HOB_TYPE_HANDOFF);
+  DEBUG ((DEBUG_VERBOSE, "PHIT HOB\n"));
+  DEBUG ((DEBUG_VERBOSE, "  PhitHob             - 0x%x\n", PhitHob));
+  DEBUG ((DEBUG_VERBOSE, "  BootMode            - 0x%x\n", PhitHob->BootMode));
+  DEBUG ((DEBUG_VERBOSE, "  EfiMemoryTop        - 0x%016lx\n", PhitHob->EfiMemoryTop));
+  DEBUG ((DEBUG_VERBOSE, "  EfiMemoryBottom     - 0x%016lx\n", PhitHob->EfiMemoryBottom));
+  DEBUG ((DEBUG_VERBOSE, "  EfiFreeMemoryTop    - 0x%016lx\n", PhitHob->EfiFreeMemoryTop));
+  DEBUG ((DEBUG_VERBOSE, "  EfiFreeMemoryBottom - 0x%016lx\n", PhitHob->EfiFreeMemoryBottom));
+  DEBUG ((DEBUG_VERBOSE, "  EfiEndOfHobList     - 0x%lx\n", PhitHob->EfiEndOfHobList));
+}
+
+/**
+  Get the highest memory.
+
+  @param HobList  the HOB list.
+
+  @return the highest memory.
+**/
+UINT64
+GetTopMemory (
+  IN VOID                        *HobList
+  )
+{
+  EFI_PEI_HOB_POINTERS        Hob;
+  EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;
+  UINT64                      TopMemory;
+  UINT64                      ResourceTop;
+
+  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) {
+      ResourceHob = Hob.ResourceDescriptor;
+      switch (ResourceHob->ResourceType) {
+      case EFI_RESOURCE_SYSTEM_MEMORY:
+        ResourceTop = ResourceHob->PhysicalStart + ResourceHob->ResourceLength;
+        if (TopMemory < ResourceTop) {
+          TopMemory = ResourceTop;
+        }
+        break;
+      default:
+        break;
+      }
+      DEBUG ((DEBUG_VERBOSE, "\n"));
+    }
+  }
+  return TopMemory;
+}
+
+/**
+  Initialize DMA protection.
+
+  @param DmaBufferSize  the DMA buffer size
+  @param DmaBufferBase  the DMA buffer base
+
+  @retval EFI_SUCCESS           the DMA protection is initialized.
+  @retval EFI_OUT_OF_RESOURCES  no enough resource to initialize DMA protection.
+**/
+EFI_STATUS
+InitDmaProtection (
+  IN   UINTN  DmaBufferSize,
+  OUT  UINTN  *DmaBufferBase
+  )
+{
+  EFI_STATUS                  Status;
+  VOID                        *HobList;
+  EFI_HOB_HANDOFF_INFO_TABLE  *PhitHob;
+  UINT32                      LowMemoryAlignment;
+  UINT64                      HighMemoryAlignment;
+  UINTN                       MemoryAlignment;
+  UINTN                       LowBottom;
+  UINTN                       LowTop;
+  UINTN                       HighBottom;
+  UINT64                      HighTop;
+
+  HobList = GetHobList ();
+  DumpPhitHob (HobList);
+  DumpResourceHob (HobList);
+
+  PhitHob = HobList;
+
+  ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
+
+  LowMemoryAlignment = GetLowMemoryAlignment ();
+  HighMemoryAlignment = GetHighMemoryAlignment ();
+  if (LowMemoryAlignment < HighMemoryAlignment) {
+    MemoryAlignment = (UINTN)HighMemoryAlignment;
+  } else {
+    MemoryAlignment = LowMemoryAlignment;
+  }
+  ASSERT (DmaBufferSize == ALIGN_VALUE(DmaBufferSize, MemoryAlignment));
+  *DmaBufferBase = (UINTN)AllocateAlignedPages (EFI_SIZE_TO_PAGES(DmaBufferSize), MemoryAlignment);
+  if (*DmaBufferBase == 0) {
+    DEBUG ((DEBUG_INFO, " InitDmaProtection : OutOfResource\n"));
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  LowBottom = 0;
+  LowTop = *DmaBufferBase;
+  HighBottom = *DmaBufferBase + DmaBufferSize;
+  HighTop = GetTopMemory (HobList);
+
+  Status = SetDmaProtectedRange (
+               (UINT32)LowBottom,
+               (UINT32)(LowTop - LowBottom),
+               HighBottom,
+               HighTop - HighBottom
+               );
+
+  if (EFI_ERROR(Status)) {
+    FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
+  }
+
+  return Status;
+}
+
+/**
+  Initializes the Intel VTd PMR PEIM.
+
+  @param  FileHandle  Handle of the file being invoked.
+  @param  PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS            Usb bot driver is successfully initialized.
+  @retval EFI_OUT_OF_RESOURCES   Can't initialize the driver.
+
+**/
+EFI_STATUS
+EFIAPI
+IntelVTdPmrInitialize (
+  IN EFI_PEI_FILE_HANDLE       FileHandle,
+  IN CONST EFI_PEI_SERVICES    **PeiServices
+  )
+{
+  EFI_STATUS                  Status;
+
+  if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  Status = PeiServicesLocatePpi (
+             &gEdkiiVTdInfoPpiGuid,
+             0,
+             NULL,
+             (VOID **)&mVTdInfoPpi
+             );
+  ASSERT_EFI_ERROR(Status);
+
+  //
+  // Find a pre-memory in resource hob as DMA buffer
+  // Mark PEI memory to be DMA protected.
+  //
+  Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
+  if (EFI_ERROR(Status)) {
+    return Status;
+  }
+
+  DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
+  DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
+
+  mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
+  mDmaBufferCurrentBottom = mDmaBufferBase;
+
+  //
+  // Install PPI.
+  //
+  Status = PeiServicesInstallPpi (&mIoMmuPpiList);
+  ASSERT_EFI_ERROR(Status);
+
+  return Status;
+}
+
diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
new file mode 100644
index 0000000..aa5926a7
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -0,0 +1,68 @@
+/** @file
+  The definition for DMA access Library.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php.
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __DMA_ACCESS_LIB_H__
+#define __DMA_ACCESS_LIB_H__
+
+/**
+  Set DMA protected region.
+
+  @param LowMemoryBase      The protected low memory region base.
+  @param LowMemoryLength    The protected low memory region length.
+  @param HighMemoryBase     The protected high memory region base.
+  @param HighMemoryLength   The protected high memory region length.
+
+  @retval EFI_SUCCESS      The DMA protection is set.
+  @retval EFI_UNSUPPORTED  The DMA protection is not set.
+**/
+EFI_STATUS
+SetDmaProtectedRange (
+  IN UINT32        LowMemoryBase,
+  IN UINT32        LowMemoryLength,
+  IN UINT64        HighMemoryBase,
+  IN UINT64        HighMemoryLength
+  );
+
+/**
+  Diable DMA protection.
+
+  @retval DMA protection is disabled.
+**/
+EFI_STATUS
+DisableDmaProtection (
+  VOID
+  );
+
+/**
+  Get protected low memory alignment.
+
+  @return protected low memory alignment.
+**/
+UINT32
+GetLowMemoryAlignment (
+  VOID
+  );
+
+/**
+  Get protected high memory alignment.
+
+  @return protected high memory alignment.
+**/
+UINT64
+GetHighMemoryAlignment (
+  VOID
+  );
+
+#endif
+
diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
new file mode 100644
index 0000000..86cd7d1
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
@@ -0,0 +1,59 @@
+## @file
+# Component INF file for the Intel VTd PMR PEIM.
+#
+# This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI
+# and provide DMA protection in PEI.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION     = 0x00010017
+  BASE_NAME       = IntelVTdPmrPei
+  MODULE_UNI_FILE = IntelVTdPmrPei.uni
+  FILE_GUID       = F906769F-4AED-4A0D-8C7C-FF21B9D1051A
+  MODULE_TYPE     = PEIM
+  VERSION_STRING  = 1.0
+  ENTRY_POINT     = IntelVTdPmrInitialize
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  IntelSiliconPkg/IntelSiliconPkg.dec
+
+[Sources]
+  IntelVTdPmrPei.c
+  IntelVTdPmrPei.h
+  IntelVTdPmr.c
+
+[LibraryClasses]
+  DebugLib
+  BaseMemoryLib
+  BaseLib
+  PeimEntryPoint
+  PeiServicesLib
+  HobLib
+  IoLib
+
+[Ppis]
+  gEdkiiIoMmuPpiGuid            ## PRODUCES
+  gEdkiiVTdInfoPpiGuid          ## CONSUMES
+
+[Pcd]
+  gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask   ## CONSUMES
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid AND
+  gEdkiiVTdInfoPpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  IntelVTdPmrPeiExtra.uni
+
diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
new file mode 100644
index 0000000..11508a4
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
@@ -0,0 +1,20 @@
+// /** @file
+// IntelVTdPmrPei Module Localized Abstract and Description Content
+//
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials are
+// licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Intel VTd PMR PEI Driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This driver initializes VTd engine based upon EDKII_VTD_INFO_PPI and provide DMA protection to device in PEI."
+
diff --git a/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
new file mode 100644
index 0000000..c6b2dec
--- /dev/null
+++ b/IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// IntelVTdPmrPei Localized Strings and Content
+//
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials are
+// licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Intel VTd PMR PEI Driver"
+
+
-- 
2.7.4.windows.1



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

* [PATCH 08/11] IntelSiliconPkg/dsc: Add IntelVTdPmrPeim.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (6 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 07/11] IntelSiliconPkg: Add IntelVTdPmrPei Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 09/11] IntelSiliconPkg: Add PlatformVTdInfoSamplePei Jiewen Yao
                   ` (3 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelSiliconPkg.dsc | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc
index 9a9920f..33e822f 100644
--- a/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -40,6 +40,14 @@
   SerialPortLib|MdePkg/Library/BaseSerialPortLibNull/BaseSerialPortLibNull.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLib/BaseCacheMaintenanceLib.inf
 
+[LibraryClasses.common.PEIM]
+  PeimEntryPoint|MdePkg/Library/PeimEntryPoint/PeimEntryPoint.inf
+  PeiServicesTablePointerLib|MdePkg/Library/PeiServicesTablePointerLib/PeiServicesTablePointerLib.inf
+  PeiServicesLib|MdePkg/Library/PeiServicesLib/PeiServicesLib.inf
+
+  MemoryAllocationLib|MdePkg/Library/PeiMemoryAllocationLib/PeiMemoryAllocationLib.inf
+  HobLib|MdePkg/Library/PeiHobLib/PeiHobLib.inf
+
 [LibraryClasses.common.DXE_DRIVER]
   UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf
   UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
@@ -72,6 +80,7 @@
 [Components]
   IntelSiliconPkg/Library/DxeSmbiosDataHobLib/DxeSmbiosDataHobLib.inf
   IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
+  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
   IntelSiliconPkg/PlatformVTdSampleDxe/PlatformVTdSampleDxe.inf
 
 [BuildOptions]
-- 
2.7.4.windows.1



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

* [PATCH 09/11] IntelSiliconPkg: Add PlatformVTdInfoSamplePei.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (7 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 08/11] IntelSiliconPkg/dsc: Add IntelVTdPmrPeim Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 10/11] IntelSiliconPkg/dsc: " Jiewen Yao
                   ` (2 subsequent siblings)
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

This is a sample driver to produce VTD_INFO PPI.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c        | 65 ++++++++++++++++++++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf      | 51 +++++++++++++++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni      | 20 ++++++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni | 20 ++++++
 4 files changed, 156 insertions(+)

diff --git a/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
new file mode 100644
index 0000000..c79398f
--- /dev/null
+++ b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
@@ -0,0 +1,65 @@
+/** @file
+  Platform VTd Info Sample PEI driver.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  This program and the accompanying materials
+  are licensed and made available under the terms and conditions of the BSD License
+  which accompanies this distribution.  The full text of the license may be found at
+  http://opensource.org/licenses/bsd-license.php
+
+  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PiPei.h>
+
+#include <Ppi/VTdInfo.h>
+
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+
+typedef struct {
+  UINT64                                  Revision;
+  UINT8                                   HostAddressWidth;
+  UINT8                                   Reserved[3];
+  UINT32                                  VTdEngineCount;
+  UINT64                                  VTdEngineAddress[2];
+} MY_VTD_INFO_PPI;
+
+MY_VTD_INFO_PPI  mPlatformVTdSample = {
+  EDKII_VTD_INFO_PPI_REVISION,
+  0x26,
+  {0},
+  2,
+  {0xFED90000, 0xFED91000},
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
+  (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+  &gEdkiiVTdInfoPpiGuid,
+  &mPlatformVTdSample
+};
+
+/**
+  Platform VTd Info sample driver.
+
+  @param[in] FileHandle  Handle of the file being invoked.
+  @param[in] PeiServices Describes the list of possible PEI Services.
+
+  @retval EFI_SUCCESS if it completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+PlatformVTdInfoSampleInitialize (
+  IN       EFI_PEI_FILE_HANDLE  FileHandle,
+  IN CONST EFI_PEI_SERVICES     **PeiServices
+  )
+{
+  EFI_STATUS  Status;
+
+  Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
+  ASSERT_EFI_ERROR (Status);
+
+  return Status;
+}
diff --git a/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
new file mode 100644
index 0000000..fe12821
--- /dev/null
+++ b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
@@ -0,0 +1,51 @@
+## @file
+# Platform VTd Info Sample PEI driver.
+#
+# Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution.  The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+  INF_VERSION                    = 0x00010005
+  BASE_NAME                      = PlatformVTdInfoSamplePei
+  MODULE_UNI_FILE                = PlatformVTdInfoSamplePei.uni
+  FILE_GUID                      = 839EB770-5C64-4EED-A6D5-EC515B2B2B23
+  MODULE_TYPE                    = PEIM
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = PlatformVTdInfoSampleInitialize
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64 IPF EBC
+#
+#
+
+[Sources]
+  PlatformVTdInfoSamplePei.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  IntelSiliconPkg/IntelSiliconPkg.dec
+
+[LibraryClasses]
+  PeimEntryPoint
+  PeiServicesLib
+
+[Ppis]
+  gEdkiiVTdInfoPpiGuid         ## PRODUCES
+
+[Depex]
+  gEfiPeiMemoryDiscoveredPpiGuid
+
+[UserExtensions.TianoCore."ExtraFiles"]
+  PlatformVTdInfoSamplePeiExtra.uni
+
diff --git a/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
new file mode 100644
index 0000000..36f9183
--- /dev/null
+++ b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
@@ -0,0 +1,20 @@
+// /** @file
+// PlatformVTdInfoSamplePei Module Localized Abstract and Description Content
+//
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials are
+// licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+
+#string STR_MODULE_ABSTRACT             #language en-US "Platform VTd Info PEI Driver."
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This driver provides sample on how to produce Platform VTd Info PPI."
+
diff --git a/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
new file mode 100644
index 0000000..df6345f
--- /dev/null
+++ b/IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
@@ -0,0 +1,20 @@
+// /** @file
+// PlatformVTdInfoSamplePei Localized Strings and Content
+//
+// Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+//
+// This program and the accompanying materials are
+// licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution.  The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Platform VTd Info Sample PEI Driver"
+
+
-- 
2.7.4.windows.1



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

* [PATCH 10/11] IntelSiliconPkg/dsc: Add PlatformVTdInfoSamplePei.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (8 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 09/11] IntelSiliconPkg: Add PlatformVTdInfoSamplePei Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-08 15:03 ` [PATCH 11/11] MdeModulePkg/XhciPei: Support IoMmu Jiewen Yao
  2017-09-13 10:13 ` [PATCH 00/11] Add IOMMU PEI support Zeng, Star
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelSiliconPkg.dsc | 1 +
 1 file changed, 1 insertion(+)

diff --git a/IntelSiliconPkg/IntelSiliconPkg.dsc b/IntelSiliconPkg/IntelSiliconPkg.dsc
index 33e822f..422e202 100644
--- a/IntelSiliconPkg/IntelSiliconPkg.dsc
+++ b/IntelSiliconPkg/IntelSiliconPkg.dsc
@@ -82,6 +82,7 @@
   IntelSiliconPkg/IntelVTdDxe/IntelVTdDxe.inf
   IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
   IntelSiliconPkg/PlatformVTdSampleDxe/PlatformVTdSampleDxe.inf
+  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
 
 [BuildOptions]
   *_*_*_CC_FLAGS = -D DISABLE_NEW_DEPRECATED_INTERFACES
-- 
2.7.4.windows.1



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

* [PATCH 11/11] MdeModulePkg/XhciPei: Support IoMmu.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (9 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 10/11] IntelSiliconPkg/dsc: " Jiewen Yao
@ 2017-09-08 15:03 ` Jiewen Yao
  2017-09-13 10:13 ` [PATCH 00/11] Add IOMMU PEI support Zeng, Star
  11 siblings, 0 replies; 19+ messages in thread
From: Jiewen Yao @ 2017-09-08 15:03 UTC (permalink / raw)
  To: edk2-devel; +Cc: Star Zeng

Update XHCI driver to consume IOMMU_PPI to allocate DMA buffer.

If no IOMMU_PPI exists, this driver still calls PEI service
to allocate DMA buffer, with assumption that DRAM==DMA.

This is a compatible change.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c    | 249 ++++++++++++++++++++
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c  |  55 +++--
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h  |   9 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c   |  55 ++++-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h   | 107 +++++++++
 MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf |   3 +
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c |  47 +++-
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h |   1 +
 8 files changed, 492 insertions(+), 34 deletions(-)

diff --git a/MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c b/MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
new file mode 100644
index 0000000..6e2c1b5
--- /dev/null
+++ b/MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
@@ -0,0 +1,249 @@
+/** @file
+The DMA memory help function.
+
+Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+
+This program and the accompanying materials
+are licensed and made available under the terms and conditions
+of the BSD License which accompanies this distribution.  The
+full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "XhcPeim.h"
+
+EDKII_IOMMU_PPI  *mIoMmu;
+
+/**
+  Provides the controller-specific addresses required to access system memory from a
+  DMA bus master.
+
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+IoMmuMap (
+  IN  EDKII_IOMMU_OPERATION Operation,
+  IN VOID                   *HostAddress,
+  IN  OUT UINTN             *NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  )
+{
+  EFI_STATUS  Status;
+  UINT64      Attribute;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->Map (
+                       mIoMmu,
+                       Operation,
+                       HostAddress,
+                       NumberOfBytes,
+                       DeviceAddress,
+                       Mapping
+                       );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    switch (Operation) {
+    case EdkiiIoMmuOperationBusMasterRead:
+    case EdkiiIoMmuOperationBusMasterRead64:
+      Attribute = EDKII_IOMMU_ACCESS_READ;
+      break;
+    case EdkiiIoMmuOperationBusMasterWrite:
+    case EdkiiIoMmuOperationBusMasterWrite64:
+      Attribute = EDKII_IOMMU_ACCESS_WRITE;
+      break;
+    case EdkiiIoMmuOperationBusMasterCommonBuffer:
+    case EdkiiIoMmuOperationBusMasterCommonBuffer64:
+      Attribute = EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE;
+      break;
+    default:
+      ASSERT(FALSE);
+      return EFI_INVALID_PARAMETER;
+    }
+    Status = mIoMmu->SetAttribute (
+                       mIoMmu,
+                       *Mapping,
+                       Attribute
+                       );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  } else {
+    *DeviceAddress = (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress;
+    *Mapping = NULL;
+    Status = EFI_SUCCESS;
+  }
+  return Status;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+**/
+EFI_STATUS
+IoMmuUnmap (
+  IN VOID                  *Mapping
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
+    Status = mIoMmu->Unmap (mIoMmu, Mapping);
+  } else {
+    Status = EFI_SUCCESS;
+  }
+  return Status;
+}
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory address of the
+                                allocated range.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+IoMmuAllocateBuffer (
+  IN UINTN                  Pages,
+  OUT VOID                  **HostAddress,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  )
+{
+  EFI_STATUS            Status;
+  UINTN                 NumberOfBytes;
+  EFI_PHYSICAL_ADDRESS  HostPhyAddress;
+
+  *HostAddress = NULL;
+  *DeviceAddress = 0;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->AllocateBuffer (
+                       mIoMmu,
+                       EfiBootServicesData,
+                       Pages,
+                       HostAddress,
+                       0
+                       );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    NumberOfBytes = EFI_PAGES_TO_SIZE(Pages);
+    Status = mIoMmu->Map (
+                       mIoMmu,
+                       EdkiiIoMmuOperationBusMasterCommonBuffer,
+                       *HostAddress,
+                       &NumberOfBytes,
+                       DeviceAddress,
+                       Mapping
+                       );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    Status = mIoMmu->SetAttribute (
+                       mIoMmu,
+                       *Mapping,
+                       EDKII_IOMMU_ACCESS_READ | EDKII_IOMMU_ACCESS_WRITE
+                       );
+    if (EFI_ERROR (Status)) {
+      return Status;
+    }
+  } else {
+    Status = PeiServicesAllocatePages (
+               EfiBootServicesData,
+               Pages,
+               &HostPhyAddress
+               );
+    if (EFI_ERROR (Status)) {
+      return EFI_OUT_OF_RESOURCES;
+    }
+    *HostAddress = (VOID *)(UINTN)HostPhyAddress;
+    *DeviceAddress = HostPhyAddress;
+    *Mapping = NULL;
+  }
+  return Status;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated range.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+IoMmuFreeBuffer (
+  IN UINTN                  Pages,
+  IN VOID                   *HostAddress,
+  IN VOID                   *Mapping
+  )
+{
+  EFI_STATUS  Status;
+
+  if (mIoMmu != NULL) {
+    Status = mIoMmu->SetAttribute (mIoMmu, Mapping, 0);
+    Status = mIoMmu->Unmap (mIoMmu, Mapping);
+    Status = mIoMmu->FreeBuffer (mIoMmu, Pages, HostAddress);
+  } else {
+    Status = EFI_SUCCESS;
+  }
+  return Status;
+}
+
+/**
+  Initialize IOMMU.
+**/
+VOID
+IoMmuInit (
+  VOID
+  )
+{
+  PeiServicesLocatePpi (
+    &gEdkiiIoMmuPpiGuid,
+    0,
+    NULL,
+    (VOID **)&mIoMmu
+    );
+}
+
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
index 6a3f3a5..5d0232c 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
+++ b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
@@ -31,6 +31,9 @@ UsbHcAllocMemBlock (
   )
 {
   USBHC_MEM_BLOCK       *Block;
+  VOID                  *BufHost;
+  VOID                  *Mapping;
+  EFI_PHYSICAL_ADDRESS  MappedAddr;
   EFI_STATUS            Status;
   UINTN                 PageNumber;
   EFI_PHYSICAL_ADDRESS  TempPtr;
@@ -71,18 +74,20 @@ UsbHcAllocMemBlock (
 
   Block->Bits = (UINT8 *) (UINTN) TempPtr;
 
-  Status = PeiServicesAllocatePages (
-             EfiBootServicesData,
+  Status = IoMmuAllocateBuffer (
              Pages,
-             &TempPtr
+             &BufHost,
+             &MappedAddr,
+             &Mapping
              );
   if (EFI_ERROR (Status)) {
     return NULL;
   }
-  ZeroMem ((VOID *) (UINTN) TempPtr, EFI_PAGES_TO_SIZE (Pages));
+  ZeroMem ((VOID *) (UINTN) BufHost, EFI_PAGES_TO_SIZE (Pages));
 
-  Block->BufHost = (UINT8 *) (UINTN) TempPtr;;
-  Block->Buf = (UINT8 *) (UINTN) TempPtr;
+  Block->BufHost = (UINT8 *) (UINTN) BufHost;
+  Block->Buf = (UINT8 *) (UINTN) MappedAddr;
+  Block->Mapping  = Mapping;
   Block->Next = NULL;
 
   return Block;
@@ -102,6 +107,9 @@ UsbHcFreeMemBlock (
   )
 {
   ASSERT ((Pool != NULL) && (Block != NULL));
+
+  IoMmuFreeBuffer (EFI_SIZE_TO_PAGES (Block->BufLen), Block->BufHost, Block->Mapping);
+
   //
   // No free memory in PEI.
   //
@@ -567,6 +575,7 @@ UsbHcFreeMem (
   @param  HostAddress           The system memory address to map to the PCI controller.
   @param  DeviceAddress         The resulting map address for the bus master PCI controller to
                                 use to access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
 
   @retval EFI_SUCCESS           Success to allocate aligned pages.
   @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
@@ -578,13 +587,16 @@ UsbHcAllocateAlignedPages (
   IN UINTN                      Pages,
   IN UINTN                      Alignment,
   OUT VOID                      **HostAddress,
-  OUT EFI_PHYSICAL_ADDRESS      *DeviceAddress
+  OUT EFI_PHYSICAL_ADDRESS      *DeviceAddress,
+  OUT VOID                      **Mapping
   )
 {
   EFI_STATUS            Status;
-  EFI_PHYSICAL_ADDRESS  Memory;
+  VOID                  *Memory;
   UINTN                 AlignedMemory;
   UINTN                 AlignmentMask;
+  EFI_PHYSICAL_ADDRESS  DeviceMemory;
+  UINTN                 AlignedDeviceMemory;
   UINTN                 RealPages;
 
   //
@@ -611,32 +623,36 @@ UsbHcAllocateAlignedPages (
     //
     ASSERT (RealPages > Pages);
 
-    Status = PeiServicesAllocatePages (
-               EfiBootServicesData,
+    Status = IoMmuAllocateBuffer (
                Pages,
-               &Memory
+               &Memory,
+               &DeviceMemory,
+               Mapping
                );
     if (EFI_ERROR (Status)) {
       return EFI_OUT_OF_RESOURCES;
     }
     AlignedMemory = ((UINTN) Memory + AlignmentMask) & ~AlignmentMask;
+    AlignedDeviceMemory = ((UINTN) DeviceMemory + AlignmentMask) & ~AlignmentMask;
   } else {
     //
     // Do not over-allocate pages in this case.
     //
-    Status = PeiServicesAllocatePages (
-               EfiBootServicesData,
+    Status = IoMmuAllocateBuffer (
                Pages,
-               &Memory
+               &Memory,
+               &DeviceMemory,
+               Mapping
                );
     if (EFI_ERROR (Status)) {
       return EFI_OUT_OF_RESOURCES;
     }
     AlignedMemory = (UINTN) Memory;
+    AlignedDeviceMemory = (UINTN) DeviceMemory;
   }
 
   *HostAddress = (VOID *) AlignedMemory;
-  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) AlignedMemory;
+  *DeviceAddress = (EFI_PHYSICAL_ADDRESS) AlignedDeviceMemory;
 
   return EFI_SUCCESS;
 }
@@ -646,17 +662,18 @@ UsbHcAllocateAlignedPages (
 
   @param  HostAddress           The system memory address to map to the PCI controller.
   @param  Pages                 The number of pages to free.
+  @param  Mapping               The mapping value returned from Map().
 
 **/
 VOID
 UsbHcFreeAlignedPages (
   IN VOID               *HostAddress,
-  IN UINTN              Pages
+  IN UINTN              Pages,
+  IN VOID               *Mapping
   )
 {
   ASSERT (Pages != 0);
-  //
-  // No free memory in PEI.
-  //
+
+  IoMmuFreeBuffer (Pages, HostAddress, Mapping);
 }
 
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
index c314e92..c315e6e 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
+++ b/MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
@@ -29,6 +29,7 @@ struct _USBHC_MEM_BLOCK {
   UINT8                 *Buf;
   UINT8                 *BufHost;
   UINTN                 BufLen; // Memory size in bytes
+  VOID                  *Mapping;
   USBHC_MEM_BLOCK       *Next;
 };
 
@@ -112,6 +113,7 @@ UsbHcGetHostAddrForPciAddr (
   @param  HostAddress           The system memory address to map to the PCI controller.
   @param  DeviceAddress         The resulting map address for the bus master PCI controller to
                                 use to access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
 
   @retval EFI_SUCCESS           Success to allocate aligned pages.
   @retval EFI_INVALID_PARAMETER Pages or Alignment is not valid.
@@ -123,7 +125,8 @@ UsbHcAllocateAlignedPages (
   IN UINTN                      Pages,
   IN UINTN                      Alignment,
   OUT VOID                      **HostAddress,
-  OUT EFI_PHYSICAL_ADDRESS      *DeviceAddress
+  OUT EFI_PHYSICAL_ADDRESS      *DeviceAddress,
+  OUT VOID                      **Mapping
   );
 
 /**
@@ -131,12 +134,14 @@ UsbHcAllocateAlignedPages (
 
   @param  HostAddress           The system memory address to map to the PCI controller.
   @param  Pages                 The number of pages to free.
+  @param  Mapping               The mapping value returned from Map().
 
 **/
 VOID
 UsbHcFreeAlignedPages (
   IN VOID               *HostAddress,
-  IN UINTN              Pages
+  IN UINTN              Pages,
+  IN VOID               *Mapping
   );
 
 #endif
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
index 38f0d21..99f69f7 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
@@ -662,7 +662,8 @@ XhcPeiControlTransfer (
     if (EFI_ERROR(RecoveryStatus)) {
       DEBUG((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiDequeueTrbFromEndpoint failed\n"));
     }
-    goto FREE_URB;
+    XhcPeiFreeUrb (Xhc, Urb);
+    goto ON_EXIT;
   } else {
     if (*TransferResult == EFI_USB_NOERROR) {
       Status = EFI_SUCCESS;
@@ -672,11 +673,17 @@ XhcPeiControlTransfer (
         DEBUG ((EFI_D_ERROR, "XhcPeiControlTransfer: XhcPeiRecoverHaltedEndpoint failed\n"));
       }
       Status = EFI_DEVICE_ERROR;
-      goto FREE_URB;
+      XhcPeiFreeUrb (Xhc, Urb);
+      goto ON_EXIT;
     } else {
-      goto FREE_URB;
+      XhcPeiFreeUrb (Xhc, Urb);
+      goto ON_EXIT;
     }
   }
+  //
+  // Unmap data before consume.
+  //
+  XhcPeiFreeUrb (Xhc, Urb);
 
   //
   // Hook Get_Descriptor request from UsbBus as we need evaluate context and configure endpoint.
@@ -704,7 +711,7 @@ XhcPeiControlTransfer (
       Xhc->UsbDevContext[SlotId].ConfDesc = AllocateZeroPool (Xhc->UsbDevContext[SlotId].DevDesc.NumConfigurations * sizeof (EFI_USB_CONFIG_DESCRIPTOR *));
       if (Xhc->UsbDevContext[SlotId].ConfDesc == NULL) {
         Status = EFI_OUT_OF_RESOURCES;
-        goto FREE_URB;
+        goto ON_EXIT;
       }
       if (Xhc->HcCParams.Data.Csz == 0) {
         Status = XhcPeiEvaluateContext (Xhc, SlotId, MaxPacket0);
@@ -722,7 +729,7 @@ XhcPeiControlTransfer (
         Xhc->UsbDevContext[SlotId].ConfDesc[Index] = AllocateZeroPool (*DataLength);
         if (Xhc->UsbDevContext[SlotId].ConfDesc[Index] == NULL) {
           Status = EFI_OUT_OF_RESOURCES;
-          goto FREE_URB;
+          goto ON_EXIT;
         }
         CopyMem (Xhc->UsbDevContext[SlotId].ConfDesc[Index], Data, *DataLength);
       }
@@ -844,9 +851,6 @@ XhcPeiControlTransfer (
     *(UINT32 *) Data = *(UINT32 *) &PortStatus;
   }
 
-FREE_URB:
-  XhcPeiFreeUrb (Xhc, Urb);
-
 ON_EXIT:
 
   if (EFI_ERROR (Status)) {
@@ -1399,6 +1403,34 @@ XhcPeiGetRootHubPortStatus (
 }
 
 /**
+  One notified function to stop the Host Controller at the end of PEI
+
+  @param[in]  PeiServices        Pointer to PEI Services Table.
+  @param[in]  NotifyDescriptor   Pointer to the descriptor for the Notification event that
+                                 caused this function to execute.
+  @param[in]  Ppi                Pointer to the PPI data associated with this function.
+
+  @retval     EFI_SUCCESS  The function completes successfully
+  @retval     others
+**/
+EFI_STATUS
+EFIAPI
+XhcEndOfPei (
+  IN EFI_PEI_SERVICES           **PeiServices,
+  IN EFI_PEI_NOTIFY_DESCRIPTOR  *NotifyDescriptor,
+  IN VOID                       *Ppi
+  )
+{
+  PEI_XHC_DEV    *Xhc;
+
+  Xhc = PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(NotifyDescriptor);
+
+  XhcPeiHaltHC (Xhc, XHC_GENERIC_TIMEOUT);
+
+  return EFI_SUCCESS;
+}
+
+/**
   @param FileHandle     Handle of the file being invoked.
   @param PeiServices    Describes the list of possible PEI Services.
 
@@ -1429,6 +1461,8 @@ XhcPeimEntry (
     return EFI_SUCCESS;
   }
 
+  IoMmuInit ();
+
   Status = PeiServicesLocatePpi (
              &gPeiUsbControllerPpiGuid,
              0,
@@ -1530,7 +1564,12 @@ XhcPeimEntry (
     XhcDev->PpiDescriptor.Guid = &gPeiUsb2HostControllerPpiGuid;
     XhcDev->PpiDescriptor.Ppi = &XhcDev->Usb2HostControllerPpi;
 
+    XhcDev->EndOfPeiNotifyList.Flags = (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST);
+    XhcDev->EndOfPeiNotifyList.Guid = &gEfiEndOfPeiSignalPpiGuid;
+    XhcDev->EndOfPeiNotifyList.Notify = XhcEndOfPei;
+
     PeiServicesInstallPpi (&XhcDev->PpiDescriptor);
+    PeiServicesNotifyPpi (&XhcDev->EndOfPeiNotifyList);
 
     Index++;
   }
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
index 99f0396..e7a100f 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
@@ -21,6 +21,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 
 #include <Ppi/UsbController.h>
 #include <Ppi/Usb2HostController.h>
+#include <Ppi/IoMmu.h>
+#include <Ppi/EndOfPeiPhase.h>
 
 #include <Library/DebugLib.h>
 #include <Library/PeimEntryPoint.h>
@@ -153,6 +155,12 @@ struct _PEI_XHC_DEV {
   USBHC_MEM_POOL                    *MemPool;
 
   //
+  // EndOfPei callback is used to stop the XHC DMA operation
+  // after exit PEI phase.
+  //
+  EFI_PEI_NOTIFY_DESCRIPTOR         EndOfPeiNotifyList;
+
+  //
   // XHCI configuration data
   //
   UINT8                             CapLength;    ///< Capability Register Length
@@ -164,7 +172,9 @@ struct _PEI_XHC_DEV {
   UINT32                            PageSize;
   UINT32                            MaxScratchpadBufs;
   UINT64                            *ScratchBuf;
+  VOID                              *ScratchMap;
   UINT64                            *ScratchEntry;
+  UINTN                             *ScratchEntryMap;
   UINT64                            *DCBAA;
   UINT32                            MaxSlotsEn;
   //
@@ -184,6 +194,7 @@ struct _PEI_XHC_DEV {
 };
 
 #define PEI_RECOVERY_USB_XHC_DEV_FROM_THIS(a) CR (a, PEI_XHC_DEV, Usb2HostControllerPpi, USB_XHC_DEV_SIGNATURE)
+#define PEI_RECOVERY_USB_XHC_DEV_FROM_THIS_NOTIFY(a) CR (a, PEI_XHC_DEV, EndOfPeiNotifyList, USB_XHC_DEV_SIGNATURE)
 
 /**
   Initialize the memory management pool for the host controller.
@@ -242,4 +253,100 @@ UsbHcFreeMem (
   )
 ;
 
+
+/**
+  Initialize IOMMU.
+**/
+VOID
+IoMmuInit (
+  VOID
+  );
+
+/**
+  Provides the controller-specific addresses required to access system memory from a
+  DMA bus master.
+
+  @param  Operation             Indicates if the bus master is going to read or write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+IoMmuMap (
+  IN  EDKII_IOMMU_OPERATION Operation,
+  IN  VOID                  *HostAddress,
+  IN  OUT UINTN             *NumberOfBytes,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  );
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+**/
+EFI_STATUS
+IoMmuUnmap (
+  IN VOID                  *Mapping
+  );
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory address of the
+                                allocated range.
+  @param  DeviceAddress         The resulting map address for the bus master PCI controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute bits are
+                                MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+IoMmuAllocateBuffer (
+  IN UINTN                  Pages,
+  OUT VOID                  **HostAddress,
+  OUT EFI_PHYSICAL_ADDRESS  *DeviceAddress,
+  OUT VOID                  **Mapping
+  );
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated range.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+IoMmuFreeBuffer (
+  IN UINTN                  Pages,
+  IN VOID                   *HostAddress,
+  IN VOID                   *Mapping
+  );
+
 #endif
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf b/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
index dc65f28..f307ea7 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
@@ -37,6 +37,7 @@
   XhcPeim.h
   XhciSched.c
   UsbHcMem.c
+  DmaMem.c
   XhciReg.h
   XhciSched.h
   UsbHcMem.h
@@ -56,6 +57,8 @@
 [Ppis]
   gPeiUsb2HostControllerPpiGuid                 ## PRODUCES
   gPeiUsbControllerPpiGuid                      ## CONSUMES
+  gEdkiiIoMmuPpiGuid                            ## CONSUMES
+  gEfiEndOfPeiSignalPpiGuid                     ## CONSUMES
 
 [Depex]
   gEfiPeiMemoryDiscoveredPpiGuid AND gPeiUsbControllerPpiGuid AND gEfiPeiBootInRecoveryModePpiGuid
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
index 3dd2b89..e5aee49 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
@@ -200,6 +200,8 @@ XhcPeiFreeUrb (
     return;
   }
 
+  IoMmuUnmap (Urb->DataMap);
+
   FreePool (Urb);
 }
 
@@ -227,6 +229,10 @@ XhcPeiCreateTransferTrb (
   UINTN                         TotalLen;
   UINTN                         Len;
   UINTN                         TrbNum;
+  EDKII_IOMMU_OPERATION         MapOp;
+  EFI_PHYSICAL_ADDRESS          PhyAddr;
+  VOID                          *Map;
+  EFI_STATUS                    Status;
 
   SlotId = XhcPeiBusDevAddrToSlotId (Xhc, Urb->Ep.BusAddr);
   if (SlotId == 0) {
@@ -249,7 +255,27 @@ XhcPeiCreateTransferTrb (
     EPType  = (UINT8) ((DEVICE_CONTEXT_64 *)OutputContext)->EP[Dci-1].EPType;
   }
 
-  Urb->DataPhy = Urb->Data;
+  //
+  // No need to remap.
+  //
+  if ((Urb->Data != NULL) && (Urb->DataMap == NULL)) {
+    if (((UINT8) (Urb->Ep.Direction)) == EfiUsbDataIn) {
+      MapOp = EdkiiIoMmuOperationBusMasterWrite;
+    } else {
+      MapOp = EdkiiIoMmuOperationBusMasterRead;
+    }
+
+    Len = Urb->DataLen;
+    Status = IoMmuMap (MapOp, Urb->Data, &Len, &PhyAddr, &Map);
+
+    if (EFI_ERROR (Status) || (Len != Urb->DataLen)) {
+      DEBUG ((DEBUG_ERROR, "XhcCreateTransferTrb: Fail to map Urb->Data.\n"));
+      return EFI_OUT_OF_RESOURCES;
+    }
+
+    Urb->DataPhy  = (VOID *) ((UINTN) PhyAddr);
+    Urb->DataMap  = Map;
+  }
 
   //
   // Construct the TRB
@@ -2812,6 +2838,7 @@ XhcPeiInitSched (
   UINT64                *ScratchEntry;
   EFI_PHYSICAL_ADDRESS  ScratchEntryPhy;
   UINT32                Index;
+  UINTN                 *ScratchEntryMap;
   EFI_STATUS            Status;
 
   //
@@ -2848,6 +2875,13 @@ XhcPeiInitSched (
   ASSERT (MaxScratchpadBufs <= 1023);
   if (MaxScratchpadBufs != 0) {
     //
+    // Allocate the buffer to record the Mapping for each scratch buffer in order to Unmap them
+    //
+    ScratchEntryMap = AllocateZeroPool (sizeof (UINTN) * MaxScratchpadBufs);
+    ASSERT (ScratchEntryMap != NULL);
+    Xhc->ScratchEntryMap = ScratchEntryMap;
+
+    //
     // Allocate the buffer to record the host address for each entry
     //
     ScratchEntry = AllocateZeroPool (sizeof (UINT64) * MaxScratchpadBufs);
@@ -2859,7 +2893,8 @@ XhcPeiInitSched (
                EFI_SIZE_TO_PAGES (MaxScratchpadBufs * sizeof (UINT64)),
                Xhc->PageSize,
                (VOID **) &ScratchBuf,
-               &ScratchPhy
+               &ScratchPhy,
+               &Xhc->ScratchMap
                );
     ASSERT_EFI_ERROR (Status);
 
@@ -2875,7 +2910,8 @@ XhcPeiInitSched (
                  EFI_SIZE_TO_PAGES (Xhc->PageSize),
                  Xhc->PageSize,
                  (VOID **) &ScratchEntry[Index],
-                 &ScratchEntryPhy
+                 &ScratchEntryPhy,
+                 (VOID **) &ScratchEntryMap[Index]
                  );
       ASSERT_EFI_ERROR (Status);
       ZeroMem ((VOID *) (UINTN) ScratchEntry[Index], Xhc->PageSize);
@@ -2967,12 +3003,13 @@ XhcPeiFreeSched (
       //
       // Free Scratchpad Buffers
       //
-      UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize));
+      UsbHcFreeAlignedPages ((VOID*) (UINTN) ScratchEntry[Index], EFI_SIZE_TO_PAGES (Xhc->PageSize), (VOID *) Xhc->ScratchEntryMap[Index]);
     }
     //
     // Free Scratchpad Buffer Array
     //
-    UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)));
+    UsbHcFreeAlignedPages (Xhc->ScratchBuf, EFI_SIZE_TO_PAGES (Xhc->MaxScratchpadBufs * sizeof (UINT64)), Xhc->ScratchMap);
+    FreePool (Xhc->ScratchEntryMap);
     FreePool (Xhc->ScratchEntry);
   }
 
diff --git a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
index b3d4c45..faf2e63 100644
--- a/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
+++ b/MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
@@ -170,6 +170,7 @@ typedef struct _URB {
   VOID                              *Data;
   UINTN                             DataLen;
   VOID                              *DataPhy;
+  VOID                              *DataMap;
   EFI_ASYNC_USB_TRANSFER_CALLBACK   Callback;
   VOID                              *Context;
   //
-- 
2.7.4.windows.1



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

* Re: [PATCH 00/11] Add IOMMU PEI support.
  2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
                   ` (10 preceding siblings ...)
  2017-09-08 15:03 ` [PATCH 11/11] MdeModulePkg/XhciPei: Support IoMmu Jiewen Yao
@ 2017-09-13 10:13 ` Zeng, Star
  2017-09-13 10:19   ` Yao, Jiewen
  11 siblings, 1 reply; 19+ messages in thread
From: Zeng, Star @ 2017-09-13 10:13 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

I have been confused by where should new module be put for some time.
When should a new module be put at XXXPkg/Universal? For example, MdeModule/Universal, UefiCpuPkg/Universal, ....
When should a new module be put at XXXPkg/Feature? For example, UefiCpuPkg/Feature.
When should a new module be put at the root of a package folder? For example, UefiCpuPkg/PiSmmCpuDxeSmm, IntelSiliconPkg/IntelVTdDxe, ....

Is it better or not to put IntelVTdDxe, PlatformVTdSampleDxe and new IntelVTdPmrPei, PlatformVTdInfoSamplePei in IntelSiliconPkg/Feature/VTd together?


Thanks,
Star
-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen Yao
Sent: Friday, September 8, 2017 11:04 PM
To: edk2-devel@lists.01.org
Subject: [edk2] [PATCH 00/11] Add IOMMU PEI support.

This series patch added IOMMU PEI support.
It is also posted to https://github.com/jyao1/edk2/tree/IoMmuPpi.

1) Patch 1 and 2 add EDKII_IOMMU_PPI.
It is similar to EDKII_IOMMU_PROTOCOL.

2) Patch 3 and 4 add Intel VTD PMR register support for DXE phase IntelVTdDxe.
This is to prepare handle PMR usage in PEI phase.

3) Patch 5 and 6 add EDKII_VTD_INFO_PPI.
This PPI is to provide Intel VTD information in PEI.
In DXE, the VTd driver can get VTD info from ACPI DMAR table.
But in PEI, there is no way to get VTD info before.
VTD_INFO_PPI is added to resolve the problem.

4) Patch 7 and 8 add IntelVTdPmrPei driver.
This driver consumes EDKII_VTD_INFO_PPI and produces IOMMU_PPI.
It enables VTD PMR register to provide DMA protection.
The PMR based DMA protection is a simple solution to mark 2 regions can be DMA protected.
The IntelVTdPmrPei allocates a small chunk buffer for DMA and protect the rest memory.

5) Patch 9 and 10 add a sample VTdInfo PEI driver.
It provides a sample to show how to report VTd info in PEI phase.

6) Patch 11 updates XhciPei driver to consume IOMMU_PPI.
If the IOMMU_PPI is present, XhciPei will use IOMMU_PPI to allocate DMA buffer. Or the XhciPei will still use old way - PeiServiceAllocatePage to allocate DRAM as DMA buffer.
This is the first PEI device driver consuming IOMMU_PPI to show the concept. The rest PEI device drivers will be updated in separated patches.


This series patch is validated on Intel Kabylake Platform.
1) We can use XHCI to do file transfer in PEI phase,
2) We can still use XHCI in DXE phase, such as shell environment.
3) If the device driver does not consume IOMMU_PPI, the DMA fails.

Jiewen Yao (11):
  MdeModulePkg/Include: Add IOMMU_PPI.
  MdeModulePkg/Dec: Add IOMMU_PPI GUID.
  IntelSiliconPkg/Vtd.h: Add definition for PMR.
  IntelSiliconPkg/VTdDxe: Disable PMR
  IntelSiliconPkg/include: Add VTD_INFO PPI.
  IntelSiliconPkg/dec: Add VTD_INFO PPI GUID
  IntelSiliconPkg: Add IntelVTdPmrPei.
  IntelSiliconPkg/dsc: Add IntelVTdPmrPeim.
  IntelSiliconPkg: Add PlatformVTdInfoSamplePei.
  IntelSiliconPkg/dsc: Add PlatformVTdInfoSamplePei.
  MdeModulePkg/XhciPei: Support IoMmu.

 IntelSiliconPkg/Include/IndustryStandard/Vtd.h                             |   6 +
 IntelSiliconPkg/Include/Ppi/VtdInfo.h                                      |  40 ++
 IntelSiliconPkg/IntelSiliconPkg.dec                                        |   3 +
 IntelSiliconPkg/IntelSiliconPkg.dsc                                        |  10 +
 IntelSiliconPkg/IntelVTdDxe/VtdReg.c                                       |  51 +-
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c                               | 314 ++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c                            | 615 ++++++++++++++++++++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h                            |  68 +++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf                          |  59 ++
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni                          |  20 +
 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni                     |  20 +
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c        |  65 +++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf      |  51 ++
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni      |  20 +
 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni |  20 +
 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c                                      | 249 ++++++++
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c                                    |  55 +-
 MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h                                    |   9 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c                                     |  55 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h                                     | 107 ++++
 MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf                                   |   3 +
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c                                   |  47 +-
 MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h                                   |   1 +
 MdeModulePkg/Include/Ppi/IoMmu.h                                           | 196 +++++++
 MdeModulePkg/MdeModulePkg.dec                                              |   3 +
 25 files changed, 2052 insertions(+), 35 deletions(-)  create mode 100644 IntelSiliconPkg/Include/Ppi/VtdInfo.h
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
 create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
 create mode 100644 IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
 create mode 100644 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
 create mode 100644 MdeModulePkg/Include/Ppi/IoMmu.h

--
2.7.4.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 00/11] Add IOMMU PEI support.
  2017-09-13 10:13 ` [PATCH 00/11] Add IOMMU PEI support Zeng, Star
@ 2017-09-13 10:19   ` Yao, Jiewen
  2017-09-14  6:32     ` Zeng, Star
  0 siblings, 1 reply; 19+ messages in thread
From: Yao, Jiewen @ 2017-09-13 10:19 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

Good question.

Yes, I think we can put all VTd related components to IntelSiliconPkg/Feature/VTd.
Once we finished the review, I would submit another patch to move all components to the new location.

Thank you
Yao Jiewen


> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, September 13, 2017 6:14 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH 00/11] Add IOMMU PEI support.
> 
> I have been confused by where should new module be put for some time.
> When should a new module be put at XXXPkg/Universal? For example,
> MdeModule/Universal, UefiCpuPkg/Universal, ....
> When should a new module be put at XXXPkg/Feature? For example,
> UefiCpuPkg/Feature.
> When should a new module be put at the root of a package folder? For example,
> UefiCpuPkg/PiSmmCpuDxeSmm, IntelSiliconPkg/IntelVTdDxe, ....
> 
> Is it better or not to put IntelVTdDxe, PlatformVTdSampleDxe and new
> IntelVTdPmrPei, PlatformVTdInfoSamplePei in IntelSiliconPkg/Feature/VTd
> together?
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Jiewen
> Yao
> Sent: Friday, September 8, 2017 11:04 PM
> To: edk2-devel@lists.01.org
> Subject: [edk2] [PATCH 00/11] Add IOMMU PEI support.
> 
> This series patch added IOMMU PEI support.
> It is also posted to https://github.com/jyao1/edk2/tree/IoMmuPpi.
> 
> 1) Patch 1 and 2 add EDKII_IOMMU_PPI.
> It is similar to EDKII_IOMMU_PROTOCOL.
> 
> 2) Patch 3 and 4 add Intel VTD PMR register support for DXE phase IntelVTdDxe.
> This is to prepare handle PMR usage in PEI phase.
> 
> 3) Patch 5 and 6 add EDKII_VTD_INFO_PPI.
> This PPI is to provide Intel VTD information in PEI.
> In DXE, the VTd driver can get VTD info from ACPI DMAR table.
> But in PEI, there is no way to get VTD info before.
> VTD_INFO_PPI is added to resolve the problem.
> 
> 4) Patch 7 and 8 add IntelVTdPmrPei driver.
> This driver consumes EDKII_VTD_INFO_PPI and produces IOMMU_PPI.
> It enables VTD PMR register to provide DMA protection.
> The PMR based DMA protection is a simple solution to mark 2 regions can be
> DMA protected.
> The IntelVTdPmrPei allocates a small chunk buffer for DMA and protect the rest
> memory.
> 
> 5) Patch 9 and 10 add a sample VTdInfo PEI driver.
> It provides a sample to show how to report VTd info in PEI phase.
> 
> 6) Patch 11 updates XhciPei driver to consume IOMMU_PPI.
> If the IOMMU_PPI is present, XhciPei will use IOMMU_PPI to allocate DMA
> buffer. Or the XhciPei will still use old way - PeiServiceAllocatePage to allocate
> DRAM as DMA buffer.
> This is the first PEI device driver consuming IOMMU_PPI to show the concept.
> The rest PEI device drivers will be updated in separated patches.
> 
> 
> This series patch is validated on Intel Kabylake Platform.
> 1) We can use XHCI to do file transfer in PEI phase,
> 2) We can still use XHCI in DXE phase, such as shell environment.
> 3) If the device driver does not consume IOMMU_PPI, the DMA fails.
> 
> Jiewen Yao (11):
>   MdeModulePkg/Include: Add IOMMU_PPI.
>   MdeModulePkg/Dec: Add IOMMU_PPI GUID.
>   IntelSiliconPkg/Vtd.h: Add definition for PMR.
>   IntelSiliconPkg/VTdDxe: Disable PMR
>   IntelSiliconPkg/include: Add VTD_INFO PPI.
>   IntelSiliconPkg/dec: Add VTD_INFO PPI GUID
>   IntelSiliconPkg: Add IntelVTdPmrPei.
>   IntelSiliconPkg/dsc: Add IntelVTdPmrPeim.
>   IntelSiliconPkg: Add PlatformVTdInfoSamplePei.
>   IntelSiliconPkg/dsc: Add PlatformVTdInfoSamplePei.
>   MdeModulePkg/XhciPei: Support IoMmu.
> 
>  IntelSiliconPkg/Include/IndustryStandard/Vtd.h
> |   6 +
>  IntelSiliconPkg/Include/Ppi/VtdInfo.h
> |  40 ++
>  IntelSiliconPkg/IntelSiliconPkg.dec
> |   3 +
>  IntelSiliconPkg/IntelSiliconPkg.dsc
> |  10 +
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> |  51 +-
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
> | 314 ++++++++++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
> | 615 ++++++++++++++++++++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
> |  68 +++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
> |  59 ++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
> |  20 +
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
> |  20 +
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
> |  65 +++
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
> |  51 ++
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
> |  20 +
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
> |  20 +
>  MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
> | 249 ++++++++
>  MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
> |  55 +-
>  MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
> |   9 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> |  55 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
> | 107 ++++
>  MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
> |   3 +
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> |  47 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> |   1 +
>  MdeModulePkg/Include/Ppi/IoMmu.h
> | 196 +++++++
>  MdeModulePkg/MdeModulePkg.dec
> |   3 +
>  25 files changed, 2052 insertions(+), 35 deletions(-)  create mode 100644
> IntelSiliconPkg/Include/Ppi/VtdInfo.h
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra.uni
>  create mode 100644 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
>  create mode 100644 MdeModulePkg/Include/Ppi/IoMmu.h
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

* Re: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
  2017-09-08 15:03 ` [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR Jiewen Yao
@ 2017-09-14  5:35   ` Zeng, Star
  2017-09-14  6:02     ` Yao, Jiewen
  0 siblings, 1 reply; 19+ messages in thread
From: Zeng, Star @ 2017-09-14  5:35 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

A minor comment.

Should or need IntelVTdPmrPei disable PMR at endofpei?


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Friday, September 8, 2017 11:04 PM
To: edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR

When VTd translation is enabled, PMR can be disable.
Or the DMA will be blocked by PMR.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
 IntelSiliconPkg/IntelVTdDxe/VtdReg.c | 51 +++++++++++++++++++-
 1 file changed, 50 insertions(+), 1 deletion(-)

diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
index 7402d81..1404af7 100644
--- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
+++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
@@ -196,6 +196,39 @@ PrepareVtdConfig (
 }
 
 /**
+  Disable PMR in all VTd engine.
+**/
+VOID
+DisablePmr (
+  VOID
+  )
+{
+  UINT32        Reg32;
+  VTD_CAP_REG   CapReg;
+  UINTN         Index;
+
+  DEBUG ((DEBUG_INFO,"DisablePmr\n"));
+  for (Index = 0; Index < mVtdUnitNumber; Index++) {
+    CapReg.Uint64 = MmioRead64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
+    if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
+      continue ;
+    }
+
+    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+    if ((Reg32 & BIT0) != 0) {
+      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
+      do {
+        Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
+      } while((Reg32 & BIT0) != 0);
+      DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
+    } else {
+      DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
+    }
+  }
+  return ;
+}
+
+/**
   Enable DMAR translation.
 
   @retval EFI_SUCCESS           DMAR translation is enabled.
@@ -259,6 +292,11 @@ EnableDmar (
     DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
   }
 
+  //
+  // Need disable PMR, since we already setup translation table.
+  //
+  DisablePmr ();
+
   mVtdEnabled = TRUE;
 
   return EFI_SUCCESS;
@@ -502,7 +540,7 @@ DumpVtdIfError (
     for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
       FrcdReg.Uint64[0] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG));
       FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
-      if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
+      if (FrcdReg.Bits.F != 0) {
         HasError = TRUE;
       }
     }
@@ -511,6 +549,17 @@ DumpVtdIfError (
       DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
       DumpVtdRegs (Num);
       DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
+      //
+      // Clear
+      //
+      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
+        FrcdReg.Uint64[1] = MmioRead64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
+        if (FrcdReg.Bits.F != 0) {
+          FrcdReg.Bits.F = 0;
+          MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), FrcdReg.Uint64[1]);
+        }
+        MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + R_FSTS_REG));
+      }
     }
   }
 }
-- 
2.7.4.windows.1



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

* Re: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
  2017-09-14  5:35   ` Zeng, Star
@ 2017-09-14  6:02     ` Yao, Jiewen
  2017-09-14  6:10       ` Zeng, Star
  0 siblings, 1 reply; 19+ messages in thread
From: Yao, Jiewen @ 2017-09-14  6:02 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

I did consider that before.
I do not disable at EndOfPei purposely that because I want to make sure that the DMA protect is still available in early DXE phase, just in case there is bug in other module which forgets disabling BME.

Later it is VTdDxe driver that disable PME, *after* it sets up translation table. As such, the DMA protection is always there.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Thursday, September 14, 2017 1:36 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
> 
> A minor comment.
> 
> Should or need IntelVTdPmrPei disable PMR at endofpei?
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, September 8, 2017 11:04 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
> 
> When VTd translation is enabled, PMR can be disable.
> Or the DMA will be blocked by PMR.
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c | 51 +++++++++++++++++++-
>  1 file changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> index 7402d81..1404af7 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> @@ -196,6 +196,39 @@ PrepareVtdConfig (
>  }
> 
>  /**
> +  Disable PMR in all VTd engine.
> +**/
> +VOID
> +DisablePmr (
> +  VOID
> +  )
> +{
> +  UINT32        Reg32;
> +  VTD_CAP_REG   CapReg;
> +  UINTN         Index;
> +
> +  DEBUG ((DEBUG_INFO,"DisablePmr\n"));
> +  for (Index = 0; Index < mVtdUnitNumber; Index++) {
> +    CapReg.Uint64 = MmioRead64
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
> +    if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
> +      continue ;
> +    }
> +
> +    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_PMEN_ENABLE_REG);
> +    if ((Reg32 & BIT0) != 0) {
> +      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_PMEN_ENABLE_REG, 0x0);
> +      do {
> +        Reg32 = MmioRead32
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
> +      } while((Reg32 & BIT0) != 0);
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
> +    } else {
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
> +    }
> +  }
> +  return ;
> +}
> +
> +/**
>    Enable DMAR translation.
> 
>    @retval EFI_SUCCESS           DMAR translation is enabled.
> @@ -259,6 +292,11 @@ EnableDmar (
>      DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
>    }
> 
> +  //
> +  // Need disable PMR, since we already setup translation table.
> +  //
> +  DisablePmr ();
> +
>    mVtdEnabled = TRUE;
> 
>    return EFI_SUCCESS;
> @@ -502,7 +540,7 @@ DumpVtdIfError (
>      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
>        FrcdReg.Uint64[0] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) +
> (Index * 16) + R_FRCD_REG));
>        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) +
> (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> -      if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
> +      if (FrcdReg.Bits.F != 0) {
>          HasError = TRUE;
>        }
>      }
> @@ -511,6 +549,17 @@ DumpVtdIfError (
>        DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
>        DumpVtdRegs (Num);
>        DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
> +      //
> +      // Clear
> +      //
> +      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
> +        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) +
> (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> +        if (FrcdReg.Bits.F != 0) {
> +          FrcdReg.Bits.F = 0;
> +          MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)),
> FrcdReg.Uint64[1]);
> +        }
> +        MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> R_FSTS_REG));
> +      }
>      }
>    }
>  }
> --
> 2.7.4.windows.1



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

* Re: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
  2017-09-14  6:02     ` Yao, Jiewen
@ 2017-09-14  6:10       ` Zeng, Star
  2017-09-14  6:15         ` Yao, Jiewen
  0 siblings, 1 reply; 19+ messages in thread
From: Zeng, Star @ 2017-09-14  6:10 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Then, if there is a driver wants to do DMA at early DXE, it must need a PEIM to allocate the DMA buffers in PEI and transfer them to DXE by HOB.
Is that what we want? I want to confirm that.


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen 
Sent: Thursday, September 14, 2017 2:03 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR

I did consider that before.
I do not disable at EndOfPei purposely that because I want to make sure that the DMA protect is still available in early DXE phase, just in case there is bug in other module which forgets disabling BME.

Later it is VTdDxe driver that disable PME, *after* it sets up translation table. As such, the DMA protection is always there.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Thursday, September 14, 2017 1:36 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
> 
> A minor comment.
> 
> Should or need IntelVTdPmrPei disable PMR at endofpei?
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, September 8, 2017 11:04 PM
> To: edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
> 
> When VTd translation is enabled, PMR can be disable.
> Or the DMA will be blocked by PMR.
> 
> Cc: Star Zeng <star.zeng@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c | 51 +++++++++++++++++++-
>  1 file changed, 50 insertions(+), 1 deletion(-)
> 
> diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> index 7402d81..1404af7 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> @@ -196,6 +196,39 @@ PrepareVtdConfig (  }
> 
>  /**
> +  Disable PMR in all VTd engine.
> +**/
> +VOID
> +DisablePmr (
> +  VOID
> +  )
> +{
> +  UINT32        Reg32;
> +  VTD_CAP_REG   CapReg;
> +  UINTN         Index;
> +
> +  DEBUG ((DEBUG_INFO,"DisablePmr\n"));  for (Index = 0; Index < 
> + mVtdUnitNumber; Index++) {
> +    CapReg.Uint64 = MmioRead64
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
> +    if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
> +      continue ;
> +    }
> +
> +    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress 
> + +
> R_PMEN_ENABLE_REG);
> +    if ((Reg32 & BIT0) != 0) {
> +      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_PMEN_ENABLE_REG, 0x0);
> +      do {
> +        Reg32 = MmioRead32
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
> +      } while((Reg32 & BIT0) != 0);
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
> +    } else {
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
> +    }
> +  }
> +  return ;
> +}
> +
> +/**
>    Enable DMAR translation.
> 
>    @retval EFI_SUCCESS           DMAR translation is enabled.
> @@ -259,6 +292,11 @@ EnableDmar (
>      DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
>    }
> 
> +  //
> +  // Need disable PMR, since we already setup translation table.
> +  //
> +  DisablePmr ();
> +
>    mVtdEnabled = TRUE;
> 
>    return EFI_SUCCESS;
> @@ -502,7 +540,7 @@ DumpVtdIfError (
>      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
>        FrcdReg.Uint64[0] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) 
> + (Index * 16) + R_FRCD_REG));
>        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) 
> + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> -      if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
> +      if (FrcdReg.Bits.F != 0) {
>          HasError = TRUE;
>        }
>      }
> @@ -511,6 +549,17 @@ DumpVtdIfError (
>        DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
>        DumpVtdRegs (Num);
>        DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
> +      //
> +      // Clear
> +      //
> +      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
> +        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16) 
> + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> +        if (FrcdReg.Bits.F != 0) {
> +          FrcdReg.Bits.F = 0;
> +          MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)), 
> FrcdReg.Uint64[1]);
> +        }
> +        MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress + 
> R_FSTS_REG));
> +      }
>      }
>    }
>  }
> --
> 2.7.4.windows.1



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

* Re: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
  2017-09-14  6:10       ` Zeng, Star
@ 2017-09-14  6:15         ` Yao, Jiewen
  0 siblings, 0 replies; 19+ messages in thread
From: Yao, Jiewen @ 2017-09-14  6:15 UTC (permalink / raw)
  To: Zeng, Star, edk2-devel@lists.01.org

Yes, I think the usage model is: Any DMA buffer MUST be requested explicitly.
We do not want to allow a driver calling AllocatePage(), then start to use the memory as DMA.

It can help:

1)       In case that the DMA buffer address is not identical.

2)       DMA protection.

Thank you
Yao Jiewen


From: Zeng, Star
Sent: Thursday, September 14, 2017 2:10 PM
To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
Cc: Zeng, Star <star.zeng@intel.com>
Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR

Then, if there is a driver wants to do DMA at early DXE, it must need a PEIM to allocate the DMA buffers in PEI and transfer them to DXE by HOB.
Is that what we want? I want to confirm that.


Thanks,
Star
-----Original Message-----
From: Yao, Jiewen
Sent: Thursday, September 14, 2017 2:03 PM
To: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR

I did consider that before.
I do not disable at EndOfPei purposely that because I want to make sure that the DMA protect is still available in early DXE phase, just in case there is bug in other module which forgets disabling BME.

Later it is VTdDxe driver that disable PME, *after* it sets up translation table. As such, the DMA protection is always there.

Thank you
Yao Jiewen

> -----Original Message-----
> From: Zeng, Star
> Sent: Thursday, September 14, 2017 1:36 PM
> To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: RE: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
>
> A minor comment.
>
> Should or need IntelVTdPmrPei disable PMR at endofpei?
>
>
> Thanks,
> Star
> -----Original Message-----
> From: Yao, Jiewen
> Sent: Friday, September 8, 2017 11:04 PM
> To: edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> Cc: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Subject: [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR
>
> When VTd translation is enabled, PMR can be disable.
> Or the DMA will be blocked by PMR.
>
> Cc: Star Zeng <star.zeng@intel.com<mailto:star.zeng@intel.com>>
> Contributed-under: TianoCore Contribution Agreement 1.1
> Signed-off-by: Jiewen Yao <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> ---
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c | 51 +++++++++++++++++++-
>  1 file changed, 50 insertions(+), 1 deletion(-)
>
> diff --git a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> index 7402d81..1404af7 100644
> --- a/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> +++ b/IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> @@ -196,6 +196,39 @@ PrepareVtdConfig (  }
>
>  /**
> +  Disable PMR in all VTd engine.
> +**/
> +VOID
> +DisablePmr (
> +  VOID
> +  )
> +{
> +  UINT32        Reg32;
> +  VTD_CAP_REG   CapReg;
> +  UINTN         Index;
> +
> +  DEBUG ((DEBUG_INFO,"DisablePmr\n"));  for (Index = 0; Index <
> + mVtdUnitNumber; Index++) {
> +    CapReg.Uint64 = MmioRead64
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_CAP_REG);
> +    if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
> +      continue ;
> +    }
> +
> +    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + +
> R_PMEN_ENABLE_REG);
> +    if ((Reg32 & BIT0) != 0) {
> +      MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_PMEN_ENABLE_REG, 0x0);
> +      do {
> +        Reg32 = MmioRead32
> (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
> +      } while((Reg32 & BIT0) != 0);
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) disabled\n", Index));
> +    } else {
> +      DEBUG ((DEBUG_INFO,"Pmr(%d) not enabled\n", Index));
> +    }
> +  }
> +  return ;
> +}
> +
> +/**
>    Enable DMAR translation.
>
>    @retval EFI_SUCCESS           DMAR translation is enabled.
> @@ -259,6 +292,11 @@ EnableDmar (
>      DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
>    }
>
> +  //
> +  // Need disable PMR, since we already setup translation table.
> +  //
> +  DisablePmr ();
> +
>    mVtdEnabled = TRUE;
>
>    return EFI_SUCCESS;
> @@ -502,7 +540,7 @@ DumpVtdIfError (
>      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
>        FrcdReg.Uint64[0] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16)
> + (Index * 16) + R_FRCD_REG));
>        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16)
> + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> -      if ((FrcdReg.Uint64[0] != 0) || (FrcdReg.Uint64[1] != 0)) {
> +      if (FrcdReg.Bits.F != 0) {
>          HasError = TRUE;
>        }
>      }
> @@ -511,6 +549,17 @@ DumpVtdIfError (
>        DEBUG((DEBUG_INFO, "\n#### ERROR ####\n"));
>        DumpVtdRegs (Num);
>        DEBUG((DEBUG_INFO, "#### ERROR ####\n\n"));
> +      //
> +      // Clear
> +      //
> +      for (Index = 0; Index < (UINTN)CapReg.Bits.NFR + 1; Index++) {
> +        FrcdReg.Uint64[1] = MmioRead64
> (mVtdUnitInformation[Num].VtdUnitBaseAddress + ((CapReg.Bits.FRO * 16)
> + (Index * 16) + R_FRCD_REG + sizeof(UINT64)));
> +        if (FrcdReg.Bits.F != 0) {
> +          FrcdReg.Bits.F = 0;
> +          MmioWrite64 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> ((CapReg.Bits.FRO * 16) + (Index * 16) + R_FRCD_REG + sizeof(UINT64)),
> FrcdReg.Uint64[1]);
> +        }
> +        MmioWrite32 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> R_FSTS_REG, MmioRead32 (mVtdUnitInformation[Num].VtdUnitBaseAddress +
> R_FSTS_REG));
> +      }
>      }
>    }
>  }
> --
> 2.7.4.windows.1


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

* Re: [PATCH 00/11] Add IOMMU PEI support.
  2017-09-13 10:19   ` Yao, Jiewen
@ 2017-09-14  6:32     ` Zeng, Star
  0 siblings, 0 replies; 19+ messages in thread
From: Zeng, Star @ 2017-09-14  6:32 UTC (permalink / raw)
  To: Yao, Jiewen, edk2-devel@lists.01.org; +Cc: Zeng, Star

Reviewed-by: Star Zeng <star.zeng@intel.com>

-----Original Message-----
From: Yao, Jiewen 
Sent: Wednesday, September 13, 2017 6:19 PM
To: Zeng, Star <star.zeng@intel.com>; edk2-devel@lists.01.org
Subject: RE: [edk2] [PATCH 00/11] Add IOMMU PEI support.

Good question.

Yes, I think we can put all VTd related components to IntelSiliconPkg/Feature/VTd.
Once we finished the review, I would submit another patch to move all components to the new location.

Thank you
Yao Jiewen


> -----Original Message-----
> From: Zeng, Star
> Sent: Wednesday, September 13, 2017 6:14 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; edk2-devel@lists.01.org
> Cc: Zeng, Star <star.zeng@intel.com>
> Subject: RE: [edk2] [PATCH 00/11] Add IOMMU PEI support.
> 
> I have been confused by where should new module be put for some time.
> When should a new module be put at XXXPkg/Universal? For example, 
> MdeModule/Universal, UefiCpuPkg/Universal, ....
> When should a new module be put at XXXPkg/Feature? For example, 
> UefiCpuPkg/Feature.
> When should a new module be put at the root of a package folder? For 
> example, UefiCpuPkg/PiSmmCpuDxeSmm, IntelSiliconPkg/IntelVTdDxe, ....
> 
> Is it better or not to put IntelVTdDxe, PlatformVTdSampleDxe and new 
> IntelVTdPmrPei, PlatformVTdInfoSamplePei in 
> IntelSiliconPkg/Feature/VTd together?
> 
> 
> Thanks,
> Star
> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of 
> Jiewen Yao
> Sent: Friday, September 8, 2017 11:04 PM
> To: edk2-devel@lists.01.org
> Subject: [edk2] [PATCH 00/11] Add IOMMU PEI support.
> 
> This series patch added IOMMU PEI support.
> It is also posted to https://github.com/jyao1/edk2/tree/IoMmuPpi.
> 
> 1) Patch 1 and 2 add EDKII_IOMMU_PPI.
> It is similar to EDKII_IOMMU_PROTOCOL.
> 
> 2) Patch 3 and 4 add Intel VTD PMR register support for DXE phase IntelVTdDxe.
> This is to prepare handle PMR usage in PEI phase.
> 
> 3) Patch 5 and 6 add EDKII_VTD_INFO_PPI.
> This PPI is to provide Intel VTD information in PEI.
> In DXE, the VTd driver can get VTD info from ACPI DMAR table.
> But in PEI, there is no way to get VTD info before.
> VTD_INFO_PPI is added to resolve the problem.
> 
> 4) Patch 7 and 8 add IntelVTdPmrPei driver.
> This driver consumes EDKII_VTD_INFO_PPI and produces IOMMU_PPI.
> It enables VTD PMR register to provide DMA protection.
> The PMR based DMA protection is a simple solution to mark 2 regions 
> can be DMA protected.
> The IntelVTdPmrPei allocates a small chunk buffer for DMA and protect 
> the rest memory.
> 
> 5) Patch 9 and 10 add a sample VTdInfo PEI driver.
> It provides a sample to show how to report VTd info in PEI phase.
> 
> 6) Patch 11 updates XhciPei driver to consume IOMMU_PPI.
> If the IOMMU_PPI is present, XhciPei will use IOMMU_PPI to allocate 
> DMA buffer. Or the XhciPei will still use old way - 
> PeiServiceAllocatePage to allocate DRAM as DMA buffer.
> This is the first PEI device driver consuming IOMMU_PPI to show the concept.
> The rest PEI device drivers will be updated in separated patches.
> 
> 
> This series patch is validated on Intel Kabylake Platform.
> 1) We can use XHCI to do file transfer in PEI phase,
> 2) We can still use XHCI in DXE phase, such as shell environment.
> 3) If the device driver does not consume IOMMU_PPI, the DMA fails.
> 
> Jiewen Yao (11):
>   MdeModulePkg/Include: Add IOMMU_PPI.
>   MdeModulePkg/Dec: Add IOMMU_PPI GUID.
>   IntelSiliconPkg/Vtd.h: Add definition for PMR.
>   IntelSiliconPkg/VTdDxe: Disable PMR
>   IntelSiliconPkg/include: Add VTD_INFO PPI.
>   IntelSiliconPkg/dec: Add VTD_INFO PPI GUID
>   IntelSiliconPkg: Add IntelVTdPmrPei.
>   IntelSiliconPkg/dsc: Add IntelVTdPmrPeim.
>   IntelSiliconPkg: Add PlatformVTdInfoSamplePei.
>   IntelSiliconPkg/dsc: Add PlatformVTdInfoSamplePei.
>   MdeModulePkg/XhciPei: Support IoMmu.
> 
>  IntelSiliconPkg/Include/IndustryStandard/Vtd.h
> |   6 +
>  IntelSiliconPkg/Include/Ppi/VtdInfo.h
> |  40 ++
>  IntelSiliconPkg/IntelSiliconPkg.dec
> |   3 +
>  IntelSiliconPkg/IntelSiliconPkg.dsc
> |  10 +
>  IntelSiliconPkg/IntelVTdDxe/VtdReg.c
> |  51 +-
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
> | 314 ++++++++++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
> | 615 ++++++++++++++++++++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
> |  68 +++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
> |  59 ++
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
> |  20 +
>  IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
> |  20 +
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
> |  65 +++
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
> |  51 ++
>  IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
> |  20 +
>  
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra
> .uni
> |  20 +
>  MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
> | 249 ++++++++
>  MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.c
> |  55 +-
>  MdeModulePkg/Bus/Pci/XhciPei/UsbHcMem.h
> |   9 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.c
> |  55 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhcPeim.h
> | 107 ++++
>  MdeModulePkg/Bus/Pci/XhciPei/XhciPei.inf
> |   3 +
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.c
> |  47 +-
>  MdeModulePkg/Bus/Pci/XhciPei/XhciSched.h
> |   1 +
>  MdeModulePkg/Include/Ppi/IoMmu.h
> | 196 +++++++
>  MdeModulePkg/MdeModulePkg.dec
> |   3 +
>  25 files changed, 2052 insertions(+), 35 deletions(-)  create mode 
> 100644 IntelSiliconPkg/Include/Ppi/VtdInfo.h
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmr.c
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.c
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.h
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.inf
>  create mode 100644 IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPei.uni
>  create mode 100644 
> IntelSiliconPkg/IntelVTdPmrPei/IntelVTdPmrPeiExtra.uni
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.uni
>  create mode 100644
> IntelSiliconPkg/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePeiExtra
> .uni  create mode 100644 MdeModulePkg/Bus/Pci/XhciPei/DmaMem.c
>  create mode 100644 MdeModulePkg/Include/Ppi/IoMmu.h
> 
> --
> 2.7.4.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


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

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

Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-09-08 15:03 [PATCH 00/11] Add IOMMU PEI support Jiewen Yao
2017-09-08 15:03 ` [PATCH 01/11] MdeModulePkg/Include: Add IOMMU_PPI Jiewen Yao
2017-09-08 15:03 ` [PATCH 02/11] MdeModulePkg/Dec: Add IOMMU_PPI GUID Jiewen Yao
2017-09-08 15:03 ` [PATCH 03/11] IntelSiliconPkg/Vtd.h: Add definition for PMR Jiewen Yao
2017-09-08 15:03 ` [PATCH 04/11] IntelSiliconPkg/VTdDxe: Disable PMR Jiewen Yao
2017-09-14  5:35   ` Zeng, Star
2017-09-14  6:02     ` Yao, Jiewen
2017-09-14  6:10       ` Zeng, Star
2017-09-14  6:15         ` Yao, Jiewen
2017-09-08 15:03 ` [PATCH 05/11] IntelSiliconPkg/include: Add VTD_INFO PPI Jiewen Yao
2017-09-08 15:03 ` [PATCH 06/11] IntelSiliconPkg/dec: Add VTD_INFO PPI GUID Jiewen Yao
2017-09-08 15:03 ` [PATCH 07/11] IntelSiliconPkg: Add IntelVTdPmrPei Jiewen Yao
2017-09-08 15:03 ` [PATCH 08/11] IntelSiliconPkg/dsc: Add IntelVTdPmrPeim Jiewen Yao
2017-09-08 15:03 ` [PATCH 09/11] IntelSiliconPkg: Add PlatformVTdInfoSamplePei Jiewen Yao
2017-09-08 15:03 ` [PATCH 10/11] IntelSiliconPkg/dsc: " Jiewen Yao
2017-09-08 15:03 ` [PATCH 11/11] MdeModulePkg/XhciPei: Support IoMmu Jiewen Yao
2017-09-13 10:13 ` [PATCH 00/11] Add IOMMU PEI support Zeng, Star
2017-09-13 10:19   ` Yao, Jiewen
2017-09-14  6:32     ` Zeng, Star

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