From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) (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 B96C921A02926 for ; Fri, 26 May 2017 13:54:39 -0700 (PDT) Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga101.jf.intel.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384; 26 May 2017 13:54:39 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.38,399,1491289200"; d="scan'208";a="105907845" Received: from mvakil-mobl1.amr.corp.intel.com (HELO localhost) ([10.254.191.209]) by orsmga005.jf.intel.com with ESMTP; 26 May 2017 13:54:38 -0700 MIME-Version: 1.0 To: Jiewen Yao , Jeff Fan , Brijesh Singh , edk2-devel@lists.01.org Message-ID: <149583207795.25973.8215621482706964409@jljusten-skl> From: Jordan Justen In-Reply-To: <1495809845-32472-5-git-send-email-brijesh.singh@amd.com> Cc: Thomas.Lendacky@amd.com, leo.duran@amd.com, Brijesh Singh , Laszlo Ersek References: <1495809845-32472-1-git-send-email-brijesh.singh@amd.com> <1495809845-32472-5-git-send-email-brijesh.singh@amd.com> User-Agent: alot/0.5.1 Date: Fri, 26 May 2017 13:54:38 -0700 Subject: Re: [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library 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, 26 May 2017 20:54:39 -0000 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Jiewen, Jeff, Brijesh, Is there a reason this shouldn't go under UefiCpuPkg rather than OvmfPkg? -Jordan On 2017-05-26 07:43:52, Brijesh Singh wrote: > Add Secure Encrypted Virtualization (SEV) helper library. > The library provides the routines to: > - set or clear memory encryption bit for a given memory region. > - query whether SEV is enabled. > = > = > Cc: Jordan Justen > Cc: Laszlo Ersek > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Brijesh Singh > Reviewed-by: Laszlo Ersek > --- > OvmfPkg/OvmfPkgIa32.dsc | 1 + > OvmfPkg/OvmfPkgIa32X64.dsc | 1 + > OvmfPkg/OvmfPkgX64.dsc | 1 + > OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf | 50 +++ > OvmfPkg/Include/Library/MemEncryptSevLib.h | 81 ++= ++ > OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h | 184 ++= ++++++ > OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c | 84 ++= ++ > OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c | 90 ++= ++ > OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c | 84 ++= ++ > OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c | 439 ++= ++++++++++++++++++ > 10 files changed, 1015 insertions(+) > = > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index b5c874b65afc..98691c0a6d99 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -145,6 +145,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSe= vLib.inf > !if $(SMM_REQUIRE) =3D=3D FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index 1d071cac2bef..3b51513a4d95 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -150,6 +150,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSe= vLib.inf > !if $(SMM_REQUIRE) =3D=3D FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index 2bea75437788..ebf07cd585dd 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -150,6 +150,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSe= vLib.inf > !if $(SMM_REQUIRE) =3D=3D FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.in= f b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf > new file mode 100644 > index 000000000000..3cfd80a28c1d > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf > @@ -0,0 +1,50 @@ > +## @file > +# Library provides the helper functions for SEV guest > +# > +# Copyright (c) 2017 Advanced Micro Devices. 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 lic= ense > +# 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. > +# > +# > +## > + > +[Defines] > + INF_VERSION =3D 1.25 > + BASE_NAME =3D MemEncryptSevLib > + FILE_GUID =3D c1594631-3888-4be4-949f-9c630dbc842b > + MODULE_TYPE =3D BASE > + VERSION_STRING =3D 1.0 > + LIBRARY_CLASS =3D MemEncryptSevLib|PEIM DXE_DRIVER DX= E_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER > + > +# > +# The following information is for reference only and not required by th= e build tools. > +# > +# VALID_ARCHITECTURES =3D IA32 X64 > +# > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + OvmfPkg/OvmfPkg.dec > + UefiCpuPkg/UefiCpuPkg.dec > + > +[Sources.X64] > + MemEncryptSevLibInternal.c > + X64/MemEncryptSevLib.c > + X64/VirtualMemory.c > + > +[Sources.IA32] > + MemEncryptSevLibInternal.c > + Ia32/MemEncryptSevLib.c > + > +[LibraryClasses] > + BaseLib > + CpuLib > + CacheMaintenanceLib > + DebugLib > + MemoryAllocationLib > diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include= /Library/MemEncryptSevLib.h > new file mode 100644 > index 000000000000..b6753762423e > --- /dev/null > +++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h > @@ -0,0 +1,81 @@ > +/** @file > + > + Define Secure Encrypted Virtualization (SEV) base library helper funct= ion > + > + Copyright (c) 2017, AMD Incorporated. All rights reserved.
> + > + This program and the accompanying materials are licensed and made avai= lable > + under the terms and conditions of the BSD License which accompanies th= is > + 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 I= MPLIED. > + > +**/ > + > +#ifndef _MEM_ENCRYPT_SEV_LIB_H_ > +#define _MEM_ENCRYPT_SEV_LIB_H_ > + > +#include > + > +/** > + Returns a boolean to indicate whether SEV is enabled > + > + @retval TRUE SEV is active > + @retval FALSE SEV is not enabled > + **/ > +BOOLEAN > +EFIAPI > +MemEncryptSevIsEnabled ( > + VOID > + ); > + > +/** > + This function clears memory encryption bit for the memory region speci= fied > + by BaseAddress and Number of pages from the current page table context. > + > + @param[in] BaseAddress The physical address that is the sta= rt address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memor= y region. > + @param[in] Flush Flush the caches before clearing the= bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were cleared for the = memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute= is not > + supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevClearPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumberOfPages, > + IN BOOLEAN CacheFlush > + ); > + > +/** > + This function sets memory encryption bit for the memory region specifi= ed by > + BaseAddress and Number of pages from the current page table context. > + > + @param[in] BaseAddress The physical address that is the sta= rt address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memor= y region. > + @param[in] Flush Flush the caches before clearing the= bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were set for the memo= ry region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute= is not > + supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevSetPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumberOfPages, > + IN BOOLEAN CacheFlush > + ); > +#endif // _MEM_ENCRYPT_SEV_LIB_H_ > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h b/O= vmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > new file mode 100644 > index 000000000000..70cd2187a326 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > @@ -0,0 +1,184 @@ > +/** @file > + > + Virtual Memory Management Services to set or clear the memory encrypti= on bit > + > +Copyright (c) 2006 - 2016, 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 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. > + > +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.h > + > +**/ > + > +#ifndef __VIRTUAL_MEMORY__ > +#define __VIRTUAL_MEMORY__ > + > +#include > +#include > +#include > +#include > +#include > + > +#include > +#define SYS_CODE64_SEL 0x38 > + > +#pragma pack(1) > + > +// > +// Page-Map Level-4 Offset (PML4) and > +// Page-Directory-Pointer Offset (PDPE) entries 4K & 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=3DW= rite-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 Reserved:1; // Reserved > + UINT64 MustBeZero:2; // Must Be Zero > + UINT64 Available:3; // Available for use by system sof= tware > + UINT64 PageTableBaseAddress:40; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system sof= tware > + UINT64 Nx:1; // No Execute bit > + } Bits; > + UINT64 Uint64; > +} PAGE_MAP_AND_DIRECTORY_POINTER; > + > +// > +// 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=3DW= rite-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 sof= tware > + UINT64 PageTableBaseAddress:40; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system sof= tware > + 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/Write > + UINT64 UserSupervisor:1; // 0 =3D Supervisor, 1=3DUser > + UINT64 WriteThrough:1; // 0 =3D Write-Back caching, 1=3DW= rite-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 sof= tware > + UINT64 PAT:1; // > + UINT64 MustBeZero:8; // Must be zero; > + UINT64 PageTableBaseAddress:31; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system sof= tware > + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Co= de Execution > + } Bits; > + UINT64 Uint64; > +} PAGE_TABLE_ENTRY; > + > +// > +// Page Table Entry 1GB > +// > +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=3DW= rite-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 sof= tware > + UINT64 PAT:1; // > + UINT64 MustBeZero:17; // Must be zero; > + UINT64 PageTableBaseAddress:22; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system sof= tware > + UINT64 Nx:1; // 0 =3D Execute Code, 1 =3D No Co= de Execution > + } Bits; > + UINT64 Uint64; > +} PAGE_TABLE_1G_ENTRY; > + > +#pragma pack() > + > +#define IA32_PG_P BIT0 > +#define IA32_PG_RW BIT1 > + > +#define PAGETABLE_ENTRY_MASK ((1UL << 9) - 1) > +#define PML4_OFFSET(x) ( (x >> 39) & PAGETABLE_ENTRY_MASK) > +#define PDP_OFFSET(x) ( (x >> 30) & PAGETABLE_ENTRY_MASK) > +#define PDE_OFFSET(x) ( (x >> 21) & PAGETABLE_ENTRY_MASK) > +#define PTE_OFFSET(x) ( (x >> 12) & PAGETABLE_ENTRY_MASK) > +#define PAGING_1G_ADDRESS_MASK_64 0x000FFFFFC0000000ull > + > +/** > + This function clears memory encryption bit for the memory region speci= fied by PhysicalAddress > + and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the s= tart address of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying t= he encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attr= ibute is not supported > +**/ > +RETURN_STATUS > +EFIAPI > +InternalMemEncryptSevSetMemoryDecrypted ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN UINT64 Length, > + IN BOOLEAN CacheFlush > + ); > + > +/** > + This function sets memory encryption bit for the memory region specifi= ed by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the s= tart address > + of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying t= he > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attr= ibute is > + not supported > +**/ > +RETURN_STATUS > +EFIAPI > +InternalMemEncryptSevSetMemoryEncrypted ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN UINT64 Length, > + IN BOOLEAN CacheFlush > + ); > + > +#endif > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c= b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c > new file mode 100644 > index 000000000000..a2ea99019917 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c > @@ -0,0 +1,84 @@ > +/** @file > + > + Secure Encrypted Virtualization (SEV) library helper function > + > + 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 lic= ense 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 I= MPLIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +/** > + This function clears memory encryption bit for the memory region speci= fied > + by BaseAddress and Number of pages from the current page table context. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use c= urrent CR3) > + @param[in] BaseAddress The physical address that is the sta= rt address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memor= y region. > + @param[in] Flush Flush the caches before clearing the= bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were cleared for the = memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute= is not > + supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevClearPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumberOfPages, > + IN BOOLEAN Flush > + ) > +{ > + // > + // Memory encryption bit is not accessible in 32-bit mode > + // > + return RETURN_UNSUPPORTED; > +} > + > +/** > + This function sets memory encryption bit for the memory region specifi= ed by > + BaseAddress and Number of pages from the current page table context. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use c= urrent CR3) > + @param[in] BaseAddress The physical address that is the sta= rt address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memor= y region. > + @param[in] Flush Flush the caches before clearing the= bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were set for the memo= ry region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing memory encryption attribute= is not > + supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevSetPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumberOfPages, > + IN BOOLEAN Flush > + ) > +{ > + // > + // Memory encryption bit is not accessible in 32-bit mode > + // > + return RETURN_UNSUPPORTED; > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInterna= l.c b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c > new file mode 100644 > index 000000000000..002f079c7eb3 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c > @@ -0,0 +1,90 @@ > +/** @file > + > + Secure Encrypted Virtualization (SEV) library helper function > + > + 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 lic= ense 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 I= MPLIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +STATIC BOOLEAN mSevStatus =3D FALSE; > +STATIC BOOLEAN mSevStatusChecked =3D FALSE; > + > +/** > + > + Returns a boolean to indicate whether SEV is enabled > + > + @retval TRUE SEV is enabled > + @retval FALSE SEV is not enabled > + **/ > +STATIC > +BOOLEAN > +EFIAPI > +InternalMemEncryptSevIsEnabled ( > + VOID > + ) > +{ > + UINT32 RegEax; > + MSR_SEV_STATUS_REGISTER Msr; > + CPUID_MEMORY_ENCRYPTION_INFO_EAX Eax; > + > + // > + // Check if memory encryption leaf exist > + // > + AsmCpuid (CPUID_EXTENDED_FUNCTION, &RegEax, NULL, NULL, NULL); > + if (RegEax >=3D CPUID_MEMORY_ENCRYPTION_INFO) { > + // > + // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) > + // > + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NUL= L); > + > + if (Eax.Bits.SevBit) { > + // > + // Check MSR_0xC0010131 Bit 0 (Sev Enabled) > + // > + Msr.Uint32 =3D AsmReadMsr32 (MSR_SEV_STATUS); > + if (Msr.Bits.SevBit) { > + return TRUE; > + } > + } > + } > + > + return FALSE; > +} > + > +/** > + > + Returns a boolean to indicate whether SEV is enabled > + > + @retval TRUE SEV is enabled > + @retval FALSE SEV is not enabled > + **/ > +BOOLEAN > +EFIAPI > +MemEncryptSevIsEnabled ( > + VOID > + ) > +{ > + if (mSevStatusChecked) { > + return mSevStatus; > + } > + > + mSevStatus =3D InternalMemEncryptSevIsEnabled(); > + mSevStatusChecked =3D TRUE; > + > + return mSevStatus; > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c = b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c > new file mode 100644 > index 000000000000..9ec76708bd7b > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c > @@ -0,0 +1,84 @@ > +/** @file > + > + Secure Encrypted Virtualization (SEV) library helper function > + > + 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 lic= ense 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 I= MPLIED. > + > +**/ > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include "VirtualMemory.h" > + > +/** > + > + This function clears memory encryption bit for the memory region speci= fied by > + BaseAddress and Number of pages from the current page table context. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use= current CR3) > + @param[in] BaseAddress The physical address that is the s= tart address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start mem= ory region. > + @param[in] Flush Flush the caches before clearing t= he bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing the memory encryption att= ribute is > + not supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevClearPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN BOOLEAN Flush > + ) > +{ > + return InternalMemEncryptSevSetMemoryDecrypted (Cr3BaseAddress, BaseAd= dress, EFI_PAGES_TO_SIZE(NumPages), Flush); > +} > + > +/** > + > + This function clears memory encryption bit for the memory region speci= fied by > + BaseAddress and Number of pages from the current page table context. > + > + @param[in] Cr3BaseAddress Cr3 Base Address (if zero then use= current CR3) > + @param[in] BaseAddress The physical address that is the s= tart address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start mem= ory region. > + @param[in] Flush Flush the caches before clearing t= he bit > + (mostly TRUE except MMIO addresses) > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Clearing the memory encryption att= ribute is > + not supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevSetPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN BOOLEAN Flush > + ) > +{ > + return InternalMemEncryptSevSetMemoryEncrypted (Cr3BaseAddress, BaseAd= dress, EFI_PAGES_TO_SIZE(NumPages), Flush); > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/O= vmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > new file mode 100644 > index 000000000000..7cbbf915f443 > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > @@ -0,0 +1,439 @@ > +/** @file > + > + Virtual Memory Management Services to set or clear the memory encrypti= on bit > + > +Copyright (c) 2006 - 2016, 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 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. > + > +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > + > +**/ > + > +#include > +#include > +#include > + > +#include "VirtualMemory.h" > + > +STATIC BOOLEAN mAddressEncMaskChecked =3D FALSE; > +STATIC UINT64 mAddressEncMask; > + > +typedef enum { > + SetCBit, > + ClearCBit > +} MAP_RANGE_MODE; > + > +/** > + Get the memory encryption mask > + > + @param[out] EncryptionMask contains the pte mask. > + > +**/ > +STATIC > +UINT64 > +GetMemEncryptionAddressMask ( > + VOID > + ) > +{ > + UINT64 EncryptionMask; > + CPUID_MEMORY_ENCRYPTION_INFO_EBX Ebx; > + > + if (mAddressEncMaskChecked) { > + return mAddressEncMask; > + } > + > + // > + // CPUID Fn8000_001F[EBX] Bit 0:5 (memory encryption bit position) > + // > + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, NULL, &Ebx.Uint32, NULL, NULL); > + EncryptionMask =3D LShiftU64 (1, Ebx.Bits.PtePosBits); > + > + mAddressEncMask =3D EncryptionMask & PAGING_1G_ADDRESS_MASK_64; > + mAddressEncMaskChecked =3D TRUE; > + > + return mAddressEncMask; > +} > + > +/** > + Split 2M page to 4K. > + > + @param[in] PhysicalAddress Start physical address the 2M pa= ge covered. > + @param[in, out] PageEntry2M Pointer to 2M page entry. > + @param[in] StackBase Stack base address. > + @param[in] StackSize Stack size. > + > +**/ > +STATIC > +VOID > +Split2MPageTo4K ( > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN OUT UINT64 *PageEntry2M, > + IN PHYSICAL_ADDRESS StackBase, > + IN UINTN StackSize > + ) > +{ > + PHYSICAL_ADDRESS PhysicalAddress4K; > + UINTN IndexOfPageTableEntries; > + PAGE_TABLE_4K_ENTRY *PageTableEntry, *PageTableEntry1; > + UINT64 AddressEncMask; > + > + PageTableEntry =3D AllocatePages(1); > + > + PageTableEntry1 =3D PageTableEntry; > + > + AddressEncMask =3D GetMemEncryptionAddressMask (); > + > + ASSERT (PageTableEntry !=3D NULL); > + ASSERT (*PageEntry2M & AddressEncMask); > + > + PhysicalAddress4K =3D PhysicalAddress; > + for (IndexOfPageTableEntries =3D 0; IndexOfPageTableEntries < 512; Ind= exOfPageTableEntries++, 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; > + if ((PhysicalAddress4K >=3D StackBase) && (PhysicalAddress4K < Stack= Base + StackSize)) { > + // > + // Set Nx bit for stack. > + // > + PageTableEntry->Bits.Nx =3D 1; > + } > + } > + > + // > + // Fill in 2M page entry. > + // > + *PageEntry2M =3D (UINT64) (UINTN) PageTableEntry1 | IA32_PG_P | IA32_P= G_RW | AddressEncMask; > +} > + > +/** > + Split 1G page to 2M. > + > + @param[in] PhysicalAddress Start physical address the 1G pa= ge covered. > + @param[in, out] PageEntry1G Pointer to 1G page entry. > + @param[in] StackBase Stack base address. > + @param[in] StackSize Stack size. > + > +**/ > +STATIC > +VOID > +Split1GPageTo2M ( > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN OUT UINT64 *PageEntry1G, > + IN PHYSICAL_ADDRESS StackBase, > + IN UINTN StackSize > + ) > +{ > + PHYSICAL_ADDRESS PhysicalAddress2M; > + UINTN IndexOfPageDirectoryEntries; > + PAGE_TABLE_ENTRY *PageDirectoryEntry; > + UINT64 AddressEncMask; > + > + PageDirectoryEntry =3D AllocatePages(1); > + > + AddressEncMask =3D GetMemEncryptionAddressMask (); > + ASSERT (PageDirectoryEntry !=3D NULL); > + ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ()); > + // > + // Fill in 1G page entry. > + // > + *PageEntry1G =3D (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA3= 2_PG_RW | AddressEncMask; > + > + PhysicalAddress2M =3D PhysicalAddress; > + for (IndexOfPageDirectoryEntries =3D 0; IndexOfPageDirectoryEntries < = 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M= +=3D SIZE_2MB) { > + if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress= 2M + SIZE_2MB) > StackBase)) { > + // > + // Need to split this 2M page that covers stack range. > + // > + Split2MPageTo4K (PhysicalAddress2M, (UINT64 *) PageDirectoryEntry,= StackBase, StackSize); > + } else { > + // > + // Fill in the Page Directory entries > + // > + PageDirectoryEntry->Uint64 =3D (UINT64) PhysicalAddress2M | Addres= sEncMask; > + PageDirectoryEntry->Bits.ReadWrite =3D 1; > + PageDirectoryEntry->Bits.Present =3D 1; > + PageDirectoryEntry->Bits.MustBe1 =3D 1; > + } > + } > +} > + > + > +/** > + Set or Clear the memory encryption bit > + > + @param[in] PagetablePoint Page table entry pointer (PTE). > + @param[in] Mode Set or Clear encryption bit > + > +**/ > +STATIC VOID > +SetOrClearCBit( > + IN OUT UINT64* PageTablePointer, > + IN MAP_RANGE_MODE Mode > + ) > +{ > + UINT64 AddressEncMask; > + > + AddressEncMask =3D GetMemEncryptionAddressMask (); > + > + if (Mode =3D=3D SetCBit) { > + *PageTablePointer |=3D AddressEncMask; > + } else { > + *PageTablePointer &=3D ~AddressEncMask; > + } > + > +} > + > +/** > + This function either sets or clears memory encryption bit for the memo= ry region > + specified by PhysicalAddress and length from the current page table co= ntext. > + > + The function iterates through the physicalAddress one page at a time, = and set > + or clears the memory encryption mask in the page table. If it encounte= rs > + that a given physical address range is part of large page then it atte= mpts to > + change the attribute at one go (based on size), otherwise it splits the > + large pages into smaller (e.g 2M page into 4K pages) and then try to s= et or > + clear the encryption bit on the smallest page size. > + > + @param[in] PhysicalAddress The physical address that is the s= tart > + address of a memory region. > + @param[in] Length The length of memory region > + @param[in] Mode Set or Clear mode > + @param[in] Flush Flush the caches before applying t= he > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attr= ibute is > + not supported > +**/ > + > +STATIC > +RETURN_STATUS > +EFIAPI > +SetMemoryEncDec ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN UINTN Length, > + IN MAP_RANGE_MODE Mode, > + IN BOOLEAN CacheFlush > + ) > +{ > + PAGE_MAP_AND_DIRECTORY_POINTER *PageMapLevel4Entry; > + PAGE_MAP_AND_DIRECTORY_POINTER *PageUpperDirectoryPointerEntry; > + PAGE_MAP_AND_DIRECTORY_POINTER *PageDirectoryPointerEntry; > + PAGE_TABLE_1G_ENTRY *PageDirectory1GEntry; > + PAGE_TABLE_ENTRY *PageDirectory2MEntry; > + PAGE_TABLE_4K_ENTRY *PageTableEntry; > + UINT64 PgTableMask; > + UINT64 AddressEncMask; > + > + // > + // Check if we have a valid memory encryption mask > + // > + AddressEncMask =3D GetMemEncryptionAddressMask (); > + if (!AddressEncMask) { > + return RETURN_ACCESS_DENIED; > + } > + > + PgTableMask =3D AddressEncMask | EFI_PAGE_MASK; > + > + if (Length =3D=3D 0) { > + return RETURN_INVALID_PARAMETER; > + } > + > + // > + // We are going to change the memory encryption attribute from C=3D0 -= > C=3D1 or > + // vice versa Flush the caches to ensure that data is written into mem= ory with > + // correct C-bit > + // > + if (CacheFlush) { > + WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Le= ngth); > + } > + > + while (Length) > + { > + // > + // If Cr3BaseAddress is not specified then read the current CR3 > + // > + if (Cr3BaseAddress =3D=3D 0) { > + Cr3BaseAddress =3D AsmReadCr3(); > + } > + > + PageMapLevel4Entry =3D (VOID*) (Cr3BaseAddress & ~PgTableMask); > + PageMapLevel4Entry +=3D PML4_OFFSET(PhysicalAddress); > + if (!PageMapLevel4Entry->Bits.Present) { > + DEBUG ((DEBUG_WARN, > + "%a:%a ERROR bad PML4 for %lx\n", gEfiCallerBaseName, __FUNCTION= __, > + PhysicalAddress)); > + return RETURN_NO_MAPPING; > + } > + > + PageDirectory1GEntry =3D (VOID*) ((PageMapLevel4Entry->Bits.PageTabl= eBaseAddress<<12) & ~PgTableMask); > + PageDirectory1GEntry +=3D PDP_OFFSET(PhysicalAddress); > + if (!PageDirectory1GEntry->Bits.Present) { > + DEBUG ((DEBUG_WARN, > + "%a:%a ERROR bad PDPE for %lx\n", gEfiCallerBaseName, > + __FUNCTION__, PhysicalAddress)); > + return RETURN_NO_MAPPING; > + } > + > + // > + // If the MustBe1 bit is not 1, it's not actually a 1GB entry > + // > + if (PageDirectory1GEntry->Bits.MustBe1) { > + // > + // Valid 1GB page > + // If we have at least 1GB to go, we can just update this entry > + // > + if (!(PhysicalAddress & (BIT30 - 1)) && Length >=3D BIT30) { > + SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode); > + DEBUG ((DEBUG_VERBOSE, > + "%a:%a Updated 1GB entry for %lx\n", gEfiCallerBaseName, > + __FUNCTION__, PhysicalAddress)); > + PhysicalAddress +=3D BIT30; > + Length -=3D BIT30; > + } else { > + // > + // We must split the page > + // > + DEBUG ((DEBUG_VERBOSE, > + "%a:%a Spliting 1GB page\n", gEfiCallerBaseName, __FUNCTION__)= ); > + Split1GPageTo2M(((UINT64)PageDirectory1GEntry->Bits.PageTableBas= eAddress)<<30, (UINT64*) PageDirectory1GEntry, 0, 0); > + continue; > + } > + } else { > + // > + // Actually a PDP > + // > + PageUpperDirectoryPointerEntry =3D (PAGE_MAP_AND_DIRECTORY_POINTER= *) PageDirectory1GEntry; > + PageDirectory2MEntry =3D (VOID*) ((PageUpperDirectoryPointerEntry-= >Bits.PageTableBaseAddress<<12) & ~PgTableMask); > + PageDirectory2MEntry +=3D PDE_OFFSET(PhysicalAddress); > + if (!PageDirectory2MEntry->Bits.Present) { > + DEBUG ((DEBUG_WARN, > + "%a:%a ERROR bad PDE for %lx\n", gEfiCallerBaseName, __FUNCTIO= N__, > + PhysicalAddress)); > + return RETURN_NO_MAPPING; > + } > + // > + // If the MustBe1 bit is not a 1, it's not a 2MB entry > + // > + if (PageDirectory2MEntry->Bits.MustBe1) { > + // > + // Valid 2MB page > + // If we have at least 2MB left to go, we can just update this e= ntry > + // > + if (!(PhysicalAddress & (BIT21-1)) && Length >=3D BIT21) { > + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); > + PhysicalAddress +=3D BIT21; > + Length -=3D BIT21; > + } else { > + // > + // We must split up this page into 4K pages > + // > + DEBUG ((DEBUG_VERBOSE, > + "%a:%a Spliting 2MB page at %lx\n", gEfiCallerBaseName,__FUN= CTION__, > + PhysicalAddress)); > + Split2MPageTo4K (((UINT64)PageDirectory2MEntry->Bits.PageTable= BaseAddress) << 21, (UINT64*) PageDirectory2MEntry, 0, 0); > + continue; > + } > + } else { > + PageDirectoryPointerEntry =3D (PAGE_MAP_AND_DIRECTORY_POINTER*) = PageDirectory2MEntry; > + PageTableEntry =3D (VOID*) (PageDirectoryPointerEntry->Bits.Page= TableBaseAddress<<12 & ~PgTableMask); > + PageTableEntry +=3D PTE_OFFSET(PhysicalAddress); > + if (!PageTableEntry->Bits.Present) { > + DEBUG ((DEBUG_WARN, > + "%a:%a ERROR bad PTE for %lx\n", gEfiCallerBaseName, > + __FUNCTION__, PhysicalAddress)); > + return RETURN_NO_MAPPING; > + } > + SetOrClearCBit (&PageTableEntry->Uint64, Mode); > + PhysicalAddress +=3D EFI_PAGE_SIZE; > + Length -=3D EFI_PAGE_SIZE; > + } > + } > + } > + > + // > + // Flush TLB > + // > + CpuFlushTlb(); > + > + return RETURN_SUCCESS; > +} > + > +/** > + This function clears memory encryption bit for the memory region speci= fied by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the s= tart > + address of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying t= he > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attr= ibute is > + not supported > +**/ > +RETURN_STATUS > +EFIAPI > +InternalMemEncryptSevSetMemoryDecrypted ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN UINTN Length, > + IN BOOLEAN Flush > + ) > +{ > + > + DEBUG ((DEBUG_VERBOSE, > + "%a:%a Clear C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n", > + gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, L= ength, > + Flush)); > + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, Clear= CBit, Flush); > +} > + > +/** > + This function sets memory encryption bit for the memory region specifi= ed by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the s= tart address > + of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying t= he > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for th= e memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attr= ibute is > + not supported > +**/ > +RETURN_STATUS > +EFIAPI > +InternalMemEncryptSevSetMemoryEncrypted ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS PhysicalAddress, > + IN UINTN Length, > + IN BOOLEAN Flush > + ) > +{ > + DEBUG ((DEBUG_VERBOSE, > + "%a:%a Set C-bit Cr3 %Lx Base %Lx Length %Lx flush %d\n", > + gEfiCallerBaseName, __FUNCTION__, Cr3BaseAddress, PhysicalAddress, L= ength, > + Flush)); > + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCB= it, Flush); > +} > -- = > 2.7.4 >=20