From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) (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 0CC77803B1 for ; Fri, 24 Mar 2017 00:20:25 -0700 (PDT) Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga104.jf.intel.com with ESMTP; 24 Mar 2017 00:20:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,213,1486454400"; d="scan'208";a="64438250" Received: from fmsmsx108.amr.corp.intel.com ([10.18.124.206]) by orsmga002.jf.intel.com with ESMTP; 24 Mar 2017 00:20:24 -0700 Received: from fmsmsx114.amr.corp.intel.com (10.18.116.8) by FMSMSX108.amr.corp.intel.com (10.18.124.206) with Microsoft SMTP Server (TLS) id 14.3.319.2; Fri, 24 Mar 2017 00:20:24 -0700 Received: from shsmsx103.ccr.corp.intel.com (10.239.4.69) by FMSMSX114.amr.corp.intel.com (10.18.116.8) with Microsoft SMTP Server (TLS) id 14.3.319.2; Fri, 24 Mar 2017 00:20:23 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.212]) by SHSMSX103.ccr.corp.intel.com ([169.254.4.253]) with mapi id 14.03.0248.002; Fri, 24 Mar 2017 15:20:21 +0800 From: "Zeng, Star" To: Leo Duran , "edk2-devel@ml01.01.org" CC: "Tian, Feng" , Brijesh Singh , "Zeng, Star" Thread-Topic: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO regions Thread-Index: AQHSpEminOKX8G1OMUyqRgmU65bEmaGjjz4A Date: Fri, 24 Mar 2017 07:20:21 +0000 Message-ID: <0C09AFA07DD0434D9E2A0C6AEB0483103B84DACA@shsmsx102.ccr.corp.intel.com> References: <1490323887-9686-1-git-send-email-leo.duran@amd.com> <1490323887-9686-2-git-send-email-leo.duran@amd.com> In-Reply-To: <1490323887-9686-2-git-send-email-leo.duran@amd.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] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO regions 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: Fri, 24 Mar 2017 07:20:25 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable I have comments below. 1. Why need to call ConvertEncryptionOnAddressRange() at GCD_FREE_MEMORY_OP= ERATION case? GCD_FREE_MEMORY_OPERATION does not change the Entry->GcdMemor= yType. 2. I think it is better to use if (Entry->GcdMemoryType =3D=3D EfiGcdMemory= TypeMemoryMappedIo) instead of if (Entry->Capabilities & EFI_MEMORY_PORT_IO= ) for GCD_REMOVE_MEMORY_OPERATION case. 3. Why need to use PAGING_4K_ADDRESS_MASK_64 in GcdHelper.c? Why need to de= fine PAGING_2M_ADDRESS_MASK_64? 4. Why need to unmask Cr3 like below in GcdHelper.c? The PageTables is not = masked at DxeIpl before written to CR3. Only the table entry needs to be un= mask in GcdHelper.c, right? GcdHelper.c: Cr3 & ~AddressEncMask DxeIpl: AsmWriteCr3 (PageTables);=20 5. Do you need to add dummy GcdHelper.c for other archs? Do you need to put= GcdHelperCommon.c and GcdHelper.h under the arch IA32 and X64 as other arc= hs do not need them? Thanks, Star -----Original Message----- From: Leo Duran [mailto:leo.duran@amd.com]=20 Sent: Friday, March 24, 2017 10:51 AM To: edk2-devel@ml01.01.org Cc: Leo Duran ; Tian, Feng ; Zeng, = Star ; Brijesh Singh Subject: [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on MMIO regions This patch intercepts MMIO configuration in the GCD module to ensure those = regions are unmasked. Cc: Feng Tian Cc: Star Zeng Cc: Brijesh Singh Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Leo Duran --- MdeModulePkg/Core/Dxe/DxeMain.inf | 11 ++ MdeModulePkg/Core/Dxe/Gcd/Gcd.c | 28 ++++++ MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h | 151 ++++++++++++++++++++++++= ++++ MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c | 120 ++++++++++++++++++++++ = MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c | 115 +++++++++++++++++++++ MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c | 129 ++++++++++++++++++++++++ 6 files changed, 554 insertions(+) create mode 100644 MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h create mode 100644 MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c create mode 100644 MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c create mode 100644 MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf b/MdeModulePkg/Core/Dxe/DxeM= ain.inf index 30d5984..183d1e7 100644 --- a/MdeModulePkg/Core/Dxe/DxeMain.inf +++ b/MdeModulePkg/Core/Dxe/DxeMain.inf @@ -4,6 +4,8 @@ # It provides an implementation of DXE Core that is compliant with DXE CI= S. # # Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+# Copyright (c) 2017, AMD Incorporated. All rights reserved.
# # This program and the accompanying materials # are licensed and made a= vailable under the terms and conditions of the BSD License # which accomp= anies this distribution. The full text of the license may be found at @@ -= 51,6 +53,8 @@ Hand/Handle.h Gcd/Gcd.c Gcd/Gcd.h + Gcd/GcdHelperCommon.c + Gcd/GcdHelper.h Mem/Pool.c Mem/Page.c Mem/MemData.c @@ -73,6 +77,12 @@ DxeMain/DxeProtocolNotify.c DxeMain/DxeMain.c =20 +[Sources.Ia32] + Gcd/Ia32/GcdHelper.c + +[Sources.X64] + Gcd/X64/GcdHelper.c + [Packages] MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec @@ -192,6 +202,7 @@ gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdImageProtectionPolicy = ## CONSUMES gEfiMdeModulePkgTokenSpaceGuid.PcdDxeNxMemoryProtectionPolicy = ## CONSUMES + gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask = ## CONSUMES =20 # [Hob] # RESOURCE_DESCRIPTOR ## CONSUMES diff --git a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c b/MdeModulePkg/Core/Dxe/Gcd/Gc= d.c index a06f8bb..6f85c21 100644 --- a/MdeModulePkg/Core/Dxe/Gcd/Gcd.c +++ b/MdeModulePkg/Core/Dxe/Gcd/Gcd.c @@ -4,6 +4,8 @@ are accessible to the CPU that is executing the DXE core. =20 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ This program and the accompanying materials are licensed and made availab= le under the terms and conditions of the BSD License which accompanies thi= s distribution. The full text of the license may be found at @@ -16,6 +18,= 7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR I= MPLIED. =20 #include "DxeMain.h" #include "Gcd.h" +#include "GcdHelper.h" =20 #define MINIMUM_INITIAL_MEMORY_SIZE 0x10000 =20 @@ -723,6 +726,7 @@ CoreConvertSpace ( LIST_ENTRY *StartLink; LIST_ENTRY *EndLink; UINT64 CpuArchAttributes; + UINT64 AddressEncMask; =20 if (Length =3D=3D 0) { DEBUG ((DEBUG_GCD, " Status =3D %r\n", EFI_INVALID_PARAMETER)); @@ -7= 41,6 +745,11 @@ CoreConvertSpace ( } =20 // + // Make sure AddressEncMask is contained to smallest supported address f= ield. + // + AddressEncMask =3D PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) &=20 + PAGING_1G_ADDRESS_MASK_64; + + // // Search for the list of descriptors that cover the range BaseAddress t= o BaseAddress+Length // Status =3D CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, &EndL= ink, Map); @@ -893,6 +902,11 @@ CoreConvertSpace ( Entry->GcdMemoryType =3D GcdMemoryType; if (GcdMemoryType =3D=3D EfiGcdMemoryTypeMemoryMappedIo) { Entry->Capabilities =3D Capabilities | EFI_MEMORY_RUNTIME | EFI_M= EMORY_PORT_IO; + Status =3D ConvertEncryptionOnAddressRange (BaseAddress, Length, C= LEAR_ADDR_ENC_OPERATION, AddressEncMask); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Could not CLEAR EncMask on Range: BaseAddr= ess =3D 0xlX, Length =3D 0xlX, Status =3D %r\n", + BaseAddress, Length, Status)); + } } else { Entry->Capabilities =3D Capabilities | EFI_MEMORY_RUNTIME; } @@ -904,6 +918,13 @@ CoreConvertSpace ( // Free operations // case GCD_FREE_MEMORY_OPERATION: + if (Entry->Capabilities & EFI_MEMORY_PORT_IO) { + Status =3D ConvertEncryptionOnAddressRange (BaseAddress, Length, S= ET_ADDR_ENC_OPERATION, AddressEncMask); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range: BaseAddres= s =3D 0xlX, Length =3D 0xlX, Status =3D %r\n", + BaseAddress, Length, Status)); + } + } case GCD_FREE_IO_OPERATION: Entry->ImageHandle =3D NULL; Entry->DeviceHandle =3D NULL; @@ -912,6 +933,13 @@ CoreConvertSpace ( // Remove operations // case GCD_REMOVE_MEMORY_OPERATION: + if (Entry->Capabilities & EFI_MEMORY_PORT_IO) { + Status =3D ConvertEncryptionOnAddressRange (BaseAddress, Length, S= ET_ADDR_ENC_OPERATION, AddressEncMask); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range: BaseAddres= s =3D 0xlX, Length =3D 0xlX, Status =3D %r\n", + BaseAddress, Length, Status)); + } + } Entry->GcdMemoryType =3D EfiGcdMemoryTypeNonExistent; Entry->Capabilities =3D 0; break; diff --git a/MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h b/MdeModulePkg/Core/Dxe/= Gcd/GcdHelper.h new file mode 100644 index 0000000..d6ec339 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/Gcd/GcdHelper.h @@ -0,0 +1,151 @@ +/** @file + Definitions for helper functions used by GCD. + +Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials are licensed and made=20 +available under the terms and conditions of the BSD License which=20 +accompanies this distribution. The full text of the license may be=20 +found at http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=20 +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#ifndef _GCD_HELPER_H_ +#define _GCD_HELPER_H_ + + +#pragma pack(1) +// +// Page Table Entry 4KB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by= processor on access to page + UINT64 PAT:1; // + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PageTableBaseAddress:40; // Page Table Base Address + UINT64 AvailableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Code= Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_4K_ENTRY; + +// +// Page Table Entry 2MB +// +typedef union { + struct { + UINT64 Present:1; // 0 =3D Not present in memory, 1 = =3D Present in memory + UINT64 ReadWrite:1; // 0 =3D Read-Only, 1=3D Read/Write + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DWri= te-Through caching + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Accesse= d (set by CPU) + UINT64 Dirty:1; // 0 =3D Not Dirty, 1 =3D written by= processor on access to page + UINT64 MustBe1:1; // Must be 1=20 + UINT64 Global:1; // 0 =3D Not global page, 1 =3D glob= al page TLB not cleared on CR3 write + UINT64 Available:3; // Available for use by system softw= are + UINT64 PAT:1; // + UINT64 MustBeZero:8; // Must be zero; + UINT64 PageTableBaseAddress:31; // Page Table Base Address + UINT64 AvailableHigh:11; // Available for use by system softw= are + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Code= Execution + } Bits; + UINT64 Uint64; +} PAGE_TABLE_2M_ENTRY; +#pragma pack() + + +typedef enum { + CLEAR_ADDR_ENC_OPERATION, + SET_ADDR_ENC_OPERATION, + INVALID_ENC_OPERATION +} ADDR_ENC_OPERATION; + + +#define IA32_PG_P BIT0 +#define IA32_PG_RW BIT1 +#define IA32_PG_PS BIT7 + +#define PAGING_4K_ADDRESS_MASK_64 0x000FFFFFFFFFF000ull #define=20 +PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull #define=20 +PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull + + +/** + Convert Encryption on address range + + @param BaseAddress Start address of the range + @param Length Length of the segment + @param Operation Convertion operation (set or clear) + @param AddressEncMask Address Encryption Mask + + @retval EFI_INVALID_PARAMETER Length or Address not aligned on EFI_PAGE= _SIZE boundary. + @retval EFI_NO_MAPPING Missing page table mappings for the speci= fied segment. + @retval EFI_SUCCESS Action successfully done. +**/ +EFI_STATUS +ConvertEncryptionOnAddressRange ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN ADDR_ENC_OPERATION Operation, + IN UINT64 AddressEncMask + ); + +/** + Convert Encryption on page table entry. + + @param PageTableEntry Start address of the range + @param Operation Convertion operation (set or clear) + @param AddressEncMask Address Encryption Mask + +**/ +VOID +ConvertEncryptionOnPageTableEntry ( + IN UINT64 *PageTableEntry, + IN ADDR_ENC_OPERATION Operation, + IN UINT64 AddressEncMask + ); + +/** + Split 1G page to 2M on Encrypted address range. + + @param[in] PhysicalAddress Address of the encryted range. + @param[in] AddressEncMask Address Encryption Mask. + @param[in, out] PageEntry1G Pointer to 1G page entry. + +**/ +VOID +Split1GPageTo2MPageOnEncRange ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 AddressEncMask, + IN OUT UINT64 *PageEntry1G + ); + +/** + Split 2M page to 4K on Encrypted address range. + + @param[in] PhysicalAddress Address of the range. + @param[in] AddressEncmask Encryption Mask. + @param[in, out] PageEntry2M Pointer to 2M page entry. + +**/ +VOID +Split2MPageTo4KPageOnEncRange ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 AddressEncMask, + IN OUT UINT64 *PageEntry2M + ); + +#endif // _GCD_HELPER_H_ + diff --git a/MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c b/MdeModulePkg/Cor= e/Dxe/Gcd/GcdHelperCommon.c new file mode 100644 index 0000000..1660732 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/Gcd/GcdHelperCommon.c @@ -0,0 +1,120 @@ +/** @file + The file contains helper functions used by GCD. + +Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials are licensed and made=20 +available under the terms and conditions of the BSD License which=20 +accompanies this distribution. The full text of the license may be=20 +found at http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=20 +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "DxeMain.h" +#include "GcdHelper.h" + + +/** + Split 2M page to 4K on Encrypted address range. + + @param[in] PhysicalAddress Address of the range. + @param[in] AddressEncmask Encryption Mask. + @param[in, out] PageEntry2M Pointer to 2M page entry. + +**/ +VOID +Split2MPageTo4KPageOnEncRange ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 AddressEncMask, + IN OUT UINT64 *PageEntry2M + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress4K; + UINTN IndexOfPageTableEntries; + PAGE_TABLE_4K_ENTRY *PageTableEntry; + + PageTableEntry =3D (PAGE_TABLE_4K_ENTRY *)AllocatePages (1); ASSERT=20 + (PageTableEntry !=3D NULL); + + // + // Fill in 2M page entry. + // + *PageEntry2M =3D (UINT64)(UINTN) PageTableEntry | AddressEncMask |=20 + IA32_PG_P | IA32_PG_RW; + + PhysicalAddress4K =3D PhysicalAddress; + for (IndexOfPageTableEntries =3D 0; IndexOfPageTableEntries < 512; Index= OfPageTableEntries++, PageTableEntry++, PhysicalAddress4K +=3D SIZE_4KB) { + // + // Fill in the Page Table entries + // + PageTableEntry->Uint64 =3D (UINT64) PhysicalAddress4K | AddressEncMask= ; + PageTableEntry->Bits.ReadWrite =3D 1; + PageTableEntry->Bits.Present =3D 1; + } +} + + +/** + Split 1G page to 2M on Encrypted address range. + + @param[in] PhysicalAddress Address of the encryted range. + @param[in] AddressEncMask Address Encryption Mask. + @param[in, out] PageEntry1G Pointer to 1G page entry. + +**/ +VOID +Split1GPageTo2MPageOnEncRange ( + IN EFI_PHYSICAL_ADDRESS PhysicalAddress, + IN UINT64 AddressEncMask, + IN OUT UINT64 *PageEntry1G + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress2M; + UINTN IndexOfPageDirectoryEntries; + PAGE_TABLE_2M_ENTRY *PageDirectoryEntry; + + PageDirectoryEntry =3D (PAGE_TABLE_2M_ENTRY *)AllocatePages (1); =20 + ASSERT (PageDirectoryEntry !=3D NULL); + + // + // Fill in 1G page entry. + // + *PageEntry1G =3D (UINT64)(UINTN) PageDirectoryEntry | AddressEncMask |=20 + IA32_PG_P | IA32_PG_RW; + + PhysicalAddress2M =3D PhysicalAddress; + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < 51= 2; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += =3D SIZE_2MB) { + // + // Fill in the Page Directory entries + // + PageDirectoryEntry->Uint64 =3D (UINT64) PhysicalAddress2M | AddressEnc= Mask; + PageDirectoryEntry->Bits.ReadWrite =3D 1; + PageDirectoryEntry->Bits.Present =3D 1; + PageDirectoryEntry->Bits.MustBe1 =3D 1; + } +} + + +/** + Convert Encryption on page table entry. + + @param PageTableEntry Start address of the range + @param Operation Convertion operation (set or clear) + @param AddressEncMask Address Encryption Mask + +**/ +VOID +ConvertEncryptionOnPageTableEntry ( + IN UINT64 *PageTableEntry, + IN ADDR_ENC_OPERATION Operation, + IN UINT64 AddressEncMask + ) +{ + if (Operation =3D=3D CLEAR_ADDR_ENC_OPERATION) { + *PageTableEntry &=3D ~AddressEncMask; + } else if (Operation =3D=3D SET_ADDR_ENC_OPERATION) { + *PageTableEntry |=3D AddressEncMask; + } +} + diff --git a/MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c b/MdeModulePkg/Core= /Dxe/Gcd/Ia32/GcdHelper.c new file mode 100644 index 0000000..4781900 --- /dev/null +++ b/MdeModulePkg/Core/Dxe/Gcd/Ia32/GcdHelper.c @@ -0,0 +1,115 @@ +/** @file + The file contains helper functions used by GCD. + +Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials are licensed and made=20 +available under the terms and conditions of the BSD License which=20 +accompanies this distribution. The full text of the license may be=20 +found at http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=20 +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "DxeMain.h" +#include "GcdHelper.h" + + +/** + Convert Encryption on address range. + + @param BaseAddress Start address of the range + @param Length Length of the range + @param Operation Convertion operation (set or clear) + @param AddressEncMask Address Encryption Mask + + @retval EFI_INVALID_PARAMETER Length or Address not aligned on EFI_PAGE= _SIZE boundary. + @retval EFI_NO_MAPPING Missing page table mappings for the speci= fied range. + @retval EFI_SUCCESS Action successfully done. +**/ +EFI_STATUS +ConvertEncryptionOnAddressRange ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN ADDR_ENC_OPERATION Operation, + IN UINT64 AddressEncMask + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT64 *PageTable; + UINTN PTIndex; + UINT64 Cr3; + + // Do we have actual work to do? + if (Length =3D=3D 0 || AddressEncMask =3D=3D 0) { + return EFI_SUCCESS; + } + + // PAE *must* be enabled on 32-bit page tables // (else we can't=20 + configure AddressEncMask) if ((AsmReadCr4 () & BIT5) =3D=3D 0) { + return EFI_SUCCESS; + } + + // Make sure we're PAGE_SIZE aligned + if ((BaseAddress & EFI_PAGE_MASK) || (Length & EFI_PAGE_MASK)) { + return EFI_INVALID_PARAMETER; + } + + // Validate Operation + if (Operation >=3D INVALID_ENC_OPERATION) { + return EFI_INVALID_PARAMETER; + } + + Cr3 =3D AsmReadCr3 (); + PhysicalAddress =3D BaseAddress; + + do { + // PDPE Present? + PageTable =3D (UINT64 *)(UINTN) (Cr3 & ~AddressEncMask & PAGING_4K_ADD= RESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 30, 31); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // PDE Present? + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & ~AddressEncMask = & PAGING_4K_ADDRESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 21, 29); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // Is it a 2MB page entry? + if ((PageTable[PTIndex] & IA32_PG_PS ) !=3D 0) { + if ((PhysicalAddress & (SIZE_2MB - 1)) =3D=3D 0 && Length >=3D SIZE_= 2MB) { + // Consume 2MB from the range + ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex], Operation,= AddressEncMask); + PhysicalAddress +=3D SIZE_2MB; + Length -=3D SIZE_2MB; + } else { + // Split 2MB page entry to consume 4K chunks + Split2MPageTo4KPageOnEncRange (PhysicalAddress, AddressEncMask, &P= ageTable[PTIndex]);=20 + } + } else { + // PTE Present? + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & ~AddressEncMas= k & PAGING_4K_ADDRESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 12, 20); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // Consume 4KB from the range + ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex], Operation, A= ddressEncMask); + PhysicalAddress +=3D SIZE_4KB; + Length -=3D SIZE_4KB; + } + } while (Length); + + // Flush TLB + AsmWriteCr3 (Cr3); + + return EFI_SUCCESS; +} + diff --git a/MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c b/MdeModulePkg/Core/= Dxe/Gcd/X64/GcdHelper.c new file mode 100644 index 0000000..5943f7a --- /dev/null +++ b/MdeModulePkg/Core/Dxe/Gcd/X64/GcdHelper.c @@ -0,0 +1,129 @@ +/** @file + The file contains helper functions used by GCD. + +Copyright (c) 2017, AMD Incorporated. All rights reserved.
+ +This program and the accompanying materials are licensed and made=20 +available under the terms and conditions of the BSD License which=20 +accompanies this distribution. The full text of the license may be=20 +found at http://opensource.org/licenses/bsd-license.php + +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,=20 +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLI= ED. + +**/ + +#include "DxeMain.h" +#include "GcdHelper.h" + + +/** + Convert Encryption on address range. + + @param BaseAddress Start address of the range + @param Length Length of the range + @param Operation Convertion operation (set or clear) + @param AddressEncMask Address Encryption Mask + + @retval EFI_INVALID_PARAMETER Length or Address not aligned on EFI_PAGE= _SIZE boundary. + @retval EFI_NO_MAPPING Missing page table mappings for the speci= fied range. + @retval EFI_SUCCESS Action successfully done. +**/ +EFI_STATUS +ConvertEncryptionOnAddressRange ( + IN EFI_PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN ADDR_ENC_OPERATION Operation, + IN UINT64 AddressEncMask + ) +{ + EFI_PHYSICAL_ADDRESS PhysicalAddress; + UINT64 *PageTable; + UINTN PTIndex; + UINT64 Cr3; + + // Do we have actual work to do? + if (Length =3D=3D 0 || AddressEncMask =3D=3D 0) { + return EFI_SUCCESS; + } + + // Make sure we're PAGE_SIZE aligned + if ((BaseAddress & EFI_PAGE_MASK) || (Length & EFI_PAGE_MASK)) { + return EFI_INVALID_PARAMETER; + } + + // Validate Operation + if (Operation >=3D INVALID_ENC_OPERATION) { + return EFI_INVALID_PARAMETER; + } + + Cr3 =3D AsmReadCr3 (); + PhysicalAddress =3D BaseAddress; + + do { + // PML4E Present? + PageTable =3D (UINT64 *)(UINTN) (Cr3 & ~AddressEncMask & PAGING_4K_ADD= RESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 39, 47); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // PDPE Present? + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & ~AddressEncMask = & PAGING_4K_ADDRESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 30, 38); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // Is it a 1GB page entry? + if ((PageTable[PTIndex] & IA32_PG_PS ) !=3D 0) { + if ((PhysicalAddress & (SIZE_1GB - 1)) =3D=3D 0 && Length >=3D SIZE_= 1GB) { + // Consume 1GB from the range + ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex], Operation,= AddressEncMask); + PhysicalAddress +=3D SIZE_1GB; + Length -=3D SIZE_1GB; + } else { + // Split 1G page entry to attempt consuming 2MB chunks + Split1GPageTo2MPageOnEncRange (PhysicalAddress, AddressEncMask, &P= ageTable[PTIndex]);=20 + } + } else { + // PDE Present? + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & ~AddressEncMas= k & PAGING_4K_ADDRESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 21, 29); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // Is it a 2MB page entry? + if ((PageTable[PTIndex] & IA32_PG_PS ) !=3D 0) { + if ((PhysicalAddress & (SIZE_2MB - 1)) =3D=3D 0 && Length >=3D SIZ= E_2MB) { + // Consume 2MB from the range + ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex], Operatio= n, AddressEncMask); + PhysicalAddress +=3D SIZE_2MB; + Length -=3D SIZE_2MB; + } else { + // Split 2MB page entry to consume 4K chunks + Split2MPageTo4KPageOnEncRange (PhysicalAddress, AddressEncMask, = &PageTable[PTIndex]);=20 + } + } else { + // PTE Present? + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & ~AddressEncM= ask & PAGING_4K_ADDRESS_MASK_64); + PTIndex =3D BitFieldRead64(PhysicalAddress, 12, 20); + if ((PageTable[PTIndex] & IA32_PG_P) =3D=3D 0) { + return EFI_NO_MAPPING; + } + + // Consume 4KB from the range + ConvertEncryptionOnPageTableEntry (&PageTable[PTIndex], Operation,= AddressEncMask); + PhysicalAddress +=3D SIZE_4KB; + Length -=3D SIZE_4KB; + } + } + } while (Length); + + // Flush TLB + AsmWriteCr3 (Cr3); + + return EFI_SUCCESS; +} + -- 2.7.4