From: Brijesh Singh <brijesh.singh@amd.com>
To: Jordan Justen <jordan.l.justen@intel.com>,
Jiewen Yao <jiewen.yao@intel.com>, Jeff Fan <jeff.fan@intel.com>,
<edk2-devel@lists.01.org>
Cc: <brijesh.singh@amd.com>, <Thomas.Lendacky@amd.com>,
<leo.duran@amd.com>, Laszlo Ersek <lersek@redhat.com>
Subject: Re: [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
Date: Fri, 26 May 2017 16:06:47 -0500 [thread overview]
Message-ID: <bf0d183c-0bc7-dfe9-19b9-7900c52b022a@amd.com> (raw)
In-Reply-To: <149583207795.25973.8215621482706964409@jljusten-skl>
Hi Jordan,
I don't have any strong feeling on where this lib should go, but since SEV (Secure Encrypted Virtualization)
feature is applicable only when are building/booting the OVMF platform hence I thought OVMF is the right place
for it.
Thanks
Brijesh
On 05/26/2017 03:54 PM, Jordan Justen wrote:
> 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 <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
>> ---
>> 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/BaseMemEncryptSevLib.inf
>> !if $(SMM_REQUIRE) == 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/BaseMemEncryptSevLib.inf
>> !if $(SMM_REQUIRE) == 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/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.<BR>
>> +#
>> +# 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.<BR>
>> +
>> + 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 <Base.h>
>> +
>> +/**
>> + 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..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 encryption bit
>> +
>> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
>> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
>> +
>> +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 <Uefi.h>
>> +#include <Library/BaseLib.h>
>> +#include <Library/BaseMemoryLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/MemoryAllocationLib.h>
>> +
>> +#include <Library/CacheMaintenanceLib.h>
>> +#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
>> +**/
>> +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 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
>> +**/
>> +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.<BR>
>> +
>> + 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 <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Register/Cpuid.h>
>> +#include <Register/Amd/Cpuid.h>
>> +#include <Register/Amd/Msr.h>
>> +#include <Library/MemEncryptSevLib.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 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.<BR>
>> +
>> + 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 <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Register/Cpuid.h>
>> +#include <Register/Amd/Cpuid.h>
>> +#include <Register/Amd/Msr.h>
>> +#include <Library/MemEncryptSevLib.h>
>> +
>> +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.<BR>
>> +
>> + 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 <Library/BaseLib.h>
>> +#include <Library/DebugLib.h>
>> +#include <Register/Cpuid.h>
>> +#include <Register/Amd/Cpuid.h>
>> +#include <Register/Amd/Msr.h>
>> +#include <Library/MemEncryptSevLib.h>
>> +
>> +#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..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 encryption bit
>> +
>> +Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
>> +Copyright (c) 2017, AMD Incorporated. All rights reserved.<BR>
>> +
>> +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 <Library/CpuLib.h>
>> +#include <Register/Cpuid.h>
>> +#include <Register/Amd/Cpuid.h>
>> +
>> +#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
>> +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 = 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
>> +**/
>> +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, 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
>> +**/
>> +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, Length,
>> + Flush));
>> + return SetMemoryEncDec (Cr3BaseAddress, PhysicalAddress, Length, SetCBit, Flush);
>> +}
>> --
>> 2.7.4
>>
next prev parent reply other threads:[~2017-05-26 21:06 UTC|newest]
Thread overview: 65+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 01/17] UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 02/17] OvmfPkg/ResetVector: Set C-bit when building initial page table Brijesh Singh
2017-06-01 8:09 ` Jordan Justen
2017-06-01 13:43 ` Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 03/17] OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library Brijesh Singh
2017-05-26 20:54 ` Jordan Justen
2017-05-26 21:06 ` Brijesh Singh [this message]
2017-05-27 1:26 ` Yao, Jiewen
2017-05-26 14:43 ` [PATCH v6 05/17] OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 06/17] OvmfPkg: Add AmdSevDxe driver Brijesh Singh
2017-05-26 14:43 ` [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID Brijesh Singh
2017-05-29 9:07 ` Laszlo Ersek
2017-05-26 14:43 ` [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib Brijesh Singh
2017-05-29 9:19 ` Laszlo Ersek
2017-05-26 14:43 ` [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver Brijesh Singh
2017-05-29 9:28 ` Laszlo Ersek
2017-05-26 14:43 ` [PATCH v6 10/17] OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library Brijesh Singh
2017-05-26 21:49 ` Jordan Justen
2017-05-26 14:43 ` [PATCH v6 11/17] OvmfPkg/QemuFwCfgLib: Prepare for SEV support Brijesh Singh
2017-05-26 14:44 ` [PATCH v6 12/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase Brijesh Singh
2017-05-26 14:44 ` [PATCH v6 13/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase Brijesh Singh
2017-05-26 14:44 ` [PATCH v6 14/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase Brijesh Singh
2017-05-29 9:40 ` Laszlo Ersek
2017-05-26 14:44 ` [PATCH v6 15/17] OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access Brijesh Singh
2017-05-26 14:44 ` [PATCH v6 16/17] OvmfPkg/QemuFwCfgLib: Add SEV support Brijesh Singh
2017-05-26 14:44 ` [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib Brijesh Singh
2017-05-29 9:47 ` Laszlo Ersek
2017-05-29 12:13 ` Laszlo Ersek
2017-05-26 21:05 ` [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Jordan Justen
2017-05-29 11:16 ` Laszlo Ersek
2017-05-29 20:38 ` Jordan Justen
2017-05-29 21:59 ` Brijesh Singh
2017-06-01 7:40 ` Jordan Justen
2017-06-01 9:10 ` Laszlo Ersek
2017-06-01 13:48 ` Andrew Fish
2017-06-01 14:56 ` Laszlo Ersek
2017-06-01 15:01 ` Brijesh Singh
2017-06-01 15:37 ` Andrew Fish
2017-06-05 21:56 ` Brijesh Singh
2017-06-06 1:12 ` Jordan Justen
2017-06-06 2:08 ` Zeng, Star
2017-06-06 3:50 ` Brijesh Singh
2017-06-06 14:54 ` Yao, Jiewen
2017-06-06 15:24 ` Andrew Fish
2017-06-06 15:43 ` Yao, Jiewen
2017-06-06 15:54 ` Duran, Leo
2017-06-06 18:39 ` Laszlo Ersek
2017-06-06 18:38 ` Laszlo Ersek
2017-06-06 18:29 ` Laszlo Ersek
2017-06-06 18:57 ` Duran, Leo
2017-07-05 22:31 ` Brijesh Singh
2017-07-05 23:38 ` Laszlo Ersek
2017-07-06 13:37 ` Brijesh Singh
2017-07-06 16:45 ` Jordan Justen
2017-07-06 20:11 ` Brijesh Singh
2017-07-06 20:40 ` Laszlo Ersek
2017-07-06 21:42 ` Jordan Justen
2017-07-06 21:44 ` Duran, Leo
2017-07-06 21:46 ` Andrew Fish
2017-07-06 21:49 ` Duran, Leo
2017-07-07 5:28 ` Jordan Justen
2017-07-07 18:29 ` Brijesh Singh
2017-07-07 23:10 ` Jordan Justen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bf0d183c-0bc7-dfe9-19b9-7900c52b022a@amd.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox