+++ /dev/null
-/** @file\r
-\r
- Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>\r
-\r
- SPDX-License-Identifier: BSD-2-Clause-Patent\r
-\r
-**/\r
-\r
-#include <PiPei.h>\r
-#include <Library/BaseLib.h>\r
-#include <Library/BaseMemoryLib.h>\r
-#include <Library/IoLib.h>\r
-#include <Library/DebugLib.h>\r
-#include <IndustryStandard/Vtd.h>\r
-#include <Ppi/VtdInfo.h>\r
-\r
-#include "IntelVTdPmrPei.h"\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
- UINT32 Data32;\r
-\r
- MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, 0xFFFFFFFF);\r
- Data32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG);\r
- Data32 = ~Data32 + 1;\r
-\r
- return Data32;\r
-}\r
-\r
-/**\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
-\r
- MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);\r
- Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);\r
- Data64 = ~Data64 + 1;\r
- Data64 = Data64 & (LShiftU64 (1, HostAddressWidth) - 1);\r
-\r
- return Data64;\r
-}\r
-\r
-/**\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
- IN VTD_INFO *VTdInfo,\r
- IN UINT64 EngineMask\r
- )\r
-{\r
- UINTN Index;\r
- UINT32 Alignment;\r
- UINT32 FinalAlignment;\r
-\r
- FinalAlignment = 0;\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
- }\r
- return FinalAlignment;\r
-}\r
-\r
-/**\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
- IN VTD_INFO *VTdInfo,\r
- IN UINT64 EngineMask\r
- )\r
-{\r
- UINTN Index;\r
- UINT64 Alignment;\r
- UINT64 FinalAlignment;\r
-\r
- FinalAlignment = 0;\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
- }\r
- return FinalAlignment;\r
-}\r
-\r
-/**\r
- Enable PMR in the VTd engine.\r
-\r
- @param VtdUnitBaseAddress The base address of the VTd engine.\r
-\r
- @retval EFI_SUCCESS The PMR is enabled.\r
- @retval EFI_UNSUPPORTED The PMR is not supported.\r
-**/\r
-EFI_STATUS\r
-EnablePmr (\r
- IN UINTN VtdUnitBaseAddress\r
- )\r
-{\r
- 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
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
- } while((Reg32 & BIT0) == 0);\r
- }\r
-\r
- DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Disable PMR in the VTd engine.\r
-\r
- @param VtdUnitBaseAddress The base address of the VTd engine.\r
-\r
- @retval EFI_SUCCESS The PMR is disabled.\r
- @retval EFI_UNSUPPORTED The PMR is not supported.\r
-**/\r
-EFI_STATUS\r
-DisablePmr (\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 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, 0x0);\r
- do {\r
- Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);\r
- } while((Reg32 & BIT0) != 0);\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\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
- @param HighMemoryBase The protected high memory region base.\r
- @param HighMemoryLength The protected high memory region length.\r
-\r
- @retval EFI_SUCCESS The PMR is set to protected region.\r
- @retval EFI_UNSUPPORTED The PMR is not supported.\r
-**/\r
-EFI_STATUS\r
-SetPmrRegion (\r
- IN UINT8 HostAddressWidth,\r
- IN UINTN VtdUnitBaseAddress,\r
- IN UINT32 LowMemoryBase,\r
- IN UINT32 LowMemoryLength,\r
- IN UINT64 HighMemoryBase,\r
- IN UINT64 HighMemoryLength\r
- )\r
-{\r
- VTD_CAP_REG CapReg;\r
- UINT32 PlmrAlignment;\r
- UINT64 PhmrAlignment;\r
-\r
- DEBUG ((DEBUG_INFO, "VtdUnitBaseAddress - 0x%x\n", VtdUnitBaseAddress));\r
-\r
- CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);\r
- if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {\r
- DEBUG ((DEBUG_ERROR, "PLMR/PHMR unsupported\n"));\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
- DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));\r
- PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);\r
- DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));\r
-\r
- if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||\r
- (LowMemoryLength != ALIGN_VALUE(LowMemoryLength, PlmrAlignment)) ||\r
- (HighMemoryBase != ALIGN_VALUE(HighMemoryBase, PhmrAlignment)) ||\r
- (HighMemoryLength != ALIGN_VALUE(HighMemoryLength, PhmrAlignment))) {\r
- DEBUG ((DEBUG_ERROR, "PLMR/PHMR alignment issue\n"));\r
- return EFI_UNSUPPORTED;\r
- }\r
-\r
- if (LowMemoryBase == 0 && LowMemoryLength == 0) {\r
- LowMemoryBase = 0xFFFFFFFF;\r
- }\r
- if (HighMemoryBase == 0 && HighMemoryLength == 0) {\r
- HighMemoryBase = 0xFFFFFFFFFFFFFFFF;\r
- }\r
-\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
-\r
-/**\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
- @param HighMemoryLength The protected high memory region length.\r
-\r
- @retval EFI_SUCCESS The DMA protection is set.\r
- @retval EFI_UNSUPPORTED The DMA protection is not set.\r
-**/\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
- IN UINT64 HighMemoryLength\r
- )\r
-{\r
- UINTN Index;\r
- EFI_STATUS Status;\r
-\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 < VTdInfo->VTdEngineCount; Index++) {\r
- if ((EngineMask & LShiftU64(1, Index)) == 0) {\r
- continue;\r
- }\r
- DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
- Status = SetPmrRegion (\r
- VTdInfo->HostAddressWidth,\r
- (UINTN)VTdInfo->VTdEngineAddress[Index],\r
- LowMemoryBase,\r
- LowMemoryLength,\r
- HighMemoryBase,\r
- HighMemoryLength\r
- );\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
- Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);\r
- if (EFI_ERROR(Status)) {\r
- return Status;\r
- }\r
- }\r
-\r
- return EFI_SUCCESS;\r
-}\r
-\r
-/**\r
- Diable DMA protection.\r
-\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
- IN VTD_INFO *VTdInfo,\r
- IN UINT64 EngineMask\r
- )\r
-{\r
- UINTN Index;\r
- EFI_STATUS Status;\r
-\r
- DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));\r
-\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
- }\r
-\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