]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
IntelSiliconPkg/VtdPmrPei: Add premem support.
[mirror_edk2.git] / IntelSiliconPkg / Feature / VTd / IntelVTdPmrPei / IntelVTdPmr.c
index ef08e2991f0abfe69ff381784dc2ea6a5c968fdd..000a81ba187940926f2448addf471eefb4d9a3f5 100644 (file)
 #include <Library/IoLib.h>\r
 #include <Library/DebugLib.h>\r
 #include <IndustryStandard/Vtd.h>\r
-#include <Ppi/VTdInfo.h>\r
+#include <Ppi/VtdInfo.h>\r
 \r
 #include "IntelVTdPmrPei.h"\r
 \r
-extern EDKII_VTD_INFO_PPI                *mVTdInfoPpi;\r
-\r
 /**\r
   Get protected low memory alignment.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
 \r
   @return protected low memory alignment.\r
 **/\r
 UINT32\r
 GetPlmrAlignment (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress\r
   )\r
 {\r
@@ -48,19 +48,18 @@ GetPlmrAlignment (
 /**\r
   Get protected high memory alignment.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
 \r
   @return protected high memory alignment.\r
 **/\r
 UINT64\r
 GetPhmrAlignment (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress\r
   )\r
 {\r
   UINT64        Data64;\r
-  UINT8         HostAddressWidth;\r
-\r
-  HostAddressWidth = mVTdInfoPpi->HostAddressWidth;\r
 \r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);\r
   Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);\r
@@ -73,11 +72,15 @@ GetPhmrAlignment (
 /**\r
   Get protected low memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
   @return protected low memory alignment.\r
 **/\r
 UINT32\r
 GetLowMemoryAlignment (\r
-  VOID\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
   )\r
 {\r
   UINTN         Index;\r
@@ -85,8 +88,11 @@ GetLowMemoryAlignment (
   UINT32        FinalAlignment;\r
 \r
   FinalAlignment = 0;\r
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
-    Alignment = GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (FinalAlignment < Alignment) {\r
       FinalAlignment = Alignment;\r
     }\r
@@ -97,11 +103,15 @@ GetLowMemoryAlignment (
 /**\r
   Get protected high memory alignment.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
   @return protected high memory alignment.\r
 **/\r
 UINT64\r
 GetHighMemoryAlignment (\r
-  VOID\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
   )\r
 {\r
   UINTN         Index;\r
@@ -109,8 +119,11 @@ GetHighMemoryAlignment (
   UINT64        FinalAlignment;\r
 \r
   FinalAlignment = 0;\r
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
-    Alignment = GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (FinalAlignment < Alignment) {\r
       FinalAlignment = Alignment;\r
     }\r
@@ -134,12 +147,19 @@ EnablePmr (
   UINT32        Reg32;\r
   VTD_CAP_REG   CapReg;\r
 \r
+  DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));\r
+\r
   CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
   if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
     return EFI_UNSUPPORTED;\r
   }\r
 \r
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if (Reg32 == 0xFFFFFFFF) {\r
+    DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));\r
+    ASSERT(FALSE);\r
+  }\r
+\r
   if ((Reg32 & BIT0) == 0) {\r
     MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);\r
     do {\r
@@ -147,6 +167,8 @@ EnablePmr (
     } while((Reg32 & BIT0) == 0);\r
   }\r
 \r
+  DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));\r
+\r
   return EFI_SUCCESS;\r
 }\r
 \r
@@ -172,6 +194,11 @@ DisablePmr (
   }\r
 \r
   Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if (Reg32 == 0xFFFFFFFF) {\r
+    DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));\r
+    ASSERT(FALSE);\r
+  }\r
+\r
   if ((Reg32 & BIT0) != 0) {\r
     MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);\r
     do {\r
@@ -185,6 +212,7 @@ DisablePmr (
 /**\r
   Set PMR region in the VTd engine.\r
 \r
+  @param HostAddressWidth   The host address width.\r
   @param VtdUnitBaseAddress The base address of the VTd engine.\r
   @param LowMemoryBase      The protected low memory region base.\r
   @param LowMemoryLength    The protected low memory region length.\r
@@ -196,6 +224,7 @@ DisablePmr (
 **/\r
 EFI_STATUS\r
 SetPmrRegion (\r
+  IN UINT8         HostAddressWidth,\r
   IN UINTN         VtdUnitBaseAddress,\r
   IN UINT32        LowMemoryBase,\r
   IN UINT32        LowMemoryLength,\r
@@ -215,9 +244,9 @@ SetPmrRegion (
     return EFI_UNSUPPORTED;\r
   }\r
 \r
-  PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);\r
+  PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
   DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));\r
-  PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);\r
+  PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
   DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));\r
 \r
   if ((LowMemoryBase    != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||\r
@@ -237,8 +266,10 @@ SetPmrRegion (
 \r
   MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG,    LowMemoryBase);\r
   MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG,  LowMemoryBase + LowMemoryLength - 1);\r
+  DEBUG ((DEBUG_INFO, "PLMR set done\n"));\r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG,   HighMemoryBase);\r
   MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);\r
+  DEBUG ((DEBUG_INFO, "PHMR set done\n"));\r
 \r
   return EFI_SUCCESS;\r
 }\r
@@ -246,6 +277,8 @@ SetPmrRegion (
 /**\r
   Set DMA protected region.\r
 \r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
   @param LowMemoryBase      The protected low memory region base.\r
   @param LowMemoryLength    The protected low memory region length.\r
   @param HighMemoryBase     The protected high memory region base.\r
@@ -256,6 +289,8 @@ SetPmrRegion (
 **/\r
 EFI_STATUS\r
 SetDmaProtectedRange (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask,\r
   IN UINT32        LowMemoryBase,\r
   IN UINT32        LowMemoryLength,\r
   IN UINT64        HighMemoryBase,\r
@@ -265,12 +300,16 @@ SetDmaProtectedRange (
   UINTN       Index;\r
   EFI_STATUS  Status;\r
 \r
-  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));\r
+  DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));\r
 \r
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
-    DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     Status = SetPmrRegion (\r
-               (UINTN)mVTdInfoPpi->VTdEngineAddress[Index],\r
+               VTdInfo->HostAddressWidth,\r
+               (UINTN)VTdInfo->VTdEngineAddress[Index],\r
                LowMemoryBase,\r
                LowMemoryLength,\r
                HighMemoryBase,\r
@@ -279,7 +318,7 @@ SetDmaProtectedRange (
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
-    Status = EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
+    Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
@@ -291,20 +330,29 @@ SetDmaProtectedRange (
 /**\r
   Diable DMA protection.\r
 \r
-  @retval DMA protection is disabled.\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
+  @retval EFI_SUCCESS DMA protection is disabled.\r
 **/\r
 EFI_STATUS\r
 DisableDmaProtection (\r
-  VOID\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
   )\r
 {\r
   UINTN       Index;\r
   EFI_STATUS  Status;\r
 \r
-  DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));\r
+  DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));\r
 \r
-  for (Index = 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) {\r
-    Status = DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]);\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index));\r
+\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
     if (EFI_ERROR(Status)) {\r
       return Status;\r
     }\r
@@ -312,3 +360,67 @@ DisableDmaProtection (
 \r
   return EFI_SUCCESS;\r
 }\r
+\r
+/**\r
+  Return if the PMR is enabled.\r
+\r
+  @param VtdUnitBaseAddress The base address of the VTd engine.\r
+\r
+  @retval TRUE  PMR is enabled.\r
+  @retval FALSE PMR is disabled or unsupported.\r
+**/\r
+BOOLEAN\r
+IsPmrEnabled (\r
+  IN UINTN         VtdUnitBaseAddress\r
+  )\r
+{\r
+  UINT32        Reg32;\r
+  VTD_CAP_REG   CapReg;\r
+\r
+  CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
+  if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
+  if ((Reg32 & BIT0) == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+/**\r
+  Return the mask of the VTd engine which is enabled.\r
+\r
+  @param VTdInfo            The VTd engine context information.\r
+  @param EngineMask         The mask of the VTd engine to be accessed.\r
+\r
+  @return the mask of the VTd engine which is enabled.\r
+**/\r
+UINT64\r
+GetDmaProtectionEnabledEngineMask (\r
+  IN VTD_INFO      *VTdInfo,\r
+  IN UINT64        EngineMask\r
+  )\r
+{\r
+  UINTN       Index;\r
+  BOOLEAN     Result;\r
+  UINT64      EnabledEngineMask;\r
+\r
+  DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask));\r
+\r
+  EnabledEngineMask = 0;\r
+  for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {\r
+    if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
+      continue;\r
+    }\r
+    Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
+    if (Result) {\r
+      EnabledEngineMask |= LShiftU64(1, Index);\r
+    }\r
+  }\r
+\r
+  DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask));\r
+  return EnabledEngineMask;\r
+}\r