IntelSiliconPkg/VtdPmrPei: Add premem support.

Remove memory discovered dependency to support both premem
VTD_INFO_PPI and postmem VTD_INFO_PPI.

If VTD_INFO_PPI is installed before memory is ready, this
driver protects all memory region.
If VTD_INFO_PPI is installed or reinstalled after memory
is ready, this driver allocates DMA buffer and protect rest.

Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
Jiewen Yao
2017-09-23 16:27:50 +08:00
parent e5d847476a
commit a1e7cd0b02
6 changed files with 1383 additions and 621 deletions

View File

@@ -22,17 +22,17 @@
#include "IntelVTdPmrPei.h"
extern VTD_INFO *mVTdInfo;
/**
Get protected low memory alignment.
@param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected low memory alignment.
**/
UINT32
GetPlmrAlignment (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
@@ -48,19 +48,18 @@ GetPlmrAlignment (
/**
Get protected high memory alignment.
@param HostAddressWidth The host address width.
@param VtdUnitBaseAddress The base address of the VTd engine.
@return protected high memory alignment.
**/
UINT64
GetPhmrAlignment (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress
)
{
UINT64 Data64;
UINT8 HostAddressWidth;
HostAddressWidth = mVTdInfo->HostAddressWidth;
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
@@ -73,12 +72,14 @@ GetPhmrAlignment (
/**
Get protected low memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected low memory alignment.
**/
UINT32
GetLowMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
@@ -87,11 +88,11 @@ GetLowMemoryAlignment (
UINT32 FinalAlignment;
FinalAlignment = 0;
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
@@ -102,12 +103,14 @@ GetLowMemoryAlignment (
/**
Get protected high memory alignment.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return protected high memory alignment.
**/
UINT64
GetHighMemoryAlignment (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
@@ -116,11 +119,11 @@ GetHighMemoryAlignment (
UINT64 FinalAlignment;
FinalAlignment = 0;
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
if (FinalAlignment < Alignment) {
FinalAlignment = Alignment;
}
@@ -144,12 +147,19 @@ EnablePmr (
UINT32 Reg32;
VTD_CAP_REG CapReg;
DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));
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 == 0xFFFFFFFF) {
DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
ASSERT(FALSE);
}
if ((Reg32 & BIT0) == 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
do {
@@ -157,6 +167,8 @@ EnablePmr (
} while((Reg32 & BIT0) == 0);
}
DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));
return EFI_SUCCESS;
}
@@ -182,6 +194,11 @@ DisablePmr (
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if (Reg32 == 0xFFFFFFFF) {
DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32));
ASSERT(FALSE);
}
if ((Reg32 & BIT0) != 0) {
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
do {
@@ -195,6 +212,7 @@ DisablePmr (
/**
Set PMR region in the VTd engine.
@param HostAddressWidth The host address width.
@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.
@@ -206,6 +224,7 @@ DisablePmr (
**/
EFI_STATUS
SetPmrRegion (
IN UINT8 HostAddressWidth,
IN UINTN VtdUnitBaseAddress,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -225,9 +244,9 @@ SetPmrRegion (
return EFI_UNSUPPORTED;
}
PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);
PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);
PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
@@ -247,8 +266,10 @@ SetPmrRegion (
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);
DEBUG ((DEBUG_INFO, "PLMR set done\n"));
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, HighMemoryBase);
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
DEBUG ((DEBUG_INFO, "PHMR set done\n"));
return EFI_SUCCESS;
}
@@ -256,6 +277,7 @@ SetPmrRegion (
/**
Set DMA protected region.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@param LowMemoryBase The protected low memory region base.
@param LowMemoryLength The protected low memory region length.
@@ -267,6 +289,7 @@ SetPmrRegion (
**/
EFI_STATUS
SetDmaProtectedRange (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -279,13 +302,14 @@ SetDmaProtectedRange (
DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength));
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
Status = SetPmrRegion (
(UINTN)mVTdInfo->VTdEngineAddress[Index],
VTdInfo->HostAddressWidth,
(UINTN)VTdInfo->VTdEngineAddress[Index],
LowMemoryBase,
LowMemoryLength,
HighMemoryBase,
@@ -294,7 +318,7 @@ SetDmaProtectedRange (
if (EFI_ERROR(Status)) {
return Status;
}
Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
@@ -306,25 +330,29 @@ SetDmaProtectedRange (
/**
Diable DMA protection.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@retval DMA protection is disabled.
@retval EFI_SUCCESS DMA protection is disabled.
**/
EFI_STATUS
DisableDmaProtection (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
EFI_STATUS Status;
DEBUG ((DEBUG_INFO, "DisableDmaProtection\n"));
DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask));
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index));
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (EFI_ERROR(Status)) {
return Status;
}
@@ -332,3 +360,67 @@ DisableDmaProtection (
return EFI_SUCCESS;
}
/**
Return if the PMR is enabled.
@param VtdUnitBaseAddress The base address of the VTd engine.
@retval TRUE PMR is enabled.
@retval FALSE PMR is disabled or unsupported.
**/
BOOLEAN
IsPmrEnabled (
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 FALSE;
}
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
if ((Reg32 & BIT0) == 0) {
return FALSE;
}
return TRUE;
}
/**
Return the mask of the VTd engine which is enabled.
@param VTdInfo The VTd engine context information.
@param EngineMask The mask of the VTd engine to be accessed.
@return the mask of the VTd engine which is enabled.
**/
UINT64
GetDmaProtectionEnabledEngineMask (
IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
)
{
UINTN Index;
BOOLEAN Result;
UINT64 EnabledEngineMask;
DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", EngineMask));
EnabledEngineMask = 0;
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
if ((EngineMask & LShiftU64(1, Index)) == 0) {
continue;
}
Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);
if (Result) {
EnabledEngineMask |= LShiftU64(1, Index);
}
}
DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask));
return EnabledEngineMask;
}