From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) (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 690598044B for ; Fri, 24 Mar 2017 00:48:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=intel.com; i=@intel.com; q=dns/txt; s=intel; t=1490341721; x=1521877721; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=qtY9l9ixcekIvnanPUqaZQkzYuHwTmw13B9VA2SuKw8=; b=NaKXwHTXtpcKM9GOkewKNUTnj6RHAvPTtiFpaial58xep3PQR97qMIZV 36lxNr+Q+tVtFaMcI0KUxDb3AzUhrg==; Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by orsmga102.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 24 Mar 2017 00:48:41 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.36,214,1486454400"; d="scan'208";a="1126534120" Received: from fmsmsx104.amr.corp.intel.com ([10.18.124.202]) by fmsmga001.fm.intel.com with ESMTP; 24 Mar 2017 00:48:40 -0700 Received: from fmsmsx121.amr.corp.intel.com (10.18.125.36) by fmsmsx104.amr.corp.intel.com (10.18.124.202) with Microsoft SMTP Server (TLS) id 14.3.319.2; Fri, 24 Mar 2017 00:48:40 -0700 Received: from shsmsx104.ccr.corp.intel.com (10.239.4.70) by fmsmsx121.amr.corp.intel.com (10.18.125.36) with Microsoft SMTP Server (TLS) id 14.3.319.2; Fri, 24 Mar 2017 00:48:40 -0700 Received: from shsmsx102.ccr.corp.intel.com ([169.254.2.212]) by SHSMSX104.ccr.corp.intel.com ([169.254.5.42]) with mapi id 14.03.0248.002; Fri, 24 Mar 2017 15:48:38 +0800 From: "Yao, Jiewen" To: "Zeng, Star" , 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: AQHSpG8ke1443pSTwEqQToPuCKkcqaGjmfCA Date: Fri, 24 Mar 2017 07:48:37 +0000 Message-ID: <74D8A39837DF1E4DA445A8C0B3885C503A9139A8@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> <0C09AFA07DD0434D9E2A0C6AEB0483103B84DACA@shsmsx102.ccr.corp.intel.com> In-Reply-To: <0C09AFA07DD0434D9E2A0C6AEB0483103B84DACA@shsmsx102.ccr.corp.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] 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:48:41 -0000 Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Hi Duran I have a little concern about this patch, because we do not introduce any C= PU specific thing in DxeCore so far. I think the basic requirement for SEV is to encrypt system memory, but not = MMIO. (Please correct me if I am wrong.) If that is the case, I would like to propose another solution for your cons= ideration. 1) In PEI phage, a platform should report PI resource description hob to de= scribe system resource, including system memory, and MMIO. 2) The DxeIpl can be updated to parse the PI resource description hob to ge= t all system memory (DRAM) and MMIO. The DxeIpl can setup page table based = upon the SEV policy on DRAM/MMIO. I think we should set SEV mask for DRAM (= no matter it is tested or untested), but always clear SEV mask for MMIO and= all rest. 3) When DxeCore gets control, the page table only has DRAM as encrypted, al= l rest MMIO as decrypted. 4) In DXE phase, if a platform module wants to add new DRAM resource, the e= ntity which submit ADD request needs to update page table. (NOTE: If a plat= form just want to convert an UNTESTED DRAM to a TESTED DRAM, this entity do= es not update page table, because it is already encrypted in DxeIpl.) If a = platform module wants to add new MMIO resource, this entity does not update= table, because it is already decrypted in DxeIpl.) Can above flow meet the AMD SEV requirement? Thank you Yao Jiewen > -----Original Message----- > From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ze= ng, > Star > Sent: Friday, March 24, 2017 3:20 PM > To: Leo Duran ; edk2-devel@ml01.01.org > Cc: Tian, Feng ; Brijesh Singh ; > Zeng, Star > Subject: Re: [edk2] [PATCH] MdeModulePkg/Core/Dxe: Clear SEV mask on > MMIO regions >=20 > I have comments below. >=20 > 1. Why need to call ConvertEncryptionOnAddressRange() at > GCD_FREE_MEMORY_OPERATION case? GCD_FREE_MEMORY_OPERATION does > not change the Entry->GcdMemoryType. > 2. I think it is better to use if (Entry->GcdMemoryType =3D=3D > EfiGcdMemoryTypeMemoryMappedIo) 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 define PAGING_2M_ADDRESS_MASK_64? > 4. Why need to unmask Cr3 like below in GcdHelper.c? The PageTables is no= t > masked at DxeIpl before written to CR3. Only the table entry needs to be > unmask in GcdHelper.c, right? > GcdHelper.c: Cr3 & ~AddressEncMask > DxeIpl: AsmWriteCr3 (PageTables); > 5. Do you need to add dummy GcdHelper.c for other archs? Do you need to p= ut > GcdHelperCommon.c and GcdHelper.h under the arch IA32 and X64 as other > archs do not need them? >=20 >=20 > Thanks, > Star > -----Original Message----- > From: Leo Duran [mailto:leo.duran@amd.com] > 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 >=20 > This patch intercepts MMIO configuration in the GCD module to ensure thos= e > regions are unmasked. >=20 > 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 >=20 > diff --git a/MdeModulePkg/Core/Dxe/DxeMain.inf > b/MdeModulePkg/Core/Dxe/DxeMain.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 = CIS. > # > # 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 > available under the terms and conditions of the BSD License # which > accompanies 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/Gcd.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 avail= able > under the terms and conditions of the BSD License which accompanies this > 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 > IMPLIED. >=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)); @@ > -741,6 +745,11 @@ CoreConvertSpace ( > } >=20 > // > + // Make sure AddressEncMask is contained to smallest supported address > field. > + // > + AddressEncMask =3D PcdGet64 (PcdPteMemoryEncryptionAddressOrMask) & > + PAGING_1G_ADDRESS_MASK_64; > + > + // > // Search for the list of descriptors that cover the range BaseAddress= to > BaseAddress+Length > // > Status =3D CoreSearchGcdMapEntry (BaseAddress, Length, &StartLink, > &EndLink, Map); @@ -893,6 +902,11 @@ CoreConvertSpace ( > Entry->GcdMemoryType =3D GcdMemoryType; > if (GcdMemoryType =3D=3D EfiGcdMemoryTypeMemoryMappedIo) { > Entry->Capabilities =3D Capabilities | EFI_MEMORY_RUNTIME | > EFI_MEMORY_PORT_IO; > + Status =3D ConvertEncryptionOnAddressRange (BaseAddress, Length, > CLEAR_ADDR_ENC_OPERATION, AddressEncMask); > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "Could not CLEAR EncMask on Range: > BaseAddress =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, > SET_ADDR_ENC_OPERATION, AddressEncMask); > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range: > BaseAddress =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, > SET_ADDR_ENC_OPERATION, AddressEncMask); > + if (EFI_ERROR (Status)) { > + DEBUG ((EFI_D_ERROR, "Could not SET EncMask on Range: > BaseAddress =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 > +available under the terms and conditions of the BSD License which > +accompanies this distribution. The full text of the license may be > +found at http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > + > +**/ > + > +#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/Writ= e > + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser > + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, > 1=3DWrite-Through caching > + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached > + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Acces= sed > (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 gl= obal > page TLB not cleared on CR3 write > + UINT64 Available:3; // Available for use by system > software > + UINT64 PageTableBaseAddress:40; // Page Table Base Address > + UINT64 AvailableHigh:11; // Available for use by system > software > + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Co= de > 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/Writ= e > + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser > + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, > 1=3DWrite-Through caching > + UINT64 CacheDisabled:1; // 0 =3D Cached, 1=3DNon-Cached > + UINT64 Accessed:1; // 0 =3D Not accessed, 1 =3D Acces= sed > (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 > + UINT64 Global:1; // 0 =3D Not global page, 1 =3D gl= obal > page TLB not cleared on CR3 write > + UINT64 Available:3; // Available for use by system > software > + UINT64 PAT:1; // > + UINT64 MustBeZero:8; // Must be zero; > + UINT64 PageTableBaseAddress:31; // Page Table Base Address > + UINT64 AvailableHigh:11; // Available for use by system > software > + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Co= de > 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 > +PAGING_2M_ADDRESS_MASK_64 0x000FFFFFFFE00000ull #define > +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 > specified 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/Core/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 > +available under the terms and conditions of the BSD License which > +accompanies this distribution. The full text of the license may be > +found at http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > + > +**/ > + > +#include "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 > + (PageTableEntry !=3D NULL); > + > + // > + // Fill in 2M page entry. > + // > + *PageEntry2M =3D (UINT64)(UINTN) PageTableEntry | AddressEncMask | > + IA32_PG_P | IA32_PG_RW; > + > + PhysicalAddress4K =3D PhysicalAddress; > + for (IndexOfPageTableEntries =3D 0; IndexOfPageTableEntries < 512; > IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K +=3D SIZE_= 4KB) > { > + // > + // Fill in the Page Table entries > + // > + PageTableEntry->Uint64 =3D (UINT64) PhysicalAddress4K | AddressEncMa= sk; > + 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); > + ASSERT (PageDirectoryEntry !=3D NULL); > + > + // > + // Fill in 1G page entry. > + // > + *PageEntry1G =3D (UINT64)(UINTN) PageDirectoryEntry | AddressEncMask | > + IA32_PG_P | IA32_PG_RW; > + > + PhysicalAddress2M =3D PhysicalAddress; > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < = 512; > IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += =3D > SIZE_2MB) { > + // > + // Fill in the Page Directory entries > + // > + PageDirectoryEntry->Uint64 =3D (UINT64) PhysicalAddress2M | > AddressEncMask; > + 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 > +available under the terms and conditions of the BSD License which > +accompanies this distribution. The full text of the license may be > +found at http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > + > +**/ > + > +#include "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 > specified 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 > + 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_ADDRESS_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] & ~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], > Operation, AddressEncMask); > + PhysicalAddress +=3D SIZE_2MB; > + Length -=3D SIZE_2MB; > + } else { > + // Split 2MB page entry to consume 4K chunks > + Split2MPageTo4KPageOnEncRange (PhysicalAddress, AddressEncMask, > &PageTable[PTIndex]); > + } > + } else { > + // PTE Present? > + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & > ~AddressEncMask & 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; > +} > + > 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 > +available under the terms and conditions of the BSD License which > +accompanies this distribution. The full text of the license may be > +found at http://opensource.org/licenses/bsd-license.php > + > +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, > +WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS > OR IMPLIED. > + > +**/ > + > +#include "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 > specified 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_ADDRESS_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] & ~AddressEncMas= k > & 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 SIZ= E_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, > &PageTable[PTIndex]); > + } > + } else { > + // 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 S= IZE_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, &PageTable[PTIndex]); > + } > + } else { > + // PTE Present? > + PageTable =3D (UINT64 *)(UINTN) (PageTable[PTIndex] & > ~AddressEncMask & 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 >=20 > _______________________________________________ > edk2-devel mailing list > edk2-devel@lists.01.org > https://lists.01.org/mailman/listinfo/edk2-devel