From nobody Fri May 3 17:52:44 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1509107314884588.7916054199628; Fri, 27 Oct 2017 05:28:34 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id DE6452034C087; Fri, 27 Oct 2017 05:24:45 -0700 (PDT) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 597D82034A898 for ; Fri, 27 Oct 2017 05:24:44 -0700 (PDT) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Oct 2017 05:28:31 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.210.199]) by fmsmga006.fm.intel.com with ESMTP; 27 Oct 2017 05:28:30 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.93; helo=mga11.intel.com; envelope-from=jiewen.yao@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,304,1505804400"; d="scan'208";a="168383170" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Fri, 27 Oct 2017 20:28:24 +0800 Message-Id: <1509107305-4420-2-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1509107305-4420-1-git-send-email-jiewen.yao@intel.com> References: <1509107305-4420-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [PATCH V3 1/2] IntelSiliconPkg/VtdPmrPei: Add premem support. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" Remove memory discovered dependency to support both premem VTD_INFO_PPI and postmem VTD_INFO_PPI. If VTD_INFO_PPI is installed before memory is ready, this driver protects all memory region. If VTD_INFO_PPI is installed or reinstalled after memory is ready, this driver allocates DMA buffer and protect rest. Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao Reviewed-by: Star Zeng --- 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/Intel= SiliconPkg/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.
+ This program and the accompanying materials + are licensed and made available under the terms and conditions of the BS= D License + which accompanies this distribution. The full text of the license may b= e 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 IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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 =3D=3D 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) =3D=3D 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 =3D (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_D= EVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH); + PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1); + for (PciPathIndex =3D 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 =3D=3D NULL) { + return; + } + + DEBUG ((DEBUG_INFO, + " *******************************************************************= ********\n" + )); + DEBUG ((DEBUG_INFO, + " * Reserved Memory Region Reporting Structure = *\n" + )); + DEBUG ((DEBUG_INFO, + " *******************************************************************= ********\n" + )); + DEBUG ((DEBUG_INFO, + (sizeof(UINTN) =3D=3D 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 =3D Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER); + DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)= (Rmrr + 1); + while (RmrrLen > 0) { + DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); + RmrrLen -=3D DmarDeviceScopeEntry->Length; + DmarDeviceScopeEntry =3D (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 =3D=3D NULL) { + return; + } + + DEBUG ((DEBUG_INFO, + " *******************************************************************= ********\n" + )); + DEBUG ((DEBUG_INFO, + " * DMA-Remapping Hardware Definition Structure = *\n" + )); + DEBUG ((DEBUG_INFO, + " *******************************************************************= ********\n" + )); + DEBUG ((DEBUG_INFO, + (sizeof(UINTN) =3D=3D 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 =3D Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER); + DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)= (Drhd + 1); + while (DrhdLen > 0) { + DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); + DrhdLen -=3D DmarDeviceScopeEntry->Length; + DmarDeviceScopeEntry =3D (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 =3D=3D NULL) { + return; + } + + // + // Dump Dmar table + // + DEBUG ((DEBUG_INFO, + "*********************************************************************= ********\n" + )); + DEBUG ((DEBUG_INFO, + "* DMAR Table = *\n" + )); + DEBUG ((DEBUG_INFO, + "*********************************************************************= ********\n" + )); + + DEBUG ((DEBUG_INFO, + (sizeof(UINTN) =3D=3D 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 =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER); + DmarHeader =3D (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 -=3D DmarHeader->Length; + DmarHeader =3D (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 =3D 0; + DmarHeader =3D (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 =3D (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, Dma= rDrhd->RegisterBaseAddress)); + VTdInfo->VTdEngineAddress[VtdIndex] =3D 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 =3D GetVtdEngineNumber (AcpiDmarTable); + if (VtdUnitNumber =3D=3D 0) { + return EFI_UNSUPPORTED; + } + + VTdInfo =3D BuildGuidHob (&mVTdInfoGuid, sizeof(VTD_INFO) + (VtdUnitNumb= er - 1) * sizeof(UINT64)); + ASSERT(VTdInfo !=3D NULL); + if (VTdInfo =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + // + // Initialize the engine mask to all. + // + VTdInfo->AcpiDmarTable =3D AcpiDmarTable; + VTdInfo->EngineMask =3D LShiftU64 (1, VtdUnitNumber) - 1; + VTdInfo->HostAddressWidth =3D AcpiDmarTable->HostAddressWidth; + VTdInfo->VTdEngineCount =3D VtdUnitNumber; + + VtdIndex =3D 0; + DmarHeader =3D (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 *)DmarHea= der); + VtdIndex++; + + break; + + default: + break; + } + DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); + } + ASSERT (VtdIndex =3D=3D 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 =3D 0; + DmarHeader =3D (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 =3D (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader; + if (DmarDrhd->SegmentNumber !=3D Segment) { + // Mismatch + break; + } + if ((DmarDrhd->Header.Length =3D=3D sizeof(EFI_ACPI_DMAR_DRHD_HEADER= )) || + ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != =3D 0)) { + // No DevScopeEntry + // Do not handle PCI_ALL + break; + } + ThisDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *= )((UINTN)(DmarDrhd + 1)); + while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header= .Length) { + if ((ThisDevScopeEntry->Length =3D=3D DevScopeEntry->Length) && + (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->= Length) =3D=3D 0)) { + return VtdIndex; + } + ThisDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER= *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length); + } + break; + default: + break; + } + DmarHeader =3D (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 =3D VTdInfo->AcpiDmarTable; + + DEBUG ((DEBUG_INFO," RMRR (Base 0x%016lx, Limit 0x%016lx)\n", DmarRmrr-= >ReservedMemoryRegionBaseAddress, DmarRmrr->ReservedMemoryRegionLimitAddres= s)); + + if ((DmarRmrr->ReservedMemoryRegionBaseAddress =3D=3D 0) || + (DmarRmrr->ReservedMemoryRegionLimitAddress =3D=3D 0)) { + return ; + } + + DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U= INTN)(DmarRmrr + 1)); + while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len= gth) { + ASSERT (DmarDevScopeEntry->Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP= E_PCI_ENDPOINT); + + VTdIndex =3D GetVTdEngineFromDevScopeEntry (AcpiDmarTable, DmarRmrr->S= egmentNumber, DmarDevScopeEntry); + if (VTdIndex !=3D (UINTN)-1) { + RmrrMask =3D LShiftU64 (1, VTdIndex); + + LowBottom =3D 0; + LowTop =3D (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress; + HighBottom =3D (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1; + HighTop =3D 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 =3D VTdInfo->EngineMask & (~RmrrMask); + } + + DmarDevScopeEntry =3D (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 =3D VTdInfo->AcpiDmarTable; + + DmarHeader =3D (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 =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); + } +} diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/Int= elSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c index 6179dfe..000a81b 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c @@ -22,17 +22,17 @@ =20 #include "IntelVTdPmrPei.h" =20 -extern VTD_INFO *mVTdInfo; - /** Get protected low memory alignment. =20 + @param HostAddressWidth The host address width. @param VtdUnitBaseAddress The base address of the VTd engine. =20 @return protected low memory alignment. **/ UINT32 GetPlmrAlignment ( + IN UINT8 HostAddressWidth, IN UINTN VtdUnitBaseAddress ) { @@ -48,19 +48,18 @@ GetPlmrAlignment ( /** Get protected high memory alignment. =20 + @param HostAddressWidth The host address width. @param VtdUnitBaseAddress The base address of the VTd engine. =20 @return protected high memory alignment. **/ UINT64 GetPhmrAlignment ( + IN UINT8 HostAddressWidth, IN UINTN VtdUnitBaseAddress ) { UINT64 Data64; - UINT8 HostAddressWidth; - - HostAddressWidth =3D mVTdInfo->HostAddressWidth; =20 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFF= FF); Data64 =3D MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG); @@ -73,12 +72,14 @@ GetPhmrAlignment ( /** Get protected low memory alignment. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 @return protected low memory alignment. **/ UINT32 GetLowMemoryAlignment ( + IN VTD_INFO *VTdInfo, IN UINT64 EngineMask ) { @@ -87,11 +88,11 @@ GetLowMemoryAlignment ( UINT32 FinalAlignment; =20 FinalAlignment =3D 0; - for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { continue; } - Alignment =3D GetPlmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Inde= x]); + Alignment =3D GetPlmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdI= nfo->VTdEngineAddress[Index]); if (FinalAlignment < Alignment) { FinalAlignment =3D Alignment; } @@ -102,12 +103,14 @@ GetLowMemoryAlignment ( /** Get protected high memory alignment. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 @return protected high memory alignment. **/ UINT64 GetHighMemoryAlignment ( + IN VTD_INFO *VTdInfo, IN UINT64 EngineMask ) { @@ -116,11 +119,11 @@ GetHighMemoryAlignment ( UINT64 FinalAlignment; =20 FinalAlignment =3D 0; - for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { continue; } - Alignment =3D GetPhmrAlignment ((UINTN)mVTdInfo->VTdEngineAddress[Inde= x]); + Alignment =3D GetPhmrAlignment (VTdInfo->HostAddressWidth, (UINTN)VTdI= nfo->VTdEngineAddress[Index]); if (FinalAlignment < Alignment) { FinalAlignment =3D Alignment; } @@ -144,12 +147,19 @@ EnablePmr ( UINT32 Reg32; VTD_CAP_REG CapReg; =20 + DEBUG ((DEBUG_INFO, "EnablePmr - %x\n", VtdUnitBaseAddress)); + CapReg.Uint64 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG); if (CapReg.Bits.PLMR =3D=3D 0 || CapReg.Bits.PHMR =3D=3D 0) { return EFI_UNSUPPORTED; } =20 Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG); + if (Reg32 =3D=3D 0xFFFFFFFF) { + DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32)); + ASSERT(FALSE); + } + if ((Reg32 & BIT0) =3D=3D 0) { MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, BIT31); do { @@ -157,6 +167,8 @@ EnablePmr ( } while((Reg32 & BIT0) =3D=3D 0); } =20 + DEBUG ((DEBUG_INFO, "EnablePmr - Done\n")); + return EFI_SUCCESS; } =20 @@ -182,6 +194,11 @@ DisablePmr ( } =20 Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG); + if (Reg32 =3D=3D 0xFFFFFFFF) { + DEBUG ((DEBUG_ERROR, "R_PMEN_ENABLE_REG - 0x%x\n", Reg32)); + ASSERT(FALSE); + } + if ((Reg32 & BIT0) !=3D 0) { MmioWrite32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG, 0x0); do { @@ -195,6 +212,7 @@ DisablePmr ( /** Set PMR region in the VTd engine. =20 + @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; } =20 - PlmrAlignment =3D GetPlmrAlignment (VtdUnitBaseAddress); + PlmrAlignment =3D GetPlmrAlignment (HostAddressWidth, VtdUnitBaseAddress= ); DEBUG ((DEBUG_INFO, "PlmrAlignment - 0x%x\n", PlmrAlignment)); - PhmrAlignment =3D GetPhmrAlignment (VtdUnitBaseAddress); + PhmrAlignment =3D GetPhmrAlignment (HostAddressWidth, VtdUnitBaseAddress= ); DEBUG ((DEBUG_INFO, "PhmrAlignment - 0x%lx\n", PhmrAlignment)); =20 if ((LowMemoryBase !=3D ALIGN_VALUE(LowMemoryBase, PlmrAlignment)) || @@ -247,8 +266,10 @@ SetPmrRegion ( =20 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")); =20 return EFI_SUCCESS; } @@ -256,6 +277,7 @@ SetPmrRegion ( /** Set DMA protected region. =20 + @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 ( =20 DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x] [0x%lx, = 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength, HighMemoryBase, High= MemoryLength)); =20 - for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { continue; } - DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); + DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]); Status =3D 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 =3D EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); + Status =3D EnablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]); if (EFI_ERROR(Status)) { return Status; } @@ -306,25 +330,29 @@ SetDmaProtectedRange ( /** Diable DMA protection. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 - @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; =20 - DEBUG ((DEBUG_INFO, "DisableDmaProtection\n")); + DEBUG ((DEBUG_INFO, "DisableDmaProtection - 0x%lx\n", EngineMask)); + + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { + DEBUG ((DEBUG_INFO, "Disabling...%d\n", Index)); =20 - for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { continue; } - Status =3D DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); + Status =3D DisablePmr ((UINTN)VTdInfo->VTdEngineAddress[Index]); if (EFI_ERROR(Status)) { return Status; } @@ -332,3 +360,67 @@ DisableDmaProtection ( =20 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 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG); + if (CapReg.Bits.PLMR =3D=3D 0 || CapReg.Bits.PHMR =3D=3D 0) { + return FALSE; + } + + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_PMEN_ENABLE_REG); + if ((Reg32 & BIT0) =3D=3D 0) { + return FALSE; + } + + return TRUE; +} + +/** + Return the mask of the VTd engine which is enabled. + + @param VTdInfo The VTd engine context information. + @param EngineMask The mask of the VTd engine to be accessed. + + @return the mask of the VTd engine which is enabled. +**/ +UINT64 +GetDmaProtectionEnabledEngineMask ( + IN VTD_INFO *VTdInfo, + IN UINT64 EngineMask + ) +{ + UINTN Index; + BOOLEAN Result; + UINT64 EnabledEngineMask; + + DEBUG ((DEBUG_INFO, "GetDmaProtectionEnabledEngineMask - 0x%lx\n", Engin= eMask)); + + EnabledEngineMask =3D 0; + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + Result =3D IsPmrEnabled ((UINTN)VTdInfo->VTdEngineAddress[Index]); + if (Result) { + EnabledEngineMask |=3D LShiftU64(1, Index); + } + } + + DEBUG ((DEBUG_INFO, "EnabledEngineMask - 0x%lx\n", EnabledEngineMask)); + return EnabledEngineMask; +} diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/= IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c index 3fe6d65..b6ff799 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c @@ -24,6 +24,7 @@ #include #include #include +#include #include =20 #include "IntelVTdPmrPei.h" @@ -31,13 +32,20 @@ #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB #define TOTAL_DMA_BUFFER_SIZE_S3 SIZE_1MB =20 -EFI_ACPI_DMAR_HEADER *mAcpiDmarTable; -VTD_INFO *mVTdInfo; -UINT64 mEngineMask; -UINTN mDmaBufferBase; -UINTN mDmaBufferSize; -UINTN mDmaBufferCurrentTop; -UINTN mDmaBufferCurrentBottom; +EFI_GUID mVTdInfoGuid =3D { + 0x222f5e30, 0x5cd, 0x49c6, { 0x8a, 0xc, 0x36, 0xd6, 0x58, 0x41, 0xe0, 0x= 82 } +}; + +EFI_GUID mDmaBufferInfoGuid =3D { + 0x7b624ec7, 0xfb67, 0x4f9c, { 0xb6, 0xb0, 0x4d, 0xfa, 0x9c, 0x88, 0x20, = 0x39 } +}; + +typedef struct { + UINTN DmaBufferBase; + UINTN DmaBufferSize; + UINTN DmaBufferCurrentTop; + UINTN DmaBufferCurrentBottom; +} DMA_BUFFER_INFO; =20 #define MAP_INFO_SIGNATURE SIGNATURE_32 ('D', 'M', 'A', 'P') typedef struct { @@ -83,7 +91,6 @@ typedef struct { +------------------+ <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D PLMR.Base (0) **/ =20 - /** Set IOMMU attribute for a system memory. =20 @@ -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 =3D GetFirstGuidHob (&mDmaBufferInfoGuid); + DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob); =20 if (Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer || Operation =3D=3D EdkiiIoMmuOperationBusMasterCommonBuffer64) { @@ -160,18 +172,18 @@ PeiIoMmuMap ( } =20 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuMap - HostAddress - 0x%x, NumberOfBytes = - %x\n", HostAddress, *NumberOfBytes)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurren= tTop)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCur= rentBottom)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->Dm= aBufferCurrentTop)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo-= >DmaBufferCurrentBottom)); =20 Length =3D *NumberOfBytes + sizeof(MAP_INFO); - if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) { + if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff= erCurrentBottom) { DEBUG ((DEBUG_ERROR, "PeiIoMmuMap - OUT_OF_RESOURCE\n")); ASSERT (FALSE); return EFI_OUT_OF_RESOURCES; } =20 - *DeviceAddress =3D mDmaBufferCurrentBottom; - mDmaBufferCurrentBottom +=3D Length; + *DeviceAddress =3D DmaBufferInfo->DmaBufferCurrentBottom; + DmaBufferInfo->DmaBufferCurrentBottom +=3D Length; =20 MapInfo =3D (VOID *)(UINTN)(*DeviceAddress + *NumberOfBytes); MapInfo->Signature =3D 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 =3D GetFirstGuidHob (&mDmaBufferInfoGuid); + DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob); =20 if (Mapping =3D=3D NULL) { return EFI_SUCCESS; } =20 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuUnmap - Mapping - %x\n", Mapping)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurren= tTop)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCur= rentBottom)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->Dm= aBufferCurrentTop)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo-= >DmaBufferCurrentBottom)); =20 MapInfo =3D Mapping; ASSERT (MapInfo->Signature =3D=3D MAP_INFO_SIGNATURE); @@ -246,8 +263,8 @@ PeiIoMmuUnmap ( } =20 Length =3D MapInfo->NumberOfBytes + sizeof(MAP_INFO); - if (mDmaBufferCurrentBottom =3D=3D MapInfo->DeviceAddress + Length) { - mDmaBufferCurrentBottom -=3D Length; + if (DmaBufferInfo->DmaBufferCurrentBottom =3D=3D MapInfo->DeviceAddress = + Length) { + DmaBufferInfo->DmaBufferCurrentBottom -=3D Length; } =20 return EFI_SUCCESS; @@ -282,20 +299,25 @@ PeiIoMmuAllocateBuffer ( IN UINT64 Attributes ) { - UINTN Length; + UINTN Length; + VOID *Hob; + DMA_BUFFER_INFO *DmaBufferInfo; + + Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid); + DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob); =20 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - page - %x\n", Pages)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurren= tTop)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCur= rentBottom)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->Dm= aBufferCurrentTop)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo-= >DmaBufferCurrentBottom)); =20 Length =3D EFI_PAGES_TO_SIZE(Pages); - if (Length > mDmaBufferCurrentTop - mDmaBufferCurrentBottom) { + if (Length > DmaBufferInfo->DmaBufferCurrentTop - DmaBufferInfo->DmaBuff= erCurrentBottom) { DEBUG ((DEBUG_ERROR, "PeiIoMmuAllocateBuffer - OUT_OF_RESOURCE\n")); ASSERT (FALSE); return EFI_OUT_OF_RESOURCES; } - *HostAddress =3D (VOID *)(UINTN)(mDmaBufferCurrentTop - Length); - mDmaBufferCurrentTop -=3D Length; + *HostAddress =3D (VOID *)(UINTN)(DmaBufferInfo->DmaBufferCurrentTop - Le= ngth); + DmaBufferInfo->DmaBufferCurrentTop -=3D Length; =20 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuAllocateBuffer - allocate - %x\n", *Host= Address)); return EFI_SUCCESS; @@ -321,15 +343,20 @@ PeiIoMmuFreeBuffer ( IN VOID *HostAddress ) { - UINTN Length; + UINTN Length; + VOID *Hob; + DMA_BUFFER_INFO *DmaBufferInfo; + + Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid); + DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob); =20 DEBUG ((DEBUG_VERBOSE, "PeiIoMmuFreeBuffer - page - %x, HostAddr - %x\n"= , Pages, HostAddress)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentTop - %x\n", mDmaBufferCurren= tTop)); - DEBUG ((DEBUG_VERBOSE, " mDmaBufferCurrentBottom - %x\n", mDmaBufferCur= rentBottom)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentTop - %x\n", DmaBufferInfo->Dm= aBufferCurrentTop)); + DEBUG ((DEBUG_VERBOSE, " DmaBufferCurrentBottom - %x\n", DmaBufferInfo-= >DmaBufferCurrentBottom)); =20 Length =3D EFI_PAGES_TO_SIZE(Pages); - if ((UINTN)HostAddress =3D=3D mDmaBufferCurrentTop) { - mDmaBufferCurrentTop +=3D Length; + if ((UINTN)HostAddress =3D=3D DmaBufferInfo->DmaBufferCurrentTop) { + DmaBufferInfo->DmaBufferCurrentTop +=3D Length; } =20 return EFI_SUCCESS; @@ -506,6 +533,7 @@ GetTopMemory ( /** Initialize DMA protection. =20 + @param VTdInfo The VTd engine context information. @param DmaBufferSize the DMA buffer size @param DmaBufferBase the DMA buffer base =20 @@ -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 ( =20 ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop); =20 - LowMemoryAlignment =3D GetLowMemoryAlignment (mEngineMask); - HighMemoryAlignment =3D GetHighMemoryAlignment (mEngineMask); + LowMemoryAlignment =3D GetLowMemoryAlignment (VTdInfo, VTdInfo->EngineMa= sk); + HighMemoryAlignment =3D GetHighMemoryAlignment (VTdInfo, VTdInfo->Engine= Mask); if (LowMemoryAlignment < HighMemoryAlignment) { MemoryAlignment =3D (UINTN)HighMemoryAlignment; } else { @@ -558,12 +587,13 @@ InitDmaProtection ( HighTop =3D GetTopMemory (); =20 Status =3D SetDmaProtectedRange ( - mEngineMask, - (UINT32)LowBottom, - (UINT32)(LowTop - LowBottom), - HighBottom, - HighTop - HighBottom - ); + VTdInfo, + VTdInfo->EngineMask, + (UINT32)LowBottom, + (UINT32)(LowTop - LowBottom), + HighBottom, + HighTop - HighBottom + ); =20 if (EFI_ERROR(Status)) { FreePages ((VOID *)*DmaBufferBase, EFI_SIZE_TO_PAGES(DmaBufferSize)); @@ -573,542 +603,188 @@ InitDmaProtection ( } =20 /** - Dump DMAR DeviceScopeEntry. + Initializes the Intel VTd Info. + + @retval EFI_SUCCESS Usb bot driver is successfully initialize= d. + @retval EFI_OUT_OF_RESOURCES Can't initialize the driver. =20 - @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 =3D=3D 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) =3D=3D 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 =3D (DmarDeviceScopeEntry->Length - sizeof(EFI_ACPI_DMAR_D= EVICE_SCOPE_STRUCTURE_HEADER)) / sizeof(EFI_ACPI_DMAR_PCI_PATH); - PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)(DmarDeviceScopeEntry + 1); - for (PciPathIndex =3D 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; =20 -/** - Dump DMAR RMRR table. + Status =3D PeiServicesLocatePpi ( + &gEdkiiVTdInfoPpiGuid, + 0, + NULL, + (VOID **)&AcpiDmarTable + ); + ASSERT_EFI_ERROR(Status); =20 - @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); =20 - if (Rmrr =3D=3D NULL) { - return; + // + // Clear old VTdInfo Hob. + // + Hob =3D GetFirstGuidHob (&mVTdInfoGuid); + if (Hob !=3D NULL) { + ZeroMem (&((EFI_HOB_GUID_TYPE *)Hob)->Name, sizeof(EFI_GUID)); } =20 - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n" - )); - DEBUG ((DEBUG_INFO, - " * Reserved Memory Region Reporting Structure = *\n" - )); - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n" - )); - DEBUG ((DEBUG_INFO, - (sizeof(UINTN) =3D=3D 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 =3D Rmrr->Header.Length - sizeof(EFI_ACPI_DMAR_RMRR_HEADER); - DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)= (Rmrr + 1); - while (RmrrLen > 0) { - DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); - RmrrLen -=3D DmarDeviceScopeEntry->Length; - DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER = *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length); + // + // Get DMAR information to local VTdInfo + // + Status =3D ParseDmarAcpiTableDrhd (AcpiDmarTable); + if (EFI_ERROR(Status)) { + return Status; } =20 - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n\n" - )); + // + // NOTE: Do not parse RMRR here, because RMRR may cause PMR programming. + // =20 - return; + return EFI_SUCCESS; } =20 /** - Dump DMAR DRHD table. + Initializes the Intel VTd PMR for all memory. + + @retval EFI_SUCCESS Usb bot driver is successfully initialize= d. + @retval EFI_OUT_OF_RESOURCES Can't initialize the driver. =20 - @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; =20 - if (Drhd =3D=3D NULL) { - return; - } + Hob =3D GetFirstGuidHob (&mVTdInfoGuid); + VTdInfo =3D GET_GUID_HOB_DATA(Hob); =20 - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n" - )); - DEBUG ((DEBUG_INFO, - " * DMA-Remapping Hardware Definition Structure = *\n" - )); - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n" - )); - DEBUG ((DEBUG_INFO, - (sizeof(UINTN) =3D=3D 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 =3D Drhd->Header.Length - sizeof(EFI_ACPI_DMAR_DRHD_HEADER); - DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)= (Drhd + 1); - while (DrhdLen > 0) { - DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); - DrhdLen -=3D DmarDeviceScopeEntry->Length; - DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER = *)((UINTN)DmarDeviceScopeEntry + DmarDeviceScopeEntry->Length); - } + LowBottom =3D 0; + LowTop =3D 0; + HighBottom =3D 0; + HighTop =3D LShiftU64 (1, VTdInfo->HostAddressWidth); =20 - DEBUG ((DEBUG_INFO, - " *******************************************************************= ********\n\n" - )); + Status =3D SetDmaProtectedRange ( + VTdInfo, + VTdInfo->EngineMask, + (UINT32)LowBottom, + (UINT32)(LowTop - LowBottom), + HighBottom, + HighTop - HighBottom + ); =20 - return; + return Status; } =20 /** - Dump DMAR ACPI table. + Initializes the Intel VTd PMR for DMA buffer. + + @retval EFI_SUCCESS Usb bot driver is successfully initialize= d. + @retval EFI_OUT_OF_RESOURCES Can't initialize the driver. =20 - @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; =20 - if (Dmar =3D=3D NULL) { - return; - } + Hob =3D GetFirstGuidHob (&mVTdInfoGuid); + VTdInfo =3D GET_GUID_HOB_DATA(Hob); =20 // - // 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) =3D=3D 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 =3D Dmar->Header.Length - sizeof(EFI_ACPI_DMAR_HEADER); - DmarHeader =3D (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 -=3D DmarHeader->Length; - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); - } - - DEBUG ((DEBUG_INFO, - "*********************************************************************= ********\n\n" - )); - - return; -} + ParseDmarAcpiTableRmrr (VTdInfo); =20 -/** - Get VTd engine number. + Hob =3D GetFirstGuidHob (&mDmaBufferInfoGuid); + DmaBufferInfo =3D GET_GUID_HOB_DATA(Hob); =20 - @return the VTd engine number. -**/ -UINTN -GetVtdEngineNumber ( - VOID - ) -{ - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - UINTN VtdIndex; - - VtdIndex =3D 0; - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable= + 1)); - while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade= r.Length) { - switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_DRHD: - VtdIndex++; - break; - default: - break; - } - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); + DEBUG ((DEBUG_INFO, " DmaBufferSize : 0x%x\n", DmaBufferInfo->DmaBufferS= ize)); + // + // Find a pre-memory in resource hob as DMA buffer + // Mark PEI memory to be DMA protected. + // + Status =3D InitDmaProtection (VTdInfo, DmaBufferInfo->DmaBufferSize, &Dm= aBufferInfo->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, Dma= rDrhd->RegisterBaseAddress)); - mVTdInfo->VTdEngineAddress[VtdIndex] =3D DmarDrhd->RegisterBaseAddress; -} =20 -/** - 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->DmaBufferB= ase)); =20 - VtdUnitNumber =3D GetVtdEngineNumber (); - if (VtdUnitNumber =3D=3D 0) { - return EFI_UNSUPPORTED; - } - - mVTdInfo =3D AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) * = sizeof(UINT64)); - if (mVTdInfo =3D=3D NULL) { - return EFI_OUT_OF_RESOURCES; - } - mVTdInfo->HostAddressWidth =3D mAcpiDmarTable->HostAddressWidth; - mVTdInfo->VTdEngineCount =3D VtdUnitNumber; - - VtdIndex =3D 0; - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable= + 1)); - while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade= r.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 =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); - } - ASSERT (VtdIndex =3D=3D VtdUnitNumber); + DmaBufferInfo->DmaBufferCurrentTop =3D DmaBufferInfo->DmaBufferBase + Dm= aBufferInfo->DmaBufferSize; + DmaBufferInfo->DmaBufferCurrentBottom =3D DmaBufferInfo->DmaBufferBase; =20 // - // Initialize the engine mask to all. + // Install PPI. // - mEngineMask =3D LShiftU64 (1, VtdUnitNumber) - 1; + Status =3D PeiServicesInstallPpi (&mIoMmuPpiList); + ASSERT_EFI_ERROR(Status); =20 - return EFI_SUCCESS; + return Status; } =20 /** - Return the VTd engine index according to the Segment and DevScopeEntry. + This function handles S3 resume task at the end of PEI =20 - @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 f= unction. =20 - @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 =3D 0; - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable= + 1)); - while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade= r.Length) { - switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_DRHD: - DmarDrhd =3D (EFI_ACPI_DMAR_DRHD_HEADER *)DmarHeader; - if (DmarDrhd->SegmentNumber !=3D Segment) { - // Mismatch - break; - } - if ((DmarDrhd->Header.Length =3D=3D sizeof(EFI_ACPI_DMAR_DRHD_HEADER= )) || - ((DmarDrhd->Flags & EFI_ACPI_DMAR_DRHD_FLAGS_INCLUDE_PCI_ALL) != =3D 0)) { - // No DevScopeEntry - // Do not handle PCI_ALL - break; - } - ThisDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *= )((UINTN)(DmarDrhd + 1)); - while ((UINTN)ThisDevScopeEntry < (UINTN)DmarDrhd + DmarDrhd->Header= .Length) { - if ((ThisDevScopeEntry->Length =3D=3D DevScopeEntry->Length) && - (CompareMem (ThisDevScopeEntry, DevScopeEntry, DevScopeEntry->= Length) =3D=3D 0)) { - return VtdIndex; - } - ThisDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER= *)((UINTN)ThisDevScopeEntry + ThisDevScopeEntry->Length); - } - break; - default: - break; - } - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); - } - return (UINTN)-1; -} - -/** - Process DMAR RMRR table. + VOID *Hob; + VTD_INFO *VTdInfo; + UINT64 EngineMask; =20 - @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->ReservedMemoryRegionLimitAddres= s)); - - if ((DmarRmrr->ReservedMemoryRegionBaseAddress =3D=3D 0) || - (DmarRmrr->ReservedMemoryRegionLimitAddress =3D=3D 0)) { - return ; - } + DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n")); =20 - DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)((U= INTN)(DmarRmrr + 1)); - while ((UINTN)DmarDevScopeEntry < (UINTN)DmarRmrr + DmarRmrr->Header.Len= gth) { - ASSERT (DmarDevScopeEntry->Type =3D=3D EFI_ACPI_DEVICE_SCOPE_ENTRY_TYP= E_PCI_ENDPOINT); - - VTdIndex =3D GetVTdEngineFromDevScopeEntry (DmarRmrr->SegmentNumber, D= marDevScopeEntry); - if (VTdIndex !=3D (UINTN)-1) { - RmrrMask =3D LShiftU64 (1, VTdIndex); - - LowBottom =3D 0; - LowTop =3D (UINTN)DmarRmrr->ReservedMemoryRegionBaseAddress; - HighBottom =3D (UINTN)DmarRmrr->ReservedMemoryRegionLimitAddress + 1; - HighTop =3D 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 =3D mEngineMask & (~RmrrMask); - } + if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) { + Hob =3D GetFirstGuidHob (&mVTdInfoGuid); + VTdInfo =3D GET_GUID_HOB_DATA(Hob); =20 - DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER *)(= (UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length); + EngineMask =3D LShiftU64 (1, VTdInfo->VTdEngineCount) - 1; + DisableDmaProtection (VTdInfo, EngineMask); } + return EFI_SUCCESS; } =20 -/** - Parse DMAR DRHD table. -**/ -VOID -ParseDmarAcpiTableRmrr ( - VOID - ) -{ - EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; - - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)(mAcpiDmarTable= + 1)); - while ((UINTN)DmarHeader < (UINTN)mAcpiDmarTable + mAcpiDmarTable->Heade= r.Length) { - switch (DmarHeader->Type) { - case EFI_ACPI_DMAR_TYPE_RMRR: - ProcessRmrr ((EFI_ACPI_DMAR_RMRR_HEADER *)DmarHeader); - break; - default: - break; - } - DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader + = DmarHeader->Length); - } -} +EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc =3D { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA= TE_LIST), + &gEfiEndOfPeiSignalPpiGuid, + S3EndOfPeiNotify +}; =20 /** - This function handles S3 resume task at the end of PEI + This function handles VTd engine setup =20 @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; + UINT64 EnabledEngineMask; + VOID *Hob; + VTD_INFO *VTdInfo; + BOOLEAN MemoryInitialized; =20 - DEBUG((DEBUG_INFO, "VTdPmr S3EndOfPeiNotify\n")); + DEBUG ((DEBUG_INFO, "VTdInfoNotify\n")); + + // + // Check if memory is initialized. + // + MemoryInitialized =3D FALSE; + Status =3D PeiServicesLocatePpi ( + &gEfiPeiMemoryDiscoveredPpiGuid, + 0, + NULL, + &MemoryDiscovered + ); + if (!EFI_ERROR(Status)) { + MemoryInitialized =3D 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 =3D GetFirstGuidHob (&mVTdInfoGuid); + VTdInfo =3D GET_GUID_HOB_DATA(Hob); + + // + // NOTE: We need check if PMR is enabled or not. + // + EnabledEngineMask =3D GetDmaProtectionEnabledEngineMask (VTdInfo, VTdI= nfo->EngineMask); + if (EnabledEngineMask !=3D 0) { + EnableVTdTranslationProtection (VTdInfo, EnabledEngineMask); + DisableDmaProtection (VTdInfo, EnabledEngineMask); + } + InitVTdPmrForDma (); + if (EnabledEngineMask !=3D 0) { + DisableVTdTranslationProtection (VTdInfo, EnabledEngineMask); + } =20 - if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT1) =3D=3D 0) { - EngineMask =3D LShiftU64 (1, mVTdInfo->VTdEngineCount) - 1; - DisableDmaProtection (EngineMask); } + return EFI_SUCCESS; } =20 -EFI_PEI_NOTIFY_DESCRIPTOR mS3EndOfPeiNotifyDesc =3D { +EFI_PEI_NOTIFY_DESCRIPTOR mVTdInfoNotifyDesc =3D { (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA= TE_LIST), - &gEfiEndOfPeiSignalPpiGuid, - S3EndOfPeiNotify + &gEdkiiVTdInfoPpiGuid, + VTdInfoNotify }; =20 /** @@ -1161,71 +890,40 @@ IntelVTdPmrInitialize ( { EFI_STATUS Status; EFI_BOOT_MODE BootMode; + DMA_BUFFER_INFO *DmaBufferInfo; + + DEBUG ((DEBUG_INFO, "IntelVTdPmrInitialize\n")); =20 if ((PcdGet8(PcdVTdPolicyPropertyMask) & BIT0) =3D=3D 0) { return EFI_UNSUPPORTED; } =20 - PeiServicesGetBootMode (&BootMode); - - Status =3D PeiServicesLocatePpi ( - &gEdkiiVTdInfoPpiGuid, - 0, - NULL, - (VOID **)&mAcpiDmarTable - ); - ASSERT_EFI_ERROR(Status); - - DumpAcpiDMAR (mAcpiDmarTable); - - // - // Get DMAR information to local VTdInfo - // - Status =3D ParseDmarAcpiTableDrhd (); - if (EFI_ERROR(Status)) { - return Status; + DmaBufferInfo =3D BuildGuidHob (&mDmaBufferInfoGuid, sizeof(DMA_BUFFER_I= NFO)); + ASSERT(DmaBufferInfo !=3D NULL); + if (DmaBufferInfo =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; } + ZeroMem (DmaBufferInfo, sizeof(DMA_BUFFER_INFO)); =20 - // - // If there is RMRR memory, parse it here. - // - ParseDmarAcpiTableRmrr (); + PeiServicesGetBootMode (&BootMode); =20 if (BootMode =3D=3D BOOT_ON_S3_RESUME) { - mDmaBufferSize =3D TOTAL_DMA_BUFFER_SIZE_S3; + DmaBufferInfo->DmaBufferSize =3D TOTAL_DMA_BUFFER_SIZE_S3; } else { - mDmaBufferSize =3D 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 =3D InitDmaProtection (mDmaBufferSize, &mDmaBufferBase); - if (EFI_ERROR(Status)) { - return Status; + DmaBufferInfo->DmaBufferSize =3D TOTAL_DMA_BUFFER_SIZE; } =20 - DEBUG ((DEBUG_INFO, " DmaBufferBase : 0x%x\n", mDmaBufferBase)); - - mDmaBufferCurrentTop =3D mDmaBufferBase + mDmaBufferSize; - mDmaBufferCurrentBottom =3D mDmaBufferBase; - - // - // Install PPI. - // - Status =3D PeiServicesInstallPpi (&mIoMmuPpiList); - ASSERT_EFI_ERROR(Status); + Status =3D PeiServicesNotifyPpi (&mVTdInfoNotifyDesc); + ASSERT_EFI_ERROR (Status); =20 // - // Register EndOfPei Notify for S3 to run FSP NotifyPhase + // Register EndOfPei Notify for S3 // if (BootMode =3D=3D BOOT_ON_S3_RESUME) { Status =3D PeiServicesNotifyPpi (&mS3EndOfPeiNotifyDesc); ASSERT_EFI_ERROR (Status); } =20 - return Status; + return EFI_SUCCESS; } =20 diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/= IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h index 720f5d4..499119d 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h @@ -16,6 +16,8 @@ #define __DMA_ACCESS_LIB_H__ =20 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. =20 + @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. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 @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. +**/ +UINT64 +GetDmaProtectionEnabledEngineMask ( + IN VTD_INFO *VTdInfo, IN UINT64 EngineMask ); =20 /** Get protected low memory alignment. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 @return protected low memory alignment. **/ UINT32 GetLowMemoryAlignment ( + IN VTD_INFO *VTdInfo, IN UINT64 EngineMask ); =20 /** Get protected high memory alignment. =20 + @param VTdInfo The VTd engine context information. @param EngineMask The mask of the VTd engine to be accessed. =20 @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 ); =20 +/** + 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 =20 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 =20 [LibraryClasses] DebugLib @@ -42,17 +44,18 @@ PeiServicesLib HobLib IoLib + CacheMaintenanceLib =20 [Ppis] - gEdkiiIoMmuPpiGuid ## PRODUCES - gEdkiiVTdInfoPpiGuid ## CONSUMES - gEfiEndOfPeiSignalPpiGuid ## CONSUMES + gEdkiiIoMmuPpiGuid ## PRODUCES + gEdkiiVTdInfoPpiGuid ## CONSUMES + gEfiPeiMemoryDiscoveredPpiGuid ## CONSUMES + gEfiEndOfPeiSignalPpiGuid ## CONSUMES =20 [Pcd] gIntelSiliconPkgTokenSpaceGuid.PcdVTdPolicyPropertyMask ## CONSUMES =20 [Depex] - gEfiPeiMemoryDiscoveredPpiGuid AND gEfiPeiMasterBootModePpiGuid AND gEdkiiVTdInfoPpiGuid =20 diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c b/IntelSil= iconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c new file mode 100644 index 0000000..888905d --- /dev/null +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/VtdReg.c @@ -0,0 +1,293 @@ +/** @file + + Copyright (c) 2017, Intel Corporation. All rights reserved.
+ + This program and the accompanying materials are licensed and made availa= ble under + the terms and conditions of the BSD License which accompanies this distr= ibution. + 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 IMP= LIED. + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 memor= y. + + @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 =3D MmioRead64 (VtdUnitBaseAddress + R_CAP_REG); + + if (CapReg.Bits.RWBF !=3D 0) { + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, Reg32 | B_GMCD_REG_WBF); + do { + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + } while ((Reg32 & B_GSTS_REG_WBF) !=3D 0); + } +} + +/** + Invalidate VTd context cache. + + @param VtdUnitBaseAddress The base address of the VTd engine. +**/ +EFI_STATUS +InvalidateContextCache ( + IN UINTN VtdUnitBaseAddress + ) +{ + UINT64 Reg64; + + Reg64 =3D MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG); + if ((Reg64 & B_CCMD_REG_ICC) !=3D 0) { + DEBUG ((DEBUG_ERROR,"ERROR: InvalidateContextCache: B_CCMD_REG_ICC is = set for VTD(%x)\n",VtdUnitBaseAddress)); + return EFI_DEVICE_ERROR; + } + + Reg64 &=3D ((~B_CCMD_REG_ICC) & (~B_CCMD_REG_CIRG_MASK)); + Reg64 |=3D (B_CCMD_REG_ICC | V_CCMD_REG_CIRG_GLOBAL); + MmioWrite64 (VtdUnitBaseAddress + R_CCMD_REG, Reg64); + + do { + Reg64 =3D MmioRead64 (VtdUnitBaseAddress + R_CCMD_REG); + } while ((Reg64 & B_CCMD_REG_ICC) !=3D 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 =3D MmioRead64 (VtdUnitBaseAddress + R_ECAP_REG); + + Reg64 =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_I= OTLB_REG); + if ((Reg64 & B_IOTLB_REG_IVT) !=3D 0) { + DEBUG ((DEBUG_ERROR,"ERROR: InvalidateIOTLB: B_IOTLB_REG_IVT is set fo= r VTD(%x)\n", VtdUnitBaseAddress)); + return EFI_DEVICE_ERROR; + } + + Reg64 &=3D ((~B_IOTLB_REG_IVT) & (~B_IOTLB_REG_IIRG_MASK)); + Reg64 |=3D (B_IOTLB_REG_IVT | V_IOTLB_REG_IIRG_GLOBAL); + MmioWrite64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R_IOTLB_REG,= Reg64); + + do { + Reg64 =3D MmioRead64 (VtdUnitBaseAddress + (ECapReg.Bits.IRO * 16) + R= _IOTLB_REG); + } while ((Reg64 & B_IOTLB_REG_IVT) !=3D 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", VtdUnitBaseA= ddress)); + + DEBUG((DEBUG_INFO, "RootEntryTable 0x%x \n", RootEntryTable)); + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, (UINT64)(UINTN)RootEntry= Table); + + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP); + + DEBUG((DEBUG_INFO, "EnableDmar: waiting for RTPS bit to be set... \n")); + do { + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + } while((Reg32 & B_GSTS_REG_RTPS) =3D=3D 0); + + // + // Init DMAr Fault Event and Data registers + // + Reg32 =3D 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 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + } while ((Reg32 & B_GSTS_REG_TE) =3D=3D 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", VtdUnitBase= Address)); + + // + // Write Buffer Flush before invalidation + // + FlushWriteBuffer (VtdUnitBaseAddress); + + // + // Disable VTd + // + MmioWrite32 (VtdUnitBaseAddress + R_GCMD_REG, B_GMCD_REG_SRTP); + do { + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + } while((Reg32 & B_GSTS_REG_RTPS) =3D=3D 0); + + Reg32 =3D MmioRead32 (VtdUnitBaseAddress + R_GSTS_REG); + DEBUG((DEBUG_INFO, "DisableDmar: GSTS_REG - 0x%08x\n", Reg32)); + + MmioWrite64 (VtdUnitBaseAddress + R_RTADDR_REG, 0); + + DEBUG ((DEBUG_INFO,"VTD () Disabled!<<<<<<\n")); + + return EFI_SUCCESS; +} + +/** + Enable VTd translation table protection. + + @param VTdInfo The VTd engine context information. + @param EngineMask The mask of the VTd engine to be accessed. +**/ +VOID +EnableVTdTranslationProtection ( + IN VTD_INFO *VTdInfo, + IN UINT64 EngineMask + ) +{ + UINTN Index; + VOID *RootEntryTable; + + DEBUG ((DEBUG_INFO, "EnableVTdTranslationProtection - 0x%lx\n", EngineMa= sk)); + + RootEntryTable =3D AllocatePages (1); + ASSERT (RootEntryTable !=3D NULL); + if (RootEntryTable =3D=3D 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 =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + EnableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index], (UINTN)RootEntryT= able); + } + + return ; +} + +/** + Disable VTd translation table protection. + + @param VTdInfo The VTd engine context information. + @param EngineMask The mask of the VTd engine to be accessed. +**/ +VOID +DisableVTdTranslationProtection ( + IN VTD_INFO *VTdInfo, + IN UINT64 EngineMask + ) +{ + UINTN Index; + + DEBUG ((DEBUG_INFO, "DisableVTdTranslationProtection - 0x%lx\n", EngineM= ask)); + + for (Index =3D 0; Index < VTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + DisableDmar ((UINTN)VTdInfo->VTdEngineAddress[Index]); + } + + return ; +} --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel From nobody Fri May 3 17:52:44 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; spf=none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) smtp.mailfrom=edk2-devel-bounces@lists.01.org Return-Path: Received: from ml01.01.org (ml01.01.org [198.145.21.10]) by mx.zohomail.com with SMTPS id 1509107317383234.72159777312334; Fri, 27 Oct 2017 05:28:37 -0700 (PDT) Received: from [127.0.0.1] (localhost [IPv6:::1]) by ml01.01.org (Postfix) with ESMTP id 2B7B1203525E5; Fri, 27 Oct 2017 05:24:46 -0700 (PDT) Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ml01.01.org (Postfix) with ESMTPS id 1D83F2034A891 for ; Fri, 27 Oct 2017 05:24:45 -0700 (PDT) Received: from fmsmga006.fm.intel.com ([10.253.24.20]) by fmsmga102.fm.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 27 Oct 2017 05:28:32 -0700 Received: from jyao1-mobl.ccr.corp.intel.com ([10.254.210.199]) by fmsmga006.fm.intel.com with ESMTP; 27 Oct 2017 05:28:31 -0700 X-Original-To: edk2-devel@lists.01.org Received-SPF: none (zoho.com: 198.145.21.10 is neither permitted nor denied by domain of lists.01.org) client-ip=198.145.21.10; envelope-from=edk2-devel-bounces@lists.01.org; helo=ml01.01.org; Received-SPF: Pass (sender SPF authorized) identity=mailfrom; client-ip=192.55.52.93; helo=mga11.intel.com; envelope-from=jiewen.yao@intel.com; receiver=edk2-devel@lists.01.org X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.44,304,1505804400"; d="scan'208";a="168383183" From: Jiewen Yao To: edk2-devel@lists.01.org Date: Fri, 27 Oct 2017 20:28:25 +0800 Message-Id: <1509107305-4420-3-git-send-email-jiewen.yao@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1509107305-4420-1-git-send-email-jiewen.yao@intel.com> References: <1509107305-4420-1-git-send-email-jiewen.yao@intel.com> Subject: [edk2] [PATCH V3 2/2] IntelSiliconPkg/VtdPeiSample: Add premem support. X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Star Zeng MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Errors-To: edk2-devel-bounces@lists.01.org Sender: "edk2-devel" X-ZohoMail: RSF_4 Z_629925259 SPT_0 Content-Type: text/plain; charset="utf-8" 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 Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao Reviewed-by: Star Zeng --- IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSample= Pei.c | 234 +++++++++++++++++--- IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoSample= Pei.inf | 2 +- 2 files changed, 201 insertions(+), 35 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformV= TdInfoSamplePei.c b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/Pl= atformVTdInfoSamplePei.c index 6267da7..852dc0e 100644 --- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoS= amplePei.c +++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoS= amplePei.c @@ -20,6 +20,7 @@ #include #include #include +#include =20 #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 =20 +EFI_GUID gEdkiiSiliconInitializedPpiGuid =3D {0x82a72dc8, 0x61ec, 0x403e, = {0xb1, 0x5a, 0x8d, 0x7a, 0x3a, 0x71, 0x84, 0x98}}; + typedef struct { EFI_ACPI_DMAR_HEADER DmarHeader; // @@ -131,50 +134,188 @@ EFI_PEI_PPI_DESCRIPTOR mPlatformVTdInfoSampleDesc = =3D { &mPlatformVTdSample }; =20 +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 =3D { + { // DmarHeader + { // Header + EFI_ACPI_4_0_DMA_REMAPPING_TABLE_SIGNATURE, + sizeof(MY_VTD_INFO_NO_IGD_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 =3D { + (EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST), + &gEdkiiVTdInfoPpiGuid, + &mPlatformVTdNoIgdSample +}; + /** - Patch Graphic UMA address in RMRR and base address. + Initialize VTd register. **/ VOID -PatchDmar ( +InitDmar ( VOID ) { UINT32 MchBar; - UINT16 IgdMode; - UINT16 GttMode; - UINT32 IgdMemSize; - UINT32 GttMemSize; - - /// - /// Calculate IGD memsize - /// - IgdMode =3D ((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 =3D IgdMode * 32 * (1024) * (1024); + + DEBUG ((DEBUG_INFO, "InitDmar\n")); + + MchBar =3D PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0; + PciWrite32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR), 0xFED10000 | BIT0); + DEBUG ((DEBUG_INFO, "MchBar - %x\n", MchBar)); + + MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)mPlatformVTdSampl= e.Drhd2.RegisterBaseAddress | 1); + DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_VTD= 2_OFFSET)))); +} + +/** + 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)) !=3D 0xFFFF) { + PlatformVTdSample =3D AllocateCopyPool (sizeof(MY_VTD_INFO_PPI), &mPla= tformVTdSample); + ASSERT(PlatformVTdSample !=3D NULL); + PlatformVTdInfoSampleDesc =3D AllocateCopyPool (sizeof(EFI_PEI_PPI_DES= CRIPTOR), &mPlatformVTdInfoSampleDesc); + ASSERT(PlatformVTdInfoSampleDesc !=3D NULL); + PlatformVTdInfoSampleDesc->Ppi =3D PlatformVTdSample; + + /// + /// Calculate IGD memsize + /// + IgdMode =3D ((PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_S= A_GGC_GMS_MASK) >> N_SKL_SA_GGC_GMS_OFFSET) & 0xFF; + if (IgdMode < 0xF0) { + IgdMemSize =3D IgdMode * 32 * (1024) * (1024); + } else { + IgdMemSize =3D 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024); + } + + /// + /// Calculate GTT mem size + /// + GttMemSize =3D 0; + GttMode =3D (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA= _GGC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET; + if (GttMode <=3D V_SKL_SA_GGC_GGMS_8MB) { + GttMemSize =3D (1 << GttMode) * (1024) * (1024); + } + + PlatformVTdSample->Rmrr1.ReservedMemoryRegionBaseAddress =3D (PciRead= 32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemS= ize; + PlatformVTdSample->Rmrr1.ReservedMemoryRegionLimitAddress =3D Platform= VTdSample->Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize = - 1; + + /// + /// Update DRHD structures of DmarTable + /// + MchBar =3D PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0; + + if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET) &~1) !=3D 0) { + PlatformVTdSample->Drhd1.RegisterBaseAddress =3D (MmioRead32 (MchBar= + R_SA_MCHBAR_VTD1_OFFSET) &~1); + } else { + MmioWrite32 (MchBar + R_SA_MCHBAR_VTD1_OFFSET, (UINT32)PlatformVTdSa= mple->Drhd1.RegisterBaseAddress | 1); + } + DEBUG ((DEBUG_INFO, "VTd1 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_V= TD1_OFFSET)))); + + if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) !=3D 0) { + PlatformVTdSample->Drhd2.RegisterBaseAddress =3D (MmioRead32 (MchBar= + R_SA_MCHBAR_VTD2_OFFSET) &~1); + } else { + MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdSa= mple->Drhd2.RegisterBaseAddress | 1); + } + DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_V= TD2_OFFSET)))); + + return PlatformVTdInfoSampleDesc; } else { - IgdMemSize =3D 4 * (IgdMode - 0xF0 + 1) * (1024) * (1024); - } + PlatformVTdNoIgdSample =3D AllocateCopyPool (sizeof(MY_VTD_INFO_NO_IGD= _PPI), &mPlatformVTdNoIgdSample); + ASSERT(PlatformVTdNoIgdSample !=3D NULL); + PlatformVTdNoIgdInfoSampleDesc =3D AllocateCopyPool (sizeof(EFI_PEI_PP= I_DESCRIPTOR), &mPlatformVTdNoIgdInfoSampleDesc); + ASSERT(PlatformVTdNoIgdInfoSampleDesc !=3D NULL); + PlatformVTdNoIgdInfoSampleDesc->Ppi =3D PlatformVTdNoIgdSample; + + /// + /// Update DRHD structures of DmarTable + /// + MchBar =3D PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0; =20 - /// - /// Calculate GTT mem size - /// - GttMemSize =3D 0; - GttMode =3D (PciRead16 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_GGC)) & B_SKL_SA_G= GC_GGMS_MASK) >> N_SKL_SA_GGC_GGMS_OFFSET; - if (GttMode <=3D V_SKL_SA_GGC_GGMS_8MB) { - GttMemSize =3D (1 << GttMode) * (1024) * (1024); + if ((MmioRead32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET) &~1) !=3D 0) { + PlatformVTdNoIgdSample->Drhd2.RegisterBaseAddress =3D (MmioRead32 (M= chBar + R_SA_MCHBAR_VTD2_OFFSET) &~1); + } else { + MmioWrite32 (MchBar + R_SA_MCHBAR_VTD2_OFFSET, (UINT32)PlatformVTdNo= IgdSample->Drhd2.RegisterBaseAddress | 1); + } + DEBUG ((DEBUG_INFO, "VTd2 - %x\n", (MmioRead32 (MchBar + R_SA_MCHBAR_V= TD2_OFFSET)))); + + return PlatformVTdNoIgdInfoSampleDesc; } +} =20 - mPlatformVTdSample.Rmrr1.ReservedMemoryRegionBaseAddress =3D (PciRead32= (PCI_LIB_ADDRESS(0, 0, 0, R_SA_TOLUD)) & ~(0x01)) - IgdMemSize - GttMemSiz= e; - mPlatformVTdSample.Rmrr1.ReservedMemoryRegionLimitAddress =3D mPlatformV= TdSample.Rmrr1.ReservedMemoryRegionBaseAddress + IgdMemSize + GttMemSize - = 1; +/** + The callback function for SiliconInitializedPpi. + It reinstalls VTD_INFO_PPI. =20 - /// - /// Update DRHD structures of DmarTable - /// - MchBar =3D PciRead32 (PCI_LIB_ADDRESS(0, 0, 0, R_SA_MCHBAR)) & ~BIT0; - mPlatformVTdSample.Drhd1.RegisterBaseAddress =3D (MmioRead32 (MchBar + R= _SA_MCHBAR_VTD1_OFFSET) &~1); - mPlatformVTdSample.Drhd2.RegisterBaseAddress =3D (MmioRead32 (MchBar + R= _SA_MCHBAR_VTD2_OFFSET) &~1); + @param[in] PeiServices General purpose services available to ever= y 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 =3D PatchDmar (); + + Status =3D PeiServicesReInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc, Pp= iDesc); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; } =20 +EFI_PEI_NOTIFY_DESCRIPTOR mSiliconInitializedNotifyList =3D { + (EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINA= TE_LIST), + &gEdkiiSiliconInitializedPpiGuid, + (EFI_PEIM_NOTIFY_ENTRY_POINT) SiliconInitializedPpiNotifyCallback +}; + /** Platform VTd Info sample driver. =20 @@ -190,12 +331,37 @@ PlatformVTdInfoSampleInitialize ( IN CONST EFI_PEI_SERVICES **PeiServices ) { - EFI_STATUS Status; + EFI_STATUS Status; + BOOLEAN SiliconInitialized; + VOID *SiliconInitializedPpi; + EFI_PEI_PPI_DESCRIPTOR *PpiDesc; + + SiliconInitialized =3D FALSE; + // + // Check if silicon is initialized. + // + Status =3D PeiServicesLocatePpi ( + &gEdkiiSiliconInitializedPpiGuid, + 0, + NULL, + &SiliconInitializedPpi + ); + if (!EFI_ERROR(Status)) { + SiliconInitialized =3D TRUE; + } + DEBUG ((DEBUG_INFO, "SiliconInitialized - %x\n", SiliconInitialized)); + if (!SiliconInitialized) { + Status =3D PeiServicesNotifyPpi (&mSiliconInitializedNotifyList); + InitDmar (); =20 - PatchDmar (); + Status =3D PeiServicesInstallPpi (&mPlatformVTdNoIgdInfoSampleDesc); + ASSERT_EFI_ERROR (Status); + } else { + PpiDesc =3D PatchDmar (); =20 - Status =3D PeiServicesInstallPpi (&mPlatformVTdInfoSampleDesc); - ASSERT_EFI_ERROR (Status); + Status =3D PeiServicesInstallPpi (PpiDesc); + ASSERT_EFI_ERROR (Status); + } =20 return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformV= TdInfoSamplePei.inf b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/= PlatformVTdInfoSamplePei.inf index 96adb70..a4ffe51 100644 --- a/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoS= amplePei.inf +++ b/IntelSiliconPkg/Feature/VTd/PlatformVTdInfoSamplePei/PlatformVTdInfoS= amplePei.inf @@ -47,7 +47,7 @@ gEdkiiVTdInfoPpiGuid ## PRODUCES =20 [Depex] - gEfiPeiMemoryDiscoveredPpiGuid + gEfiPeiMasterBootModePpiGuid =20 [UserExtensions.TianoCore."ExtraFiles"] PlatformVTdInfoSamplePeiExtra.uni --=20 2.7.4.windows.1 _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel