From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) (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 32DED21AE3CA2 for ; Wed, 24 May 2017 06:06:23 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 782CD61B91; Wed, 24 May 2017 13:06:22 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 782CD61B91 Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx10.extmail.prod.ext.phx2.redhat.com; spf=pass smtp.mailfrom=lersek@redhat.com DKIM-Filter: OpenDKIM Filter v2.11.0 mx1.redhat.com 782CD61B91 Received: from lacos-laptop-7.usersys.redhat.com (ovpn-116-23.phx2.redhat.com [10.3.116.23]) by smtp.corp.redhat.com (Postfix) with ESMTP id ACB317F8C2; Wed, 24 May 2017 13:06:20 +0000 (UTC) To: Brijesh Singh , edk2-devel@lists.01.org, jordan.l.justen@intel.com Cc: Thomas.Lendacky@amd.com, leo.duran@amd.com References: <1495466592-21641-1-git-send-email-brijesh.singh@amd.com> <1495466592-21641-5-git-send-email-brijesh.singh@amd.com> From: Laszlo Ersek Message-ID: <868ad318-c652-55c2-4b4c-eeeec2f826c6@redhat.com> Date: Wed, 24 May 2017 15:06:19 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.1.1 MIME-Version: 1.0 In-Reply-To: <1495466592-21641-5-git-send-email-brijesh.singh@amd.com> X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.39]); Wed, 24 May 2017 13:06:22 +0000 (UTC) Subject: Re: [PATCH v5 04/14] 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: Wed, 24 May 2017 13:06:23 -0000 Content-Type: text/plain; charset=utf-8 Content-Language: en-US Content-Transfer-Encoding: 7bit On 05/22/17 17:23, 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 | 428 ++++++++++++++++++++ > 10 files changed, 1004 insertions(+) I have some comments for the case if you have to post a v6. Right now a v6 is not needed just for these comments. (1) In I mentioned "Since this is a BASE library, please don't use EFI_STATUS, EFI_INVALID_PARAMETER, EFI_NO_MAPPING, EFI_SUCCESS; use RETURN_xxx instead." You replaced most of them, but you left in "EFI_STATUS". That should be "RETURN_STATUS". (2) please check the lines where you added (as I asked, thanks) gEfiCallerBaseName and __FUNCTION__. On most lines, the indentation is incorrect, relative to "DEBUG ((". (3) Furthermore, in some spots where you added __FUNCTION__, you forgot to add a space after the comma. Again, no need to resubmit just because of this, but if you do resubmit anyway, these should be fixed up. Thanks Laszlo > diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc > index f3889c29f426..25b7d73807b6 100644 > --- a/OvmfPkg/OvmfPkgIa32.dsc > +++ b/OvmfPkg/OvmfPkgIa32.dsc > @@ -143,6 +143,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf > !if $(SMM_REQUIRE) == FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc > index 2aaa21f79e49..88bf73b3fa01 100644 > --- a/OvmfPkg/OvmfPkgIa32X64.dsc > +++ b/OvmfPkg/OvmfPkgIa32X64.dsc > @@ -148,6 +148,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf > !if $(SMM_REQUIRE) == FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc > index b1e35942ba03..b34fed16a860 100644 > --- a/OvmfPkg/OvmfPkgX64.dsc > +++ b/OvmfPkg/OvmfPkgX64.dsc > @@ -148,6 +148,7 @@ [LibraryClasses] > QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf > VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf > LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf > + MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf > !if $(SMM_REQUIRE) == FALSE > LockBoxLib|OvmfPkg/Library/LockBoxLib/LockBoxBaseLib.inf > !endif > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf 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 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. > +# > +# > +## > + > +[Defines] > + INF_VERSION = 1.25 > + BASE_NAME = MemEncryptSevLib > + FILE_GUID = c1594631-3888-4be4-949f-9c630dbc842b > + MODULE_TYPE = BASE > + VERSION_STRING = 1.0 > + LIBRARY_CLASS = MemEncryptSevLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER UEFI_DRIVER > + > +# > +# The following information is for reference only and not required by the build tools. > +# > +# VALID_ARCHITECTURES = 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 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 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 _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 specified > + by BaseAddress and Number of pages from the current page table context. > + > + @param[in] BaseAddress The physical address that is the start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 specified by > + BaseAddress and Number of pages from the current page table context. > + > + @param[in] BaseAddress The physical address that is the start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 memory 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/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > new file mode 100644 > index 000000000000..808a386ca07a > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h > @@ -0,0 +1,184 @@ > +/** @file > + > + Virtual Memory Management Services to set or clear the memory encryption 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 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. > + > +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 = Not present in memory, 1 = Present in memory > + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write > + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User > + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching > + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached > + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) > + UINT64 Reserved:1; // Reserved > + UINT64 MustBeZero:2; // Must Be Zero > + UINT64 Available:3; // Available for use by system software > + UINT64 PageTableBaseAddress:40; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system software > + 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 = Not present in memory, 1 = Present in memory > + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write > + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User > + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching > + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached > + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) > + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page > + UINT64 PAT:1; // > + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write > + UINT64 Available:3; // Available for use by system software > + UINT64 PageTableBaseAddress:40; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system software > + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution > + } Bits; > + UINT64 Uint64; > +} PAGE_TABLE_4K_ENTRY; > + > +// > +// Page Table Entry 2MB > +// > +typedef union { > + struct { > + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory > + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write > + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User > + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching > + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached > + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) > + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page > + UINT64 MustBe1:1; // Must be 1 > + UINT64 Global:1; // 0 = Not global page, 1 = global 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 AvabilableHigh:11; // Available for use by system software > + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code Execution > + } Bits; > + UINT64 Uint64; > +} PAGE_TABLE_ENTRY; > + > +// > +// Page Table Entry 1GB > +// > +typedef union { > + struct { > + UINT64 Present:1; // 0 = Not present in memory, 1 = Present in memory > + UINT64 ReadWrite:1; // 0 = Read-Only, 1= Read/Write > + UINT64 UserSupervisor:1; // 0 = Supervisor, 1=User > + UINT64 WriteThrough:1; // 0 = Write-Back caching, 1=Write-Through caching > + UINT64 CacheDisabled:1; // 0 = Cached, 1=Non-Cached > + UINT64 Accessed:1; // 0 = Not accessed, 1 = Accessed (set by CPU) > + UINT64 Dirty:1; // 0 = Not Dirty, 1 = written by processor on access to page > + UINT64 MustBe1:1; // Must be 1 > + UINT64 Global:1; // 0 = Not global page, 1 = global page TLB not cleared on CR3 write > + UINT64 Available:3; // Available for use by system software > + UINT64 PAT:1; // > + UINT64 MustBeZero:17; // Must be zero; > + UINT64 PageTableBaseAddress:22; // Page Table Base Address > + UINT64 AvabilableHigh:11; // Available for use by system software > + UINT64 Nx:1; // 0 = Execute Code, 1 = No Code 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 specified by PhysicalAddress > + and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the start address of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying the encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for the memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is not supported > +**/ > +EFI_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 specified by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the start address > + of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying the > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for the memory region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is > + not supported > +**/ > +EFI_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 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 > +#include > +#include > +#include > +#include > +#include > + > +/** > + This function clears memory encryption bit for the memory region specified > + 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 start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 specified 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 start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 memory 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/MemEncryptSevLibInternal.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 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 > +#include > +#include > +#include > +#include > +#include > + > +STATIC BOOLEAN mSevStatus = FALSE; > +STATIC BOOLEAN mSevStatusChecked = 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 >= CPUID_MEMORY_ENCRYPTION_INFO) { > + // > + // CPUID Fn8000_001F[EAX] Bit 1 (Sev supported) > + // > + AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax.Uint32, NULL, NULL, NULL); > + > + if (Eax.Bits.SevBit) { > + // > + // Check MSR_0xC0010131 Bit 0 (Sev Enabled) > + // > + Msr.Uint32 = 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 = InternalMemEncryptSevIsEnabled(); > + mSevStatusChecked = 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 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 > +#include > +#include > +#include > +#include > +#include > + > +#include "VirtualMemory.h" > + > +/** > + > + This function clears memory encryption bit for the memory region specified 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 start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 the memory encryption attribute is > + not supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevClearPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN BOOLEAN Flush > + ) > +{ > + return InternalMemEncryptSevSetMemoryDecrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush); > +} > + > +/** > + > + This function clears memory encryption bit for the memory region specified 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 start address > + of a memory region. > + @param[in] NumberOfPages The number of pages from start memory 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 the memory encryption attribute is > + not supported > + **/ > +RETURN_STATUS > +EFIAPI > +MemEncryptSevSetPageEncMask ( > + IN PHYSICAL_ADDRESS Cr3BaseAddress, > + IN PHYSICAL_ADDRESS BaseAddress, > + IN UINTN NumPages, > + IN BOOLEAN Flush > + ) > +{ > + return InternalMemEncryptSevSetMemoryEncrypted (Cr3BaseAddress, BaseAddress, EFI_PAGES_TO_SIZE(NumPages), Flush); > +} > diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > new file mode 100644 > index 000000000000..fa103a531dfb > --- /dev/null > +++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c > @@ -0,0 +1,428 @@ > +/** @file > + > + Virtual Memory Management Services to set or clear the memory encryption 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 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. > + > +Code is derived from MdeModulePkg/Core/DxeIplPeim/X64/VirtualMemory.c > + > +**/ > + > +#include > +#include > +#include > + > +#include "VirtualMemory.h" > + > +STATIC BOOLEAN mAddressEncMaskChecked = 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 = LShiftU64 (1, Ebx.Bits.PtePosBits); > + > + mAddressEncMask = EncryptionMask & PAGING_1G_ADDRESS_MASK_64; > + mAddressEncMaskChecked = TRUE; > + > + return mAddressEncMask; > +} > + > +/** > + Split 2M page to 4K. > + > + @param[in] PhysicalAddress Start physical address the 2M page 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 = AllocatePages(1); > + > + PageTableEntry1 = PageTableEntry; > + > + AddressEncMask = GetMemEncryptionAddressMask (); > + > + ASSERT (PageTableEntry != NULL); > + ASSERT (*PageEntry2M & AddressEncMask); > + > + PhysicalAddress4K = PhysicalAddress; > + for (IndexOfPageTableEntries = 0; IndexOfPageTableEntries < 512; IndexOfPageTableEntries++, PageTableEntry++, PhysicalAddress4K += SIZE_4KB) { > + // > + // Fill in the Page Table entries > + // > + PageTableEntry->Uint64 = (UINT64) PhysicalAddress4K | AddressEncMask; > + PageTableEntry->Bits.ReadWrite = 1; > + PageTableEntry->Bits.Present = 1; > + if ((PhysicalAddress4K >= StackBase) && (PhysicalAddress4K < StackBase + StackSize)) { > + // > + // Set Nx bit for stack. > + // > + PageTableEntry->Bits.Nx = 1; > + } > + } > + > + // > + // Fill in 2M page entry. > + // > + *PageEntry2M = (UINT64) (UINTN) PageTableEntry1 | IA32_PG_P | IA32_PG_RW | AddressEncMask; > +} > + > +/** > + Split 1G page to 2M. > + > + @param[in] PhysicalAddress Start physical address the 1G page 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 = AllocatePages(1); > + > + AddressEncMask = GetMemEncryptionAddressMask (); > + ASSERT (PageDirectoryEntry != NULL); > + ASSERT (*PageEntry1G & GetMemEncryptionAddressMask ()); > + // > + // Fill in 1G page entry. > + // > + *PageEntry1G = (UINT64) (UINTN) PageDirectoryEntry | IA32_PG_P | IA32_PG_RW | AddressEncMask; > + > + PhysicalAddress2M = PhysicalAddress; > + for (IndexOfPageDirectoryEntries = 0; IndexOfPageDirectoryEntries < 512; IndexOfPageDirectoryEntries++, PageDirectoryEntry++, PhysicalAddress2M += SIZE_2MB) { > + if ((PhysicalAddress2M < StackBase + StackSize) && ((PhysicalAddress2M + 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 = (UINT64) PhysicalAddress2M | AddressEncMask; > + PageDirectoryEntry->Bits.ReadWrite = 1; > + PageDirectoryEntry->Bits.Present = 1; > + PageDirectoryEntry->Bits.MustBe1 = 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 = GetMemEncryptionAddressMask (); > + > + if (Mode == SetCBit) { > + *PageTablePointer |= AddressEncMask; > + } else { > + *PageTablePointer &= ~AddressEncMask; > + } > + > +} > + > +/** > + This function either sets or clears memory encryption bit for the memory region > + specified by PhysicalAddress and length from the current page table context. > + > + 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 encounters > + that a given physical address range is part of large page then it attempts 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 set or > + clear the encryption bit on the smallest page size. > + > + @param[in] PhysicalAddress The physical address that is the start > + 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 the > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for the memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is > + not supported > +**/ > + > +STATIC > +EFI_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 = GetMemEncryptionAddressMask (); > + if (!AddressEncMask) { > + return RETURN_ACCESS_DENIED; > + } > + > + PgTableMask = AddressEncMask | EFI_PAGE_MASK; > + > + if (Length == 0) { > + return RETURN_INVALID_PARAMETER; > + } > + > + // > + // We are going to change the memory encryption attribute from C=0 -> C=1 or > + // vice versa Flush the caches to ensure that data is written into memory with > + // correct C-bit > + // > + if (CacheFlush) { > + WriteBackInvalidateDataCacheRange((VOID*) (UINTN)PhysicalAddress, Length); > + } > + > + while (Length) > + { > + // > + // If Cr3BaseAddress is not specified then read the current CR3 > + // > + if (Cr3BaseAddress == 0) { > + Cr3BaseAddress = AsmReadCr3(); > + } > + > + PageMapLevel4Entry = (VOID*) (Cr3BaseAddress & ~PgTableMask); > + PageMapLevel4Entry += 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 = (VOID*) ((PageMapLevel4Entry->Bits.PageTableBaseAddress<<12) & ~PgTableMask); > + PageDirectory1GEntry += 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 >= BIT30) { > + SetOrClearCBit(&PageDirectory1GEntry->Uint64, Mode); > + DEBUG ((DEBUG_VERBOSE, "%a:%a Updated 1GB entry for %lx\n", > + gEfiCallerBaseName, __FUNCTION__, PhysicalAddress)); > + PhysicalAddress += BIT30; > + Length -= BIT30; > + } else { > + // > + // We must split the page > + // > + DEBUG ((DEBUG_VERBOSE, "%a:%a Spliting 1GB page\n", gEfiCallerBaseName, __FUNCTION__)); > + Split1GPageTo2M(((UINT64)PageDirectory1GEntry->Bits.PageTableBaseAddress)<<30, (UINT64*) PageDirectory1GEntry, 0, 0); > + continue; > + } > + } else { > + // > + // Actually a PDP > + // > + PageUpperDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory1GEntry; > + PageDirectory2MEntry = (VOID*) ((PageUpperDirectoryPointerEntry->Bits.PageTableBaseAddress<<12) & ~PgTableMask); > + PageDirectory2MEntry += PDE_OFFSET(PhysicalAddress); > + if (!PageDirectory2MEntry->Bits.Present) { > + DEBUG ((DEBUG_WARN, "%a:%a ERROR bad PDE for %lx\n", gEfiCallerBaseName, > + __FUNCTION__,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 entry > + // > + if (!(PhysicalAddress & (BIT21-1)) && Length >= BIT21) { > + SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode); > + PhysicalAddress += BIT21; > + Length -= BIT21; > + } else { > + // > + // We must split up this page into 4K pages > + // > + DEBUG ((DEBUG_VERBOSE, "%a:%a Spliting 2MB page at %lx\n", gEfiCallerBaseName, > + __FUNCTION__, PhysicalAddress)); > + Split2MPageTo4K (((UINT64)PageDirectory2MEntry->Bits.PageTableBaseAddress) << 21, (UINT64*) PageDirectory2MEntry, 0, 0); > + continue; > + } > + } else { > + PageDirectoryPointerEntry = (PAGE_MAP_AND_DIRECTORY_POINTER*) PageDirectory2MEntry; > + PageTableEntry = (VOID*) (PageDirectoryPointerEntry->Bits.PageTableBaseAddress<<12 & ~PgTableMask); > + PageTableEntry += 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 += EFI_PAGE_SIZE; > + Length -= EFI_PAGE_SIZE; > + } > + } > + } > + > + // > + // Flush TLB > + // > + CpuFlushTlb(); > + > + return RETURN_SUCCESS; > +} > + > +/** > + This function clears memory encryption bit for the memory region specified by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the start > + address of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying the > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for the memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is > + not supported > +**/ > +EFI_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, Length, Flush)); > + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, ClearCBit, Flush); > +} > + > +/** > + This function sets memory encryption bit for the memory region specified by > + PhysicalAddress and length from the current page table context. > + > + @param[in] PhysicalAddress The physical address that is the start address > + of a memory region. > + @param[in] Length The length of memory region > + @param[in] Flush Flush the caches before applying the > + encryption mask > + > + @retval RETURN_SUCCESS The attributes were cleared for the memory > + region. > + @retval RETURN_INVALID_PARAMETER Number of pages is zero. > + @retval RETURN_UNSUPPORTED Setting the memory encyrption attribute is > + not supported > +**/ > +EFI_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, Length, Flush)); > + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit, Flush); > +} >