From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) (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 409E821E945F3 for ; Tue, 19 Sep 2017 23:26:24 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP; 19 Sep 2017 23:29:29 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.42,420,1500966000"; d="scan'208";a="137384307" Received: from fmsmsx103.amr.corp.intel.com ([10.18.124.201]) by orsmga002.jf.intel.com with ESMTP; 19 Sep 2017 23:29:28 -0700 Received: from FMSMSX109.amr.corp.intel.com (10.18.116.9) by FMSMSX103.amr.corp.intel.com (10.18.124.201) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 19 Sep 2017 23:29:28 -0700 Received: from shsmsx101.ccr.corp.intel.com (10.239.4.153) by fmsmsx109.amr.corp.intel.com (10.18.116.9) with Microsoft SMTP Server (TLS) id 14.3.319.2; Tue, 19 Sep 2017 23:29:27 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.175]) by SHSMSX101.ccr.corp.intel.com ([169.254.1.159]) with mapi id 14.03.0319.002; Wed, 20 Sep 2017 14:29:25 +0800 From: "Zeng, Star" To: "Yao, Jiewen" , "edk2-devel@lists.01.org" CC: "Zeng, Star" Thread-Topic: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table. Thread-Index: AQHTL3srhWGjty7XBkG1i68rdVv46aK9VHqA Date: Wed, 20 Sep 2017 06:29:24 +0000 Message-ID: <0C09AFA07DD0434D9E2A0C6AEB0483103B976906@shsmsx102.ccr.corp.intel.com> References: <1505628407-7368-1-git-send-email-jiewen.yao@intel.com> <1505628407-7368-3-git-send-email-jiewen.yao@intel.com> In-Reply-To: <1505628407-7368-3-git-send-email-jiewen.yao@intel.com> Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.239.127.40] MIME-Version: 1.0 Subject: Re: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table. 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: , X-List-Received-Date: Wed, 20 Sep 2017 06:26:24 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable The typo "reset" in commit log? Should it be "reset"? Thanks, Star -----Original Message----- From: Yao, Jiewen=20 Sent: Sunday, September 17, 2017 2:07 PM To: edk2-devel@lists.01.org Cc: Zeng, Star Subject: [PATCH 2/3] IntelSiliconPkg/IntelVTdPmrPei: Parse RMRR table. In order to support PEI graphic, we let VTdPmrPei driver parse DMAR table R= MRR entry and allow the UMA access. If a system has no PEI IGD, no RMRR is needed. The behavior is unchanged. If a system has PEI IGD, it must report RMRR in PEI phase. The PeiVTdPrm will program the IGD VTd engine to skip the RMRR region, and = program the reset PCI VTd engine to skip the another DMA buffer allocated i= n PEI phase for other device driver. Cc: Star Zeng Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Jiewen Yao --- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c | 52 +- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c | 581 ++++++++= +++++++++++- IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h |= 20 +- 3 files changed, 624 insertions(+), 29 deletions(-) diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c b/Int= elSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c index ef08e29..be841aa 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmr.c @@ -22,7 +22,7 @@ =20 #include "IntelVTdPmrPei.h" =20 -extern EDKII_VTD_INFO_PPI *mVTdInfoPpi; +extern VTD_INFO *mVTdInfo; =20 /** Get protected low memory alignment. @@ -60,7 +60,7 @@ GetPhmrAlignment ( UINT64 Data64; UINT8 HostAddressWidth; =20 - HostAddressWidth =3D mVTdInfoPpi->HostAddressWidth; + HostAddressWidth =3D mVTdInfo->HostAddressWidth; =20 MmioWrite64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG, 0xFFFFFFFFFFFFFF= FF); Data64 =3D MmioRead64 (VtdUnitBaseAddress + R_PMEN_HIGH_BASE_REG); @@ -7= 3,11 +73,13 @@ GetPhmrAlignment ( /** Get protected low memory alignment. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @return protected low memory alignment. **/ UINT32 GetLowMemoryAlignment ( - VOID + IN UINT64 EngineMask ) { UINTN Index; @@ -85,8 +87,11 @@ GetLowMemoryAlignment ( UINT32 FinalAlignment; =20 FinalAlignment =3D 0; - for (Index =3D 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) { - Alignment =3D GetPlmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[I= ndex]); + for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + Alignment =3D GetPlmrAlignment=20 + ((UINTN)mVTdInfo->VTdEngineAddress[Index]); if (FinalAlignment < Alignment) { FinalAlignment =3D Alignment; } @@ -97,11 +102,13 @@ GetLowMemoryAlignment ( /** Get protected high memory alignment. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @return protected high memory alignment. **/ UINT64 GetHighMemoryAlignment ( - VOID + IN UINT64 EngineMask ) { UINTN Index; @@ -109,8 +116,11 @@ GetHighMemoryAlignment ( UINT64 FinalAlignment; =20 FinalAlignment =3D 0; - for (Index =3D 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) { - Alignment =3D GetPhmrAlignment ((UINTN)mVTdInfoPpi->VTdEngineAddress[I= ndex]); + for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + Alignment =3D GetPhmrAlignment=20 + ((UINTN)mVTdInfo->VTdEngineAddress[Index]); if (FinalAlignment < Alignment) { FinalAlignment =3D Alignment; } @@ -246,6 +256,7 @@ SetPmrRegion ( /** Set DMA protected region. =20 + @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. @param HighMemoryBase The protected high memory region base. @@ -256,6 +267,7 @@ SetPmrRegion ( **/ EFI_STATUS SetDmaProtectedRange ( + IN UINT64 EngineMask, IN UINT32 LowMemoryBase, IN UINT32 LowMemoryLength, IN UINT64 HighMemoryBase, @@ -265,12 +277,15 @@ SetDmaProtectedRange ( UINTN Index; EFI_STATUS Status; =20 - DEBUG ((DEBUG_INFO, "SetDmaProtectedRange - [0x%x, 0x%x] [0x%lx, 0x%lx]\= n", LowMemoryBase, LowMemoryLength, HighMemoryBase, HighMemoryLength)); + DEBUG ((DEBUG_INFO, "SetDmaProtectedRange(0x%lx) - [0x%x, 0x%x]=20 + [0x%lx, 0x%lx]\n", EngineMask, LowMemoryBase, LowMemoryLength,=20 + HighMemoryBase, HighMemoryLength)); =20 - for (Index =3D 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) { - DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]); + for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); Status =3D SetPmrRegion ( - (UINTN)mVTdInfoPpi->VTdEngineAddress[Index], + (UINTN)mVTdInfo->VTdEngineAddress[Index], LowMemoryBase, LowMemoryLength, HighMemoryBase, @@ -279,7 +294,7 @@ SetDmaProtectedRange ( if (EFI_ERROR(Status)) { return Status; } - Status =3D EnablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]); + Status =3D EnablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); if (EFI_ERROR(Status)) { return Status; } @@ -291,11 +306,13 @@ SetDmaProtectedRange ( /** Diable DMA protection. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @retval DMA protection is disabled. **/ EFI_STATUS DisableDmaProtection ( - VOID + IN UINT64 EngineMask ) { UINTN Index; @@ -303,8 +320,11 @@ DisableDmaProtection ( =20 DEBUG ((DEBUG_INFO, "DisableDmaProtection\n")); =20 - for (Index =3D 0; Index < mVTdInfoPpi->VTdEngineCount; Index++) { - Status =3D DisablePmr ((UINTN)mVTdInfoPpi->VTdEngineAddress[Index]); + for (Index =3D 0; Index < mVTdInfo->VTdEngineCount; Index++) { + if ((EngineMask & LShiftU64(1, Index)) =3D=3D 0) { + continue; + } + Status =3D DisablePmr ((UINTN)mVTdInfo->VTdEngineAddress[Index]); if (EFI_ERROR(Status)) { return Status; } diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c b/= IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c index d118b7e..063e8cd 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.c @@ -29,7 +29,9 @@ =20 #define TOTAL_DMA_BUFFER_SIZE SIZE_4MB =20 -EDKII_VTD_INFO_PPI *mVTdInfoPpi; +EFI_ACPI_DMAR_HEADER *mAcpiDmarTable; +VTD_INFO *mVTdInfo; +UINT64 mEngineMask; UINTN mDmaBufferBase; UINTN mDmaBufferSize =3D TOTAL_DMA_BUFFER_SIZE= ; UINTN mDmaBufferCurrentTop; @@ -48,15 +50,19 @@ typedef struct { =20 PEI Memory Layout: =20 + +------------------+ <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D PHMR.Limit (Top of memory) + | Mem Resource | + | | + +------------------+ <------- EfiMemoryTop | PEI allocated | - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D PHMR.Bas= e ^ | Commom Buf | | | -------------- | DMA Buffer | * DMA FREE * | | | -------------- | V | Read/Write Buf | - =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ + =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D+ <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D PLMR.Lim= it | PEI allocated | | -------------- | <------- EfiFreeMemoryTop | * PEI FREE * | @@ -70,6 +76,9 @@ typedef struct { | Mem Alloc Hob | +------------------+ =20 + | | + | Mem Resource | + +------------------+ <=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D PLMR.Base (0) **/ =20 =20 @@ -457,20 +466,21 @@ DumpPhitHob ( /** Get the highest memory. =20 - @param HobList the HOB list. - @return the highest memory. **/ UINT64 GetTopMemory ( - IN VOID *HobList + VOID ) { + VOID *HobList; EFI_PEI_HOB_POINTERS Hob; EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob; UINT64 TopMemory; UINT64 ResourceTop; =20 + HobList =3D GetHobList (); + TopMemory =3D 0; for (Hob.Raw =3D HobList; !END_OF_HOB_LIST (Hob); Hob.Raw =3D GET_NEXT_H= OB (Hob)) { if (GET_HOB_TYPE (Hob) =3D=3D EFI_HOB_TYPE_RESOURCE_DESCRIPTOR) { @@ -= 525,8 +535,8 @@ InitDmaProtection ( =20 ASSERT (PhitHob->EfiMemoryBottom < PhitHob->EfiMemoryTop); =20 - LowMemoryAlignment =3D GetLowMemoryAlignment (); - HighMemoryAlignment =3D GetHighMemoryAlignment (); + LowMemoryAlignment =3D GetLowMemoryAlignment (mEngineMask); =20 + HighMemoryAlignment =3D GetHighMemoryAlignment (mEngineMask); if (LowMemoryAlignment < HighMemoryAlignment) { MemoryAlignment =3D (UINTN)HighMemoryAlignment; } else { @@ -542,9 +552,10 @@ InitDmaProtection ( LowBottom =3D 0; LowTop =3D *DmaBufferBase; HighBottom =3D *DmaBufferBase + DmaBufferSize; - HighTop =3D GetTopMemory (HobList); + HighTop =3D GetTopMemory (); =20 Status =3D SetDmaProtectedRange ( + mEngineMask, (UINT32)LowBottom, (UINT32)(LowTop - LowBottom), HighBottom, @@ -559,6 +570,541 @@ InitDmaProtection ( } =20 /** + Dump DMAR DeviceScopeEntry. + + @param[in] DmarDeviceScopeEntry DMAR DeviceScopeEntry **/ VOID=20 +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=20 + 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 -=20 + sizeof(EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER)) /=20 + sizeof(EFI_ACPI_DMAR_PCI_PATH); PciPath =3D (EFI_ACPI_DMAR_PCI_PATH *)(D= marDeviceScopeEntry + 1); for (PciPathIndex =3D 0; PciPathIndex < PciPathN= umber; 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=20 + *)(Rmrr + 1); while (RmrrLen > 0) { + DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); + RmrrLen -=3D DmarDeviceScopeEntry->Length; + DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER= =20 + *)((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=20 + *)(Drhd + 1); while (DrhdLen > 0) { + DumpDmarDeviceScopeEntry (DmarDeviceScopeEntry); + DrhdLen -=3D DmarDeviceScopeEntry->Length; + DmarDeviceScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER= =20 + *)((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); =20 + DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)(Dmar + 1); while=20 + (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 += =20 + DmarHeader->Length); } + + DEBUG ((DEBUG_INFO, + "*********************************************************************= ********\n\n" + )); + + return; +} + +/** + Get VTd engine number. + + @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=20 +*)((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 += =20 +DmarHeader->Length); + } + 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,=20 +DmarDrhd->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; + + VtdUnitNumber =3D GetVtdEngineNumber (); if (VtdUnitNumber =3D=3D 0) { + return EFI_UNSUPPORTED; + } + + mVTdInfo =3D AllocateZeroPool (sizeof(VTD_INFO) + (VtdUnitNumber - 1) *= =20 + 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=20 + *)((UINTN)(mAcpiDmarTable + 1)); while ((UINTN)DmarHeader < (UINTN)mAcpi= DmarTable + 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 =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER *)((UINTN)DmarHeader += =20 + DmarHeader->Length); } ASSERT (VtdIndex =3D=3D VtdUnitNumber); + + // + // Initialize the engine mask to all. + // + mEngineMask =3D LShiftU64 (1, VtdUnitNumber) - 1; + + return EFI_SUCCESS; +} + +/** + Return the VTd engine index according to the Segment and DevScopeEntry. + + @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 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=20 +*)((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 += =20 +DmarHeader->Length); + } + return (UINTN)-1; +} + +/** + Process DMAR RMRR table. + + @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",=20 + DmarRmrr->ReservedMemoryRegionBaseAddress,=20 + DmarRmrr->ReservedMemoryRegionLimitAddress)); + + if ((DmarRmrr->ReservedMemoryRegionBaseAddress =3D=3D 0) || + (DmarRmrr->ReservedMemoryRegionLimitAddress =3D=3D 0)) { + return ; + } + + DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER=20 + *)((UINTN)(DmarRmrr + 1)); while ((UINTN)DmarDevScopeEntry < (UINTN)Dmar= Rmrr + DmarRmrr->Header.Length) { + ASSERT (DmarDevScopeEntry->Type =3D=3D=20 + EFI_ACPI_DEVICE_SCOPE_ENTRY_TYPE_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); + } + + DmarDevScopeEntry =3D (EFI_ACPI_DMAR_DEVICE_SCOPE_STRUCTURE_HEADER=20 +*)((UINTN)DmarDevScopeEntry + DmarDevScopeEntry->Length); + } +} + +/** + Parse DMAR DRHD table. +**/ +VOID +ParseDmarAcpiTableRmrr ( + VOID + ) +{ + EFI_ACPI_DMAR_STRUCTURE_HEADER *DmarHeader; + + DmarHeader =3D (EFI_ACPI_DMAR_STRUCTURE_HEADER=20 +*)((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 += =20 +DmarHeader->Length); + } +} + +/** Initializes the Intel VTd PMR PEIM. =20 @param FileHandle Handle of the file being invoked. @@ -585,10 +1131,25 @@ IntelVTdPmrInitialize ( &gEdkiiVTdInfoPpiGuid, 0, NULL, - (VOID **)&mVTdInfoPpi + (VOID **)&mAcpiDmarTable ); ASSERT_EFI_ERROR(Status); =20 + DumpAcpiDMAR (mAcpiDmarTable); + + // + // Get DMAR information to local VTdInfo // Status =3D=20 + ParseDmarAcpiTableDrhd (); if (EFI_ERROR(Status)) { + return Status; + } + + // + // If there is RMRR memory, parse it here. + // + ParseDmarAcpiTableRmrr (); + // // Find a pre-memory in resource hob as DMA buffer // Mark PEI memory to be DMA protected. diff --git a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h b/= IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h index aa5926a7..720f5d4 100644 --- a/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h +++ b/IntelSiliconPkg/Feature/VTd/IntelVTdPmrPei/IntelVTdPmrPei.h @@ -15,9 +15,16 @@ #ifndef __DMA_ACCESS_LIB_H__ #define __DMA_ACCESS_LIB_H__ =20 +typedef struct { + UINT8 HostAddressWidth; + UINTN VTdEngineCount; + UINT64 VTdEngineAddress[1]; +} VTD_INFO; + /** Set DMA protected region. =20 + @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. @param HighMemoryBase The protected high memory region base. @@ -28,6 +35,7 @@ **/ EFI_STATUS SetDmaProtectedRange ( + IN UINT64 EngineMask, IN UINT32 LowMemoryBase, IN UINT32 LowMemoryLength, IN UINT64 HighMemoryBase, @@ -37,31 +45,37 @@ SetDmaProtectedRange ( /** Diable DMA protection. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @retval DMA protection is disabled. **/ EFI_STATUS DisableDmaProtection ( - VOID + IN UINT64 EngineMask ); =20 /** Get protected low memory alignment. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @return protected low memory alignment. **/ UINT32 GetLowMemoryAlignment ( - VOID + IN UINT64 EngineMask ); =20 /** Get protected high memory alignment. =20 + @param EngineMask The mask of the VTd engine to be accessed. + @return protected high memory alignment. **/ UINT64 GetHighMemoryAlignment ( - VOID + IN UINT64 EngineMask ); =20 #endif -- 2.7.4.windows.1