* [PATCH 0/2] Add Pre-Memory DMA protection in PEI
@ 2017-10-24 13:30 Jiewen Yao
2017-10-24 13:30 ` [PATCH 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
2017-10-24 13:30 ` [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
0 siblings, 2 replies; 4+ messages in thread
From: Jiewen Yao @ 2017-10-24 13:30 UTC (permalink / raw)
To: edk2-devel
This series patch adds Pre-Memory DMA protection in PEI.
The purpose is to make sure when the system memory is initialized, the DMA
protection takes effect immediately.
The IntelVTdPmrPei driver is updated to remove the global variable and
add VTD_INFO_PPI notification.
The VTdInfoSample driver is updated to install the initial
VTD_INFO_PPI before memory init, and add more content after memory init
by reinstalling VTD_INFO_PPI.
This patch is validated on one Intel Client kabylake platform.
Jiewen Yao (2):
IntelSiliconPkg/VtdPmrPei: Add premem support.
IntelSiliconPkg/VtdPeiSample: Add premem support.
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c | 580 ++++++++++++++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c | 130 ++-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 846 +++++++-------------
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h | 93 +++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf | 11 +-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c | 293 +++++++
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c | 234 +++++-
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf | 2 +-
8 files changed, 1558 insertions(+), 631 deletions(-)
create mode 100644 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
create mode 100644 IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
--
2.7.4.windows.1
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support.
2017-10-24 13:30 [PATCH 0/2] Add Pre-Memory DMA protection in PEI Jiewen Yao
@ 2017-10-24 13:30 ` Jiewen Yao
2017-10-24 13:30 ` [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
1 sibling, 0 replies; 4+ messages in thread
From: Jiewen Yao @ 2017-10-24 13:30 UTC (permalink / raw)
To: edk2-devel; +Cc: Zeng Star
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: Zeng Star <zeng.star@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c | 580 ++++++++++++++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c | 130 ++-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 846 +++++++-------------
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h | 93 +++
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf | 11 +-
IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c | 293 +++++++
6 files changed, 1356 insertions(+), 597 deletions(-)
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
new file mode 100644
index 0000000..891efa6
--- /dev/null
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/DmarTable.c
@@ -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);
+ }
+}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
index 6179dfe..08d8a1d 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c
@@ -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%x\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 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.
+**/
+BOOLEAN
+IsDmaProtectionEnabled (
+ IN VTD_INFO *VTdInfo,
+ IN UINT64 EngineMask
+ )
+{
+ UINTN Index;
+ BOOLEAN Result;
+
+ DEBUG ((DEBUG_INFO, "IsDmaProtectionEnabled ..."));
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ if ((EngineMask & LShiftU64(1, Index)) == 0) {
+ continue;
+ }
+ Result = IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]);
+ if (Result) {
+ DEBUG ((DEBUG_INFO, "TRUE\n"));
+ return TRUE;
+ }
+ }
+
+ DEBUG ((DEBUG_INFO, "FALSE\n"));
+ return FALSE;
+}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
index 3fe6d65..e067dc0 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c
@@ -24,6 +24,7 @@
#include <IndustryStandard/Vtd.h>
#include <Ppi/IoMmu.h>
#include <Ppi/VtdInfo.h>
+#include <Ppi/MemoryDiscovered.h>
#include <Ppi/EndOfPeiPhase.h>
#include "IntelVTdPmrPei.h"
@@ -31,13 +32,20 @@
#define TOTAL_DMA_BUFFER_SIZE SIZE_4MB
#define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB
-EFI_ACPI_DMAR_HEADER *mAcpiDmarTable;
-VTD_INFO *mVTdInfo;
-UINT64 mEngineMask;
-UINTN mDmaBufferBase;
-UINTN mDmaBufferSize;
-UINTN mDmaBufferCurrentTop;
-UINTN mDmaBufferCurrentBottom;
+EFI_GUID mVTdInfoGuid = {
+ 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x82 }
+};
+
+EFI_GUID mDmaBufferInfoGuid = {
+ 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, 0x39 }
+};
+
+typedef struct {
+ UINTN DmaBufferBase;
+ UINTN DmaBufferSize;
+ UINTN DmaBufferCurrentTop;
+ UINTN DmaBufferCurrentBottom;
+} DMA_BUFFER_INFO;
#define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P')
typedef struct {
@@ -83,7 +91,6 @@ typedef struct {
+------------------+ <=============== PLMR.Base (0)
**/
-
/**
Set IOMMU attribute for a system memory.
@@ -149,8 +156,13 @@ PeiIoMmuMap (
OUT VOID **Mapping
)
{
- MAP_INFO *MapInfo;
- UINTN Length;
+ MAP_INFO *MapInfo;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
@@ -160,18 +172,18 @@ PeiIoMmuMap (
}
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes - %x\n", HostAddress, *NumberOfBytes));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = *NumberOfBytes + sizeof(MAP_INFO);
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
- *DeviceAddress = mDmaBufferCurrentBottom;
- mDmaBufferCurrentBottom += Length;
+ *DeviceAddress = DmaBufferInfo->DmaBufferCurrentBottom;
+ DmaBufferInfo->DmaBufferCurrentBottom += Length;
MapInfo = (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes);
MapInfo->Signature = MAP_INFO_SIGNATURE;
@@ -216,16 +228,21 @@ PeiIoMmuUnmap (
IN VOID *Mapping
)
{
- MAP_INFO *MapInfo;
- UINTN Length;
+ MAP_INFO *MapInfo;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
if (Mapping == NULL) {
return EFI_SUCCESS;
}
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
MapInfo = Mapping;
ASSERT (MapInfo->Signature == MAP_INFO_SIGNATURE);
@@ -246,8 +263,8 @@ PeiIoMmuUnmap (
}
Length = MapInfo->NumberOfBytes + sizeof(MAP_INFO);
- if (mDmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
- mDmaBufferCurrentBottom -= Length;
+ if (DmaBufferInfo->DmaBufferCurrentBottom == MapInfo->DeviceAddress + Length) {
+ DmaBufferInfo->DmaBufferCurrentBottom -= Length;
}
return EFI_SUCCESS;
@@ -282,20 +299,25 @@ PeiIoMmuAllocateBuffer (
IN UINT64 Attributes
)
{
- UINTN Length;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = EFI_PAGES_TO_SIZE(Pages);
- if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) {
+ if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBufferCurrentBottom) {
DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n"));
ASSERT (FALSE);
return EFI_OUT_OF_RESOURCES;
}
- *HostAddress = (VOID *)(UINTN)(mDmaBufferCurrentTop - Length);
- mDmaBufferCurrentTop -= Length;
+ *HostAddress = (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Length);
+ DmaBufferInfo->DmaBufferCurrentTop -= Length;
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *HostAddress));
return EFI_SUCCESS;
@@ -321,15 +343,20 @@ PeiIoMmuFreeBuffer (
IN VOID *HostAddress
)
{
- UINTN Length;
+ UINTN Length;
+ VOID *Hob;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n", Pages, HostAddress));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurrentTop));
- DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCurrentBottom));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->DmaBufferCurrentTop));
+ DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo->DmaBufferCurrentBottom));
Length = EFI_PAGES_TO_SIZE(Pages);
- if ((UINTN)HostAddress == mDmaBufferCurrentTop) {
- mDmaBufferCurrentTop += Length;
+ if ((UINTN)HostAddress == DmaBufferInfo->DmaBufferCurrentTop) {
+ DmaBufferInfo->DmaBufferCurrentTop += Length;
}
return EFI_SUCCESS;
@@ -506,6 +533,7 @@ GetTopMemory (
/**
Initialize DMA protection.
+ @param VTdInfo The VTd engine context information.
@param DmaBufferSize the DMA buffer size
@param DmaBufferBase the DMA buffer base
@@ -514,8 +542,9 @@ GetTopMemory (
**/
EFI_STATUS
InitDmaProtection (
- IN UINTN DmaBufferSize,
- OUT UINTN *DmaBufferBase
+ IN VTD_INFO *VTdInfo,
+ IN UINTN DmaBufferSize,
+ OUT UINTN *DmaBufferBase
)
{
EFI_STATUS Status;
@@ -537,8 +566,8 @@ InitDmaProtection (
ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop);
- LowMemoryAlignment = GetLowMemoryAlignment (mEngineMask);
- HighMemoryAlignment = GetHighMemoryAlignment (mEngineMask);
+ LowMemoryAlignment = GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
+ HighMemoryAlignment = GetHighMemoryAlignment (VTdInfo, VTdInfo->EngineMask);
if (LowMemoryAlignment < HighMemoryAlignment) {
MemoryAlignment = (UINTN)HighMemoryAlignment;
} else {
@@ -558,12 +587,13 @@ InitDmaProtection (
HighTop = GetTopMemory ();
Status = SetDmaProtectedRange (
- mEngineMask,
- (UINT32)LowBottom,
- (UINT32)(LowTop - LowBottom),
- HighBottom,
- HighTop - HighBottom
- );
+ VTdInfo,
+ VTdInfo->EngineMask,
+ (UINT32)LowBottom,
+ (UINT32)(LowTop - LowBottom),
+ HighBottom,
+ HighTop - HighBottom
+ );
if (EFI_ERROR(Status)) {
FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize));
@@ -573,542 +603,188 @@ InitDmaProtection (
}
/**
- Dump DMAR DeviceScopeEntry.
+ Initializes the Intel VTd Info.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry
**/
-VOID
-DumpDmarDeviceScopeEntry (
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry
+EFI_STATUS
+InitVTdInfo (
+ VOID
)
{
- 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;
-}
+ EFI_STATUS Status;
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ VOID *Hob;
-/**
- Dump DMAR RMRR table.
+ Status = PeiServicesLocatePpi (
+ &gEdkiiVTdInfoPpiGuid,
+ 0,
+ NULL,
+ (VOID **)&AcpiDmarTable
+ );
+ ASSERT_EFI_ERROR(Status);
- @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;
+ DumpAcpiDMAR (AcpiDmarTable);
- if (Rmrr == NULL) {
- return;
+ //
+ // Clear old VTdInfo Hob.
+ //
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ if (Hob != NULL) {
+ ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID));
}
- 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);
+ //
+ // Get DMAR information to local VTdInfo
+ //
+ Status = ParseDmarAcpiTableDrhd (AcpiDmarTable);
+ if (EFI_ERROR(Status)) {
+ return Status;
}
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
+ //
+ // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming.
+ //
- return;
+ return EFI_SUCCESS;
}
/**
- Dump DMAR DRHD table.
+ Initializes the Intel VTd PMR for all memory.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] Drhd DMAR DRHD table
**/
-VOID
-DumpDmarDrhd (
- IN EFI_ACPI_DMAR_DRHD_HEADER *Drhd
+EFI_STATUS
+InitVTdPmrForAll (
+ VOID
)
{
- EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DmarDeviceScopeEntry;
- INTN DrhdLen;
+ EFI_STATUS Status;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ UINTN LowBottom;
+ UINTN LowTop;
+ UINTN HighBottom;
+ UINT64 HighTop;
- if (Drhd == NULL) {
- return;
- }
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
- 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);
- }
+ LowBottom = 0;
+ LowTop = 0;
+ HighBottom = 0;
+ HighTop = LShiftU64 (1, VTdInfo->HostAddressWidth);
- DEBUG ((DEBUG_INFO,
- " ***************************************************************************\n\n"
- ));
+ Status = SetDmaProtectedRange (
+ VTdInfo,
+ VTdInfo->EngineMask,
+ (UINT32)LowBottom,
+ (UINT32)(LowTop - LowBottom),
+ HighBottom,
+ HighTop - HighBottom
+ );
- return;
+ return Status;
}
/**
- Dump DMAR ACPI table.
+ Initializes the Intel VTd PMR for DMA buffer.
+
+ @retval EFI_SUCCESS Usb bot driver is successfully initialized.
+ @retval EFI_OUT_OF_RESOURCES Can't initialize the driver.
- @param[in] Dmar DMAR ACPI table
**/
-VOID
-DumpAcpiDMAR (
- IN EFI_ACPI_DMAR_HEADER *Dmar
+EFI_STATUS
+InitVTdPmrForDma (
+ VOID
)
{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- INTN DmarLen;
+ EFI_STATUS Status;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ DMA_BUFFER_INFO *DmaBufferInfo;
- if (Dmar == NULL) {
- return;
- }
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
//
- // Dump Dmar table
+ // If there is RMRR memory, parse it here.
//
- 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;
-}
+ ParseDmarAcpiTableRmrr (VTdInfo);
-/**
- Get VTd engine number.
+ Hob = GetFirstGuidHob (&mDmaBufferInfoGuid);
+ DmaBufferInfo = GET_GUID_HOB_DATA(Hob);
- @return the VTd engine number.
-**/
-UINTN
-GetVtdEngineNumber (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdIndex;
-
- VtdIndex = 0;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->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);
+ DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferSize));
+ //
+ // Find a pre-memory in resource hob as DMA buffer
+ // Mark PEI memory to be DMA protected.
+ //
+ Status = InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &DmaBufferInfo->DmaBufferBase);
+ if (EFI_ERROR(Status)) {
+ return Status;
}
- return VtdIndex ;
-}
-
-/**
- Process DMAR DHRD table.
-
- @param[in] VtdIndex The index of VTd engine.
- @param[in] DmarDrhd The DRHD table.
-**/
-VOID
-ProcessDhrd (
- IN UINTN VtdIndex,
- IN EFI_ACPI_DMAR_DRHD_HEADER *DmarDrhd
- )
-{
- DEBUG ((DEBUG_INFO," VTD (%d) BaseAddress - 0x%016lx\n", VtdIndex, DmarDrhd->RegisterBaseAddress));
- mVTdInfo->VTdEngineAddress[VtdIndex] = DmarDrhd->RegisterBaseAddress;
-}
-/**
- Parse DMAR DRHD table.
-
- @return EFI_SUCCESS The DMAR DRHD table is parsed.
-**/
-EFI_STATUS
-ParseDmarAcpiTableDrhd (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
- UINTN VtdUnitNumber;
- UINTN VtdIndex;
+ DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", DmaBufferInfo->DmaBufferBase));
- VtdUnitNumber = GetVtdEngineNumber ();
- if (VtdUnitNumber == 0) {
- return EFI_UNSUPPORTED;
- }
-
- mVTdInfo = AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * sizeof(UINT64));
- if (mVTdInfo == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- mVTdInfo->HostAddressWidth = mAcpiDmarTable->HostAddressWidth;
- mVTdInfo->VTdEngineCount = VtdUnitNumber;
-
- VtdIndex = 0;
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_DRHD:
- ASSERT (VtdIndex < VtdUnitNumber);
- ProcessDhrd (VtdIndex, (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader);
- VtdIndex++;
-
- break;
-
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
- ASSERT (VtdIndex == VtdUnitNumber);
+ DmaBufferInfo->DmaBufferCurrentTop = DmaBufferInfo->DmaBufferBase + DmaBufferInfo->DmaBufferSize;
+ DmaBufferInfo->DmaBufferCurrentBottom = DmaBufferInfo->DmaBufferBase;
//
- // Initialize the engine mask to all.
+ // Install PPI.
//
- mEngineMask = LShiftU64 (1, VtdUnitNumber) - 1;
+ Status = PeiServicesInstallPpi (&mIoMmuPpiList);
+ ASSERT_EFI_ERROR(Status);
- return EFI_SUCCESS;
+ return Status;
}
/**
- Return the VTd engine index according to the Segment and DevScopeEntry.
+ This function handles S3 resume task at the end of PEI
- @param Segment The segment of the VTd engine
- @param DevScopeEntry The DevScopeEntry of the VTd engine
+ @param[in] PeiServices Pointer to PEI Services Table.
+ @param[in] NotifyDesc Pointer to the descriptor for the Notification event that
+ caused this function to execute.
+ @param[in] Ppi Pointer to the PPI data associated with this function.
- @return The VTd engine index according to the Segment and DevScopeEntry.
- @retval -1 The VTd engine is not found.
+ @retval EFI_STATUS Always return EFI_SUCCESS
**/
-UINTN
-GetVTdEngineFromDevScopeEntry (
- IN UINT16 Segment,
- IN EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *DevScopeEntry
+EFI_STATUS
+EFIAPI
+S3EndOfPeiNotify(
+ IN EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
+ IN VOID *Ppi
)
{
- 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)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->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.
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ UINT64 EngineMask;
- @param[in] DmarRmrr The RMRR table.
-**/
-VOID
-ProcessRmrr (
- 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;
-
- DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr->ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddress));
-
- if ((DmarRmrr->ReservedMemoryRegionBaseAddress == 0) ||
- (DmarRmrr->ReservedMemoryRegionLimitAddress == 0)) {
- return ;
- }
+ DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
- 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 (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 (
- 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.
- //
- mEngineMask = mEngineMask & (~RmrrMask);
- }
+ if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
- DmarDevScopeEntry = (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length);
+ EngineMask = LShiftU64 (1, VTdInfo->VTdEngineCount) - 1;
+ DisableDmaProtection (VTdInfo, EngineMask);
}
+ return EFI_SUCCESS;
}
-/**
- Parse DMAR DRHD table.
-**/
-VOID
-ParseDmarAcpiTableRmrr (
- VOID
- )
-{
- EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader;
-
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable + 1));
- while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Header.Length) {
- switch (DmarHeader->Type) {
- case EFI_ACPI_DMAR_TYPE_RMRR:
- ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader);
- break;
- default:
- break;
- }
- DmarHeader = (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + DmarHeader->Length);
- }
-}
+EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEfiEndOfPeiSignalPpiGuid,
+ S3EndOfPeiNotify
+};
/**
- This function handles S3 resume task at the end of PEI
+ This function handles VTd engine setup
@param[in] PeiServices Pointer to PEI Services Table.
@param[in] NotifyDesc Pointer to the descriptor for the Notification event that
@@ -1119,27 +795,80 @@ ParseDmarAcpiTableRmrr (
**/
EFI_STATUS
EFIAPI
-S3EndOfPeiNotify(
+VTdInfoNotify (
IN EFI_PEI_SERVICES **PeiServices,
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
IN VOID *Ppi
)
{
- UINT64 EngineMask;
+ EFI_STATUS Status;
+ VOID *MemoryDiscovered;
+ BOOLEAN PmrEnabled;
+ VOID *Hob;
+ VTD_INFO *VTdInfo;
+ BOOLEAN MemoryInitialized;
- DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n"));
+ DEBUG ((DEBUG_INFO, "VTdInfoNotify\n"));
+
+ //
+ // Check if memory is initialized.
+ //
+ MemoryInitialized = FALSE;
+ Status = PeiServicesLocatePpi (
+ &gEfiPeiMemoryDiscoveredPpiGuid,
+ 0,
+ NULL,
+ &MemoryDiscovered
+ );
+ if (!EFI_ERROR(Status)) {
+ MemoryInitialized = TRUE;
+ }
+
+ DEBUG ((DEBUG_INFO, "MemoryInitialized - %x\n", MemoryInitialized));
+
+ if (!MemoryInitialized) {
+ //
+ // If the memory is not initialized,
+ // Protect all system memory
+ //
+ InitVTdInfo ();
+ InitVTdPmrForAll ();
+ } else {
+ //
+ // If the memory is initialized,
+ // Allocate DMA buffer and protect rest system memory
+ //
+
+ //
+ // NOTE: We need reinit VTdInfo because previous information might be overriden.
+ //
+ InitVTdInfo ();
+
+ Hob = GetFirstGuidHob (&mVTdInfoGuid);
+ VTdInfo = GET_GUID_HOB_DATA(Hob);
+
+ //
+ // NOTE: We need check if PMR is enabled or not.
+ //
+ PmrEnabled = IsDmaProtectionEnabled (VTdInfo, VTdInfo->EngineMask);
+ if (PmrEnabled) {
+ EnableVTdTranslationProtection (VTdInfo, VTdInfo->EngineMask);
+ DisableDmaProtection (VTdInfo, VTdInfo->EngineMask);
+ }
+ InitVTdPmrForDma ();
+ if (PmrEnabled) {
+ DisableVTdTranslationProtection (VTdInfo, VTdInfo->EngineMask);
+ }
- if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) == 0) {
- EngineMask = LShiftU64 (1, mVTdInfo->VTdEngineCount) - 1;
- DisableDmaProtection (EngineMask);
}
+
return EFI_SUCCESS;
}
-EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc = {
+EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc = {
(EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
- &gEfiEndOfPeiSignalPpiGuid,
- S3EndOfPeiNotify
+ &gEdkiiVTdInfoPpiGuid,
+ VTdInfoNotify
};
/**
@@ -1161,71 +890,40 @@ IntelVTdPmrInitialize (
{
EFI_STATUS Status;
EFI_BOOT_MODE BootMode;
+ DMA_BUFFER_INFO *DmaBufferInfo;
+
+ DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n"));
if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) == 0) {
return EFI_UNSUPPORTED;
}
- PeiServicesGetBootMode (&BootMode);
-
- Status = PeiServicesLocatePpi (
- &gEdkiiVTdInfoPpiGuid,
- 0,
- NULL,
- (VOID **)&mAcpiDmarTable
- );
- ASSERT_EFI_ERROR(Status);
-
- DumpAcpiDMAR (mAcpiDmarTable);
-
- //
- // Get DMAR information to local VTdInfo
- //
- Status = ParseDmarAcpiTableDrhd ();
- if (EFI_ERROR(Status)) {
- return Status;
+ DmaBufferInfo = BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_INFO));
+ ASSERT(DmaBufferInfo != NULL);
+ if (DmaBufferInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
}
+ ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO));
- //
- // If there is RMRR memory, parse it here.
- //
- ParseDmarAcpiTableRmrr ();
+ PeiServicesGetBootMode (&BootMode);
if (BootMode == BOOT_ON_S3_RESUME) {
- mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE_S3;
} else {
- mDmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
- }
- DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", mDmaBufferSize));
-
- //
- // Find a pre-memory in resource hob as DMA buffer
- // Mark PEI memory to be DMA protected.
- //
- Status = InitDmaProtection (mDmaBufferSize, &mDmaBufferBase);
- if (EFI_ERROR(Status)) {
- return Status;
+ DmaBufferInfo->DmaBufferSize = TOTAL_DMA_BUFFER_SIZE;
}
- DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase));
-
- mDmaBufferCurrentTop = mDmaBufferBase + mDmaBufferSize;
- mDmaBufferCurrentBottom = mDmaBufferBase;
-
- //
- // Install PPI.
- //
- Status = PeiServicesInstallPpi (&mIoMmuPpiList);
- ASSERT_EFI_ERROR(Status);
+ Status = PeiServicesNotifyPpi (&mVTdInfoNotifyDesc);
+ ASSERT_EFI_ERROR (Status);
//
- // Register EndOfPei Notify for S3 to run FSP NotifyPhase
+ // Register EndOfPei Notify for S3
//
if (BootMode == BOOT_ON_S3_RESUME) {
Status = PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc);
ASSERT_EFI_ERROR (Status);
}
- return Status;
+ return EFI_SUCCESS;
}
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
index 720f5d4..38cc8c3 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h
@@ -16,6 +16,8 @@
#define __DMA_ACCESS_LIB_H__
typedef struct {
+ EFI_ACPI_DMAR_HEADER *AcpiDmarTable;
+ UINT64 EngineMask;
UINT8 HostAddressWidth;
UINTN VTdEngineCount;
UINT64 VTdEngineAddress[1];
@@ -24,6 +26,7 @@ typedef struct {
/**
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.
@@ -35,6 +38,7 @@ typedef struct {
**/
EFI_STATUS
SetDmaProtectedRange (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask,
IN UINT32 LowMemoryBase,
IN UINT32 LowMemoryLength,
@@ -45,38 +49,127 @@ 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.
**/
EFI_STATUS
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.
+**/
+BOOLEAN
+IsDmaProtectionEnabled (
+ IN VTD_INFO *VTdInfo,
IN UINT64 EngineMask
);
/**
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
);
/**
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
);
+/**
+ 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
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
index 4d0e187..e6d0323 100644
--- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.inf
@@ -33,6 +33,8 @@
IntelVTdPmrPei.c
IntelVTdPmrPei.h
IntelVTdPmr.c
+ DmarTable.c
+ VtdReg.c
[LibraryClasses]
DebugLib
@@ -42,17 +44,18 @@
PeiServicesLib
HobLib
IoLib
+ CacheMaintenanceLib
[Ppis]
- gEdkiiIoMmuPpiGuid ## PRODUCES
- gEdkiiVTdInfoPpiGuid ## CONSUMES
- gEfiEndOfPeiSignalPpiGuid ## CONSUMES
+ gEdkiiIoMmuPpiGuid ## PRODUCES
+ gEdkiiVTdInfoPpiGuid ## CONSUMES
+ gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES
+ gEfiEndOfPeiSignalPpiGuid ## CONSUMES
[Pcd]
gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES
[Depex]
- gEfiPeiMemoryDiscoveredPpiGuid AND
gEfiPeiMasterBootModePpiGuid AND
gEdkiiVTdInfoPpiGuid
diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
new file mode 100644
index 0000000..aa53774
--- /dev/null
+++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c
@@ -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\n"));
+
+ 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\n"));
+
+ for (Index = 0; Index < VTdInfo->VTdEngineCount; Index++) {
+ if ((EngineMask & LShiftU64(1, Index)) == 0) {
+ continue;
+ }
+ DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]);
+ }
+
+ return ;
+}
--
2.7.4.windows.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
2017-10-24 13:30 [PATCH 0/2] Add Pre-Memory DMA protection in PEI Jiewen Yao
2017-10-24 13:30 ` [PATCH 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
@ 2017-10-24 13:30 ` Jiewen Yao
1 sibling, 0 replies; 4+ messages in thread
From: Jiewen Yao @ 2017-10-24 13:30 UTC (permalink / raw)
To: edk2-devel; +Cc: Zeng Star
Before memory is ready, this sample produces one VTd engine.
After memory and silicon is initialized, this sample produces
both IGD VTd engine and all-rest VTd engine by reinstall the
FV_INFO_PPI.
This update is to demonstrate how to support pre-mem VTd usage.
Cc: Zeng Star <zeng.star@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c | 234 +++++++++++++++++---
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf | 2 +-
2 files changed, 202 insertions(+), 34 deletions(-)
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index 6267da7..921daef 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
@@ -20,6 +20,7 @@
#include <Library/DebugLib.h>
#include <Library/PciLib.h>
#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
#define R_SA_MCHBAR (0x48)
#define R_SA_GGC (0x50)
@@ -33,6 +34,8 @@
#define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT for IGD
#define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT for all other - PEG, USB, SATA etc
+EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
+
typedef struct {
EFI_ACPI_DMAR_HEADER DmarHeader;
//
@@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
&mPlatformVTdSample
};
+typedef struct {
+ EFI_ACPI_DMAR_HEADER DmarHeader;
+ //
+ // VTd engine 2 - all rest
+ //
+ EFI_ACPI_DMAR_DRHD_HEADER Drhd2;
+} MY_VTD_INFO_NO_IGD_PPI;
+
+MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample = {
+ { // DmarHeader
+ { // Header
+ EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+ sizeof(MY_VTD_INFO_PPI),
+ EFI_ACPI_DMAR_REVISION,
+ },
+ 0x26, // HostAddressWidth
+ },
+
+ { // Drhd2
+ { // Header
+ EFI_ACPI_DMAR_TYPE_DRHD,
+ sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+ },
+ EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+ 0, // Reserved
+ 0, // SegmentNumber
+ 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+ },
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiVTdInfoPpiGuid,
+ &mPlatformVTdNoIgdSample
+};
+
/**
Patch Graphic UMA address in RMRR and base address.
**/
VOID
-PatchDmar (
+InitDmar (
VOID
)
{
UINT32 MchBar;
- UINT16 IgdMode;
- UINT16 GttMode;
- UINT32 IgdMemSize;
- UINT32 GttMemSize;
-
- ///
- /// Calculate IGD memsize
- ///
- IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
- if (IgdMode < 0xF0) {
- IgdMemSize = IgdMode * 32 * (1024) * (1024);
+
+ DEBUG ((DEBUG_INFO, "InitDmar\n"));
+
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+ PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0);
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+}
+
+/**
+ Patch Graphic UMA address in RMRR and base address.
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+PatchDmar (
+ VOID
+ )
+{
+ UINT32 MchBar;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+ MY_VTD_INFO_PPI *PlatformVTdSample;
+ EFI_PEI_PPI_DESCRIPTOR *PlatformVTdInfoSampleDesc;
+ MY_VTD_INFO_NO_IGD_PPI *PlatformVTdNoIgdSample;
+ EFI_PEI_PPI_DESCRIPTOR *PlatformVTdNoIgdInfoSampleDesc;
+
+ DEBUG ((DEBUG_INFO, "PatchDmar\n"));
+
+ if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
+ PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
+ ASSERT(PlatformVTdSample != NULL);
+ PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
+ ASSERT(PlatformVTdInfoSampleDesc != NULL);
+ PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
+
+ ///
+ /// Calculate IGD memsize
+ ///
+ IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+ if (IgdMode < 0xF0) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+ }
+
+ ///
+ /// Calculate GTT mem size
+ ///
+ GttMemSize = 0;
+ GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+ if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+ GttMemSize = (1 << GttMode) * (1024) * (1024);
+ }
+
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+
+ DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
+ PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
+ }
+
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+ PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
+ }
+
+ return PlatformVTdInfoSampleDesc;
} else {
- IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
- }
+ PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
+ ASSERT(PlatformVTdNoIgdSample != NULL);
+ PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
+ ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
+ PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
+
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
- ///
- /// Calculate GTT mem size
- ///
- GttMemSize = 0;
- GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
- if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
- GttMemSize = (1 << GttMode) * (1024) * (1024);
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+ PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
+ }
+
+ return PlatformVTdNoIgdInfoSampleDesc;
}
+}
- mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
- mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+/**
+ Install Firmware Volume Hob's once there is main memory
- ///
- /// Update DRHD structures of DmarTable
- ///
- MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
- mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
- mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor Notify that this module published.
+ @param[in] Ppi PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SiliconInitializedPpiNotifyCallback (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
+
+ PpiDesc = PatchDmar ();
+
+ Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, PpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
}
+EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiSiliconInitializedPpiGuid,
+ (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
+};
+
/**
Platform VTd Info sample driver.
@@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ BOOLEAN SiliconInitialized;
+ VOID *SiliconInitializedPpi;
+ EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
+
+ SiliconInitialized = FALSE;
+ //
+ // Check if silicon is initialized.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEdkiiSiliconInitializedPpiGuid,
+ 0,
+ NULL,
+ &SiliconInitializedPpi
+ );
+ if (!EFI_ERROR(Status)) {
+ SiliconInitialized = TRUE;
+ }
+ DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized));
+ if (!SiliconInitialized) {
+ Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
+ InitDmar ();
- PatchDmar ();
+ Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ PpiDesc = PatchDmar ();
- Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
- ASSERT_EFI_ERROR (Status);
+ Status = PeiServicesInstallPpi (PpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ }
return Status;
}
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index 96adb70..a4ffe51 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
@@ -47,7 +47,7 @@
gEdkiiVTdInfoPpiGuid ## PRODUCES
[Depex]
- gEfiPeiMemoryDiscoveredPpiGuid
+ gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
PlatformVTdInfoSamplePeiExtra.uni
--
2.7.4.windows.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support.
2017-10-24 13:54 [PATCH 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI Jiewen Yao
@ 2017-10-24 13:54 ` Jiewen Yao
0 siblings, 0 replies; 4+ messages in thread
From: Jiewen Yao @ 2017-10-24 13:54 UTC (permalink / raw)
To: edk2-devel; +Cc: Star Zeng
Before memory is ready, this sample produces one VTd engine.
After memory and silicon is initialized, this sample produces
both IGD VTd engine and all-rest VTd engine by reinstall the
FV_INFO_PPI.
This update is to demonstrate how to support pre-mem VTd usage.
Cc: Star Zeng <star.zeng@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Jiewen Yao <jiewen.yao@intel.com>
---
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c | 234 +++++++++++++++++---
IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf | 2 +-
2 files changed, 202 insertions(+), 34 deletions(-)
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
index 6267da7..921daef 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.c
@@ -20,6 +20,7 @@
#include <Library/DebugLib.h>
#include <Library/PciLib.h>
#include <Library/IoLib.h>
+#include <Library/MemoryAllocationLib.h>
#define R_SA_MCHBAR (0x48)
#define R_SA_GGC (0x50)
@@ -33,6 +34,8 @@
#define R_SA_MCHBAR_VTD1_OFFSET 0x5400 ///< HW UNIT for IGD
#define R_SA_MCHBAR_VTD2_OFFSET 0x5410 ///< HW UNIT for all other - PEG, USB, SATA etc
+EFI_GUID gEdkiiSiliconInitializedPpiGuid = {0x82a72dc8, 0x61ec, 0x403e, {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}};
+
typedef struct {
EFI_ACPI_DMAR_HEADER DmarHeader;
//
@@ -131,50 +134,190 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = {
&mPlatformVTdSample
};
+typedef struct {
+ EFI_ACPI_DMAR_HEADER DmarHeader;
+ //
+ // VTd engine 2 - all rest
+ //
+ EFI_ACPI_DMAR_DRHD_HEADER Drhd2;
+} MY_VTD_INFO_NO_IGD_PPI;
+
+MY_VTD_INFO_NO_IGD_PPI mPlatformVTdNoIgdSample = {
+ { // DmarHeader
+ { // Header
+ EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE,
+ sizeof(MY_VTD_INFO_PPI),
+ EFI_ACPI_DMAR_REVISION,
+ },
+ 0x26, // HostAddressWidth
+ },
+
+ { // Drhd2
+ { // Header
+ EFI_ACPI_DMAR_TYPE_DRHD,
+ sizeof(EFI_ACPI_DMAR_DRHD_HEADER)
+ },
+ EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL, // Flags
+ 0, // Reserved
+ 0, // SegmentNumber
+ 0xFED91000 // RegisterBaseAddress -- TO BE PATCHED
+ },
+};
+
+EFI_PEI_PPI_DESCRIPTOR mPlatformVTdNoIgdInfoSampleDesc = {
+ (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiVTdInfoPpiGuid,
+ &mPlatformVTdNoIgdSample
+};
+
/**
Patch Graphic UMA address in RMRR and base address.
**/
VOID
-PatchDmar (
+InitDmar (
VOID
)
{
UINT32 MchBar;
- UINT16 IgdMode;
- UINT16 GttMode;
- UINT32 IgdMemSize;
- UINT32 GttMemSize;
-
- ///
- /// Calculate IGD memsize
- ///
- IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
- if (IgdMode < 0xF0) {
- IgdMemSize = IgdMode * 32 * (1024) * (1024);
+
+ DEBUG ((DEBUG_INFO, "InitDmar\n"));
+
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+ PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0);
+ DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar));
+
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSample.Drhd2.RegisterBaseAddress | 1);
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1)));
+}
+
+/**
+ Patch Graphic UMA address in RMRR and base address.
+**/
+EFI_PEI_PPI_DESCRIPTOR *
+PatchDmar (
+ VOID
+ )
+{
+ UINT32 MchBar;
+ UINT16 IgdMode;
+ UINT16 GttMode;
+ UINT32 IgdMemSize;
+ UINT32 GttMemSize;
+ MY_VTD_INFO_PPI *PlatformVTdSample;
+ EFI_PEI_PPI_DESCRIPTOR *PlatformVTdInfoSampleDesc;
+ MY_VTD_INFO_NO_IGD_PPI *PlatformVTdNoIgdSample;
+ EFI_PEI_PPI_DESCRIPTOR *PlatformVTdNoIgdInfoSampleDesc;
+
+ DEBUG ((DEBUG_INFO, "PatchDmar\n"));
+
+ if (PciRead16 (PCI_LIB_ADDRESS(0, 2, 0, 0)) != 0xFFFF) {
+ PlatformVTdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPlatformVTdSample);
+ ASSERT(PlatformVTdSample != NULL);
+ PlatformVTdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdInfoSampleDesc);
+ ASSERT(PlatformVTdInfoSampleDesc != NULL);
+ PlatformVTdInfoSampleDesc->Ppi = PlatformVTdSample;
+
+ ///
+ /// Calculate IGD memsize
+ ///
+ IgdMode = ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF;
+ if (IgdMode < 0xF0) {
+ IgdMemSize = IgdMode * 32 * (1024) * (1024);
+ } else {
+ IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
+ }
+
+ ///
+ /// Calculate GTT mem size
+ ///
+ GttMemSize = 0;
+ GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
+ if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
+ GttMemSize = (1 << GttMode) * (1024) * (1024);
+ }
+
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
+ PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress = PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
+
+ DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) != 0) {
+ PlatformVTdSample->Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSample->Drhd1.RegisterBaseAddress | 1);
+ }
+
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+ PlatformVTdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSample->Drhd2.RegisterBaseAddress | 1);
+ }
+
+ return PlatformVTdInfoSampleDesc;
} else {
- IgdMemSize = 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024);
- }
+ PlatformVTdNoIgdSample = AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD_PPI), &mPlatformVTdNoIgdSample);
+ ASSERT(PlatformVTdNoIgdSample != NULL);
+ PlatformVTdNoIgdInfoSampleDesc = AllocateCopyPool (sizeof(EFI_PEI_PPI_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc);
+ ASSERT(PlatformVTdNoIgdInfoSampleDesc != NULL);
+ PlatformVTdNoIgdInfoSampleDesc->Ppi = PlatformVTdNoIgdSample;
+
+ ///
+ /// Update DRHD structures of DmarTable
+ ///
+ MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
- ///
- /// Calculate GTT mem size
- ///
- GttMemSize = 0;
- GttMode = (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET;
- if (GttMode <= V_SKL_SA_GGC_GGMS_8MB) {
- GttMemSize = (1 << GttMode) * (1024) * (1024);
+ DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET))));
+ if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) != 0) {
+ PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ } else {
+ MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress | 1);
+ }
+
+ return PlatformVTdNoIgdInfoSampleDesc;
}
+}
- mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress = (PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSize;
- mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress = mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - 1;
+/**
+ Install Firmware Volume Hob's once there is main memory
- ///
- /// Update DRHD structures of DmarTable
- ///
- MchBar = PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0;
- mPlatformVTdSample.Drhd1.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1);
- mPlatformVTdSample.Drhd2.RegisterBaseAddress = (MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1);
+ @param[in] PeiServices General purpose services available to every PEIM.
+ @param[in] NotifyDescriptor Notify that this module published.
+ @param[in] Ppi PPI that was installed.
+
+ @retval EFI_SUCCESS The function completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+SiliconInitializedPpiNotifyCallback (
+ IN CONST EFI_PEI_SERVICES **PeiServices,
+ IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDescriptor,
+ IN VOID *Ppi
+ )
+{
+ EFI_STATUS Status;
+ EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
+
+ PpiDesc = PatchDmar ();
+
+ Status = PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, PpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ return EFI_SUCCESS;
}
+EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList = {
+ (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
+ &gEdkiiSiliconInitializedPpiGuid,
+ (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback
+};
+
/**
Platform VTd Info sample driver.
@@ -190,12 +333,37 @@ PlatformVTdInfoSampleInitialize (
IN CONST EFI_PEI_SERVICES **PeiServices
)
{
- EFI_STATUS Status;
+ EFI_STATUS Status;
+ BOOLEAN SiliconInitialized;
+ VOID *SiliconInitializedPpi;
+ EFI_PEI_PPI_DESCRIPTOR *PpiDesc;
+
+ SiliconInitialized = FALSE;
+ //
+ // Check if silicon is initialized.
+ //
+ Status = PeiServicesLocatePpi (
+ &gEdkiiSiliconInitializedPpiGuid,
+ 0,
+ NULL,
+ &SiliconInitializedPpi
+ );
+ if (!EFI_ERROR(Status)) {
+ SiliconInitialized = TRUE;
+ }
+ DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized));
+ if (!SiliconInitialized) {
+ Status = PeiServicesNotifyPpi (&mSiliconInitializedNotifyList);
+ InitDmar ();
- PatchDmar ();
+ Status = PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc);
+ ASSERT_EFI_ERROR (Status);
+ } else {
+ PpiDesc = PatchDmar ();
- Status = PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc);
- ASSERT_EFI_ERROR (Status);
+ Status = PeiServicesInstallPpi (PpiDesc);
+ ASSERT_EFI_ERROR (Status);
+ }
return Status;
}
diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
index 96adb70..a4ffe51 100644
--- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
+++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSamplePei.inf
@@ -47,7 +47,7 @@
gEdkiiVTdInfoPpiGuid ## PRODUCES
[Depex]
- gEfiPeiMemoryDiscoveredPpiGuid
+ gEfiPeiMasterBootModePpiGuid
[UserExtensions.TianoCore."ExtraFiles"]
PlatformVTdInfoSamplePeiExtra.uni
--
2.7.4.windows.1
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2017-10-24 13:51 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-10-24 13:30 [PATCH 0/2] Add Pre-Memory DMA protection in PEI Jiewen Yao
2017-10-24 13:30 ` [PATCH 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support Jiewen Yao
2017-10-24 13:30 ` [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: " Jiewen Yao
-- strict thread matches above, loose matches on Subject: below --
2017-10-24 13:54 [PATCH 0/2] IntelSiliconPkg: Add Pre-Memory DMA protection in PEI Jiewen Yao
2017-10-24 13:54 ` [PATCH 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support Jiewen Yao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox