mirror of https://github.com/acidanthera/audk.git
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:
parent
e5d847476a
commit
a1e7cd0b02
|
@ -0,0 +1,580 @@
|
||||||
|
/** @file
|
||||||
|
|
||||||
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||||
|
This program and the accompanying materials
|
||||||
|
are licensed and made available under the terms and conditions of the BSD License
|
||||||
|
which accompanies this distribution. The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php.
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <Uefi.h>
|
||||||
|
#include <PiPei.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/HobLib.h>
|
||||||
|
#include <IndustryStandard/Vtd.h>
|
||||||
|
#include <Ppi/VtdInfo.h>
|
||||||
|
|
||||||
|
#include "IntelVTdPmrPei.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump DMAR DeviceScopeEntry.
|
||||||
|
|
||||||
|
@param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpDmarDeviceScopeEntry (
|
||||||
|
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN PciPathNumber;
|
||||||
|
UINTN PciPathIndex;
|
||||||
|
EFI_ACPI_DMAR_PCI_PATH *PciPath;
|
||||||
|
|
||||||
|
if (DmarDeviceScopeEntry == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" *************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" * DMA-Remapping Device Scope Entry Structure *\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" *************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
||||||
|
" DMAR Device Scope Entry address ...................... 0x%016lx\n" :
|
||||||
|
" DMAR Device Scope Entry address ...................... 0x%08x\n",
|
||||||
|
DmarDeviceScopeEntry
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Device Scope Entry Type ............................ 0x%02x\n",
|
||||||
|
DmarDeviceScopeEntry->Type
|
||||||
|
));
|
||||||
|
switch (DmarDeviceScopeEntry->Type) {
|
||||||
|
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT:
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" PCI Endpoint Device\n"
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
case EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_BRIDGE:
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" PCI Sub-hierachy\n"
|
||||||
|
));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Length ............................................. 0x%02x\n",
|
||||||
|
DmarDeviceScopeEntry->Length
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Enumeration ID ..................................... 0x%02x\n",
|
||||||
|
DmarDeviceScopeEntry->EnumerationId
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Starting Bus Number ................................ 0x%02x\n",
|
||||||
|
DmarDeviceScopeEntry->StartBusNumber
|
||||||
|
));
|
||||||
|
|
||||||
|
PciPathNumber = (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH);
|
||||||
|
PciPath = (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1);
|
||||||
|
for (PciPathIndex = 0; PciPathIndex < PciPathNumber; PciPathIndex++) {
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Device ............................................. 0x%02x\n",
|
||||||
|
PciPath[PciPathIndex].Device
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Function ........................................... 0x%02x\n",
|
||||||
|
PciPath[PciPathIndex].Function
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" *************************************************************************\n\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump DMAR RMRR table.
|
||||||
|
|
||||||
|
@param[in] Rmrr DMAR RMRR table
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpDmarRmrr (
|
||||||
|
IN EFI_ACPI_DMAR_RMRR_HEADER *Rmrr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
|
||||||
|
INTN RmrrLen;
|
||||||
|
|
||||||
|
if (Rmrr == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" * Reserved Memory Region Reporting Structure *\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
||||||
|
" RMRR address ........................................... 0x%016lx\n" :
|
||||||
|
" RMRR address ........................................... 0x%08x\n",
|
||||||
|
Rmrr
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Type ................................................. 0x%04x\n",
|
||||||
|
Rmrr->Header.Type
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Length ............................................... 0x%04x\n",
|
||||||
|
Rmrr->Header.Length
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Segment Number ....................................... 0x%04x\n",
|
||||||
|
Rmrr->SegmentNumber
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Reserved Memory Region Base Address .................. 0x%016lx\n",
|
||||||
|
Rmrr->ReservedMemoryRegionBaseAddress
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Reserved Memory Region Limit Address ................. 0x%016lx\n",
|
||||||
|
Rmrr->ReservedMemoryRegionLimitAddress
|
||||||
|
));
|
||||||
|
|
||||||
|
RmrrLen = Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER);
|
||||||
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Rmrr + 1);
|
||||||
|
while (RmrrLen > 0) {
|
||||||
|
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
|
||||||
|
RmrrLen -= DmarDeviceScopeEntry->Length;
|
||||||
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump DMAR DRHD table.
|
||||||
|
|
||||||
|
@param[in] Drhd DMAR DRHD table
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpDmarDrhd (
|
||||||
|
IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
|
||||||
|
INTN DrhdLen;
|
||||||
|
|
||||||
|
if (Drhd == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" * DMA-Remapping Hardware Definition Structure *\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
||||||
|
" DRHD address ........................................... 0x%016lx\n" :
|
||||||
|
" DRHD address ........................................... 0x%08x\n",
|
||||||
|
Drhd
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Type ................................................. 0x%04x\n",
|
||||||
|
Drhd->Header.Type
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Length ............................................... 0x%04x\n",
|
||||||
|
Drhd->Header.Length
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Flags ................................................ 0x%02x\n",
|
||||||
|
Drhd->Flags
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" INCLUDE_PCI_ALL .................................... 0x%02x\n",
|
||||||
|
Drhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Segment Number ....................................... 0x%04x\n",
|
||||||
|
Drhd->SegmentNumber
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Register Base Address ................................ 0x%016lx\n",
|
||||||
|
Drhd->RegisterBaseAddress
|
||||||
|
));
|
||||||
|
|
||||||
|
DrhdLen = Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER);
|
||||||
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(Drhd + 1);
|
||||||
|
while (DrhdLen > 0) {
|
||||||
|
DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry);
|
||||||
|
DrhdLen -= DmarDeviceScopeEntry->Length;
|
||||||
|
DmarDeviceScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" ***************************************************************************\n\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump DMAR ACPI table.
|
||||||
|
|
||||||
|
@param[in] Dmar DMAR ACPI table
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpAcpiDMAR (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *Dmar
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
||||||
|
INTN DmarLen;
|
||||||
|
|
||||||
|
if (Dmar == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Dump Dmar table
|
||||||
|
//
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
"*****************************************************************************\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
"* DMAR Table *\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
"*****************************************************************************\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
(sizeof(UINTN) == sizeof(UINT64)) ?
|
||||||
|
"DMAR address ............................................. 0x%016lx\n" :
|
||||||
|
"DMAR address ............................................. 0x%08x\n",
|
||||||
|
Dmar
|
||||||
|
));
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Table Contents:\n"
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Host Address Width ................................... 0x%02x\n",
|
||||||
|
Dmar->HostAddressWidth
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" Flags ................................................ 0x%02x\n",
|
||||||
|
Dmar->Flags
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" INTR_REMAP ......................................... 0x%02x\n",
|
||||||
|
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_INTR_REMAP
|
||||||
|
));
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
" X2APIC_OPT_OUT_SET ................................. 0x%02x\n",
|
||||||
|
Dmar->Flags & EFI_ACPI_DMAR_FLAGS_X2APIC_OPT_OUT
|
||||||
|
));
|
||||||
|
|
||||||
|
DmarLen = Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER);
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1);
|
||||||
|
while (DmarLen > 0) {
|
||||||
|
switch (DmarHeader->Type) {
|
||||||
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
||||||
|
DumpDmarDrhd ((EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
|
||||||
|
break;
|
||||||
|
case EFI_ACPI_DMAR_TYPE_RMRR:
|
||||||
|
DumpDmarRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DmarLen -= DmarHeader->Length;
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,
|
||||||
|
"*****************************************************************************\n\n"
|
||||||
|
));
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get VTd engine number.
|
||||||
|
|
||||||
|
@param[in] AcpiDmarTable DMAR ACPI table
|
||||||
|
|
||||||
|
@return the VTd engine number.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
GetVtdEngineNumber (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
||||||
|
UINTN VtdIndex;
|
||||||
|
|
||||||
|
VtdIndex = 0;
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
||||||
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
||||||
|
switch (DmarHeader->Type) {
|
||||||
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
||||||
|
VtdIndex++;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
||||||
|
}
|
||||||
|
return VtdIndex ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process DMAR DHRD table.
|
||||||
|
|
||||||
|
@param[in] VTdInfo The VTd engine context information.
|
||||||
|
@param[in] VtdIndex The index of VTd engine.
|
||||||
|
@param[in] DmarDrhd The DRHD table.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ProcessDhrd (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINTN VtdIndex,
|
||||||
|
IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
|
||||||
|
VTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse DMAR DRHD table.
|
||||||
|
|
||||||
|
@param[in] AcpiDmarTable DMAR ACPI table
|
||||||
|
|
||||||
|
@return EFI_SUCCESS The DMAR DRHD table is parsed.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ParseDmarAcpiTableDrhd (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
||||||
|
UINTN VtdUnitNumber;
|
||||||
|
UINTN VtdIndex;
|
||||||
|
VTD_INFO *VTdInfo;
|
||||||
|
|
||||||
|
VtdUnitNumber = GetVtdEngineNumber (AcpiDmarTable);
|
||||||
|
if (VtdUnitNumber == 0) {
|
||||||
|
return EFI_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
VTdInfo = BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
|
||||||
|
ASSERT(VTdInfo != NULL);
|
||||||
|
if (VTdInfo == NULL) {
|
||||||
|
return EFI_OUT_OF_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize the engine mask to all.
|
||||||
|
//
|
||||||
|
VTdInfo->AcpiDmarTable = AcpiDmarTable;
|
||||||
|
VTdInfo->EngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
|
||||||
|
VTdInfo->HostAddressWidth = AcpiDmarTable->HostAddressWidth;
|
||||||
|
VTdInfo->VTdEngineCount = VtdUnitNumber;
|
||||||
|
|
||||||
|
VtdIndex = 0;
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
||||||
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
||||||
|
switch (DmarHeader->Type) {
|
||||||
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
||||||
|
ASSERT (VtdIndex < VtdUnitNumber);
|
||||||
|
ProcessDhrd (VTdInfo, VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
|
||||||
|
VtdIndex++;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
||||||
|
}
|
||||||
|
ASSERT (VtdIndex == VtdUnitNumber);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return the VTd engine index according to the Segment and DevScopeEntry.
|
||||||
|
|
||||||
|
@param AcpiDmarTable DMAR ACPI table
|
||||||
|
@param Segment The segment of the VTd engine
|
||||||
|
@param DevScopeEntry The DevScopeEntry of the VTd engine
|
||||||
|
|
||||||
|
@return The VTd engine index according to the Segment and DevScopeEntry.
|
||||||
|
@retval -1 The VTd engine is not found.
|
||||||
|
**/
|
||||||
|
UINTN
|
||||||
|
GetVTdEngineFromDevScopeEntry (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable,
|
||||||
|
IN UINT16 Segment,
|
||||||
|
IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
||||||
|
UINTN VtdIndex;
|
||||||
|
EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd;
|
||||||
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *ThisDevScopeEntry;
|
||||||
|
|
||||||
|
VtdIndex = 0;
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
||||||
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
||||||
|
switch (DmarHeader->Type) {
|
||||||
|
case EFI_ACPI_DMAR_TYPE_DRHD:
|
||||||
|
DmarDrhd = (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader;
|
||||||
|
if (DmarDrhd->SegmentNumber != Segment) {
|
||||||
|
// Mismatch
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ((DmarDrhd->Header.Length == sizeof(EFI_ACPI_DMAR_DRHD_HEADER)) ||
|
||||||
|
((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != 0)) {
|
||||||
|
// No DevScopeEntry
|
||||||
|
// Do not handle PCI_ALL
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarDrhd + 1));
|
||||||
|
while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header.Length) {
|
||||||
|
if ((ThisDevScopeEntry->Length == DevScopeEntry->Length) &&
|
||||||
|
(CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->Length) == 0)) {
|
||||||
|
return VtdIndex;
|
||||||
|
}
|
||||||
|
ThisDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
||||||
|
}
|
||||||
|
return (UINTN)-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Process DMAR RMRR table.
|
||||||
|
|
||||||
|
@param[in] VTdInfo The VTd engine context information.
|
||||||
|
@param[in] DmarRmrr The RMRR table.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ProcessRmrr (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN EFI_ACPI_DMAR_RMRR_HEADER *DmarRmrr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDevScopeEntry;
|
||||||
|
UINTN VTdIndex;
|
||||||
|
UINT64 RmrrMask;
|
||||||
|
UINTN LowBottom;
|
||||||
|
UINTN LowTop;
|
||||||
|
UINTN HighBottom;
|
||||||
|
UINT64 HighTop;
|
||||||
|
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
|
||||||
|
|
||||||
|
AcpiDmarTable = VTdInfo->AcpiDmarTable;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
|
||||||
|
|
||||||
|
if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
|
||||||
|
(DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)(DmarRmrr + 1));
|
||||||
|
while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Length) {
|
||||||
|
ASSERT (DmarDevScopeEntry->Type == EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_PCI_ENDPOINT);
|
||||||
|
|
||||||
|
VTdIndex = GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->SegmentNumber, DmarDevScopeEntry);
|
||||||
|
if (VTdIndex != (UINTN)-1) {
|
||||||
|
RmrrMask = LShiftU64 (1, VTdIndex);
|
||||||
|
|
||||||
|
LowBottom = 0;
|
||||||
|
LowTop = (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress;
|
||||||
|
HighBottom = (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1;
|
||||||
|
HighTop = GetTopMemory ();
|
||||||
|
|
||||||
|
SetDmaProtectedRange (
|
||||||
|
VTdInfo,
|
||||||
|
RmrrMask,
|
||||||
|
0,
|
||||||
|
(UINT32)(LowTop - LowBottom),
|
||||||
|
HighBottom,
|
||||||
|
HighTop - HighBottom
|
||||||
|
);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Remove the engine from the engine mask.
|
||||||
|
// The assumption is that any other PEI driver does not access
|
||||||
|
// the device covered by this engine.
|
||||||
|
//
|
||||||
|
VTdInfo->EngineMask = VTdInfo->EngineMask & (~RmrrMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse DMAR DRHD table.
|
||||||
|
|
||||||
|
@param[in] VTdInfo The VTd engine context information.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ParseDmarAcpiTableRmrr (
|
||||||
|
IN VTD_INFO *VTdInfo
|
||||||
|
)
|
||||||
|
{
|
||||||
|
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
|
||||||
|
EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
|
||||||
|
|
||||||
|
AcpiDmarTable = VTdInfo->AcpiDmarTable;
|
||||||
|
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(AcpiDmarTable + 1));
|
||||||
|
while ((UINTN)DmarHeader < (UINTN)AcpiDmarTable + AcpiDmarTable->Header.Length) {
|
||||||
|
switch (DmarHeader->Type) {
|
||||||
|
case EFI_ACPI_DMAR_TYPE_RMRR:
|
||||||
|
ProcessRmrr (VTdInfo, (EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,17 +22,17 @@
|
||||||
|
|
||||||
#include "IntelVTdPmrPei.h"
|
#include "IntelVTdPmrPei.h"
|
||||||
|
|
||||||
extern VTD_INFO *mVTdInfo;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get protected low memory alignment.
|
Get protected low memory alignment.
|
||||||
|
|
||||||
|
@param HostAddressWidth The host address width.
|
||||||
@param VtdUnitBaseAddress The base address of the VTd engine.
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
|
||||||
@return protected low memory alignment.
|
@return protected low memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT32
|
UINT32
|
||||||
GetPlmrAlignment (
|
GetPlmrAlignment (
|
||||||
|
IN UINT8 HostAddressWidth,
|
||||||
IN UINTN VtdUnitBaseAddress
|
IN UINTN VtdUnitBaseAddress
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -48,19 +48,18 @@ GetPlmrAlignment (
|
||||||
/**
|
/**
|
||||||
Get protected high memory alignment.
|
Get protected high memory alignment.
|
||||||
|
|
||||||
|
@param HostAddressWidth The host address width.
|
||||||
@param VtdUnitBaseAddress The base address of the VTd engine.
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
|
||||||
@return protected high memory alignment.
|
@return protected high memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT64
|
UINT64
|
||||||
GetPhmrAlignment (
|
GetPhmrAlignment (
|
||||||
|
IN UINT8 HostAddressWidth,
|
||||||
IN UINTN VtdUnitBaseAddress
|
IN UINTN VtdUnitBaseAddress
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINT64 Data64;
|
UINT64 Data64;
|
||||||
UINT8 HostAddressWidth;
|
|
||||||
|
|
||||||
HostAddressWidth = mVTdInfo->HostAddressWidth;
|
|
||||||
|
|
||||||
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
|
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFFFF);
|
||||||
Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
|
Data64 = MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG);
|
||||||
|
@ -73,12 +72,14 @@ GetPhmrAlignment (
|
||||||
/**
|
/**
|
||||||
Get protected low memory alignment.
|
Get protected low memory alignment.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
@return protected low memory alignment.
|
@return protected low memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT32
|
UINT32
|
||||||
GetLowMemoryAlignment (
|
GetLowMemoryAlignment (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -87,11 +88,11 @@ GetLowMemoryAlignment (
|
||||||
UINT32 FinalAlignment;
|
UINT32 FinalAlignment;
|
||||||
|
|
||||||
FinalAlignment = 0;
|
FinalAlignment = 0;
|
||||||
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
|
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
|
||||||
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Alignment = GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
|
Alignment = GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
if (FinalAlignment < Alignment) {
|
if (FinalAlignment < Alignment) {
|
||||||
FinalAlignment = Alignment;
|
FinalAlignment = Alignment;
|
||||||
}
|
}
|
||||||
|
@ -102,12 +103,14 @@ GetLowMemoryAlignment (
|
||||||
/**
|
/**
|
||||||
Get protected high memory alignment.
|
Get protected high memory alignment.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
@return protected high memory alignment.
|
@return protected high memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT64
|
UINT64
|
||||||
GetHighMemoryAlignment (
|
GetHighMemoryAlignment (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -116,11 +119,11 @@ GetHighMemoryAlignment (
|
||||||
UINT64 FinalAlignment;
|
UINT64 FinalAlignment;
|
||||||
|
|
||||||
FinalAlignment = 0;
|
FinalAlignment = 0;
|
||||||
for (Index = 0; Index < mVTdInfo->VTdEngineCount; Index++) {
|
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
|
||||||
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Alignment = GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
|
Alignment = GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
if (FinalAlignment < Alignment) {
|
if (FinalAlignment < Alignment) {
|
||||||
FinalAlignment = Alignment;
|
FinalAlignment = Alignment;
|
||||||
}
|
}
|
||||||
|
@ -144,12 +147,19 @@ EnablePmr (
|
||||||
UINT32 Reg32;
|
UINT32 Reg32;
|
||||||
VTD_CAP_REG CapReg;
|
VTD_CAP_REG CapReg;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress));
|
||||||
|
|
||||||
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
|
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
|
||||||
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
|
if (CapReg.Bits.PLMR == 0 || CapReg.Bits.PHMR == 0) {
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
|
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) {
|
if ((Reg32 & BIT0) == 0) {
|
||||||
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
|
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31);
|
||||||
do {
|
do {
|
||||||
|
@ -157,6 +167,8 @@ EnablePmr (
|
||||||
} while((Reg32 & BIT0) == 0);
|
} while((Reg32 & BIT0) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "EnablePmr - Done\n"));
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +194,11 @@ DisablePmr (
|
||||||
}
|
}
|
||||||
|
|
||||||
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG);
|
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) {
|
if ((Reg32 & BIT0) != 0) {
|
||||||
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
|
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0);
|
||||||
do {
|
do {
|
||||||
|
@ -195,6 +212,7 @@ DisablePmr (
|
||||||
/**
|
/**
|
||||||
Set PMR region in the VTd engine.
|
Set PMR region in the VTd engine.
|
||||||
|
|
||||||
|
@param HostAddressWidth The host address width.
|
||||||
@param VtdUnitBaseAddress The base address of the VTd engine.
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
@param LowMemoryBase The protected low memory region base.
|
@param LowMemoryBase The protected low memory region base.
|
||||||
@param LowMemoryLength The protected low memory region length.
|
@param LowMemoryLength The protected low memory region length.
|
||||||
|
@ -206,6 +224,7 @@ DisablePmr (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SetPmrRegion (
|
SetPmrRegion (
|
||||||
|
IN UINT8 HostAddressWidth,
|
||||||
IN UINTN VtdUnitBaseAddress,
|
IN UINTN VtdUnitBaseAddress,
|
||||||
IN UINT32 LowMemoryBase,
|
IN UINT32 LowMemoryBase,
|
||||||
IN UINT32 LowMemoryLength,
|
IN UINT32 LowMemoryLength,
|
||||||
|
@ -225,9 +244,9 @@ SetPmrRegion (
|
||||||
return EFI_UNSUPPORTED;
|
return EFI_UNSUPPORTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlmrAlignment = GetPlmrAlignment (VtdUnitBaseAddress);
|
PlmrAlignment = GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
|
||||||
DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
|
DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment));
|
||||||
PhmrAlignment = GetPhmrAlignment (VtdUnitBaseAddress);
|
PhmrAlignment = GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress);
|
||||||
DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
|
DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment));
|
||||||
|
|
||||||
if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
|
if ((LowMemoryBase != ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) ||
|
||||||
|
@ -247,8 +266,10 @@ SetPmrRegion (
|
||||||
|
|
||||||
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);
|
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_BASE_REG, LowMemoryBase);
|
||||||
MmioWrite32 (VtdUnitBaseAddress + R_PMEN_LOW_LIMITE_REG, LowMemoryBase + LowMemoryLength - 1);
|
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_BASE_REG, HighMemoryBase);
|
||||||
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
|
MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_LIMITE_REG, HighMemoryBase + HighMemoryLength - 1);
|
||||||
|
DEBUG ((DEBUG_INFO, "PHMR set done\n"));
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
return EFI_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -256,6 +277,7 @@ SetPmrRegion (
|
||||||
/**
|
/**
|
||||||
Set DMA protected region.
|
Set DMA protected region.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
@param LowMemoryBase The protected low memory region base.
|
@param LowMemoryBase The protected low memory region base.
|
||||||
@param LowMemoryLength The protected low memory region length.
|
@param LowMemoryLength The protected low memory region length.
|
||||||
|
@ -267,6 +289,7 @@ SetPmrRegion (
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SetDmaProtectedRange (
|
SetDmaProtectedRange (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask,
|
IN UINT64 EngineMask,
|
||||||
IN UINT32 LowMemoryBase,
|
IN UINT32 LowMemoryBase,
|
||||||
IN UINT32 LowMemoryLength,
|
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));
|
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) {
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
|
DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
Status = SetPmrRegion (
|
Status = SetPmrRegion (
|
||||||
(UINTN)mVTdInfo->VTdEngineAddress[Index],
|
VTdInfo->HostAddressWidth,
|
||||||
|
(UINTN)VTdInfo->VTdEngineAddress[Index],
|
||||||
LowMemoryBase,
|
LowMemoryBase,
|
||||||
LowMemoryLength,
|
LowMemoryLength,
|
||||||
HighMemoryBase,
|
HighMemoryBase,
|
||||||
|
@ -294,7 +318,7 @@ SetDmaProtectedRange (
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
Status = EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
|
Status = EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -306,25 +330,29 @@ SetDmaProtectedRange (
|
||||||
/**
|
/**
|
||||||
Diable DMA protection.
|
Diable DMA protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@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
|
EFI_STATUS
|
||||||
DisableDmaProtection (
|
DisableDmaProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
UINTN Index;
|
UINTN Index;
|
||||||
EFI_STATUS Status;
|
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) {
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Status = DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]);
|
Status = DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
if (EFI_ERROR(Status)) {
|
if (EFI_ERROR(Status)) {
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
@ -332,3 +360,67 @@ DisableDmaProtection (
|
||||||
|
|
||||||
return EFI_SUCCESS;
|
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;
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,8 @@
|
||||||
#define __DMA_ACCESS_LIB_H__
|
#define __DMA_ACCESS_LIB_H__
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
|
||||||
|
UINT64 EngineMask;
|
||||||
UINT8 HostAddressWidth;
|
UINT8 HostAddressWidth;
|
||||||
UINTN VTdEngineCount;
|
UINTN VTdEngineCount;
|
||||||
UINT64 VTdEngineAddress[1];
|
UINT64 VTdEngineAddress[1];
|
||||||
|
@ -24,6 +26,7 @@ typedef struct {
|
||||||
/**
|
/**
|
||||||
Set DMA protected region.
|
Set DMA protected region.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
@param LowMemoryBase The protected low memory region base.
|
@param LowMemoryBase The protected low memory region base.
|
||||||
@param LowMemoryLength The protected low memory region length.
|
@param LowMemoryLength The protected low memory region length.
|
||||||
|
@ -35,6 +38,7 @@ typedef struct {
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
SetDmaProtectedRange (
|
SetDmaProtectedRange (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask,
|
IN UINT64 EngineMask,
|
||||||
IN UINT32 LowMemoryBase,
|
IN UINT32 LowMemoryBase,
|
||||||
IN UINT32 LowMemoryLength,
|
IN UINT32 LowMemoryLength,
|
||||||
|
@ -45,38 +49,127 @@ SetDmaProtectedRange (
|
||||||
/**
|
/**
|
||||||
Diable DMA protection.
|
Diable DMA protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
@retval DMA protection is disabled.
|
@retval DMA protection is disabled.
|
||||||
**/
|
**/
|
||||||
EFI_STATUS
|
EFI_STATUS
|
||||||
DisableDmaProtection (
|
DisableDmaProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINT64 EngineMask
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Return if the DMA protection is enabled.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
|
@retval TRUE DMA protection is enabled in at least one VTd engine.
|
||||||
|
@retval FALSE DMA protection is disabled in all VTd engines.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
GetDmaProtectionEnabledEngineMask (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get protected low memory alignment.
|
Get protected low memory alignment.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
@return protected low memory alignment.
|
@return protected low memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT32
|
UINT32
|
||||||
GetLowMemoryAlignment (
|
GetLowMemoryAlignment (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Get protected high memory alignment.
|
Get protected high memory alignment.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
@param EngineMask The mask of the VTd engine to be accessed.
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
|
||||||
@return protected high memory alignment.
|
@return protected high memory alignment.
|
||||||
**/
|
**/
|
||||||
UINT64
|
UINT64
|
||||||
GetHighMemoryAlignment (
|
GetHighMemoryAlignment (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
IN UINT64 EngineMask
|
IN UINT64 EngineMask
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable VTd translation table protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EnableVTdTranslationProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINT64 EngineMask
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable VTd translation table protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DisableVTdTranslationProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINT64 EngineMask
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse DMAR DRHD table.
|
||||||
|
|
||||||
|
@param[in] AcpiDmarTable DMAR ACPI table
|
||||||
|
|
||||||
|
@return EFI_SUCCESS The DMAR DRHD table is parsed.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
ParseDmarAcpiTableDrhd (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *AcpiDmarTable
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Parse DMAR DRHD table.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ParseDmarAcpiTableRmrr (
|
||||||
|
IN VTD_INFO *VTdInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Dump DMAR ACPI table.
|
||||||
|
|
||||||
|
@param[in] Dmar DMAR ACPI table
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DumpAcpiDMAR (
|
||||||
|
IN EFI_ACPI_DMAR_HEADER *Dmar
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the highest memory.
|
||||||
|
|
||||||
|
@return the highest memory.
|
||||||
|
**/
|
||||||
|
UINT64
|
||||||
|
GetTopMemory (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
extern EFI_GUID mVTdInfoGuid;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -33,6 +33,8 @@
|
||||||
IntelVTdPmrPei.c
|
IntelVTdPmrPei.c
|
||||||
IntelVTdPmrPei.h
|
IntelVTdPmrPei.h
|
||||||
IntelVTdPmr.c
|
IntelVTdPmr.c
|
||||||
|
DmarTable.c
|
||||||
|
VtdReg.c
|
||||||
|
|
||||||
[LibraryClasses]
|
[LibraryClasses]
|
||||||
DebugLib
|
DebugLib
|
||||||
|
@ -42,17 +44,18 @@
|
||||||
PeiServicesLib
|
PeiServicesLib
|
||||||
HobLib
|
HobLib
|
||||||
IoLib
|
IoLib
|
||||||
|
CacheMaintenanceLib
|
||||||
|
|
||||||
[Ppis]
|
[Ppis]
|
||||||
gEdkiiIoMmuPpiGuid ## PRODUCES
|
gEdkiiIoMmuPpiGuid ## PRODUCES
|
||||||
gEdkiiVTdInfoPpiGuid ## CONSUMES
|
gEdkiiVTdInfoPpiGuid ## CONSUMES
|
||||||
|
gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES
|
||||||
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
|
gEfiEndOfPeiSignalPpiGuid ## CONSUMES
|
||||||
|
|
||||||
[Pcd]
|
[Pcd]
|
||||||
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
|
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
|
||||||
|
|
||||||
[Depex]
|
[Depex]
|
||||||
gEfiPeiMemoryDiscoveredPpiGuid AND
|
|
||||||
gEfiPeiMasterBootModePpiGuid AND
|
gEfiPeiMasterBootModePpiGuid AND
|
||||||
gEdkiiVTdInfoPpiGuid
|
gEdkiiVTdInfoPpiGuid
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,293 @@
|
||||||
|
/** @file
|
||||||
|
|
||||||
|
Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
|
||||||
|
|
||||||
|
This program and the accompanying materials are licensed and made available under
|
||||||
|
the terms and conditions of the BSD License which accompanies this distribution.
|
||||||
|
The full text of the license may be found at
|
||||||
|
http://opensource.org/licenses/bsd-license.php
|
||||||
|
|
||||||
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#include <PiPei.h>
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/BaseMemoryLib.h>
|
||||||
|
#include <Library/IoLib.h>
|
||||||
|
#include <Library/DebugLib.h>
|
||||||
|
#include <Library/MemoryAllocationLib.h>
|
||||||
|
#include <Library/CacheMaintenanceLib.h>
|
||||||
|
#include <IndustryStandard/Vtd.h>
|
||||||
|
#include <Ppi/VtdInfo.h>
|
||||||
|
|
||||||
|
#include "IntelVTdPmrPei.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush VTD page table and context table memory.
|
||||||
|
|
||||||
|
This action is to make sure the IOMMU engine can get final data in memory.
|
||||||
|
|
||||||
|
@param[in] Base The base address of memory to be flushed.
|
||||||
|
@param[in] Size The size of memory in bytes to be flushed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FlushPageTableMemory (
|
||||||
|
IN UINTN Base,
|
||||||
|
IN UINTN Size
|
||||||
|
)
|
||||||
|
{
|
||||||
|
WriteBackDataCacheRange ((VOID *)Base, Size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Flush VTd engine write buffer.
|
||||||
|
|
||||||
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
FlushWriteBuffer (
|
||||||
|
IN UINTN VtdUnitBaseAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Reg32;
|
||||||
|
VTD_CAP_REG CapReg;
|
||||||
|
|
||||||
|
CapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_CAP_REG);
|
||||||
|
|
||||||
|
if (CapReg.Bits.RWBF != 0) {
|
||||||
|
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
|
||||||
|
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF);
|
||||||
|
do {
|
||||||
|
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
|
||||||
|
} while ((Reg32 & B_GSTS_REG_WBF) != 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Invalidate VTd context cache.
|
||||||
|
|
||||||
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InvalidateContextCache (
|
||||||
|
IN UINTN VtdUnitBaseAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 Reg64;
|
||||||
|
|
||||||
|
Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
|
||||||
|
if ((Reg64 & B_CCMD_REG_ICC) != 0) {
|
||||||
|
DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is set for VTD(%x)\n",VtdUnitBaseAddress));
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reg64 &= ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK));
|
||||||
|
Reg64 |= (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL);
|
||||||
|
MmioWrite64 (VtdUnitBaseAddress + R_CCMD_REG, Reg64);
|
||||||
|
|
||||||
|
do {
|
||||||
|
Reg64 = MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG);
|
||||||
|
} while ((Reg64 & B_CCMD_REG_ICC) != 0);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Invalidate VTd IOTLB.
|
||||||
|
|
||||||
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
InvalidateIOTLB (
|
||||||
|
IN UINTN VtdUnitBaseAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT64 Reg64;
|
||||||
|
VTD_ECAP_REG ECapReg;
|
||||||
|
|
||||||
|
ECapReg.Uint64 = MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG);
|
||||||
|
|
||||||
|
Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
|
||||||
|
if ((Reg64 & B_IOTLB_REG_IVT) != 0) {
|
||||||
|
DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set for VTD(%x)\n", VtdUnitBaseAddress));
|
||||||
|
return EFI_DEVICE_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
Reg64 &= ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK));
|
||||||
|
Reg64 |= (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL);
|
||||||
|
MmioWrite64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG, Reg64);
|
||||||
|
|
||||||
|
do {
|
||||||
|
Reg64 = MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG);
|
||||||
|
} while ((Reg64 & B_IOTLB_REG_IVT) != 0);
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable DMAR translation.
|
||||||
|
|
||||||
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
@param RootEntryTable The address of the VTd RootEntryTable.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS DMAR translation is enabled.
|
||||||
|
@retval EFI_DEVICE_ERROR DMAR translation is not enabled.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
EnableDmar (
|
||||||
|
IN UINTN VtdUnitBaseAddress,
|
||||||
|
IN UINTN RootEntryTable
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Reg32;
|
||||||
|
|
||||||
|
DEBUG((DEBUG_INFO, ">>>>>>EnableDmar() for engine [%x] \n", VtdUnitBaseAddress));
|
||||||
|
|
||||||
|
DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable));
|
||||||
|
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)RootEntryTable);
|
||||||
|
|
||||||
|
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Init DMAr Fault Event and Data registers
|
||||||
|
//
|
||||||
|
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_FEDATA_REG);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write Buffer Flush before invalidation
|
||||||
|
//
|
||||||
|
FlushWriteBuffer (VtdUnitBaseAddress);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Invalidate the context cache
|
||||||
|
//
|
||||||
|
InvalidateContextCache (VtdUnitBaseAddress);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Invalidate the IOTLB cache
|
||||||
|
//
|
||||||
|
InvalidateIOTLB (VtdUnitBaseAddress);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Enable VTd
|
||||||
|
//
|
||||||
|
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, 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);
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,"VTD () enabled!<<<<<<\n"));
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable DMAR translation.
|
||||||
|
|
||||||
|
@param VtdUnitBaseAddress The base address of the VTd engine.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS DMAR translation is disabled.
|
||||||
|
@retval EFI_DEVICE_ERROR DMAR translation is not disabled.
|
||||||
|
**/
|
||||||
|
EFI_STATUS
|
||||||
|
DisableDmar (
|
||||||
|
IN UINTN VtdUnitBaseAddress
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINT32 Reg32;
|
||||||
|
|
||||||
|
DEBUG((DEBUG_INFO, ">>>>>>DisableDmar() for engine [%x] \n", VtdUnitBaseAddress));
|
||||||
|
|
||||||
|
//
|
||||||
|
// Write Buffer Flush before invalidation
|
||||||
|
//
|
||||||
|
FlushWriteBuffer (VtdUnitBaseAddress);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Disable VTd
|
||||||
|
//
|
||||||
|
MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP);
|
||||||
|
do {
|
||||||
|
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
|
||||||
|
} while((Reg32 & B_GSTS_REG_RTPS) == 0);
|
||||||
|
|
||||||
|
Reg32 = MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG);
|
||||||
|
DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32));
|
||||||
|
|
||||||
|
MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0);
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n"));
|
||||||
|
|
||||||
|
return EFI_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Enable VTd translation table protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
EnableVTdTranslationProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINT64 EngineMask
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
VOID *RootEntryTable;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtection - 0x%lx\n", EngineMask));
|
||||||
|
|
||||||
|
RootEntryTable = AllocatePages (1);
|
||||||
|
ASSERT (RootEntryTable != NULL);
|
||||||
|
if (RootEntryTable == NULL) {
|
||||||
|
DEBUG ((DEBUG_INFO, " EnableVTdTranslationProtection : OutOfResource\n"));
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
ZeroMem (RootEntryTable, EFI_PAGES_TO_SIZE(1));
|
||||||
|
FlushPageTableMemory ((UINTN)RootEntryTable, EFI_PAGES_TO_SIZE(1));
|
||||||
|
|
||||||
|
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
|
||||||
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
EnableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index], (UINTN)RootEntryTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Disable VTd translation table protection.
|
||||||
|
|
||||||
|
@param VTdInfo The VTd engine context information.
|
||||||
|
@param EngineMask The mask of the VTd engine to be accessed.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
DisableVTdTranslationProtection (
|
||||||
|
IN VTD_INFO *VTdInfo,
|
||||||
|
IN UINT64 EngineMask
|
||||||
|
)
|
||||||
|
{
|
||||||
|
UINTN Index;
|
||||||
|
|
||||||
|
DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineMask));
|
||||||
|
|
||||||
|
for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
|
||||||
|
if ((EngineMask & LShiftU64(1, Index)) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ;
|
||||||
|
}
|
Loading…
Reference in New Issue