public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* Re: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM
       [not found] <1711EAB1819FAD8B.21447@groups.io>
@ 2022-09-29  3:54 ` Huang, Jenny
  2022-09-29  8:32   ` Sheng Wei
  0 siblings, 1 reply; 2+ messages in thread
From: Huang, Jenny @ 2022-09-29  3:54 UTC (permalink / raw)
  To: devel@edk2.groups.io, Sheng, W
  Cc: Ni, Ray, Chaganty, Rangasai V, Kowalewski, Robert

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

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sheng, W
Sent: Monday, September 5, 2022 1:49 AM
To: devel@edk2.groups.io
Cc: Huang, Jenny <jenny.huang@intel.com>; Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Kowalewski, Robert <robert.kowalewski@intel.com>
Subject: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM

In Abort DMA Mode(ADM), hardware will abort all DMA operations without the need to set up a roottable. Enable Abort DMA Mode, when change Translation Table Mode(TTM)

Change-Id: I74207fe96ef7a57d89a355d40dfbdd36186f06c3
Signed-off-by: Sheng Wei <w.sheng@intel.com>
Cc: Jenny Huang <jenny.huang@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>

Cc: Robert Kowalewski <robert.kowalewski@intel.com>
---
 .../VTd/IntelVTdDmarPei/IntelVTdDmar.c        | 157 +++++++++++-----
 .../Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf   |   1 +
 .../Feature/VTd/IntelVTdDxe/VtdReg.c          | 169 +++++++++++++-----
 .../Intel/IntelSiliconPkg/IntelSiliconPkg.dec |  12 +-
 4 files changed, 245 insertions(+), 94 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index b5b78f779..24beccd26 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
+++ Dmar.c
@@ -361,6 +361,68 @@ InvalidateIOTLB (
   return EFI_SUCCESS;

 }

 

+/**

+  Clear Global Command Register Bits

+

+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.

+  @param[in] BitMask            Bit mask.

+**/

+VOID

+ClearGlobalCommandRegisterBits (

+  IN UINTN     VtdUnitBaseAddress,

+  IN UINT32    BitMask

+  )

+{

+  UINT32    Reg32;

+  UINT32    Status;

+  UINT32    Command;

+

+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

+  Command = (Status & (~BitMask));

+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

+

+  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));

+

+  //

+  // Poll on Status bit of Global status register to become zero

+  //

+  do {

+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  } while ((Reg32 & BitMask) == BitMask);

+}

+

+/**

+  Set Global Command Register Bits

+

+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.

+  @param[in] BitMask            Bit mask.

+**/

+VOID

+SetGlobalCommandRegisterBits (

+  IN UINTN     VtdUnitBaseAddress,

+  IN UINT32    BitMask

+  )

+{

+  UINT32    Reg32;

+  UINT32    Status;

+  UINT32    Command;

+

+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

+  Command = (Status | BitMask);

+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

+

+  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));

+

+  //

+  // Poll on Status bit of Global status register to become not zero

+  //

+  do {

+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  } while ((Reg32 & BitMask) == 0);

+}

+

 /**

   Enable DMAR translation in pre-mem phase.

 

@@ -383,13 +445,10 @@ EnableDmarPreMem (
   DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));

   MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue);

 

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);

-

   DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be set... \n"));

-  do {

-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);

+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);

+

+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

   DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG = 0x%x \n", Reg32));

 

   //

@@ -405,12 +464,7 @@ EnableDmarPreMem (
   //

   // Enable VTd

   //

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);

-  DEBUG ((DEBUG_INFO, "EnableDmarPreMem: Waiting B_GSTS_REG_TE ...\n"));

-  do {

-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  } while ((Reg32 & B_GSTS_REG_TE) == 0);

+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

 

   DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));

 

@@ -434,22 +488,43 @@ EnableDmar (
 {

   UINT32                        Reg32;

   UINTN                         VtdUnitBaseAddress;

+  BOOLEAN                       TEWasEnabled;

 

   VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;

 

   DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));

 

-  DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));

-  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);

+  //

+  // Check TE was enabled or not.

+  //

+  TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & 
+ B_GSTS_REG_TE) == B_GSTS_REG_TE);

 

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);

+  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) && 
+ PcdGetBool (PcdVTdSupportAbortDmaMode)) {

+    //

+    // For implementations reporting Enhanced SRTP Support (ESRTPS) 
+ field as

+    // Clear in the Capability register, software must not modify this 
+ field while

+    // DMA remapping is active (TES=1 in Global Status register).

+    //

+    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {

+      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, 
+ B_GMCD_REG_TE);

+    }

+

+    //

+    // Enable ADM

+    //

+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) 
+ (RootEntryTable | V_RTADDR_REG_TTM_ADM));

+

+    DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));

+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

+

+  } else {

+    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));

+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) 
+ RootEntryTable);

+

+  }

 

   DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));

-  do {

-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);

-  DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));

+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);

 

   //

   // Init DMAr Fault Event and Data registers

@@ -471,15 +546,19 @@ EnableDmar (
   //

   InvalidateIOTLB (VTdUnitInfo);

 

+  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) && 
+ PcdGetBool (PcdVTdSupportAbortDmaMode)) {

+    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {

+      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, 
+ B_GMCD_REG_TE);

+    }

+

+    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));

+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) 
+ RootEntryTable);

+  }

+

   //

   // Enable VTd

   //

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);

-  DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));

-  do {

-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  } while ((Reg32 & B_GSTS_REG_TE) == 0);

+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

 

   DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));

 

@@ -500,8 +579,6 @@ DisableDmar (
   )

 {

   UINT32                        Reg32;

-  UINT32                        Status;

-  UINT32                        Command;

 

   DEBUG ((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));

 

@@ -516,28 +593,12 @@ DisableDmar (
   //

   // Set TE (Translation Enable: BIT31) of Global command register to zero

   //

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

-  Command = (Status & ~B_GMCD_REG_TE);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

-

-   //

-   // Poll on TE Status bit of Global status register to become zero

-   //

-   do {

-     Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-   } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);

+  ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

 

   //

   // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in order to update the root table pointerDisable VTd

   //

-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

-  Command = (Status | B_GMCD_REG_SRTP);

-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

-  do {

-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);

+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);

 

   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

   DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));

@@ -568,12 +629,12 @@ EnableVTdTranslationProtectionBlockDma (
 

   DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress));

 

-  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", FixedPcdGetBool (PcdVTdSupportAbortDmaMode)));

+  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", PcdGetBool 
+ (PcdVTdSupportAbortDmaMode)));

 

   ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);

   DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));

 

-  if ((ECapReg.Bits.ADMS == 1) && FixedPcdGetBool (PcdVTdSupportAbortDmaMode)) {

+  if ((ECapReg.Bits.ADMS == 1) && PcdGetBool 
+ (PcdVTdSupportAbortDmaMode)) {

     //

     // Use Abort DMA Mode

     //

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
index 387f90e37..b152831c0 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.
+++ inf
@@ -75,6 +75,7 @@
 [Pcd]

   gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask   ## CONSUMES

   gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError       ## CONSUMES

+  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode  ## CONSUMES

 

 [Depex]

   gEfiPciRootBridgeIoProtocolGuid

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index c7a56cf57..396aa4a70 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -475,6 +475,92 @@ DisablePmr (
   return ;

 }

 

+/**

+  Clear Global Command Register Bits

+

+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.

+  @param[in] BitMask            Bit mask.

+**/

+VOID

+ClearGlobalCommandRegisterBits (

+  IN UINTN     VtdUnitBaseAddress,

+  IN UINT32    BitMask

+  )

+{

+  UINT32    Reg32;

+  UINT32    Status;

+  UINT32    Command;

+

+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

+  Command = (Status & (~BitMask));

+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

+

+  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));

+

+  //

+  // Poll on Status bit of Global status register to become zero

+  //

+  do {

+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  } while ((Reg32 & BitMask) == BitMask);

+}

+

+/**

+  Set Global Command Register Bits

+

+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.

+  @param[in] BitMask            Bit mask.

+**/

+VOID

+SetGlobalCommandRegisterBits (

+  IN UINTN     VtdUnitBaseAddress,

+  IN UINT32    BitMask

+  )

+{

+  UINT32    Reg32;

+  UINT32    Status;

+  UINT32    Command;

+

+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

+  Command = (Status | BitMask);

+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);

+

+  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));

+

+  //

+  // Poll on Status bit of Global status register to become not zero

+  //

+  do {

+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);

+  } while ((Reg32 & BitMask) == 0);

+}

+

+/**

+  Update Root Table Address Register

+

+  @param[in]  VtdIndex          The index used to identify a VTd engine.

+  @param[in]  EnableADM         TRUE - Enable ADM in TTM bits

+**/

+VOID

+UpdateRootTableAddressRegister (

+  IN UINTN   VtdIndex,

+  IN BOOLEAN EnableADM

+  )

+{

+  UINT64 Reg64;

+

+  if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable != NULL) {

+    DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", 
+ mVtdUnitInformation[VtdIndex].ExtRootEntryTable));

+    Reg64 = 
+ (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable | 
+ (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);

+  } else {

+    DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", 
+ mVtdUnitInformation[VtdIndex].RootEntryTable));

+    Reg64 = (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable 
+ | (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);

+  }

+  MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + 
+ R_RTADDR_REG, Reg64);

+}

+

 /**

   Enable DMAR translation.

 

@@ -488,25 +574,43 @@ EnableDmar (
 {

   UINTN     Index;

   UINT32    Reg32;

+  UINTN     VtdUnitBaseAddress;

+  BOOLEAN   TEWasEnabled;

 

   for (Index = 0; Index < mVtdUnitNumber; Index++) {

-    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));

+    VtdUnitBaseAddress = mVtdUnitInformation[Index].VtdUnitBaseAddress;

+    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR 
+ [0x%x]\n", Index, VtdUnitBaseAddress));

+

+    //

+    // Check TE was enabled or not.

+    //

+    TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & 
+ B_GSTS_REG_TE) == B_GSTS_REG_TE);

+

+    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS 
+ == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {

+      //

+      // For implementations reporting Enhanced SRTP Support (ESRTPS) 
+ field as

+      // Clear in the Capability register, software must not modify 
+ this field while

+      // DMA remapping is active (TES=1 in Global Status register).

+      //

+      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {

+        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, 
+ B_GMCD_REG_TE);

+      }

+

+      //

+      // Enable ADM

+      //

+      UpdateRootTableAddressRegister (Index, TRUE);

+

+      DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));

+      SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

 

-    if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {

-      DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));

-      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);

     } else {

-      DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));

-      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);

-    }

+      UpdateRootTableAddressRegister (Index, FALSE);

 

-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);

+    }

 

     DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));

-    do {

-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    } while((Reg32 & B_GSTS_REG_RTPS) == 0);

+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);

 

     //

     // Init DMAr Fault Event and Data registers

@@ -528,15 +632,19 @@ EnableDmar (
     //

     InvalidateIOTLB (Index);

 

+    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS 
+ == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {

+      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {

+        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, 
+ B_GMCD_REG_TE);

+      }

+

+      UpdateRootTableAddressRegister (Index, FALSE);

+    }

+

     //

     // Enable VTd

     //

-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);

-    DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));

-    do {

-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    } while ((Reg32 & B_GSTS_REG_TE) == 0);

+    DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));

+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);

 

     DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));

   }

@@ -565,8 +673,6 @@ DisableDmar (
   UINTN     Index;

   UINTN     SubIndex;

   UINT32    Reg32;

-  UINT32    Status;

-  UINT32    Command;

 

   for (Index = 0; Index < mVtdUnitNumber; Index++) {

     DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));

@@ -582,32 +688,15 @@ DisableDmar (
     //

     // Set TE (Translation Enable: BIT31) of Global command register to zero

     //

-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

-    Command = (Status & ~B_GMCD_REG_TE);

-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Command);

-

-    //

-    // Poll on TE Status bit of Global status register to become zero

-    //

-    do {

-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);

+    ClearGlobalCommandRegisterBits 
+ (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GMCD_REG_TE);

 

     //

     // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in order to update the root table pointerDisable VTd

     //

-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits

-    Command = (Status | B_GMCD_REG_SRTP);

-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Command);

-

-    do {

-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    } while((Reg32 & B_GSTS_REG_RTPS) == 0);

+    SetGlobalCommandRegisterBits 
+ (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GSTS_REG_RTPS);

 

     Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);

-    DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));

+    DEBUG ((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));

 

     DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));

 

diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index c36d130a0..9166e599a 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -135,12 +135,6 @@
   gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UINT32|0x0000000A

   gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|UINT32|0x0000000B

 

-  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>

-  #   TRUE  - Support VTd abort DMA mode.

-  #   FALSE - Not support VTd abort DMA mode.

-  # @Prompt VTd abort DMA mode support.

-  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0x0000000C

-

 [PcdsFixedAtBuild, PcdsPatchableInModule]

   ## Error code for VTd error.<BR><BR>

   #  EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000<BR>

@@ -178,3 +172,9 @@
   # @Prompt The VTd PEI DMA buffer size for S3.

   gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3|0x00200000|UINT32|0x00000004

 

+  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>

+  #   TRUE  - Support VTd abort DMA mode.

+  #   FALSE - Not support VTd abort DMA mode.

+  # @Prompt VTd abort DMA mode support.

+  
+ gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN
+ |0x0000000C

+

--
2.26.2.windows.1



-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#93138): https://edk2.groups.io/g/devel/message/93138
Mute This Topic: https://groups.io/mt/93474620/2558558
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [w.sheng@intel.com]
-=-=-=-=-=-=



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

* Re: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM
  2022-09-29  3:54 ` [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM Huang, Jenny
@ 2022-09-29  8:32   ` Sheng Wei
  0 siblings, 0 replies; 2+ messages in thread
From: Sheng Wei @ 2022-09-29  8:32 UTC (permalink / raw)
  To: Ni, Ray
  Cc: Chaganty, Rangasai V, Kowalewski, Robert, Huang, Jenny,
	devel@edk2.groups.io

[-- Attachment #1: Type: text/plain, Size: 25418 bytes --]

Hi Ray,
Could you help to review the merge the patch to the VTd driver in edkplatform branch ?
This patch is used to enable Abort DMA Mode(ADM) when change the TTM .
The comment from VTd spec is below.

 For implementations reporting Enhanced SRTP Support (ESRTPS) field as
 Clear in the Capability register, software must not modify this field while
 DMA remapping is active (TES=1 in Global Status register).

So, we will enable ADM while TE is disable.
Thank you
BR
Sheng Wei

> -----Original Message-----
> From: Huang, Jenny <jenny.huang@intel.com>
> Sent: 2022年9月29日 11:54
> To: devel@edk2.groups.io; Sheng, W <w.sheng@intel.com>
> Cc: Ni, Ray <ray.ni@intel.com>; Chaganty, Rangasai V
> <rangasai.v.chaganty@intel.com>; Kowalewski, Robert
> <robert.kowalewski@intel.com>
> Subject: RE: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when
> change TTM
> 
> Reviewed-by: Jenny Huang <jenny.huang@intel.com>
> 
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Sheng,
> W
> Sent: Monday, September 5, 2022 1:49 AM
> To: devel@edk2.groups.io
> Cc: Huang, Jenny <jenny.huang@intel.com>; Ni, Ray <ray.ni@intel.com>;
> Chaganty, Rangasai V <rangasai.v.chaganty@intel.com>; Kowalewski,
> Robert <robert.kowalewski@intel.com>
> Subject: [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change
> TTM
> 
> In Abort DMA Mode(ADM), hardware will abort all DMA operations without
> the need to set up a roottable. Enable Abort DMA Mode, when change
> Translation Table Mode(TTM)
> 
> Change-Id: I74207fe96ef7a57d89a355d40dfbdd36186f06c3
> Signed-off-by: Sheng Wei <w.sheng@intel.com>
> Cc: Jenny Huang <jenny.huang@intel.com>
> Cc: Ray Ni <ray.ni@intel.com>
> Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
> 
> Cc: Robert Kowalewski <robert.kowalewski@intel.com>
> ---
>  .../VTd/IntelVTdDmarPei/IntelVTdDmar.c        | 157 +++++++++++-----
>  .../Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf   |   1 +
>  .../Feature/VTd/IntelVTdDxe/VtdReg.c          | 169 +++++++++++++-----
>  .../Intel/IntelSiliconPkg/IntelSiliconPkg.dec |  12 +-
>  4 files changed, 245 insertions(+), 94 deletions(-)
> 
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> index b5b78f779..24beccd26 100644
> ---
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.
> c
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTd
> +++ Dmar.c
> @@ -361,6 +361,68 @@ InvalidateIOTLB (
>    return EFI_SUCCESS;
> 
>  }
> 
> 
> 
> +/**
> 
> +  Clear Global Command Register Bits
> 
> +
> 
> +  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
> 
> +  @param[in] BitMask            Bit mask.
> 
> +**/
> 
> +VOID
> 
> +ClearGlobalCommandRegisterBits (
> 
> +  IN UINTN     VtdUnitBaseAddress,
> 
> +  IN UINT32    BitMask
> 
> +  )
> 
> +{
> 
> +  UINT32    Reg32;
> 
> +  UINT32    Status;
> 
> +  UINT32    Command;
> 
> +
> 
> +  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> +  Command = (Status & (~BitMask));
> 
> +  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> +
> 
> +  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));
> 
> +
> 
> +  //
> 
> +  // Poll on Status bit of Global status register to become zero
> 
> +  //
> 
> +  do {
> 
> +    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  } while ((Reg32 & BitMask) == BitMask);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Set Global Command Register Bits
> 
> +
> 
> +  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
> 
> +  @param[in] BitMask            Bit mask.
> 
> +**/
> 
> +VOID
> 
> +SetGlobalCommandRegisterBits (
> 
> +  IN UINTN     VtdUnitBaseAddress,
> 
> +  IN UINT32    BitMask
> 
> +  )
> 
> +{
> 
> +  UINT32    Reg32;
> 
> +  UINT32    Status;
> 
> +  UINT32    Command;
> 
> +
> 
> +  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> +  Command = (Status | BitMask);
> 
> +  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> +
> 
> +  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));
> 
> +
> 
> +  //
> 
> +  // Poll on Status bit of Global status register to become not zero
> 
> +  //
> 
> +  do {
> 
> +    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  } while ((Reg32 & BitMask) == 0);
> 
> +}
> 
> +
> 
>  /**
> 
>    Enable DMAR translation in pre-mem phase.
> 
> 
> 
> @@ -383,13 +445,10 @@ EnableDmarPreMem (
>    DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));
> 
>    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue);
> 
> 
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_SRTP);
> 
> -
> 
>    DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be
> set... \n"));
> 
> -  do {
> 
> -    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> 
> +  SetGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_SRTP);
> 
> +
> 
> +  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
>    DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG = 0x%x \n",
> Reg32));
> 
> 
> 
>    //
> 
> @@ -405,12 +464,7 @@ EnableDmarPreMem (
>    //
> 
>    // Enable VTd
> 
>    //
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_TE);
> 
> -  DEBUG ((DEBUG_INFO, "EnableDmarPreMem: Waiting
> B_GSTS_REG_TE ...\n"));
> 
> -  do {
> 
> -    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  } while ((Reg32 & B_GSTS_REG_TE) == 0);
> 
> +  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
> 
> 
> 
>    DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
> 
> 
> 
> @@ -434,22 +488,43 @@ EnableDmar (
>  {
> 
>    UINT32                        Reg32;
> 
>    UINTN                         VtdUnitBaseAddress;
> 
> +  BOOLEAN                       TEWasEnabled;
> 
> 
> 
>    VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
> 
> 
> 
>    DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n",
> VtdUnitBaseAddress));
> 
> 
> 
> -  DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
> 
> -  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)
> RootEntryTable);
> 
> +  //
> 
> +  // Check TE was enabled or not.
> 
> +  //
> 
> +  TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) &
> + B_GSTS_REG_TE) == B_GSTS_REG_TE);
> 
> 
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_SRTP);
> 
> +  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) &&
> + PcdGetBool (PcdVTdSupportAbortDmaMode)) {
> 
> +    //
> 
> +    // For implementations reporting Enhanced SRTP Support (ESRTPS)
> + field as
> 
> +    // Clear in the Capability register, software must not modify this
> + field while
> 
> +    // DMA remapping is active (TES=1 in Global Status register).
> 
> +    //
> 
> +    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {
> 
> +      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress,
> + B_GMCD_REG_TE);
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // Enable ADM
> 
> +    //
> 
> +    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)
> + (RootEntryTable | V_RTADDR_REG_TTM_ADM));
> 
> +
> 
> +    DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
> 
> +    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
> 
> +
> 
> +  } else {
> 
> +    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
> 
> +    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)
> + RootEntryTable);
> 
> +
> 
> +  }
> 
> 
> 
>    DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
> 
> -  do {
> 
> -    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> 
> -  DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
> 
> +  SetGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_SRTP);
> 
> 
> 
>    //
> 
>    // Init DMAr Fault Event and Data registers
> 
> @@ -471,15 +546,19 @@ EnableDmar (
>    //
> 
>    InvalidateIOTLB (VTdUnitInfo);
> 
> 
> 
> +  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) &&
> + PcdGetBool (PcdVTdSupportAbortDmaMode)) {
> 
> +    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {
> 
> +      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress,
> + B_GMCD_REG_TE);
> 
> +    }
> 
> +
> 
> +    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
> 
> +    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)
> + RootEntryTable);
> 
> +  }
> 
> +
> 
>    //
> 
>    // Enable VTd
> 
>    //
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 |
> B_GMCD_REG_TE);
> 
> -  DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
> 
> -  do {
> 
> -    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  } while ((Reg32 & B_GSTS_REG_TE) == 0);
> 
> +  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
> 
> 
> 
>    DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
> 
> 
> 
> @@ -500,8 +579,6 @@ DisableDmar (
>    )
> 
>  {
> 
>    UINT32                        Reg32;
> 
> -  UINT32                        Status;
> 
> -  UINT32                        Command;
> 
> 
> 
>    DEBUG ((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n",
> VtdUnitBaseAddress));
> 
> 
> 
> @@ -516,28 +593,12 @@ DisableDmar (
>    //
> 
>    // Set TE (Translation Enable: BIT31) of Global command register to zero
> 
>    //
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> -  Command = (Status & ~B_GMCD_REG_TE);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> -
> 
> -   //
> 
> -   // Poll on TE Status bit of Global status register to become zero
> 
> -   //
> 
> -   do {
> 
> -     Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -   } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);
> 
> +  ClearGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_TE);
> 
> 
> 
>    //
> 
>    // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in
> order to update the root table pointerDisable VTd
> 
>    //
> 
> -  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> -  Command = (Status | B_GMCD_REG_SRTP);
> 
> -  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> -  do {
> 
> -    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> -  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> 
> +  SetGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_SRTP);
> 
> 
> 
>    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
>    DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
> 
> @@ -568,12 +629,12 @@ EnableVTdTranslationProtectionBlockDma (
> 
> 
>    DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma -
> 0x%08x\n", VtdUnitBaseAddress));
> 
> 
> 
> -  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n",
> FixedPcdGetBool (PcdVTdSupportAbortDmaMode)));
> 
> +  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n",
> PcdGetBool
> + (PcdVTdSupportAbortDmaMode)));
> 
> 
> 
>    ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
> 
>    DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));
> 
> 
> 
> -  if ((ECapReg.Bits.ADMS == 1) && FixedPcdGetBool
> (PcdVTdSupportAbortDmaMode)) {
> 
> +  if ((ECapReg.Bits.ADMS == 1) && PcdGetBool
> + (PcdVTdSupportAbortDmaMode)) {
> 
>      //
> 
>      // Use Abort DMA Mode
> 
>      //
> 
> diff --git
> a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
> index 387f90e37..b152831c0 100644
> --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.
> +++ inf
> @@ -75,6 +75,7 @@
>  [Pcd]
> 
>    gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask   ##
> CONSUMES
> 
>    gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError       ## CONSUMES
> 
> +  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode  ##
> CONSUMES
> 
> 
> 
>  [Depex]
> 
>    gEfiPciRootBridgeIoProtocolGuid
> 
> diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> index c7a56cf57..396aa4a70 100644
> --- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> +++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
> @@ -475,6 +475,92 @@ DisablePmr (
>    return ;
> 
>  }
> 
> 
> 
> +/**
> 
> +  Clear Global Command Register Bits
> 
> +
> 
> +  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
> 
> +  @param[in] BitMask            Bit mask.
> 
> +**/
> 
> +VOID
> 
> +ClearGlobalCommandRegisterBits (
> 
> +  IN UINTN     VtdUnitBaseAddress,
> 
> +  IN UINT32    BitMask
> 
> +  )
> 
> +{
> 
> +  UINT32    Reg32;
> 
> +  UINT32    Status;
> 
> +  UINT32    Command;
> 
> +
> 
> +  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> +  Command = (Status & (~BitMask));
> 
> +  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> +
> 
> +  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));
> 
> +
> 
> +  //
> 
> +  // Poll on Status bit of Global status register to become zero
> 
> +  //
> 
> +  do {
> 
> +    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  } while ((Reg32 & BitMask) == BitMask);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Set Global Command Register Bits
> 
> +
> 
> +  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
> 
> +  @param[in] BitMask            Bit mask.
> 
> +**/
> 
> +VOID
> 
> +SetGlobalCommandRegisterBits (
> 
> +  IN UINTN     VtdUnitBaseAddress,
> 
> +  IN UINT32    BitMask
> 
> +  )
> 
> +{
> 
> +  UINT32    Reg32;
> 
> +  UINT32    Status;
> 
> +  UINT32    Command;
> 
> +
> 
> +  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> +  Command = (Status | BitMask);
> 
> +  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
> 
> +
> 
> +  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));
> 
> +
> 
> +  //
> 
> +  // Poll on Status bit of Global status register to become not zero
> 
> +  //
> 
> +  do {
> 
> +    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
> 
> +  } while ((Reg32 & BitMask) == 0);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Update Root Table Address Register
> 
> +
> 
> +  @param[in]  VtdIndex          The index used to identify a VTd engine.
> 
> +  @param[in]  EnableADM         TRUE - Enable ADM in TTM bits
> 
> +**/
> 
> +VOID
> 
> +UpdateRootTableAddressRegister (
> 
> +  IN UINTN   VtdIndex,
> 
> +  IN BOOLEAN EnableADM
> 
> +  )
> 
> +{
> 
> +  UINT64 Reg64;
> 
> +
> 
> +  if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable != NULL) {
> 
> +    DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n",
> + mVtdUnitInformation[VtdIndex].ExtRootEntryTable));
> 
> +    Reg64 =
> + (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable |
> + (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);
> 
> +  } else {
> 
> +    DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n",
> + mVtdUnitInformation[VtdIndex].RootEntryTable));
> 
> +    Reg64 =
> (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable
> + | (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);
> 
> +  }
> 
> +  MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress +
> + R_RTADDR_REG, Reg64);
> 
> +}
> 
> +
> 
>  /**
> 
>    Enable DMAR translation.
> 
> 
> 
> @@ -488,25 +574,43 @@ EnableDmar (
>  {
> 
>    UINTN     Index;
> 
>    UINT32    Reg32;
> 
> +  UINTN     VtdUnitBaseAddress;
> 
> +  BOOLEAN   TEWasEnabled;
> 
> 
> 
>    for (Index = 0; Index < mVtdUnitNumber; Index++) {
> 
> -    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));
> 
> +    VtdUnitBaseAddress = mVtdUnitInformation[Index].VtdUnitBaseAddress;
> 
> +    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR
> + [0x%x]\n", Index, VtdUnitBaseAddress));
> 
> +
> 
> +    //
> 
> +    // Check TE was enabled or not.
> 
> +    //
> 
> +    TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) &
> + B_GSTS_REG_TE) == B_GSTS_REG_TE);
> 
> +
> 
> +    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS
> + == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
> 
> +      //
> 
> +      // For implementations reporting Enhanced SRTP Support (ESRTPS)
> + field as
> 
> +      // Clear in the Capability register, software must not modify
> + this field while
> 
> +      // DMA remapping is active (TES=1 in Global Status register).
> 
> +      //
> 
> +      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {
> 
> +        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress,
> + B_GMCD_REG_TE);
> 
> +      }
> 
> +
> 
> +      //
> 
> +      // Enable ADM
> 
> +      //
> 
> +      UpdateRootTableAddressRegister (Index, TRUE);
> 
> +
> 
> +      DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
> 
> +      SetGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_TE);
> 
> 
> 
> -    if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
> 
> -      DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n",
> mVtdUnitInformation[Index].ExtRootEntryTable));
> 
> -      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_RTADDR_REG,
> (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);
> 
>      } else {
> 
> -      DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n",
> mVtdUnitInformation[Index].RootEntryTable));
> 
> -      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_RTADDR_REG,
> (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);
> 
> -    }
> 
> +      UpdateRootTableAddressRegister (Index, FALSE);
> 
> 
> 
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
> 
> +    }
> 
> 
> 
>      DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
> 
> -    do {
> 
> -      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> 
> +    SetGlobalCommandRegisterBits (VtdUnitBaseAddress,
> B_GMCD_REG_SRTP);
> 
> 
> 
>      //
> 
>      // Init DMAr Fault Event and Data registers
> 
> @@ -528,15 +632,19 @@ EnableDmar (
>      //
> 
>      InvalidateIOTLB (Index);
> 
> 
> 
> +    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS
> + == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
> 
> +      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {
> 
> +        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress,
> + B_GMCD_REG_TE);
> 
> +      }
> 
> +
> 
> +      UpdateRootTableAddressRegister (Index, FALSE);
> 
> +    }
> 
> +
> 
>      //
> 
>      // Enable VTd
> 
>      //
> 
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
> 
> -    DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
> 
> -    do {
> 
> -      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    } while ((Reg32 & B_GSTS_REG_TE) == 0);
> 
> +    DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
> 
> +    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
> 
> 
> 
>      DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
> 
>    }
> 
> @@ -565,8 +673,6 @@ DisableDmar (
>    UINTN     Index;
> 
>    UINTN     SubIndex;
> 
>    UINT32    Reg32;
> 
> -  UINT32    Status;
> 
> -  UINT32    Command;
> 
> 
> 
>    for (Index = 0; Index < mVtdUnitNumber; Index++) {
> 
>      DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));
> 
> @@ -582,32 +688,15 @@ DisableDmar (
>      //
> 
>      // Set TE (Translation Enable: BIT31) of Global command register to zero
> 
>      //
> 
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> -    Command = (Status & ~B_GMCD_REG_TE);
> 
> -    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, Command);
> 
> -
> 
> -    //
> 
> -    // Poll on TE Status bit of Global status register to become zero
> 
> -    //
> 
> -    do {
> 
> -      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);
> 
> +    ClearGlobalCommandRegisterBits
> + (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GMCD_REG_TE);
> 
> 
> 
>      //
> 
>      // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in
> order to update the root table pointerDisable VTd
> 
>      //
> 
> -    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
> 
> -    Command = (Status | B_GMCD_REG_SRTP);
> 
> -    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress +
> R_GCMD_REG, Command);
> 
> -
> 
> -    do {
> 
> -      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    } while((Reg32 & B_GSTS_REG_RTPS) == 0);
> 
> +    SetGlobalCommandRegisterBits
> + (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GSTS_REG_RTPS);
> 
> 
> 
>      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress
> + R_GSTS_REG);
> 
> -    DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
> 
> +    DEBUG ((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
> 
> 
> 
>      DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));
> 
> 
> 
> diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> index c36d130a0..9166e599a 100644
> --- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> +++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
> @@ -135,12 +135,6 @@
> 
> gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UIN
> T32|0x0000000A
> 
> 
> gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|U
> INT32|0x0000000B
> 
> 
> 
> -  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>
> 
> -  #   TRUE  - Support VTd abort DMA mode.
> 
> -  #   FALSE - Not support VTd abort DMA mode.
> 
> -  # @Prompt VTd abort DMA mode support.
> 
> -
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOO
> LEAN|0x0000000C
> 
> -
> 
>  [PcdsFixedAtBuild, PcdsPatchableInModule]
> 
>    ## Error code for VTd error.<BR><BR>
> 
>    #  EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED |
> (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000<BR>
> 
> @@ -178,3 +172,9 @@
>    # @Prompt The VTd PEI DMA buffer size for S3.
> 
> 
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3|0x00200000|U
> INT32|0x00000004
> 
> 
> 
> +  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>
> 
> +  #   TRUE  - Support VTd abort DMA mode.
> 
> +  #   FALSE - Not support VTd abort DMA mode.
> 
> +  # @Prompt VTd abort DMA mode support.
> 
> +
> +
> gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOO
> LEAN
> + |0x0000000C
> 
> +
> 
> --
> 2.26.2.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#93138): https://edk2.groups.io/g/devel/message/93138
> Mute This Topic: https://groups.io/mt/93474620/2558558
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [w.sheng@intel.com]
> -=-=-=-=-=-=
> 


[-- Attachment #2: 0001-IntelSiliconPkg-VTd-Enable-ADM-when-change-TTM.patch --]
[-- Type: application/octet-stream, Size: 20538 bytes --]

From 85eabf0be2c8f649af8c0759e98073381896e2ec Mon Sep 17 00:00:00 2001
From: Sheng Wei <w.sheng@intel.com>
Date: Wed, 24 Aug 2022 13:30:16 +0800
Subject: [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM

In Abort DMA Mode(ADM), hardware will abort all DMA operations without
the need to set up a roottable. Enable Abort DMA Mode, when change
Translation Table Mode(TTM)

Change-Id: I74207fe96ef7a57d89a355d40dfbdd36186f06c3
Signed-off-by: Sheng Wei <w.sheng@intel.com>
Reviewed-by: Jenny Huang <jenny.huang@intel.com>
Cc: Ray Ni <ray.ni@intel.com>
Cc: Rangasai V Chaganty <rangasai.v.chaganty@intel.com>
---
 .../VTd/IntelVTdDmarPei/IntelVTdDmar.c        | 157 +++++++++++-----
 .../Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf   |   1 +
 .../Feature/VTd/IntelVTdDxe/VtdReg.c          | 169 +++++++++++++-----
 .../Intel/IntelSiliconPkg/IntelSiliconPkg.dec |  12 +-
 4 files changed, 245 insertions(+), 94 deletions(-)

diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
index b5b78f779..24beccd26 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDmarPei/IntelVTdDmar.c
@@ -361,6 +361,68 @@ InvalidateIOTLB (
   return EFI_SUCCESS;
 }
 
+/**
+  Clear Global Command Register Bits
+
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+  @param[in] BitMask            Bit mask.
+**/
+VOID
+ClearGlobalCommandRegisterBits (
+  IN UINTN     VtdUnitBaseAddress,
+  IN UINT32    BitMask
+  )
+{
+  UINT32    Reg32;
+  UINT32    Status;
+  UINT32    Command;
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
+  Command = (Status & (~BitMask));
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
+
+  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));
+
+  //
+  // Poll on Status bit of Global status register to become zero
+  //
+  do {
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  } while ((Reg32 & BitMask) == BitMask);
+}
+
+/**
+  Set Global Command Register Bits
+
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+  @param[in] BitMask            Bit mask.
+**/
+VOID
+SetGlobalCommandRegisterBits (
+  IN UINTN     VtdUnitBaseAddress,
+  IN UINT32    BitMask
+  )
+{
+  UINT32    Reg32;
+  UINT32    Status;
+  UINT32    Command;
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
+  Command = (Status | BitMask);
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
+
+  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));
+
+  //
+  // Poll on Status bit of Global status register to become not zero
+  //
+  do {
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  } while ((Reg32 & BitMask) == 0);
+}
+
 /**
   Enable DMAR translation in pre-mem phase.
 
@@ -383,13 +445,10 @@ EnableDmarPreMem (
   DEBUG ((DEBUG_INFO, "RTADDR_REG : 0x%016lx \n", RtaddrRegValue));
   MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, RtaddrRegValue);
 
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
-
   DEBUG ((DEBUG_INFO, "EnableDmarPreMem: waiting for RTPS bit to be set... \n"));
-  do {
-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   DEBUG ((DEBUG_INFO, "EnableDmarPreMem: R_GSTS_REG = 0x%x \n", Reg32));
 
   //
@@ -405,12 +464,7 @@ EnableDmarPreMem (
   //
   // Enable VTd
   //
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
-  DEBUG ((DEBUG_INFO, "EnableDmarPreMem: Waiting B_GSTS_REG_TE ...\n"));
-  do {
-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  } while ((Reg32 & B_GSTS_REG_TE) == 0);
+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
 
   DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
 
@@ -434,22 +488,43 @@ EnableDmar (
 {
   UINT32                        Reg32;
   UINTN                         VtdUnitBaseAddress;
+  BOOLEAN                       TEWasEnabled;
 
   VtdUnitBaseAddress = VTdUnitInfo->VtdUnitBaseAddress;
 
   DEBUG ((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
 
-  DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
-  MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
+  //
+  // Check TE was enabled or not.
+  //
+  TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GSTS_REG_TE) == B_GSTS_REG_TE);
 
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
+  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
+    //
+    // For implementations reporting Enhanced SRTP Support (ESRTPS) field as
+    // Clear in the Capability register, software must not modify this field while
+    // DMA remapping is active (TES=1 in Global Status register).
+    //
+    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {
+      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
+    }
+
+    //
+    // Enable ADM
+    //
+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) (RootEntryTable | V_RTADDR_REG_TTM_ADM));
+
+    DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
+
+  } else {
+    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
+
+  }
 
   DEBUG ((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
-  do {
-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
-  DEBUG ((DEBUG_INFO, "EnableDmar: R_GSTS_REG = 0x%x \n", Reg32));
+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
 
   //
   // Init DMAr Fault Event and Data registers
@@ -471,15 +546,19 @@ EnableDmar (
   //
   InvalidateIOTLB (VTdUnitInfo);
 
+  if (TEWasEnabled && (VTdUnitInfo->ECapReg.Bits.ADMS == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
+    if (VTdUnitInfo->CapReg.Bits.ESRTPS == 0) {
+      ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
+    }
+
+    DEBUG ((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
+    MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64) RootEntryTable);
+  }
+
   //
   // Enable VTd
   //
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
-  DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
-  do {
-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  } while ((Reg32 & B_GSTS_REG_TE) == 0);
+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
 
   DEBUG ((DEBUG_INFO, "VTD () enabled!<<<<<<\n"));
 
@@ -500,8 +579,6 @@ DisableDmar (
   )
 {
   UINT32                        Reg32;
-  UINT32                        Status;
-  UINT32                        Command;
 
   DEBUG ((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));
 
@@ -516,28 +593,12 @@ DisableDmar (
   //
   // Set TE (Translation Enable: BIT31) of Global command register to zero
   //
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
-  Command = (Status & ~B_GMCD_REG_TE);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
-
-   //
-   // Poll on TE Status bit of Global status register to become zero
-   //
-   do {
-     Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-   } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);
+  ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
 
   //
   // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in order to update the root table pointerDisable VTd
   //
-  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
-  Command = (Status | B_GMCD_REG_SRTP);
-  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
-  do {
-    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
-  } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+  SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
 
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
   DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
@@ -568,12 +629,12 @@ EnableVTdTranslationProtectionBlockDma (
 
   DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtectionBlockDma - 0x%08x\n", VtdUnitBaseAddress));
 
-  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", FixedPcdGetBool (PcdVTdSupportAbortDmaMode)));
+  DEBUG ((DEBUG_INFO, "PcdVTdSupportAbortDmaMode : %d\n", PcdGetBool (PcdVTdSupportAbortDmaMode)));
 
   ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
   DEBUG ((DEBUG_INFO, "ECapReg.ADMS : %d\n", ECapReg.Bits.ADMS));
 
-  if ((ECapReg.Bits.ADMS == 1) && FixedPcdGetBool (PcdVTdSupportAbortDmaMode)) {
+  if ((ECapReg.Bits.ADMS == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
     //
     // Use Abort DMA Mode
     //
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
index 387f90e37..b152831c0 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/IntelVTdDxe.inf
@@ -75,6 +75,7 @@
 [Pcd]
   gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask   ## CONSUMES
   gIntelSiliconPkgTokenSpaceGuid.PcdErrorCodeVTdError       ## CONSUMES
+  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode  ## CONSUMES
 
 [Depex]
   gEfiPciRootBridgeIoProtocolGuid
diff --git a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
index c7a56cf57..396aa4a70 100644
--- a/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
+++ b/Silicon/Intel/IntelSiliconPkg/Feature/VTd/IntelVTdDxe/VtdReg.c
@@ -475,6 +475,92 @@ DisablePmr (
   return ;
 }
 
+/**
+  Clear Global Command Register Bits
+
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+  @param[in] BitMask            Bit mask.
+**/
+VOID
+ClearGlobalCommandRegisterBits (
+  IN UINTN     VtdUnitBaseAddress,
+  IN UINT32    BitMask
+  )
+{
+  UINT32    Reg32;
+  UINT32    Status;
+  UINT32    Command;
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
+  Command = (Status & (~BitMask));
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
+
+  DEBUG((DEBUG_INFO, "Clear GCMD_REG bits 0x%x.\n", BitMask));
+
+  //
+  // Poll on Status bit of Global status register to become zero
+  //
+  do {
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  } while ((Reg32 & BitMask) == BitMask);
+}
+
+/**
+  Set Global Command Register Bits
+
+  @param[in] VtdUnitBaseAddress The base address of the VTd engine.
+  @param[in] BitMask            Bit mask.
+**/
+VOID
+SetGlobalCommandRegisterBits (
+  IN UINTN     VtdUnitBaseAddress,
+  IN UINT32    BitMask
+  )
+{
+  UINT32    Reg32;
+  UINT32    Status;
+  UINT32    Command;
+
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
+  Command = (Status | BitMask);
+  MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Command);
+
+  DEBUG((DEBUG_INFO, "Set GCMD_REG bits 0x%x.\n", BitMask));
+
+  //
+  // Poll on Status bit of Global status register to become not zero
+  //
+  do {
+    Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
+  } while ((Reg32 & BitMask) == 0);
+}
+
+/**
+  Update Root Table Address Register
+
+  @param[in]  VtdIndex          The index used to identify a VTd engine.
+  @param[in]  EnableADM         TRUE - Enable ADM in TTM bits
+**/
+VOID
+UpdateRootTableAddressRegister (
+  IN UINTN   VtdIndex,
+  IN BOOLEAN EnableADM
+  )
+{
+  UINT64 Reg64;
+
+  if (mVtdUnitInformation[VtdIndex].ExtRootEntryTable != NULL) {
+    DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[VtdIndex].ExtRootEntryTable));
+    Reg64 = (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].ExtRootEntryTable | (EnableADM ? V_RTADDR_REG_TTM_ADM : BIT11);
+  } else {
+    DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[VtdIndex].RootEntryTable));
+    Reg64 = (UINT64)(UINTN)mVtdUnitInformation[VtdIndex].RootEntryTable | (EnableADM ? V_RTADDR_REG_TTM_ADM : 0);
+  }
+  MmioWrite64 (mVtdUnitInformation[VtdIndex].VtdUnitBaseAddress + R_RTADDR_REG, Reg64);
+}
+
 /**
   Enable DMAR translation.
 
@@ -488,25 +574,43 @@ EnableDmar (
 {
   UINTN     Index;
   UINT32    Reg32;
+  UINTN     VtdUnitBaseAddress;
+  BOOLEAN   TEWasEnabled;
 
   for (Index = 0; Index < mVtdUnitNumber; Index++) {
-    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] \n", Index));
+    VtdUnitBaseAddress = mVtdUnitInformation[Index].VtdUnitBaseAddress;
+    DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%d] BAR [0x%x]\n", Index, VtdUnitBaseAddress));
+
+    //
+    // Check TE was enabled or not.
+    //
+    TEWasEnabled = ((MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG) & B_GSTS_REG_TE) == B_GSTS_REG_TE);
+
+    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
+      //
+      // For implementations reporting Enhanced SRTP Support (ESRTPS) field as
+      // Clear in the Capability register, software must not modify this field while
+      // DMA remapping is active (TES=1 in Global Status register).
+      //
+      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {
+        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
+      }
+
+      //
+      // Enable ADM
+      //
+      UpdateRootTableAddressRegister (Index, TRUE);
+
+      DEBUG((DEBUG_INFO, "Enable Abort DMA Mode...\n"));
+      SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
 
-    if (mVtdUnitInformation[Index].ExtRootEntryTable != NULL) {
-      DEBUG((DEBUG_INFO, "ExtRootEntryTable 0x%x \n", mVtdUnitInformation[Index].ExtRootEntryTable));
-      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].ExtRootEntryTable | BIT11);
     } else {
-      DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", mVtdUnitInformation[Index].RootEntryTable));
-      MmioWrite64 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)mVtdUnitInformation[Index].RootEntryTable);
-    }
+      UpdateRootTableAddressRegister (Index, FALSE);
 
-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_SRTP);
+    }
 
     DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n"));
-    do {
-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_SRTP);
 
     //
     // Init DMAr Fault Event and Data registers
@@ -528,15 +632,19 @@ EnableDmar (
     //
     InvalidateIOTLB (Index);
 
+    if (TEWasEnabled && (mVtdUnitInformation[Index].ECapReg.Bits.ADMS == 1) && PcdGetBool (PcdVTdSupportAbortDmaMode)) {
+      if (mVtdUnitInformation[Index].CapReg.Bits.ESRTPS == 0) {
+        ClearGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
+      }
+
+      UpdateRootTableAddressRegister (Index, FALSE);
+    }
+
     //
     // Enable VTd
     //
-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_TE);
-    DEBUG((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
-    do {
-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    } while ((Reg32 & B_GSTS_REG_TE) == 0);
+    DEBUG ((DEBUG_INFO, "EnableDmar: Waiting B_GSTS_REG_TE ...\n"));
+    SetGlobalCommandRegisterBits (VtdUnitBaseAddress, B_GMCD_REG_TE);
 
     DEBUG ((DEBUG_INFO,"VTD (%d) enabled!<<<<<<\n",Index));
   }
@@ -565,8 +673,6 @@ DisableDmar (
   UINTN     Index;
   UINTN     SubIndex;
   UINT32    Reg32;
-  UINT32    Status;
-  UINT32    Command;
 
   for (Index = 0; Index < mVtdUnitNumber; Index++) {
     DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%d] \n", Index));
@@ -582,32 +688,15 @@ DisableDmar (
     //
     // Set TE (Translation Enable: BIT31) of Global command register to zero
     //
-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
-    Command = (Status & ~B_GMCD_REG_TE);
-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Command);
-
-    //
-    // Poll on TE Status bit of Global status register to become zero
-    //
-    do {
-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    } while ((Reg32 & B_GSTS_REG_TE) == B_GSTS_REG_TE);
+    ClearGlobalCommandRegisterBits (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GMCD_REG_TE);
 
     //
     // Set SRTP (Set Root Table Pointer: BIT30) of Global command register in order to update the root table pointerDisable VTd
     //
-    Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    Status = (Reg32 & 0x96FFFFFF);       // Reset the one-shot bits
-    Command = (Status | B_GMCD_REG_SRTP);
-    MmioWrite32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GCMD_REG, Command);
-
-    do {
-      Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    } while((Reg32 & B_GSTS_REG_RTPS) == 0);
+    SetGlobalCommandRegisterBits (mVtdUnitInformation[Index].VtdUnitBaseAddress, B_GSTS_REG_RTPS);
 
     Reg32 = MmioRead32 (mVtdUnitInformation[Index].VtdUnitBaseAddress + R_GSTS_REG);
-    DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
+    DEBUG ((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
 
     DEBUG ((DEBUG_INFO,"VTD (%d) Disabled!<<<<<<\n",Index));
 
diff --git a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
index c36d130a0..9166e599a 100644
--- a/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
+++ b/Silicon/Intel/IntelSiliconPkg/IntelSiliconPkg.dec
@@ -135,12 +135,6 @@
   gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvSize|0x000A0000|UINT32|0x0000000A
   gIntelSiliconPkgTokenSpaceGuid.PcdFlashMicrocodeFvOffset|0x00660000|UINT32|0x0000000B
 
-  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>
-  #   TRUE  - Support VTd abort DMA mode.
-  #   FALSE - Not support VTd abort DMA mode.
-  # @Prompt VTd abort DMA mode support.
-  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0x0000000C
-
 [PcdsFixedAtBuild, PcdsPatchableInModule]
   ## Error code for VTd error.<BR><BR>
   #  EDKII_ERROR_CODE_VTD_ERROR = (EFI_IO_BUS_UNSPECIFIED | (EFI_OEM_SPECIFIC | 0x00000000)) = 0x02008000<BR>
@@ -178,3 +172,9 @@
   # @Prompt The VTd PEI DMA buffer size for S3.
   gIntelSiliconPkgTokenSpaceGuid.PcdVTdPeiDmaBufferSizeS3|0x00200000|UINT32|0x00000004
 
+  ## Indicates if VTd Abort DMA Mode is supported.<BR><BR>
+  #   TRUE  - Support VTd abort DMA mode.
+  #   FALSE - Not support VTd abort DMA mode.
+  # @Prompt VTd abort DMA mode support.
+  gIntelSiliconPkgTokenSpaceGuid.PcdVTdSupportAbortDmaMode|FALSE|BOOLEAN|0x0000000C
+
-- 
2.26.2.windows.1


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

end of thread, other threads:[~2022-09-29  8:32 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <1711EAB1819FAD8B.21447@groups.io>
2022-09-29  3:54 ` [edk2-devel] [PATCH] IntelSiliconPkg/VTd: Enable ADM when change TTM Huang, Jenny
2022-09-29  8:32   ` Sheng Wei

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