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:
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user