public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
@ 2017-05-26 14:43 Brijesh Singh
  2017-05-26 14:43 ` [PATCH v6 01/17] UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR Brijesh Singh
                   ` (18 more replies)
  0 siblings, 19 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jeff Fan, Liming Gao,
	Jordan Justen, Laszlo Ersek, Jiewen Yao

The patch series provides support for AMD's new Secure Encrypted
Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. The SEV feature allows
the memory contents of a virtual machine (VM) to be transparently encrypted
with a key unique to the guest VM. The memory controller contains a
high performance encryption engine which can be programmed with multiple
keys for use by a different VMs in the system. The programming and
management of these keys is handled by the AMD Secure Processor firmware
which exposes a commands for these tasks.

SEV guest VMs have the concept of private and shared memory.  Private memory is
encrypted with the guest-specific key, while shared memory may be encrypted
with hypervisor key.  Certain types of memory (namely instruction pages and
guest page tables) are always treated as private memory by the hardware.
For data memory, SEV guest VMs can choose which pages they would like to be
private. The choice is done using the standard CPU page tables using the C-bit,
and is fully controlled by the guest. Due to security reasons all the DMA
operations inside the  guest must be performed on shared pages (C-bit clear).
Note that since C-bit is only controllable by the guest OS when it is operating
in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware forces the
C-bit to a 1.

The following links provide additional details:

AMD Memory Encryption whitepaper:
http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf

AMD64 Architecture Programmer's Manual:
    http://support.amd.com/TechDocs/24593.pdf
    SME is section 7.10
    SEV is section 15.34

Secure Encrypted Virutualization Key Management:
http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf

KVM Forum Presentation:
http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf

[1] http://marc.info/?l=linux-mm&m=148846752931115&w=2

---

Patch series is based on commit aff463c825a3
 (Vlv2TbltDevicePkg/FvbRuntimeDxe: correct NumOfLba vararg type in EraseBlocks())

https://github.com/codomania/edk2/tree/v6

The patch series is tested with OvmfIa32.dsc, OvmfIa32X64.dsc and OvmfX64.dsc.
Since memory encryption bit is not accessiable when processor is in 32-bit mode
hence any DMA access in this mode would cause assert. I have also tested the
suspend and resume path, it seems to be working fine. I still need to work to
finish adding the SEV Dma support in QemuFwCfgS3Lib package (see TODO).

Changes since v5:
 - add placeholder gIoMmuAbsentProtocolGuid
 - add PlatformHasIoMmuLib
 - fix indentation

Changes since v4:
 - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
   IoMmuDxe driver. And introduce a placeholder protocol to provide the
   dependency support for the dependent modules.
 - update debug messages to use gEfiCallerBaseName where applicable.
 - fix QemuFwCfgSecLib build errors and simplify SEV support
 - update QemuFwCfgDxeLib to assert when failed to locate IOMMU
 - update comments "host buffer" to " host buffer"

Changes since v3:
 - update AmdSevDxe driver to produce IOMMU protocol
 - remove BmDmaLib dependency
 - update QemuFwCfgLib to use IOMMU protocol to allocate SEV DMA buffer

Changes since v2:
 - move memory encryption CPUID and MSR definition into UefiCpuPkg
 - fix the argument order for SUB instruction in ResetVector and add more
   comments
 - update PlatformPei to use BaseMemEncryptSevLib
 - break the overlong comment lines to 79 chars
 - variable aligment and other formating fixes
 - split the SEV DMA support patch for QemuFwCfgLib into multiple patches as
   recommended by Laszlo
 - add AmdSevDxe driver which runs very early in DXE phase and clear the C-bit
   from MMIO memory region
 - drop 'QemuVideoDxe: Clear C-bit from framebuffer' patch since AmdSevDxe
   driver takes care of clearing the C-bit from MMIO region
 - Verified that Qemu PFLASH works fine with SEV guest, Found a KVM driver issue
   which was causing #PF when PFLASH was enabled. I have submitted patch to
   fix it in upstream http://marc.info/?l=kvm&m=149304930814202&w=2

Changes since v1:
 - bug fixes in OvmfPkg/ResetVector (pointed by Tom Lendacky)
 - add SEV CPUID and MSR register definition in standard include file
 - remove the MemEncryptLib dependency from PlatformPei. Move AmdSevInitialize()
   implementation in local file inside the PlatformPei package
 - rename MemCryptSevLib to MemEncryptSevLib and add functions to set or
   clear memory encryption attribute on memory region
 - integerate SEV support in BmDmaLib
 - split QemuFwCfgDxePei.c into QemuFwCfgDxe.c and QemuFwCfgPei.c to
   allow building seperate QemuFwCfgLib for Dxe and Pei phase
   (recommended by Laszlo Ersek)
 - add SEV support in QemuFwCfgLib
 - clear the memory encryption attribute from framebuffer memory region


TODO:
(Will add these features after basic SEV support patches are accepted in upstream)
 - add support for DMA operation in QemuFwCfgS3Lib when SEV is enabled
 - investigate SMM/SMI support

Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>

Brijesh Singh (17):
  UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
  OvmfPkg/ResetVector: Set C-bit when building initial page table
  OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
  OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
  OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
  OvmfPkg: Add AmdSevDxe driver
  OvmfPkg: Introduce IoMmuAbsent Protocol GUID
  OvmfPkg: Add PlatformHasIoMmuLib
  OvmfPkg: Add IoMmuDxe driver
  OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
  OvmfPkg/QemuFwCfgLib: Prepare for SEV support
  OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
  OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
  OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
  OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
  OvmfPkg/QemuFwCfgLib: Add SEV support
  OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib

 OvmfPkg/OvmfPkg.dec                                                    |   1 +
 OvmfPkg/OvmfPkgIa32.dsc                                                |  11 +-
 OvmfPkg/OvmfPkgIa32X64.dsc                                             |  12 +-
 OvmfPkg/OvmfPkgX64.dsc                                                 |  12 +-
 OvmfPkg/OvmfPkgIa32.fdf                                                |   1 +
 OvmfPkg/OvmfPkgIa32X64.fdf                                             |   3 +
 OvmfPkg/OvmfPkgX64.fdf                                                 |   3 +
 OvmfPkg/AmdSevDxe/AmdSevDxe.inf                                        |  43 ++
 OvmfPkg/IoMmuDxe/IoMmuDxe.inf                                          |  49 +++
 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf          |  50 +++
 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf            |  37 ++
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} |  15 +-
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} |   9 +-
 OvmfPkg/PlatformPei/PlatformPei.inf                                    |   3 +
 OvmfPkg/Include/Library/MemEncryptSevLib.h                             |  81 ++++
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h                                         |  43 ++
 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h               | 184 ++++++++
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h                    |  37 ++
 OvmfPkg/PlatformPei/Platform.h                                         |   5 +
 UefiCpuPkg/Include/Register/Amd/Cpuid.h                                | 162 +++++++
 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h                             |  62 +++
 UefiCpuPkg/Include/Register/Amd/Msr.h                                  |  29 ++
 OvmfPkg/AmdSevDxe/AmdSevDxe.c                                          |  75 ++++
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                         | 459 ++++++++++++++++++++
 OvmfPkg/IoMmuDxe/IoMmuDxe.c                                            |  53 +++
 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 +++++++++++++++++++
 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c              |  32 ++
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c                            | 230 ++++++++++
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c                            |  67 ++-
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     |  72 ++-
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c                            |  57 +++
 OvmfPkg/PlatformPei/AmdSev.c                                           |  62 +++
 OvmfPkg/PlatformPei/Platform.c                                         |   1 +
 OvmfPkg/ResetVector/Ia32/PageTables64.asm                              |  70 ++-
 37 files changed, 2703 insertions(+), 24 deletions(-)
 create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
 create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
 copy OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} (71%)
 rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} (80%)
 create mode 100644 OvmfPkg/Include/Library/MemEncryptSevLib.h
 create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
 create mode 100644 UefiCpuPkg/Include/Register/Amd/Cpuid.h
 create mode 100644 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
 create mode 100644 UefiCpuPkg/Include/Register/Amd/Msr.h
 create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.c
 create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
 create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
 create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
 create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
 rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c} (61%)
 create mode 100644 OvmfPkg/PlatformPei/AmdSev.c

-- 
2.7.4



^ permalink raw reply	[flat|nested] 65+ messages in thread

* [PATCH v6 01/17] UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
@ 2017-05-26 14:43 ` Brijesh Singh
  2017-05-26 14:43 ` [PATCH v6 02/17] OvmfPkg/ResetVector: Set C-bit when building initial page table Brijesh Singh
                   ` (17 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek, Jeff Fan, Liming Gao

The patch defines AMD's Memory Encryption Information CPUID leaf and SEV
status MSR. The complete description for CPUID leaf is available in APM
volume 2, Section 15.34.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Jeff Fan <jeff.fan@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Leo Duran <leo.duran@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
---
 UefiCpuPkg/Include/Register/Amd/Cpuid.h    | 162 ++++++++++++++++++++
 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h |  62 ++++++++
 UefiCpuPkg/Include/Register/Amd/Msr.h      |  29 ++++
 3 files changed, 253 insertions(+)

diff --git a/UefiCpuPkg/Include/Register/Amd/Cpuid.h b/UefiCpuPkg/Include/Register/Amd/Cpuid.h
new file mode 100644
index 000000000000..5cd42667dc46
--- /dev/null
+++ b/UefiCpuPkg/Include/Register/Amd/Cpuid.h
@@ -0,0 +1,162 @@
+/** @file
+  CPUID leaf definitions.
+
+  Provides defines for CPUID leaf indexes.  Data structures are provided for
+  registers returned by a CPUID leaf that contain one or more bit fields.
+  If a register returned is a single 32-bit value, then a data structure is
+  not provided for that register.
+
+  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.
+
+  @par Specification Reference:
+  AMD64 Architecture Programming Manaul volume 2, March 2017, Sections 15.34
+
+**/
+
+#ifndef __AMD_CPUID_H__
+#define __AMD_CPUID_H__
+
+/**
+
+  Memory Encryption Information
+
+  @param   EAX  CPUID_MEMORY_ENCRYPTION_INFO (0x8000001F)
+
+  @retval  EAX  Returns the memory encryption feature support status.
+  @retval  EBX  If memory encryption feature is present then return
+                the page table bit number used to enable memory encryption support
+                and reducing of physical address space in bits.
+  @retval  ECX  Returns number of encrypted guest supported simultaneosuly.
+  @retval  EDX  Returns minimum SEV enabled and SEV disbled ASID..
+
+  <b>Example usage</b>
+  @code
+  UINT32 Eax;
+  UINT32 Ebx;
+  UINT32 Ecx;
+  UINT32 Edx;
+
+  AsmCpuid (CPUID_MEMORY_ENCRYPTION_INFO, &Eax, &Ebx, &Ecx, &Edx);
+  @endcode
+**/
+
+#define CPUID_MEMORY_ENCRYPTION_INFO             0x8000001F
+
+/**
+  CPUID Memory Encryption support information EAX for CPUID leaf
+  #CPUID_MEMORY_ENCRYPTION_INFO.
+**/
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    ///
+    /// [Bit 0] Secure Memory Encryption (Sme) Support
+    ///
+    UINT32  SmeBit:1;
+
+    ///
+    /// [Bit 1] Secure Encrypted Virtualization (Sev) Support
+    ///
+    UINT32  SevBit:1;
+
+    ///
+    /// [Bit 2] Page flush MSR support
+    ///
+    UINT32  PageFlushMsrBit:1;
+
+    ///
+    /// [Bit 3] Encrypted state support
+    ///
+    UINT32  SevEsBit:1;
+
+    ///
+    /// [Bit 4:31] Reserved
+    ///
+    UINT32  ReservedBits:28;
+  } Bits;
+  ///
+  /// All bit fields as a 32-bit value
+  ///
+  UINT32  Uint32;
+} CPUID_MEMORY_ENCRYPTION_INFO_EAX;
+
+/**
+  CPUID Memory Encryption support information EBX for CPUID leaf
+  #CPUID_MEMORY_ENCRYPTION_INFO.
+**/
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    ///
+    /// [Bit 0:5] Page table bit number used to enable memory encryption
+    ///
+    UINT32  PtePosBits:6;
+
+    ///
+    /// [Bit 6:11] Reduction of system physical address space bits when memory encryption is enabled
+    ///
+    UINT32  ReducedPhysBits:5;
+
+    ///
+    /// [Bit 12:31] Reserved
+    ///
+    UINT32  ReservedBits:21;
+  } Bits;
+  ///
+  /// All bit fields as a 32-bit value
+  ///
+  UINT32  Uint32;
+} CPUID_MEMORY_ENCRYPTION_INFO_EBX;
+
+/**
+  CPUID Memory Encryption support information ECX for CPUID leaf
+  #CPUID_MEMORY_ENCRYPTION_INFO.
+**/
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    ///
+    /// [Bit 0:31] Number of encrypted guest supported simultaneously
+    ///
+    UINT32  NumGuests;
+  } Bits;
+  ///
+  /// All bit fields as a 32-bit value
+  ///
+  UINT32  Uint32;
+} CPUID_MEMORY_ENCRYPTION_INFO_ECX;
+
+/**
+  CPUID Memory Encryption support information EDX for CPUID leaf
+  #CPUID_MEMORY_ENCRYPTION_INFO.
+**/
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    ///
+    /// [Bit 0:31] Minimum SEV enabled, SEV-ES disabled ASID
+    ///
+    UINT32  MinAsid;
+  } Bits;
+  ///
+  /// All bit fields as a 32-bit value
+  ///
+  UINT32  Uint32;
+} CPUID_MEMORY_ENCRYPTION_INFO_EDX;
+
+#endif
diff --git a/UefiCpuPkg/Include/Register/Amd/Fam17Msr.h b/UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
new file mode 100644
index 000000000000..2c5d9738fae8
--- /dev/null
+++ b/UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
@@ -0,0 +1,62 @@
+/** @file
+  MSR Definitions.
+
+  Provides defines for Machine Specific Registers(MSR) indexes. Data structures
+  are provided for MSRs that contain one or more bit fields.  If the MSR value
+  returned is a single 32-bit or 64-bit value, then a data structure is not
+  provided for that MSR.
+
+  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.
+
+  @par Specification Reference:
+  AMD64 Architecture Programming Manaul volume 2, March 2017, Sections 15.34
+
+**/
+
+#ifndef __FAM17_MSR_H
+#define __FAM17_MSR_H
+
+/**
+  Secure Encrypted Virtualization (SEV) status register
+
+**/
+#define MSR_SEV_STATUS                     0xc0010131
+
+/**
+  MSR information returned for #MSR_SEV_STATUS
+**/
+typedef union {
+  ///
+  /// Individual bit fields
+  ///
+  struct {
+    ///
+    /// [Bit 0] Secure Encrypted Virtualization (Sev) is enabled
+    ///
+    UINT32  SevBit:1;
+
+    ///
+    /// [Bit 1] Secure Encrypted Virtualization Encrypted State (SevEs) is enabled
+    ///
+    UINT32  SevEsBit:1;
+
+    UINT32  Reserved:30;
+  } Bits;
+  ///
+  /// All bit fields as a 32-bit value
+  ///
+  UINT32  Uint32;
+  ///
+  /// All bit fields as a 64-bit value
+  ///
+  UINT64  Uint64;
+} MSR_SEV_STATUS_REGISTER;
+
+#endif
diff --git a/UefiCpuPkg/Include/Register/Amd/Msr.h b/UefiCpuPkg/Include/Register/Amd/Msr.h
new file mode 100644
index 000000000000..bde830feb0c5
--- /dev/null
+++ b/UefiCpuPkg/Include/Register/Amd/Msr.h
@@ -0,0 +1,29 @@
+/** @file
+  MSR Definitions.
+
+  Provides defines for Machine Specific Registers(MSR) indexes. Data structures
+  are provided for MSRs that contain one or more bit fields.  If the MSR value
+  returned is a single 32-bit or 64-bit value, then a data structure is not
+  provided for that MSR.
+
+  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.
+
+  @par Specification Reference:
+  AMD64 Architecture Programming Manaul volume 2, March 2017, Sections 15.34
+
+**/
+
+#ifndef __AMD_MSR_H__
+#define __AMD_MSR_H__
+
+#include <Register/ArchitecturalMsr.h>
+#include <Register/Amd/Fam17Msr.h>
+
+#endif
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 02/17] OvmfPkg/ResetVector: Set C-bit when building initial page table
  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 ` Brijesh Singh
  2017-06-01  8:09   ` Jordan Justen
  2017-05-26 14:43 ` [PATCH v6 03/17] OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf Brijesh Singh
                   ` (16 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

SEV guest VMs have the concept of private and shared memory. Private
memory is encrypted with the guest-specific key, while shared memory
may be encrypted with hypervisor key. Certain types of memory (namely
instruction pages and guest page tables) are always treated as private
memory by the hardware. The C-bit in PTE indicate whether the page is
private or shared. The C-bit position for the PTE can be obtained from
CPUID Fn8000_001F[EBX].

When SEV is active, the BIOS is encrypted by the Qemu launch sequence,
we must set the C-bit when building the page table.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Tom Lendacky <Thomas.Lendacky@amd.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/ResetVector/Ia32/PageTables64.asm | 70 +++++++++++++++++++-
 1 file changed, 69 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
index 6201cad1f5dc..3d4b04844cdf 100644
--- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
+++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
@@ -37,9 +37,60 @@ BITS    32
                        PAGE_READ_WRITE + \
                        PAGE_PRESENT)
 
+; Check if Secure Encrypted Virtualization (SEV) feature is enabled
+;
+; If SEV is enabled then EAX will be at least 32
+; If SEV is disabled then EAX will be zero.
+;
+CheckSevFeature:
+    ; CPUID will clobber EBX, ECX, EDX, save these registers
+    push  ebx
+    push  ecx
+    push  edx
+
+    ; Check if we have a valid (0x8000_001F) CPUID leaf
+    mov       eax, 0x80000000
+    cpuid
+
+    ; This check should fail on Intel or Non SEV AMD CPUs and in future if
+    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
+    ; same bit definition.
+    cmp       eax, 0x8000001f
+    jl        NoSev
+
+    ; Check for memory encryption feature:
+    ;  CPUID  Fn8000_001F[EAX] - Bit 1
+    ;
+    mov       eax,  0x8000001f
+    cpuid
+    bt        eax, 1
+    jnc       NoSev
+
+    ; Check if memory encryption is enabled
+    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
+    mov       ecx, 0xc0010131
+    rdmsr
+    bt        eax, 0
+    jnc       NoSev
+
+    ; Get pte bit position to enable memory encryption
+    ; CPUID Fn8000_001F[EBX] - Bits 5:0
+    ;
+    mov       eax, ebx
+    and       eax, 0x3f
+    jmp       SevExit
+
+NoSev:
+    xor       eax, eax
+
+SevExit:
+    pop       edx
+    pop       ecx
+    pop       ebx
+    OneTimeCallRet CheckSevFeature
 
 ;
-; Modified:  EAX, ECX
+; Modified:  EAX, ECX, EDX
 ;
 SetCr3ForPageTables64:
 
@@ -60,18 +111,34 @@ clearPageTablesMemoryLoop:
     mov     dword[ecx * 4 + PT_ADDR (0) - 4], eax
     loop    clearPageTablesMemoryLoop
 
+    OneTimeCall   CheckSevFeature
+    xor     edx, edx
+    test    eax, eax
+    jz      SevNotActive
+
+    ; If SEV is enabled, Memory encryption bit is always above 31
+    sub     eax, 32
+    bts     edx, eax
+
+SevNotActive:
+
     ;
     ; Top level Page Directory Pointers (1 * 512GB entry)
     ;
     mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (4)], edx
 
     ;
     ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
     ;
     mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x1004)], edx
     mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x100C)], edx
     mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x1014)], edx
     mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
+    mov     dword[PT_ADDR (0x101C)], edx
 
     ;
     ; Page Table Entries (2048 * 2MB entries => 4GB)
@@ -83,6 +150,7 @@ pageTableEntriesLoop:
     shl     eax, 21
     add     eax, PAGE_2M_PDE_ATTR
     mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
+    mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
     loop    pageTableEntriesLoop
 
     ;
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 03/17] OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
  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-05-26 14:43 ` Brijesh Singh
  2017-05-26 14:43 ` [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library Brijesh Singh
                   ` (15 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

When SEV is enabled then we must unroll the rep String I/O instructions.

The patch updates dsc file to use SEV version of IoLib inf. The main
difference between BaseIoLibIntrinsic.inf and BaseIoLibIntrinsicSev.inf
is, SEV version checks if its running under SEV enabled guest, If so
then it unroll the String I/O (REP INS/OUTS) otherwise fallbacks to
rep ins/outs.


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    | 2 +-
 OvmfPkg/OvmfPkgIa32X64.dsc | 2 +-
 OvmfPkg/OvmfPkgX64.dsc     | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 0647f346257a..b5c874b65afc 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -122,7 +122,7 @@ [LibraryClasses]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
-  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
   SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
   MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 1182b1858a7d..1d071cac2bef 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -127,7 +127,7 @@ [LibraryClasses]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
-  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
   SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
   MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 636dfb1b5638..2bea75437788 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -127,7 +127,7 @@ [LibraryClasses]
   PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
   PciLib|MdePkg/Library/BasePciLibCf8/BasePciLibCf8.inf
   PciSegmentLib|MdePkg/Library/BasePciSegmentLibPci/BasePciSegmentLibPci.inf
-  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+  IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsicSev.inf
   OemHookStatusCodeLib|MdeModulePkg/Library/OemHookStatusCodeLibNull/OemHookStatusCodeLibNull.inf
   SerialPortLib|PcAtChipsetPkg/Library/SerialIoLib/SerialIoLib.inf
   MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (2 preceding siblings ...)
  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 ` Brijesh Singh
  2017-05-26 20:54   ` Jordan Justen
  2017-05-26 14:43 ` [PATCH v6 05/17] OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled Brijesh Singh
                   ` (14 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

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



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 05/17] OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (3 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library Brijesh Singh
@ 2017-05-26 14:43 ` Brijesh Singh
  2017-05-26 14:43 ` [PATCH v6 06/17] OvmfPkg: Add AmdSevDxe driver Brijesh Singh
                   ` (13 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Secure Encrypted Virtualization (SEV) guest VMs have the concept of
private and shared memory. Private memory is encrypted with the
guest-specific key, while shared memory may be encrypted with hypervisor
key.  Certain types of memory (namely instruction pages and guest page
tables) are always treated as private memory by the hardware.
For data memory, SEV guest VMs can choose which pages they would like
to be private. The choice is done using the standard CPU page tables
using the C-bit. When building the initial page table we mark all the
memory as private.

The patch sets the memory encryption PCD. The PCD is consumed by the
following edk2 modules, which manipulate page tables:

- PEI phase modules: CapsulePei, DxeIplPeim, S3Resume2Pei.

CapsulePei is not used by OVMF. DxeIplPeim consumes the PCD at the
end of the PEI phase, when it builds the initial page tables for the
DXE core / DXE phase. S3Resume2Pei does not consume the PCD in its
entry point function, only when DxeIplPeim branches to the S3 resume
path at the end of the PEI phase, and calls S3Resume2Pei's
EFI_PEI_S3_RESUME2_PPI.S3RestoreConfig2() member function.

Therefore it is safe to set the PCD for these modules in PlatformPei.

- DXE phase modules: BootScriptExecutorDxe, CpuDxe, PiSmmCpuDxeSmm.

They are all dispatched after the PEI phase, so setting the PCD for
them in PlatformPei is safe. (BootScriptExecutorDxe is launched "for
real" in the PEI phase during S3 resume, but it caches the PCD into a
static variable when its entry point is originally invoked in DXE.)

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             |  3 +
 OvmfPkg/OvmfPkgIa32X64.dsc          |  3 +
 OvmfPkg/OvmfPkgX64.dsc              |  3 +
 OvmfPkg/PlatformPei/PlatformPei.inf |  3 +
 OvmfPkg/PlatformPei/Platform.h      |  5 ++
 OvmfPkg/PlatformPei/AmdSev.c        | 62 ++++++++++++++++++++
 OvmfPkg/PlatformPei/Platform.c      |  1 +
 7 files changed, 80 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 98691c0a6d99..55f7e4269938 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -534,6 +534,9 @@ [PcdsDynamicDefault]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000
 
+  # Set memory encryption mask
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
 !if $(SMM_REQUIRE) == TRUE
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode|0x01
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout|100000
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 3b51513a4d95..dfc2534fc998 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -542,6 +542,9 @@ [PcdsDynamicDefault]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000
 
+  # Set memory encryption mask
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
 !if $(SMM_REQUIRE) == TRUE
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode|0x01
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout|100000
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index ebf07cd585dd..60e42794483b 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -541,6 +541,9 @@ [PcdsDynamicDefault]
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber|64
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds|50000
 
+  # Set memory encryption mask
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask|0x0
+
 !if $(SMM_REQUIRE) == TRUE
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmSyncMode|0x01
   gUefiCpuPkgTokenSpaceGuid.PcdCpuSmmApSyncTimeout|100000
diff --git a/OvmfPkg/PlatformPei/PlatformPei.inf b/OvmfPkg/PlatformPei/PlatformPei.inf
index a1e12c1fc7e2..16a8db7b0bd2 100644
--- a/OvmfPkg/PlatformPei/PlatformPei.inf
+++ b/OvmfPkg/PlatformPei/PlatformPei.inf
@@ -29,6 +29,7 @@ [Defines]
 #
 
 [Sources]
+  AmdSev.c
   Cmos.c
   FeatureControl.c
   Fv.c
@@ -60,6 +61,7 @@ [LibraryClasses]
   QemuFwCfgLib
   QemuFwCfgS3Lib
   MtrrLib
+  MemEncryptSevLib
   PcdLib
 
 [Pcd]
@@ -93,6 +95,7 @@ [Pcd]
   gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack
   gEfiMdeModulePkgTokenSpaceGuid.PcdPropertiesTableEnable
   gEfiMdeModulePkgTokenSpaceGuid.PcdAcpiS3Enable
+  gEfiMdeModulePkgTokenSpaceGuid.PcdPteMemoryEncryptionAddressOrMask
   gUefiCpuPkgTokenSpaceGuid.PcdCpuLocalApicBaseAddress
   gUefiCpuPkgTokenSpaceGuid.PcdCpuMaxLogicalProcessorNumber
   gUefiCpuPkgTokenSpaceGuid.PcdCpuApInitTimeOutInMicroSeconds
diff --git a/OvmfPkg/PlatformPei/Platform.h b/OvmfPkg/PlatformPei/Platform.h
index 18f42c3f0ea8..a7729b9df44b 100644
--- a/OvmfPkg/PlatformPei/Platform.h
+++ b/OvmfPkg/PlatformPei/Platform.h
@@ -88,6 +88,11 @@ XenDetect (
   VOID
   );
 
+VOID
+AmdSevInitialize (
+  VOID
+  );
+
 extern BOOLEAN mXen;
 
 VOID
diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
new file mode 100644
index 000000000000..26f7c3fdbb13
--- /dev/null
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -0,0 +1,62 @@
+/**@file
+  Initialize Secure Encrypted Virtualization (SEV) support
+
+  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.
+
+**/
+//
+// The package level header files this module uses
+//
+#include <PiPei.h>
+
+#include <Library/DebugLib.h>
+#include <Library/PcdLib.h>
+#include <Register/Cpuid.h>
+#include <Register/Amd/Cpuid.h>
+#include <Library/MemEncryptSevLib.h>
+
+/**
+
+  Function checks if SEV support is available, if present then it sets
+  the dynamic PcdPteMemoryEncryptionAddressOrMask with memory encryption mask.
+
+  **/
+VOID
+EFIAPI
+AmdSevInitialize (
+  VOID
+  )
+{
+  CPUID_MEMORY_ENCRYPTION_INFO_EBX  Ebx;
+  UINT64                            EncryptionMask;
+  RETURN_STATUS                     PcdStatus;
+
+  //
+  // Check if SEV is enabled
+  //
+  if (!MemEncryptSevIsEnabled ()) {
+    return;
+  }
+
+  //
+  // 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);
+
+  //
+  // Set Memory Encryption Mask PCD
+  //
+  PcdStatus = PcdSet64S (PcdPteMemoryEncryptionAddressOrMask, EncryptionMask);
+  ASSERT_RETURN_ERROR (PcdStatus);
+
+  DEBUG ((DEBUG_INFO, "SEV is enabled (mask 0x%lx)\n", EncryptionMask));
+}
diff --git a/OvmfPkg/PlatformPei/Platform.c b/OvmfPkg/PlatformPei/Platform.c
index 3e9fda7c7ab0..ede4a1298558 100644
--- a/OvmfPkg/PlatformPei/Platform.c
+++ b/OvmfPkg/PlatformPei/Platform.c
@@ -668,6 +668,7 @@ InitializePlatform (
     NoexecDxeInitialization ();
   }
 
+  AmdSevInitialize ();
   MiscInitialization ();
   InstallFeatureControlCallback ();
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 06/17] OvmfPkg: Add AmdSevDxe driver
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (4 preceding siblings ...)
  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 ` Brijesh Singh
  2017-05-26 14:43 ` [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID Brijesh Singh
                   ` (12 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek, Jiewen Yao

When SEV is enabled, the MMIO memory range must be mapped as unencrypted
(i.e C-bit cleared).

We need to clear the C-bit for MMIO GCD entries in order to cover the
ranges that were added during the PEI phase (through memory resource
descriptor HOBs). Additionally, the NonExistent ranges are processed
in order to cover, in advance, MMIO ranges added later in the DXE phase
by various device drivers, via the appropriate DXE memory space services.

The approach is not transparent for later addition of system memory ranges
to the GCD memory space map. (Such ranges should be encrypted.) OVMF does
not do such a thing at the moment, so this approach should be OK.

The driver is being added to the APRIORI DXE file so that, we clear the
C-bit from MMIO regions before any driver accesses it.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Suggested-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
---
 OvmfPkg/OvmfPkgIa32X64.dsc      |  1 +
 OvmfPkg/OvmfPkgX64.dsc          |  1 +
 OvmfPkg/OvmfPkgIa32X64.fdf      |  2 +
 OvmfPkg/OvmfPkgX64.fdf          |  2 +
 OvmfPkg/AmdSevDxe/AmdSevDxe.inf | 43 +++++++++++
 OvmfPkg/AmdSevDxe/AmdSevDxe.c   | 75 ++++++++++++++++++++
 6 files changed, 124 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index dfc2534fc998..8dd6179893a9 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -824,6 +824,7 @@ [Components.X64]
 !endif
 
   OvmfPkg/PlatformDxe/Platform.inf
+  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 60e42794483b..6324941ca2ab 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -822,6 +822,7 @@ [Components]
 !endif
 
   OvmfPkg/PlatformDxe/Platform.inf
+  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 5233314139bc..12871860d001 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -190,6 +190,7 @@ [FV.DXEFV]
 APRIORI DXE {
   INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
   INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 !if $(SMM_REQUIRE) == FALSE
   INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 !endif
@@ -351,6 +352,7 @@ [FV.DXEFV]
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
+INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
 INF  OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index 36150101e784..ae6e66a1c08d 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -190,6 +190,7 @@ [FV.DXEFV]
 APRIORI DXE {
   INF  MdeModulePkg/Universal/DevicePathDxe/DevicePathDxe.inf
   INF  MdeModulePkg/Universal/PCD/Dxe/Pcd.inf
+  INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 !if $(SMM_REQUIRE) == FALSE
   INF  OvmfPkg/QemuFlashFvbServicesRuntimeDxe/FvbServicesRuntimeDxe.inf
 !endif
@@ -351,6 +352,7 @@ [FV.DXEFV]
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
+INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
 INF  OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
new file mode 100644
index 000000000000..41635a57a454
--- /dev/null
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
@@ -0,0 +1,43 @@
+#/** @file
+#
+#  Driver clears the encryption attribute from MMIO regions when SEV is enabled
+#
+#  Copyright (c) 2017, AMD Inc. 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                      = AmdSevDxe
+  FILE_GUID                      = 2ec9da37-ee35-4de9-86c5-6d9a81dc38a7
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = AmdSevDxeEntryPoint
+
+[Sources]
+  AmdSevDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DxeServicesTableLib
+  DebugLib
+  MemEncryptSevLib
+
+[Depex]
+  TRUE
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
new file mode 100644
index 000000000000..e472096320ea
--- /dev/null
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -0,0 +1,75 @@
+/** @file
+
+  AMD Sev Dxe driver. This driver is dispatched early in DXE, due to being list
+  in APRIORI. It clears C-bit from MMIO and NonExistent Memory space when SEV is
+  enabled.
+
+  Copyright (c) 2017, AMD Inc. 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+EFI_STATUS
+EFIAPI
+AmdSevDxeEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS                       Status;
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *AllDescMap;
+  UINTN                            NumEntries;
+  UINTN                            Index;
+
+  //
+  // Do nothing when SEV is not enabled
+  //
+  if (!MemEncryptSevIsEnabled ()) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Iterate through the GCD map and clear the C-bit from MMIO and NonExistent
+  // memory space. The NonExistent memory space will be used for mapping the MMIO
+  // space added later (eg PciRootBridge). By clearing both known MMIO and
+  // NonExistent memory space can gurantee that current and furture MMIO adds
+  // will have C-bit cleared.
+  //
+  Status = gDS->GetMemorySpaceMap (&NumEntries, &AllDescMap);
+  if (!EFI_ERROR (Status)) {
+    for (Index = 0; Index < NumEntries; Index++) {
+      CONST EFI_GCD_MEMORY_SPACE_DESCRIPTOR *Desc;
+
+      Desc = &AllDescMap[Index];
+      if (Desc->GcdMemoryType == EfiGcdMemoryTypeMemoryMappedIo ||
+          Desc->GcdMemoryType == EfiGcdMemoryTypeNonExistent) {
+        Status = MemEncryptSevClearPageEncMask (0,
+                                                Desc->BaseAddress,
+                                                EFI_SIZE_TO_PAGES(Desc->Length),
+                                                FALSE);
+        ASSERT_EFI_ERROR (Status);
+      }
+    }
+
+    FreePool (AllDescMap);
+  }
+
+  return EFI_SUCCESS;
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (5 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 06/17] OvmfPkg: Add AmdSevDxe driver Brijesh Singh
@ 2017-05-26 14:43 ` Brijesh Singh
  2017-05-29  9:07   ` Laszlo Ersek
  2017-05-26 14:43 ` [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib Brijesh Singh
                   ` (11 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Platforms that optionally provide an IOMMU protocol should do so by
including a DXE driver (usually called IoMmuDxe) that produces either
the IOMMU protocol -- if the underlying capabilities are available --,
or gIoMmuAbsentProtocolGuid, to signal that the IOMMU capability
detection completed with negative result (i.e., no IOMMU will be
available in the system).

In turn, DXE drivers (and library instances) that are supposed to use
the IOMMU protocol if it is available should add the following to
their DEPEX:

gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid

This ensures these client modules will only be dispatched after IOMMU
detection completes (with positive or negative result).


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leo Duran <leo.duran@amd.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/OvmfPkg.dec | 1 +
 1 file changed, 1 insertion(+)

diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index 5627be0bab0a..4241af10c3d0 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -69,6 +69,7 @@ [Protocols]
   gBlockMmioProtocolGuid              = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}}
   gXenBusProtocolGuid                 = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
   gXenIoProtocolGuid                  = {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}}
+  gIoMmuAbsentProtocolGuid            = {0xf8775d50, 0x8abd, 0x4adf, {0x92, 0xac, 0x85, 0x3e, 0x51, 0xf6, 0xc8, 0xdc}}
 
 [PcdsFixedAtBuild]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (6 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID Brijesh Singh
@ 2017-05-26 14:43 ` Brijesh Singh
  2017-05-29  9:19   ` Laszlo Ersek
  2017-05-26 14:43 ` [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver Brijesh Singh
                   ` (10 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Add the shorter-term library instance outlined in the previous patch to
OvmfPkg, so that we can imbue PciHostBridgeDxe with a protocol dependency
on gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf | 37 ++++++++++++++++++++
 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c   | 32 +++++++++++++++++
 2 files changed, 69 insertions(+)

diff --git a/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
new file mode 100644
index 000000000000..6d97293a3334
--- /dev/null
+++ b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
@@ -0,0 +1,37 @@
+## @file
+# A hook-in library for MdeModulePkg/Bus/Pci/PciHostBridgeDxe.
+#
+#  Plugging this library instance into PciHostBridgeDxe makes
+#  EFI_IOMMU_PROTOCOL depend on the platform's dynamic decision whether
+#  to provide IOMMU implementation (usually through IoMmuDxe driver).
+#
+# Copyright (C) 2017, AMD, Inc.
+#
+# 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                      = PlatformHasIoMmuLib
+  FILE_GUID                      = 49b4b018-0558-448b-1e1a-12226342877d
+  MODULE_TYPE                    = BASE
+  VERSION_STRING                 = 1.0
+  LIBRARY_CLASS                  = PlatformHasIoMmuLib|DXE_DRIVER
+  CONSTRUCTOR                    = PlatformHasIoMmuInitialize
+
+[Sources]
+  PlatformHasIoMmuLib.c
+
+[Packages]
+  MdeModulePkg/MdeModulePkg.dec
+  MdePkg/MdePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[Depex]
+  gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
diff --git a/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
new file mode 100644
index 000000000000..9ead2637e2c8
--- /dev/null
+++ b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
@@ -0,0 +1,32 @@
+/** @file
+  A hook-in library for MdeModulePkg/Bus/Pci/PciHostBridgeDxe.
+
+  Plugging this library instance into PciHostBridgeDxe makes
+  EFI_IOMMU_PROTOCOL depend on the platform's dynamic decision whether
+  to provide IOMMU implementation (usually through IoMmuDxe driver).
+
+  Copyright (C) 2017, AMD, Inc.
+
+  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 <Base.h>
+
+RETURN_STATUS
+EFIAPI
+PlatformHasIoMmuInitialize (
+  VOID
+  )
+{
+  //
+  // Do nothing, just imbue PciHostBridgeDxe with a protocol dependency on
+  // gIoMmuAbsentProtocolGuid OR gEdkiiIoMmuProtocolGuid.
+  //
+  return RETURN_SUCCESS;
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (7 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib Brijesh Singh
@ 2017-05-26 14:43 ` 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
                   ` (9 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek, Jiewen Yao

The IOMMU protocol driver provides capabilities to set a DMA access
attribute and methods to allocate, free, map and unmap the DMA memory
for the PCI Bus devices.

Due to security reasons all DMA operations inside the SEV guest must
be performed on shared (i.e unencrypted) pages. The IOMMU protocol
driver for the SEV guest uses a bounce buffer to map guest DMA buffer
to shared pages inorder to provide the support for DMA operations inside
SEV guest.

IoMmuDxe driver looks for SEV capabilities, if present then it installs
the real IOMMU protocol otherwise it installs placeholder protocol.
Currently, PciHostBridgeDxe and QemuFWCfgLib need to know the existance
of IOMMU protocol. The modules needing to know the existance of IOMMU
support should add

  gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid

in their depex to ensure that platform IOMMU detection has been performed.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Leo Duran <leo.duran@amd.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Suggested-by: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
---
 OvmfPkg/OvmfPkgIa32.dsc        |   1 +
 OvmfPkg/OvmfPkgIa32X64.dsc     |   1 +
 OvmfPkg/OvmfPkgX64.dsc         |   1 +
 OvmfPkg/OvmfPkgIa32.fdf        |   1 +
 OvmfPkg/OvmfPkgIa32X64.fdf     |   1 +
 OvmfPkg/OvmfPkgX64.fdf         |   1 +
 OvmfPkg/IoMmuDxe/IoMmuDxe.inf  |  49 +++
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h |  43 ++
 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 459 ++++++++++++++++++++
 OvmfPkg/IoMmuDxe/IoMmuDxe.c    |  53 +++
 10 files changed, 610 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 55f7e4269938..18544d7cfd73 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -815,6 +815,7 @@ [Components]
 !endif
 
   OvmfPkg/PlatformDxe/Platform.inf
+  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 8dd6179893a9..1b3bf3517a9f 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -825,6 +825,7 @@ [Components.X64]
 
   OvmfPkg/PlatformDxe/Platform.inf
   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 6324941ca2ab..9fdabaf0eac4 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -823,6 +823,7 @@ [Components]
 
   OvmfPkg/PlatformDxe/Platform.inf
   OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
   OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf
index 09c165882c3f..c6c60bf81413 100644
--- a/OvmfPkg/OvmfPkgIa32.fdf
+++ b/OvmfPkg/OvmfPkgIa32.fdf
@@ -351,6 +351,7 @@ [FV.DXEFV]
 INF  OvmfPkg/QemuVideoDxe/QemuVideoDxe.inf
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
+INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
 INF  OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf
index 12871860d001..6bd574459bd0 100644
--- a/OvmfPkg/OvmfPkgIa32X64.fdf
+++ b/OvmfPkg/OvmfPkgIa32X64.fdf
@@ -353,6 +353,7 @@ [FV.DXEFV]
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
 INF  OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf
index ae6e66a1c08d..c3d75ca9d72f 100644
--- a/OvmfPkg/OvmfPkgX64.fdf
+++ b/OvmfPkg/OvmfPkgX64.fdf
@@ -353,6 +353,7 @@ [FV.DXEFV]
 INF  OvmfPkg/VirtioGpuDxe/VirtioGpu.inf
 INF  OvmfPkg/PlatformDxe/Platform.inf
 INF  OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+INF  OvmfPkg/IoMmuDxe/IoMmuDxe.inf
 
 !if $(SMM_REQUIRE) == TRUE
 INF  OvmfPkg/SmmAccess/SmmAccess2Dxe.inf
diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.inf b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf
new file mode 100644
index 000000000000..b90dc80dfd37
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.inf
@@ -0,0 +1,49 @@
+#/** @file
+#
+#  Driver provides the IOMMU protcol support for PciHostBridgeIo and others
+#  drivers.
+#
+#  Copyright (c) 2017, AMD Inc. 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                      = IoMmuDxe
+  FILE_GUID                      = 8657015b-ea43-440d-949a-af3be365c0fc
+  MODULE_TYPE                    = DXE_DRIVER
+  VERSION_STRING                 = 1.0
+  ENTRY_POINT                    = IoMmuDxeEntryPoint
+
+[Sources]
+  AmdSevIoMmu.c
+  IoMmuDxe.c
+
+[Packages]
+  MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
+  OvmfPkg/OvmfPkg.dec
+
+[LibraryClasses]
+  BaseLib
+  UefiLib
+  UefiDriverEntryPoint
+  UefiBootServicesTableLib
+  DxeServicesTableLib
+  DebugLib
+  MemEncryptSevLib
+
+[Protocols]
+  gEdkiiIoMmuProtocolGuid                     ## SOMETIME_PRODUCES
+  gIoMmuAbsentProtocolGuid                    ## SOMETIME_PRODUCES
+
+[Depex]
+  TRUE
diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
new file mode 100644
index 000000000000..8b3962a8c395
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
@@ -0,0 +1,43 @@
+/** @file
+
+  The protocol provides support to allocate, free, map and umap a DMA buffer for
+  bus master (e.g PciHostBridge). When SEV is enabled, the DMA operations must
+  be performed on unencrypted buffer hence protocol clear the encryption bit
+  from the DMA buffer.
+
+  Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2017, AMD Inc. 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 __AMD_SEV_IOMMU_H_
+#define __AMD_SEV_IOMMU_H
+
+#include <Protocol/IoMmu.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+/**
+  Install IOMMU protocol to provide the DMA support for PciHostBridge and
+  MemEncryptSevLib.
+
+**/
+VOID
+EFIAPI
+AmdSevInstallIoMmuProtocol (
+  VOID
+  );
+
+#endif
diff --git a/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
new file mode 100644
index 000000000000..9e78058b7242
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
@@ -0,0 +1,459 @@
+/** @file
+
+  The protocol provides support to allocate, free, map and umap a DMA buffer for
+  bus master (e.g PciHostBridge). When SEV is enabled, the DMA operations must
+  be performed on unencrypted buffer hence we use a bounce buffer to map the guest
+  buffer into an unencrypted DMA buffer.
+
+  Copyright (c) 2017, AMD Inc. All rights reserved.<BR>
+  Copyright (c) 2017, Intel Corporation. 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 "AmdSevIoMmu.h"
+
+typedef struct {
+  EDKII_IOMMU_OPERATION                     Operation;
+  UINTN                                     NumberOfBytes;
+  UINTN                                     NumberOfPages;
+  EFI_PHYSICAL_ADDRESS                      HostAddress;
+  EFI_PHYSICAL_ADDRESS                      DeviceAddress;
+} MAP_INFO;
+
+#define NO_MAPPING             (VOID *) (UINTN) -1
+
+/**
+  Provides the controller-specific addresses required to access system memory from a
+  DMA bus master. On SEV guest, the DMA operations must be performed on shared
+  buffer hence we allocate a bounce buffer to map the HostAddress to a DeviceAddress.
+  The Encryption attribute is removed from the DeviceAddress buffer.
+
+  @param  This                  The protocol instance pointer.
+  @param  Operation             Indicates if the bus master is going to read or
+                                write to system memory.
+  @param  HostAddress           The system memory address to map to the PCI controller.
+  @param  NumberOfBytes         On input the number of bytes to map. On output
+                                the number of bytes
+                                that were mapped.
+  @param  DeviceAddress         The resulting map address for the bus master PCI
+                                controller to use to
+                                access the hosts HostAddress.
+  @param  Mapping               A resulting value to pass to Unmap().
+
+  @retval EFI_SUCCESS           The range was mapped for the returned NumberOfBytes.
+  @retval EFI_UNSUPPORTED       The HostAddress cannot be mapped as a common buffer.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack
+                                of resources.
+  @retval EFI_DEVICE_ERROR      The system hardware could not map the requested address.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuMap (
+  IN     EDKII_IOMMU_PROTOCOL                       *This,
+  IN     EDKII_IOMMU_OPERATION                      Operation,
+  IN     VOID                                       *HostAddress,
+  IN OUT UINTN                                      *NumberOfBytes,
+  OUT    EFI_PHYSICAL_ADDRESS                       *DeviceAddress,
+  OUT    VOID                                       **Mapping
+  )
+{
+  EFI_STATUS                                        Status;
+  EFI_PHYSICAL_ADDRESS                              PhysicalAddress;
+  MAP_INFO                                          *MapInfo;
+  EFI_PHYSICAL_ADDRESS                              DmaMemoryTop;
+  EFI_ALLOCATE_TYPE                                 AllocateType;
+
+  if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL ||
+      Mapping == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // Make sure that Operation is valid
+  //
+  if ((UINT32) Operation >= EdkiiIoMmuOperationMaximum) {
+    return EFI_INVALID_PARAMETER;
+  }
+  PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+
+  DmaMemoryTop = (UINTN)-1;
+  AllocateType = AllocateAnyPages;
+
+  if (((Operation != EdkiiIoMmuOperationBusMasterRead64 &&
+        Operation != EdkiiIoMmuOperationBusMasterWrite64 &&
+        Operation != EdkiiIoMmuOperationBusMasterCommonBuffer64)) &&
+      ((PhysicalAddress + *NumberOfBytes) > SIZE_4GB)) {
+    //
+    // If the root bridge or the device cannot handle performing DMA above
+    // 4GB but any part of the DMA transfer being mapped is above 4GB, then
+    // map the DMA transfer to a buffer below 4GB.
+    //
+    DmaMemoryTop = SIZE_4GB - 1;
+    AllocateType = AllocateMaxAddress;
+
+    if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
+        Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
+        //
+        // Common Buffer operations can not be remapped.  If the common buffer
+        // if above 4GB, then it is not possible to generate a mapping, so return
+        // an error.
+        //
+        return EFI_UNSUPPORTED;
+    }
+  }
+
+  //
+  // CommandBuffer was allocated by us (AllocateBuffer) and is already in
+  // unencryted buffer so no need to create bounce buffer
+  //
+  if (Operation == EdkiiIoMmuOperationBusMasterCommonBuffer ||
+      Operation == EdkiiIoMmuOperationBusMasterCommonBuffer64) {
+    *Mapping = NO_MAPPING;
+    *DeviceAddress = PhysicalAddress;
+
+    return EFI_SUCCESS;
+  }
+
+  //
+  // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+  // called later.
+  //
+  MapInfo = AllocatePool (sizeof (MAP_INFO));
+  if (MapInfo == NULL) {
+    *NumberOfBytes = 0;
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // Initialize the MAP_INFO structure
+  //
+  MapInfo->Operation         = Operation;
+  MapInfo->NumberOfBytes     = *NumberOfBytes;
+  MapInfo->NumberOfPages     = EFI_SIZE_TO_PAGES (MapInfo->NumberOfBytes);
+  MapInfo->HostAddress       = PhysicalAddress;
+  MapInfo->DeviceAddress     = DmaMemoryTop;
+
+  //
+  // Allocate a buffer to map the transfer to.
+  //
+  Status = gBS->AllocatePages (
+                  AllocateType,
+                  EfiBootServicesData,
+                  MapInfo->NumberOfPages,
+                  &MapInfo->DeviceAddress
+                  );
+  if (EFI_ERROR (Status)) {
+    FreePool (MapInfo);
+    *NumberOfBytes = 0;
+    return Status;
+  }
+
+  //
+  // Clear the memory encryption mask from the device buffer
+  //
+  Status = MemEncryptSevClearPageEncMask (0, MapInfo->DeviceAddress, MapInfo->NumberOfPages, TRUE);
+  ASSERT_EFI_ERROR(Status);
+
+  //
+  // If this is a read operation from the Bus Master's point of view,
+  // then copy the contents of the real buffer into the mapped buffer
+  // so the Bus Master can read the contents of the real buffer.
+  //
+  if (Operation == EdkiiIoMmuOperationBusMasterRead ||
+      Operation == EdkiiIoMmuOperationBusMasterRead64) {
+    CopyMem (
+      (VOID *) (UINTN) MapInfo->DeviceAddress,
+      (VOID *) (UINTN) MapInfo->HostAddress,
+      MapInfo->NumberOfBytes
+      );
+  }
+
+  //
+  // The DeviceAddress is the address of the maped buffer below 4GB
+  //
+  *DeviceAddress = MapInfo->DeviceAddress;
+
+  //
+  // Return a pointer to the MAP_INFO structure in Mapping
+  //
+  *Mapping       = MapInfo;
+
+  DEBUG ((DEBUG_VERBOSE, "%a Device 0x%Lx Host 0x%Lx Pages 0x%Lx Bytes 0x%Lx\n",
+        __FUNCTION__, MapInfo->DeviceAddress, MapInfo->HostAddress,
+        MapInfo->NumberOfPages, MapInfo->NumberOfBytes));
+
+  return EFI_SUCCESS;
+}
+
+/**
+  Completes the Map() operation and releases any corresponding resources.
+
+  @param  This                  The protocol instance pointer.
+  @param  Mapping               The mapping value returned from Map().
+
+  @retval EFI_SUCCESS           The range was unmapped.
+  @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+  @retval EFI_DEVICE_ERROR      The data was not committed to the target system memory.
+**/
+EFI_STATUS
+EFIAPI
+IoMmuUnmap (
+  IN  EDKII_IOMMU_PROTOCOL                     *This,
+  IN  VOID                                     *Mapping
+  )
+{
+  MAP_INFO                 *MapInfo;
+  EFI_STATUS               Status;
+
+  if (Mapping == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // See if the Map() operation associated with this Unmap() required a mapping
+  // buffer. If a mapping buffer was not required, then this function simply
+  // buffer. If a mapping buffer was not required, then this function simply
+  //
+  if (Mapping == NO_MAPPING) {
+    return EFI_SUCCESS;
+  }
+
+  MapInfo = (MAP_INFO *)Mapping;
+
+  //
+  // If this is a write operation from the Bus Master's point of view,
+  // then copy the contents of the mapped buffer into the real buffer
+  // so the processor can read the contents of the real buffer.
+  //
+  if (MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite ||
+      MapInfo->Operation == EdkiiIoMmuOperationBusMasterWrite64) {
+    CopyMem (
+      (VOID *) (UINTN) MapInfo->HostAddress,
+      (VOID *) (UINTN) MapInfo->DeviceAddress,
+      MapInfo->NumberOfBytes
+      );
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "%a Device 0x%Lx Host 0x%Lx Pages 0x%Lx Bytes 0x%Lx\n",
+        __FUNCTION__, MapInfo->DeviceAddress, MapInfo->HostAddress,
+        MapInfo->NumberOfPages, MapInfo->NumberOfBytes));
+  //
+  // Restore the memory encryption mask
+  //
+  Status = MemEncryptSevSetPageEncMask (0, MapInfo->DeviceAddress, MapInfo->NumberOfPages, TRUE);
+  ASSERT_EFI_ERROR(Status);
+
+  //
+  // Free the mapped buffer and the MAP_INFO structure.
+  //
+  gBS->FreePages (MapInfo->DeviceAddress, MapInfo->NumberOfPages);
+  FreePool (Mapping);
+  return EFI_SUCCESS;
+}
+
+/**
+  Allocates pages that are suitable for an OperationBusMasterCommonBuffer or
+  OperationBusMasterCommonBuffer64 mapping.
+
+  @param  This                  The protocol instance pointer.
+  @param  Type                  This parameter is not used and must be ignored.
+  @param  MemoryType            The type of memory to allocate, EfiBootServicesData
+                                or EfiRuntimeServicesData.
+  @param  Pages                 The number of pages to allocate.
+  @param  HostAddress           A pointer to store the base system memory address
+                                of the allocated range.
+  @param  Attributes            The requested bit mask of attributes for the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were allocated.
+  @retval EFI_UNSUPPORTED       Attributes is unsupported. The only legal attribute
+                                bits are MEMORY_WRITE_COMBINE and MEMORY_CACHED.
+  @retval EFI_INVALID_PARAMETER One or more parameters are invalid.
+  @retval EFI_OUT_OF_RESOURCES  The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuAllocateBuffer (
+  IN     EDKII_IOMMU_PROTOCOL                     *This,
+  IN     EFI_ALLOCATE_TYPE                        Type,
+  IN     EFI_MEMORY_TYPE                          MemoryType,
+  IN     UINTN                                    Pages,
+  IN OUT VOID                                     **HostAddress,
+  IN     UINT64                                   Attributes
+  )
+{
+  EFI_STATUS                Status;
+  EFI_PHYSICAL_ADDRESS      PhysicalAddress;
+
+  //
+  // Validate Attributes
+  //
+  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+    return EFI_UNSUPPORTED;
+  }
+
+  //
+  // Check for invalid inputs
+  //
+  if (HostAddress == NULL) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  //
+  // The only valid memory types are EfiBootServicesData and
+  // EfiRuntimeServicesData
+  //
+  if (MemoryType != EfiBootServicesData &&
+      MemoryType != EfiRuntimeServicesData) {
+    return EFI_INVALID_PARAMETER;
+  }
+
+  PhysicalAddress = (UINTN)-1;
+  if ((Attributes & EDKII_IOMMU_ATTRIBUTE_DUAL_ADDRESS_CYCLE) == 0) {
+    //
+    // Limit allocations to memory below 4GB
+    //
+    PhysicalAddress = SIZE_4GB - 1;
+  }
+  Status = gBS->AllocatePages (
+                  AllocateMaxAddress,
+                  MemoryType,
+                  Pages,
+                  &PhysicalAddress
+                  );
+  if (!EFI_ERROR (Status)) {
+    *HostAddress = (VOID *) (UINTN) PhysicalAddress;
+
+    //
+    // Clear memory encryption mask
+    //
+    Status = MemEncryptSevClearPageEncMask (0, PhysicalAddress, Pages, TRUE);
+    ASSERT_EFI_ERROR(Status);
+  }
+
+  DEBUG ((DEBUG_VERBOSE, "%a Address 0x%Lx Pages 0x%Lx\n", __FUNCTION__, PhysicalAddress, Pages));
+  return Status;
+}
+
+/**
+  Frees memory that was allocated with AllocateBuffer().
+
+  @param  This                  The protocol instance pointer.
+  @param  Pages                 The number of pages to free.
+  @param  HostAddress           The base system memory address of the allocated range.
+
+  @retval EFI_SUCCESS           The requested memory pages were freed.
+  @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+                                was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuFreeBuffer (
+  IN  EDKII_IOMMU_PROTOCOL                     *This,
+  IN  UINTN                                    Pages,
+  IN  VOID                                     *HostAddress
+  )
+{
+  EFI_STATUS  Status;
+
+  //
+  // Set memory encryption mask
+  //
+  Status = MemEncryptSevSetPageEncMask (0, (EFI_PHYSICAL_ADDRESS)(UINTN)HostAddress, Pages, TRUE);
+  ASSERT_EFI_ERROR(Status);
+
+  DEBUG ((DEBUG_VERBOSE, "%a Address 0x%Lx Pages 0x%Lx\n", __FUNCTION__, (UINTN)HostAddress, Pages));
+  return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+
+/**
+  Set IOMMU attribute for a system memory.
+
+  If the IOMMU protocol exists, the system memory cannot be used
+  for DMA by default.
+
+  When a device requests a DMA access for a system memory,
+  the device driver need use SetAttribute() to update the IOMMU
+  attribute to request DMA access (read and/or write).
+
+  The DeviceHandle is used to identify which device submits the request.
+  The IOMMU implementation need translate the device path to an IOMMU device ID,
+  and set IOMMU hardware register accordingly.
+  1) DeviceHandle can be a standard PCI device.
+     The memory for BusMasterRead need set EDKII_IOMMU_ACCESS_READ.
+     The memory for BusMasterWrite need set EDKII_IOMMU_ACCESS_WRITE.
+     The memory for BusMasterCommonBuffer need set EDKII_IOMMU_ACCESS_READ|EDKII_IOMMU_ACCESS_WRITE.
+     After the memory is used, the memory need set 0 to keep it being protected.
+  2) DeviceHandle can be an ACPI device (ISA, I2C, SPI, etc).
+     The memory for DMA access need set EDKII_IOMMU_ACCESS_READ and/or EDKII_IOMMU_ACCESS_WRITE.
+
+  @param[in]  This              The protocol instance pointer.
+  @param[in]  DeviceHandle      The device who initiates the DMA access request.
+  @param[in]  Mapping           The mapping value returned from Map().
+  @param[in]  IoMmuAccess       The IOMMU access.
+
+  @retval EFI_SUCCESS            The IoMmuAccess is set for the memory range specified by DeviceAddress and Length.
+  @retval EFI_INVALID_PARAMETER  DeviceHandle is an invalid handle.
+  @retval EFI_INVALID_PARAMETER  Mapping is not a value that was returned by Map().
+  @retval EFI_INVALID_PARAMETER  IoMmuAccess specified an illegal combination of access.
+  @retval EFI_UNSUPPORTED        DeviceHandle is unknown by the IOMMU.
+  @retval EFI_UNSUPPORTED        The bit mask of IoMmuAccess is not supported by the IOMMU.
+  @retval EFI_UNSUPPORTED        The IOMMU does not support the memory range specified by Mapping.
+  @retval EFI_OUT_OF_RESOURCES   There are not enough resources available to modify the IOMMU access.
+  @retval EFI_DEVICE_ERROR       The IOMMU device reported an error while attempting the operation.
+
+**/
+EFI_STATUS
+EFIAPI
+IoMmuSetAttribute (
+  IN EDKII_IOMMU_PROTOCOL  *This,
+  IN EFI_HANDLE            DeviceHandle,
+  IN VOID                  *Mapping,
+  IN UINT64                IoMmuAccess
+  )
+{
+  return EFI_UNSUPPORTED;
+}
+
+EDKII_IOMMU_PROTOCOL  mAmdSev = {
+  EDKII_IOMMU_PROTOCOL_REVISION,
+  IoMmuSetAttribute,
+  IoMmuMap,
+  IoMmuUnmap,
+  IoMmuAllocateBuffer,
+  IoMmuFreeBuffer,
+};
+
+/**
+  Initialize Iommu Protocol.
+
+**/
+VOID
+EFIAPI
+AmdSevInstallIoMmuProtocol (
+  VOID
+  )
+{
+  EFI_STATUS  Status;
+  EFI_HANDLE  Handle;
+
+  Handle = NULL;
+  Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gEdkiiIoMmuProtocolGuid, &mAmdSev,
+                  NULL
+                  );
+  ASSERT_EFI_ERROR (Status);
+}
diff --git a/OvmfPkg/IoMmuDxe/IoMmuDxe.c b/OvmfPkg/IoMmuDxe/IoMmuDxe.c
new file mode 100644
index 000000000000..101157e228b3
--- /dev/null
+++ b/OvmfPkg/IoMmuDxe/IoMmuDxe.c
@@ -0,0 +1,53 @@
+/** @file
+
+  IoMmuDxe driver installs EDKII_IOMMU_PROTOCOL to provide the support for DMA
+  operations when SEV is enabled.
+
+  Copyright (c) 2017, AMD Inc. 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 <PiDxe.h>
+
+#include <Library/BaseLib.h>
+#include <Library/DebugLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
+
+#include "AmdSevIoMmu.h"
+
+EFI_STATUS
+EFIAPI
+IoMmuDxeEntryPoint (
+  IN EFI_HANDLE         ImageHandle,
+  IN EFI_SYSTEM_TABLE   *SystemTable
+  )
+{
+  EFI_STATUS    Status = EFI_SUCCESS;
+  EFI_HANDLE    Handle = NULL;
+
+  //
+  // When SEV is enabled, install IoMmu protocol otherwise install the
+  // placeholder protocol so that other dependent module can run.
+  //
+  if (MemEncryptSevIsEnabled ()) {
+    AmdSevInstallIoMmuProtocol ();
+  } else {
+    Status = gBS->InstallMultipleProtocolInterfaces (
+                  &Handle,
+                  &gIoMmuAbsentProtocolGuid,
+                  NULL, NULL);
+  }
+
+  return Status;
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 10/17] OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (8 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver Brijesh Singh
@ 2017-05-26 14:43 ` 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
                   ` (8 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Current QemuFwCfgLib.inf is used in both Pei and Dxe phases. Add Pei
and Dxe inf file to provide a seperate QemuFwCfgLib instances for Pei
and Dxe phases.


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                                                | 3 ++-
 OvmfPkg/OvmfPkgIa32X64.dsc                                             | 3 ++-
 OvmfPkg/OvmfPkgX64.dsc                                                 | 3 ++-
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} | 8 ++++----
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} | 8 ++++----
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgDxe.c}     | 0
 OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     | 0
 7 files changed, 14 insertions(+), 11 deletions(-)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index 18544d7cfd73..fffee6b0610b 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -142,7 +142,7 @@ [LibraryClasses]
   DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
   UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
-  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
@@ -260,6 +260,7 @@ [LibraryClasses.common.PEIM]
   MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index 1b3bf3517a9f..a7a6c4694bca 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -147,7 +147,7 @@ [LibraryClasses]
   DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
   UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
-  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
@@ -265,6 +265,7 @@ [LibraryClasses.common.PEIM]
   MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 9fdabaf0eac4..31145b4bcfad 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -147,7 +147,7 @@ [LibraryClasses]
   DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
   UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
   SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
-  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
   VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
   LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
   MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
@@ -265,6 +265,7 @@ [LibraryClasses.common.PEIM]
   MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
   QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
   PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
+  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
 
 [LibraryClasses.common.DXE_CORE]
   HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
similarity index 80%
copy from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
copy to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
index 689476032d39..d7e368e5435d 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
@@ -18,11 +18,11 @@
 
 [Defines]
   INF_VERSION                    = 0x00010005
-  BASE_NAME                      = QemuFwCfgLib
-  FILE_GUID                      = fdd53716-31e1-4acc-9007-8bd5d877c96f
+  BASE_NAME                      = QemuFwCfgDxeLib
+  FILE_GUID                      = 80474090-55e7-4c28-b25c-9f236ba41f28
   MODULE_TYPE                    = BASE
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = QemuFwCfgLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
 
   CONSTRUCTOR                    = QemuFwCfgInitialize
 
@@ -35,7 +35,7 @@ [Defines]
 [Sources]
   QemuFwCfgLibInternal.h
   QemuFwCfgLib.c
-  QemuFwCfgPeiDxe.c
+  QemuFwCfgDxe.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
similarity index 80%
rename from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
rename to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
index 689476032d39..47e23b97eccf 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
@@ -18,11 +18,11 @@
 
 [Defines]
   INF_VERSION                    = 0x00010005
-  BASE_NAME                      = QemuFwCfgLib
-  FILE_GUID                      = fdd53716-31e1-4acc-9007-8bd5d877c96f
+  BASE_NAME                      = QemuFwCfgPeiLib
+  FILE_GUID                      = ddd4f5f0-5304-42a8-9efa-d14bf11a3533
   MODULE_TYPE                    = BASE
   VERSION_STRING                 = 1.0
-  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
+  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM
 
   CONSTRUCTOR                    = QemuFwCfgInitialize
 
@@ -35,7 +35,7 @@ [Defines]
 [Sources]
   QemuFwCfgLibInternal.h
   QemuFwCfgLib.c
-  QemuFwCfgPeiDxe.c
+  QemuFwCfgPei.c
 
 [Packages]
   MdePkg/MdePkg.dec
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
similarity index 100%
copy from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c
copy to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
similarity index 100%
rename from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c
rename to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 11/17] OvmfPkg/QemuFwCfgLib: Prepare for SEV support
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (9 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 10/17] OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library Brijesh Singh
@ 2017-05-26 14:43 ` Brijesh Singh
  2017-05-26 14:44 ` [PATCH v6 12/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase Brijesh Singh
                   ` (7 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:43 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Add SEV specific internal functions which will be used while intergrating
the SEV support into QemuFwCfgLib.


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/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h | 37 ++++++++++++++++++++
 1 file changed, 37 insertions(+)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
index 6e87c625102e..8cfa7913ffae 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h
@@ -2,6 +2,7 @@
   Internal interfaces specific to the QemuFwCfgLib instances in OvmfPkg.
 
   Copyright (C) 2016, Red Hat, Inc.
+  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
@@ -43,4 +44,40 @@ InternalQemuFwCfgDmaIsAvailable (
   VOID
   );
 
+/**
+ Returns a boolean indicating whether SEV support is enabled
+
+ @retval    TRUE    SEV is enabled
+ @retval    FALSE   SEV is disabled
+**/
+BOOLEAN
+InternalQemuFwCfgSevIsEnabled (
+  VOID
+  );
+
+/**
+ Allocate a bounce buffer for SEV DMA.
+
+  @param[out]    Buffer   Allocated DMA Buffer pointer
+  @param[in]     NumPage  Number of pages.
+
+**/
+VOID
+InternalQemuFwCfgSevDmaAllocateBuffer (
+  OUT    VOID     **Buffer,
+  IN     UINT32   NumPages
+  );
+
+/**
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+
+  @param[in]     NumPage  Number of pages.
+  @param[in]     Buffer   DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaFreeBuffer (
+  IN     VOID     *Buffer,
+  IN     UINT32   NumPages
+  );
 #endif
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 12/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (10 preceding siblings ...)
  2017-05-26 14:43 ` [PATCH v6 11/17] OvmfPkg/QemuFwCfgLib: Prepare for SEV support Brijesh Singh
@ 2017-05-26 14:44 ` Brijesh Singh
  2017-05-26 14:44 ` [PATCH v6 13/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase Brijesh Singh
                   ` (6 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

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/Library/QemuFwCfgLib/QemuFwCfgSec.c | 57 ++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
index 465ccbe90dad..071b8d9b91d4 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c
@@ -6,6 +6,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  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
@@ -94,3 +95,59 @@ InternalQemuFwCfgDmaIsAvailable (
 {
   return FALSE;
 }
+
+/**
+
+ Returns a boolean indicating whether SEV is enabled
+
+ @retval    TRUE    SEV is enabled
+ @retval    FALSE   SEV is disabled
+**/
+BOOLEAN
+InternalQemuFwCfgSevIsEnabled (
+  VOID
+  )
+{
+  //
+  // DMA is not supported in SEC phase hence SEV support is irrelevant
+  //
+  return FALSE;
+}
+
+/**
+ Allocate a bounce buffer for SEV DMA.
+
+  @param[in]     NumPage  Number of pages.
+  @param[out]    Buffer   Allocated DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaAllocateBuffer (
+  OUT    VOID     **Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  //
+  // We should never reach here
+  //
+  ASSERT (FALSE);
+}
+
+/**
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+
+  @param[in]     NumPage  Number of pages.
+  @param[in]     Buffer   DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaFreeBuffer (
+  IN     VOID     *Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  //
+  // We should never reach here
+  //
+  ASSERT (FALSE);
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 13/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (11 preceding siblings ...)
  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 ` Brijesh Singh
  2017-05-26 14:44 ` [PATCH v6 14/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase Brijesh Singh
                   ` (5 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

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/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf |  1 +
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c      | 72 +++++++++++++++++++-
 2 files changed, 71 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
index 47e23b97eccf..7e51c3f160ac 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
@@ -47,4 +47,5 @@ [LibraryClasses]
   DebugLib
   IoLib
   MemoryAllocationLib
+  MemEncryptSevLib
 
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
index ac05f4c347f3..40f89c3b53e2 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
@@ -4,6 +4,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  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
@@ -14,8 +15,10 @@
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
+#include <Library/BaseLib.h>
 #include <Library/DebugLib.h>
 #include <Library/QemuFwCfgLib.h>
+#include <Library/MemEncryptSevLib.h>
 
 #include "QemuFwCfgLibInternal.h"
 
@@ -76,8 +79,18 @@ QemuFwCfgInitialize (
   if ((Revision & FW_CFG_F_DMA) == 0) {
     DEBUG ((DEBUG_INFO, "QemuFwCfg interface (IO Port) is supported.\n"));
   } else {
-    mQemuFwCfgDmaSupported = TRUE;
-    DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
+    //
+    // If SEV is enabled then we do not support DMA operations in PEI phase.
+    // This is mainly because DMA in SEV guest requires using bounce buffer
+    // (which need to allocate dynamic memory and allocating a PAGE size'd
+    // buffer can be challenge in PEI phase)
+    //
+    if (InternalQemuFwCfgSevIsEnabled ()) {
+      DEBUG ((DEBUG_INFO, "SEV: QemuFwCfg fallback to IO Port interface.\n"));
+    } else {
+      mQemuFwCfgDmaSupported = TRUE;
+      DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
+    }
   }
   return RETURN_SUCCESS;
 }
@@ -114,3 +127,58 @@ InternalQemuFwCfgDmaIsAvailable (
 {
   return mQemuFwCfgDmaSupported;
 }
+
+/**
+
+ Returns a boolean indicating whether SEV is enabled
+
+ @retval    TRUE    SEV is enabled
+ @retval    FALSE   SEV is disabled
+**/
+BOOLEAN
+InternalQemuFwCfgSevIsEnabled (
+  VOID
+  )
+{
+  return MemEncryptSevIsEnabled ();
+}
+
+/**
+ Allocate a bounce buffer for SEV DMA.
+
+  @param[in]     NumPage  Number of pages.
+  @param[out]    Buffer   Allocated DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaAllocateBuffer (
+  OUT    VOID     **Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  //
+  // We should never reach here
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
+
+/**
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+
+  @param[in]     NumPage  Number of pages.
+  @param[in]     Buffer   DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaFreeBuffer (
+  IN     VOID     *Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  //
+  // We should never reach here
+  //
+  ASSERT (FALSE);
+  CpuDeadLoop ();
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 14/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (12 preceding siblings ...)
  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 ` 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
                   ` (4 subsequent siblings)
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

When SEV is enabled, the DMA must be performed on unencrypted pages.
So when get asked to perfom FWCFG DMA read or write, we allocate a
intermediate (bounce buffer) unencrypted buffer and use this buffer
for DMA read or write.


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>
---
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf |   7 ++
 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c      | 114 ++++++++++++++++++++
 2 files changed, 121 insertions(+)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
index d7e368e5435d..11cbb3c4f393 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
@@ -39,6 +39,7 @@ [Sources]
 
 [Packages]
   MdePkg/MdePkg.dec
+  MdeModulePkg/MdeModulePkg.dec
   OvmfPkg/OvmfPkg.dec
 
 [LibraryClasses]
@@ -47,4 +48,10 @@ [LibraryClasses]
   DebugLib
   IoLib
   MemoryAllocationLib
+  MemEncryptSevLib
 
+[Protocols]
+  gEdkiiIoMmuProtocolGuid                         ## SOMETIMES_CONSUMES
+
+[Depex]
+  gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
index ac05f4c347f3..f8eb03bc3a9a 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
@@ -4,6 +4,7 @@
 
   Copyright (C) 2013, Red Hat, Inc.
   Copyright (c) 2011 - 2013, Intel Corporation. All rights reserved.<BR>
+  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
@@ -14,14 +15,36 @@
   WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/
 
+#include <Uefi.h>
+
+#include <Protocol/IoMmu.h>
+
+#include <Library/BaseLib.h>
 #include <Library/DebugLib.h>
 #include <Library/QemuFwCfgLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/MemEncryptSevLib.h>
 
 #include "QemuFwCfgLibInternal.h"
 
 STATIC BOOLEAN mQemuFwCfgSupported = FALSE;
 STATIC BOOLEAN mQemuFwCfgDmaSupported;
 
+STATIC EDKII_IOMMU_PROTOCOL        *mIoMmuProtocol;
+/**
+
+ Returns a boolean indicating whether SEV is enabled
+
+ @retval    TRUE    SEV is enabled
+ @retval    FALSE   SEV is disabled
+**/
+BOOLEAN
+InternalQemuFwCfgSevIsEnabled (
+  VOID
+  )
+{
+  return MemEncryptSevIsEnabled ();
+}
 
 /**
   Returns a boolean indicating if the firmware configuration interface
@@ -79,6 +102,24 @@ QemuFwCfgInitialize (
     mQemuFwCfgDmaSupported = TRUE;
     DEBUG ((DEBUG_INFO, "QemuFwCfg interface (DMA) is supported.\n"));
   }
+
+  if (mQemuFwCfgDmaSupported && MemEncryptSevIsEnabled ()) {
+    EFI_STATUS   Status;
+
+    //
+    // IoMmuDxe driver must have installed the IOMMU protocol. If we are not
+    // able to locate the protocol then something must have gone wrong.
+    //
+    Status = gBS->LocateProtocol (&gEdkiiIoMmuProtocolGuid, NULL, (VOID **)&mIoMmuProtocol);
+    if (EFI_ERROR (Status)) {
+      DEBUG ((DEBUG_ERROR,
+        "QemuFwCfgSevDma %a:%a Failed to locate IOMMU protocol.\n",
+        gEfiCallerBaseName, __FUNCTION__));
+      ASSERT (FALSE);
+      CpuDeadLoop ();
+    }
+  }
+
   return RETURN_SUCCESS;
 }
 
@@ -114,3 +155,76 @@ InternalQemuFwCfgDmaIsAvailable (
 {
   return mQemuFwCfgDmaSupported;
 }
+
+/**
+ Allocate a bounce buffer for SEV DMA.
+
+  @param[in]     NumPage  Number of pages.
+  @param[out]    Buffer   Allocated DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaAllocateBuffer (
+  OUT    VOID     **Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  EFI_STATUS    Status;
+
+  ASSERT (mIoMmuProtocol != NULL);
+
+  Status = mIoMmuProtocol->AllocateBuffer (
+                            mIoMmuProtocol,
+                            0,
+                            EfiBootServicesData,
+                            NumPages,
+                            Buffer,
+                            EDKII_IOMMU_ATTRIBUTE_MEMORY_CACHED
+                          );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a:%a failed to allocate %u pages\n", gEfiCallerBaseName, __FUNCTION__,
+      NumPages));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  DEBUG ((DEBUG_VERBOSE,
+    "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName, __FUNCTION__,
+    (UINT64)(UINTN)Buffer, NumPages));
+}
+
+/**
+ Free the DMA buffer allocated using InternalQemuFwCfgSevDmaAllocateBuffer
+
+  @param[in]     NumPage  Number of pages.
+  @param[in]     Buffer   DMA Buffer pointer
+
+**/
+VOID
+InternalQemuFwCfgSevDmaFreeBuffer (
+  IN     VOID     *Buffer,
+  IN     UINT32   NumPages
+  )
+{
+  EFI_STATUS    Status;
+
+  ASSERT (mIoMmuProtocol != NULL);
+
+  Status = mIoMmuProtocol->FreeBuffer (
+                            mIoMmuProtocol,
+                            NumPages,
+                            Buffer
+                          );
+  if (EFI_ERROR (Status)) {
+    DEBUG ((DEBUG_ERROR,
+      "%a:%a failed to free buffer 0x%Lx pages %u\n", gEfiCallerBaseName,
+      __FUNCTION__, (UINT64)(UINTN)Buffer, NumPages));
+    ASSERT (FALSE);
+    CpuDeadLoop ();
+  }
+
+  DEBUG ((DEBUG_VERBOSE,
+    "%a:%a buffer 0x%Lx Pages %u\n", gEfiCallerBaseName,__FUNCTION__,
+    (UINT64)(UINTN)Buffer, NumPages));
+}
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 15/17] OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (13 preceding siblings ...)
  2017-05-26 14:44 ` [PATCH v6 14/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase Brijesh Singh
@ 2017-05-26 14:44 ` Brijesh Singh
  2017-05-26 14:44 ` [PATCH v6 16/17] OvmfPkg/QemuFwCfgLib: Add SEV support Brijesh Singh
                   ` (3 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

Update InternalQemuFwCfgDmaBytes() to work with DMA Access pointer.
The change provides the flexibility to dynamically allocate the "Access"
when 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/Library/QemuFwCfgLib/QemuFwCfgLib.c | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
index 1bf725d8b7ae..73a19772bee1 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
@@ -68,7 +68,8 @@ InternalQemuFwCfgDmaBytes (
   IN     UINT32   Control
   )
 {
-  volatile FW_CFG_DMA_ACCESS Access;
+  volatile FW_CFG_DMA_ACCESS LocalAccess;
+  volatile FW_CFG_DMA_ACCESS *Access;
   UINT32                     AccessHigh, AccessLow;
   UINT32                     Status;
 
@@ -79,9 +80,11 @@ InternalQemuFwCfgDmaBytes (
     return;
   }
 
-  Access.Control = SwapBytes32 (Control);
-  Access.Length  = SwapBytes32 (Size);
-  Access.Address = SwapBytes64 ((UINTN)Buffer);
+  Access = &LocalAccess;
+
+  Access->Control = SwapBytes32 (Control);
+  Access->Length  = SwapBytes32 (Size);
+  Access->Address = SwapBytes64 ((UINTN)Buffer);
 
   //
   // Delimit the transfer from (a) modifications to Access, (b) in case of a
@@ -92,8 +95,8 @@ InternalQemuFwCfgDmaBytes (
   //
   // Start the transfer.
   //
-  AccessHigh = (UINT32)RShiftU64 ((UINTN)&Access, 32);
-  AccessLow  = (UINT32)(UINTN)&Access;
+  AccessHigh = (UINT32)RShiftU64 ((UINTN)Access, 32);
+  AccessLow  = (UINT32)(UINTN)Access;
   IoWrite32 (FW_CFG_IO_DMA_ADDRESS,     SwapBytes32 (AccessHigh));
   IoWrite32 (FW_CFG_IO_DMA_ADDRESS + 4, SwapBytes32 (AccessLow));
 
@@ -106,7 +109,7 @@ InternalQemuFwCfgDmaBytes (
   // Wait for the transfer to complete.
   //
   do {
-    Status = SwapBytes32 (Access.Control);
+    Status = SwapBytes32 (Access->Control);
     ASSERT ((Status & FW_CFG_DMA_CTL_ERROR) == 0);
   } while (Status != 0);
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 16/17] OvmfPkg/QemuFwCfgLib: Add SEV support
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (14 preceding siblings ...)
  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 ` Brijesh Singh
  2017-05-26 14:44 ` [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib Brijesh Singh
                   ` (2 subsequent siblings)
  18 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

When SEV is enabled, use a bounce buffer to perform the DMA operation.


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/Library/QemuFwCfgLib/QemuFwCfgLib.c | 54 +++++++++++++++++++-
 1 file changed, 52 insertions(+), 2 deletions(-)

diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
index 73a19772bee1..dbebd36b1853 100644
--- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
+++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c
@@ -72,6 +72,8 @@ InternalQemuFwCfgDmaBytes (
   volatile FW_CFG_DMA_ACCESS *Access;
   UINT32                     AccessHigh, AccessLow;
   UINT32                     Status;
+  UINT32                     NumPages;
+  VOID                       *DmaBuffer, *BounceBuffer;
 
   ASSERT (Control == FW_CFG_DMA_CTL_WRITE || Control == FW_CFG_DMA_CTL_READ ||
     Control == FW_CFG_DMA_CTL_SKIP);
@@ -80,11 +82,44 @@ InternalQemuFwCfgDmaBytes (
     return;
   }
 
-  Access = &LocalAccess;
+  //
+  // When SEV is enabled then allocate DMA bounce buffer
+  //
+  if (InternalQemuFwCfgSevIsEnabled ()) {
+    UINTN  TotalSize;
+
+    TotalSize = sizeof (*Access);
+    //
+    // Skip operation does not need buffer
+    //
+    if (Control != FW_CFG_DMA_CTL_SKIP) {
+      TotalSize += Size;
+    }
+
+    //
+    // Allocate SEV DMA buffer
+    //
+    NumPages = (UINT32)EFI_SIZE_TO_PAGES (TotalSize);
+    InternalQemuFwCfgSevDmaAllocateBuffer (&BounceBuffer, NumPages);
+
+    Access = BounceBuffer;
+    DmaBuffer = (UINT8*)BounceBuffer + sizeof (*Access);
+
+    //
+    //  Decrypt data from encrypted guest buffer into DMA buffer
+    //
+    if (Control == FW_CFG_DMA_CTL_WRITE) {
+      CopyMem (DmaBuffer, Buffer, Size);
+    }
+  } else {
+    Access = &LocalAccess;
+    DmaBuffer = Buffer;
+    BounceBuffer = NULL;
+  }
 
   Access->Control = SwapBytes32 (Control);
   Access->Length  = SwapBytes32 (Size);
-  Access->Address = SwapBytes64 ((UINTN)Buffer);
+  Access->Address = SwapBytes64 ((UINTN)DmaBuffer);
 
   //
   // Delimit the transfer from (a) modifications to Access, (b) in case of a
@@ -117,6 +152,21 @@ InternalQemuFwCfgDmaBytes (
   // After a read, the caller will want to use Buffer.
   //
   MemoryFence ();
+
+  //
+  // If Bounce buffer was allocated then copy the data into guest buffer and
+  // free the bounce buffer
+  //
+  if (BounceBuffer != NULL) {
+    //
+    //  Encrypt the data from DMA buffer into guest buffer
+    //
+    if (Control == FW_CFG_DMA_CTL_READ) {
+      CopyMem (Buffer, DmaBuffer, Size);
+    }
+
+    InternalQemuFwCfgSevDmaFreeBuffer (BounceBuffer, NumPages);
+  }
 }
 
 
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (15 preceding siblings ...)
  2017-05-26 14:44 ` [PATCH v6 16/17] OvmfPkg/QemuFwCfgLib: Add SEV support Brijesh Singh
@ 2017-05-26 14:44 ` Brijesh Singh
  2017-05-29  9:47   ` Laszlo Ersek
  2017-05-26 21:05 ` [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Jordan Justen
  2017-07-05 22:31 ` Brijesh Singh
  18 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 14:44 UTC (permalink / raw)
  To: edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jordan Justen,
	Laszlo Ersek

This patch enables PciHostBridgeDxe driver to use Platform IoMMU detection
library to ensure that PciHostBridgeDxe is run after platform IoMmuDxe
driver has checked whether platform need to install IOMMU protocol provider.


Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Suggested-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
 OvmfPkg/OvmfPkgIa32.dsc    | 1 +
 OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
 OvmfPkg/OvmfPkgX64.dsc     | 1 +
 3 files changed, 3 insertions(+)

diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
index fffee6b0610b..7bc2404ca84a 100644
--- a/OvmfPkg/OvmfPkgIa32.dsc
+++ b/OvmfPkg/OvmfPkgIa32.dsc
@@ -626,6 +626,7 @@ [Components]
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
     <LibraryClasses>
       PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
   }
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
     <LibraryClasses>
diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
index a7a6c4694bca..e6773084a0f5 100644
--- a/OvmfPkg/OvmfPkgIa32X64.dsc
+++ b/OvmfPkg/OvmfPkgIa32X64.dsc
@@ -635,6 +635,7 @@ [Components.X64]
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
     <LibraryClasses>
       PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
   }
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
     <LibraryClasses>
diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
index 31145b4bcfad..905ed30232ef 100644
--- a/OvmfPkg/OvmfPkgX64.dsc
+++ b/OvmfPkg/OvmfPkgX64.dsc
@@ -633,6 +633,7 @@ [Components]
   MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
     <LibraryClasses>
       PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
+      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
   }
   MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
     <LibraryClasses>
-- 
2.7.4



^ permalink raw reply related	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
  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
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-05-26 20:54 UTC (permalink / raw)
  To: Jiewen Yao, Jeff Fan, Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Laszlo Ersek

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
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (16 preceding siblings ...)
  2017-05-26 14:44 ` [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib Brijesh Singh
@ 2017-05-26 21:05 ` Jordan Justen
  2017-05-29 11:16   ` Laszlo Ersek
  2017-07-05 22:31 ` Brijesh Singh
  18 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-05-26 21:05 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Jeff Fan, Liming Gao,
	Laszlo Ersek, Jiewen Yao

On 2017-05-26 07:43:48, Brijesh Singh wrote:
> Changes since v4:
>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
>    dependency support for the dependent modules.

I think you split IoMmuDxe out from AmdSevDxe based on my feedback
regarding APRIORI, but I don't think this helped.

Ideally I would like to see one driver named IoMmuDxe that is *not* in
APRIORI.

I think because of QemuFlashFvbServicesRuntimeDxe in APRIORI, we also
need IoMmuDxe in the APRIORI. Hopefully we can figure our how to
remove QemuFlashFvbServicesRuntimeDxe and then be able to remove
IoMmuDxe.

-Jordan

>  - update debug messages to use gEfiCallerBaseName where applicable.
>  - fix QemuFwCfgSecLib build errors and simplify SEV support
>  - update QemuFwCfgDxeLib to assert when failed to locate IOMMU
>  - update comments "host buffer" to " host buffer"
> 
> Changes since v3:
>  - update AmdSevDxe driver to produce IOMMU protocol
>  - remove BmDmaLib dependency
>  - update QemuFwCfgLib to use IOMMU protocol to allocate SEV DMA buffer
> 
> Changes since v2:
>  - move memory encryption CPUID and MSR definition into UefiCpuPkg
>  - fix the argument order for SUB instruction in ResetVector and add more
>    comments
>  - update PlatformPei to use BaseMemEncryptSevLib
>  - break the overlong comment lines to 79 chars
>  - variable aligment and other formating fixes
>  - split the SEV DMA support patch for QemuFwCfgLib into multiple patches as
>    recommended by Laszlo
>  - add AmdSevDxe driver which runs very early in DXE phase and clear the C-bit
>    from MMIO memory region
>  - drop 'QemuVideoDxe: Clear C-bit from framebuffer' patch since AmdSevDxe
>    driver takes care of clearing the C-bit from MMIO region
>  - Verified that Qemu PFLASH works fine with SEV guest, Found a KVM driver issue
>    which was causing #PF when PFLASH was enabled. I have submitted patch to
>    fix it in upstream http://marc.info/?l=kvm&m=149304930814202&w=2
> 
> Changes since v1:
>  - bug fixes in OvmfPkg/ResetVector (pointed by Tom Lendacky)
>  - add SEV CPUID and MSR register definition in standard include file
>  - remove the MemEncryptLib dependency from PlatformPei. Move AmdSevInitialize()
>    implementation in local file inside the PlatformPei package
>  - rename MemCryptSevLib to MemEncryptSevLib and add functions to set or
>    clear memory encryption attribute on memory region
>  - integerate SEV support in BmDmaLib
>  - split QemuFwCfgDxePei.c into QemuFwCfgDxe.c and QemuFwCfgPei.c to
>    allow building seperate QemuFwCfgLib for Dxe and Pei phase
>    (recommended by Laszlo Ersek)
>  - add SEV support in QemuFwCfgLib
>  - clear the memory encryption attribute from framebuffer memory region
> 
> 
> TODO:
> (Will add these features after basic SEV support patches are accepted in upstream)
>  - add support for DMA operation in QemuFwCfgS3Lib when SEV is enabled
>  - investigate SMM/SMI support
> 
> Cc: Jeff Fan <jeff.fan@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> 
> Brijesh Singh (17):
>   UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
>   OvmfPkg/ResetVector: Set C-bit when building initial page table
>   OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
>   OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
>   OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
>   OvmfPkg: Add AmdSevDxe driver
>   OvmfPkg: Introduce IoMmuAbsent Protocol GUID
>   OvmfPkg: Add PlatformHasIoMmuLib
>   OvmfPkg: Add IoMmuDxe driver
>   OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
>   OvmfPkg/QemuFwCfgLib: Prepare for SEV support
>   OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
>   OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
>   OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
>   OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
>   OvmfPkg/QemuFwCfgLib: Add SEV support
>   OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
> 
>  OvmfPkg/OvmfPkg.dec                                                    |   1 +
>  OvmfPkg/OvmfPkgIa32.dsc                                                |  11 +-
>  OvmfPkg/OvmfPkgIa32X64.dsc                                             |  12 +-
>  OvmfPkg/OvmfPkgX64.dsc                                                 |  12 +-
>  OvmfPkg/OvmfPkgIa32.fdf                                                |   1 +
>  OvmfPkg/OvmfPkgIa32X64.fdf                                             |   3 +
>  OvmfPkg/OvmfPkgX64.fdf                                                 |   3 +
>  OvmfPkg/AmdSevDxe/AmdSevDxe.inf                                        |  43 ++
>  OvmfPkg/IoMmuDxe/IoMmuDxe.inf                                          |  49 +++
>  OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf          |  50 +++
>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf            |  37 ++
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} |  15 +-
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} |   9 +-
>  OvmfPkg/PlatformPei/PlatformPei.inf                                    |   3 +
>  OvmfPkg/Include/Library/MemEncryptSevLib.h                             |  81 ++++
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.h                                         |  43 ++
>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h               | 184 ++++++++
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h                    |  37 ++
>  OvmfPkg/PlatformPei/Platform.h                                         |   5 +
>  UefiCpuPkg/Include/Register/Amd/Cpuid.h                                | 162 +++++++
>  UefiCpuPkg/Include/Register/Amd/Fam17Msr.h                             |  62 +++
>  UefiCpuPkg/Include/Register/Amd/Msr.h                                  |  29 ++
>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                                          |  75 ++++
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                         | 459 ++++++++++++++++++++
>  OvmfPkg/IoMmuDxe/IoMmuDxe.c                                            |  53 +++
>  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 +++++++++++++++++++
>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c              |  32 ++
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c                            | 230 ++++++++++
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c                            |  67 ++-
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     |  72 ++-
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c                            |  57 +++
>  OvmfPkg/PlatformPei/AmdSev.c                                           |  62 +++
>  OvmfPkg/PlatformPei/Platform.c                                         |   1 +
>  OvmfPkg/ResetVector/Ia32/PageTables64.asm                              |  70 ++-
>  37 files changed, 2703 insertions(+), 24 deletions(-)
>  create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>  create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
>  create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>  copy OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} (71%)
>  rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} (80%)
>  create mode 100644 OvmfPkg/Include/Library/MemEncryptSevLib.h
>  create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Cpuid.h
>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Msr.h
>  create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.c
>  create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
>  create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
>  create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
>  create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
>  rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c} (61%)
>  create mode 100644 OvmfPkg/PlatformPei/AmdSev.c
> 
> -- 
> 2.7.4
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
  2017-05-26 20:54   ` Jordan Justen
@ 2017-05-26 21:06     ` Brijesh Singh
  2017-05-27  1:26       ` Yao, Jiewen
  0 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-26 21:06 UTC (permalink / raw)
  To: Jordan Justen, Jiewen Yao, Jeff Fan, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Laszlo Ersek

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
>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 10/17] OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
  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
  0 siblings, 0 replies; 65+ messages in thread
From: Jordan Justen @ 2017-05-26 21:49 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Laszlo Ersek

On 2017-05-26 07:43:58, Brijesh Singh wrote:
> Current QemuFwCfgLib.inf is used in both Pei and Dxe phases. Add Pei
> and Dxe inf file to provide a seperate QemuFwCfgLib instances for Pei
> and Dxe phases.
> 
> 

We usually have 1 rather than 2 blank lines before the signature
block.

10-16 Reviewed-by: Jordan Justen <jordan.l.justen@intel.com>

> 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                                                | 3 ++-
>  OvmfPkg/OvmfPkgIa32X64.dsc                                             | 3 ++-
>  OvmfPkg/OvmfPkgX64.dsc                                                 | 3 ++-
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} | 8 ++++----
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} | 8 ++++----
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgDxe.c}     | 0
>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     | 0
>  7 files changed, 14 insertions(+), 11 deletions(-)
> 
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index 18544d7cfd73..fffee6b0610b 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -142,7 +142,7 @@ [LibraryClasses]
>    DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
>    UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
>    SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
> -  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
>    VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
>    LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
>    MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
> @@ -260,6 +260,7 @@ [LibraryClasses.common.PEIM]
>    MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
>    QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
>    PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
>  
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> index 1b3bf3517a9f..a7a6c4694bca 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> @@ -147,7 +147,7 @@ [LibraryClasses]
>    DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
>    UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
>    SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
> -  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
>    VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
>    LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
>    MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
> @@ -265,6 +265,7 @@ [LibraryClasses.common.PEIM]
>    MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
>    QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
>    PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
>  
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 9fdabaf0eac4..31145b4bcfad 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -147,7 +147,7 @@ [LibraryClasses]
>    DpcLib|MdeModulePkg/Library/DxeDpcLib/DxeDpcLib.inf
>    UefiUsbLib|MdePkg/Library/UefiUsbLib/UefiUsbLib.inf
>    SerializeVariablesLib|OvmfPkg/Library/SerializeVariablesLib/SerializeVariablesLib.inf
> -  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
>    VirtioLib|OvmfPkg/Library/VirtioLib/VirtioLib.inf
>    LoadLinuxLib|OvmfPkg/Library/LoadLinuxLib/LoadLinuxLib.inf
>    MemEncryptSevLib|OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
> @@ -265,6 +265,7 @@ [LibraryClasses.common.PEIM]
>    MpInitLib|UefiCpuPkg/Library/MpInitLib/PeiMpInitLib.inf
>    QemuFwCfgS3Lib|OvmfPkg/Library/QemuFwCfgS3Lib/PeiQemuFwCfgS3LibFwCfg.inf
>    PcdLib|MdePkg/Library/PeiPcdLib/PeiPcdLib.inf
> +  QemuFwCfgLib|OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
>  
>  [LibraryClasses.common.DXE_CORE]
>    HobLib|MdePkg/Library/DxeCoreHobLib/DxeCoreHobLib.inf
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
> similarity index 80%
> copy from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> copy to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
> index 689476032d39..d7e368e5435d 100644
> --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf
> @@ -18,11 +18,11 @@
>  
>  [Defines]
>    INF_VERSION                    = 0x00010005
> -  BASE_NAME                      = QemuFwCfgLib
> -  FILE_GUID                      = fdd53716-31e1-4acc-9007-8bd5d877c96f
> +  BASE_NAME                      = QemuFwCfgDxeLib
> +  FILE_GUID                      = 80474090-55e7-4c28-b25c-9f236ba41f28
>    MODULE_TYPE                    = BASE
>    VERSION_STRING                 = 1.0
> -  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> +  LIBRARY_CLASS                  = QemuFwCfgLib|DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
>  
>    CONSTRUCTOR                    = QemuFwCfgInitialize
>  
> @@ -35,7 +35,7 @@ [Defines]
>  [Sources]
>    QemuFwCfgLibInternal.h
>    QemuFwCfgLib.c
> -  QemuFwCfgPeiDxe.c
> +  QemuFwCfgDxe.c
>  
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
> similarity index 80%
> rename from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> rename to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
> index 689476032d39..47e23b97eccf 100644
> --- a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.inf
> +++ b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiLib.inf
> @@ -18,11 +18,11 @@
>  
>  [Defines]
>    INF_VERSION                    = 0x00010005
> -  BASE_NAME                      = QemuFwCfgLib
> -  FILE_GUID                      = fdd53716-31e1-4acc-9007-8bd5d877c96f
> +  BASE_NAME                      = QemuFwCfgPeiLib
> +  FILE_GUID                      = ddd4f5f0-5304-42a8-9efa-d14bf11a3533
>    MODULE_TYPE                    = BASE
>    VERSION_STRING                 = 1.0
> -  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SMM_DRIVER
> +  LIBRARY_CLASS                  = QemuFwCfgLib|PEIM
>  
>    CONSTRUCTOR                    = QemuFwCfgInitialize
>  
> @@ -35,7 +35,7 @@ [Defines]
>  [Sources]
>    QemuFwCfgLibInternal.h
>    QemuFwCfgLib.c
> -  QemuFwCfgPeiDxe.c
> +  QemuFwCfgPei.c
>  
>  [Packages]
>    MdePkg/MdePkg.dec
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> similarity index 100%
> copy from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c
> copy to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> diff --git a/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c b/OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
> similarity index 100%
> rename from OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPeiDxe.c
> rename to OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgPei.c
> -- 
> 2.7.4
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 04/17] OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
  2017-05-26 21:06     ` Brijesh Singh
@ 2017-05-27  1:26       ` Yao, Jiewen
  0 siblings, 0 replies; 65+ messages in thread
From: Yao, Jiewen @ 2017-05-27  1:26 UTC (permalink / raw)
  To: Brijesh Singh, Justen, Jordan L, Fan, Jeff,
	edk2-devel@lists.01.org
  Cc: Thomas.Lendacky@amd.com, leo.duran@amd.com, Laszlo Ersek

Agree. Per my understanding this driver is only needed for virtualization firmware, it is not needed for a real platform firmware. Putting it to OVMF makes more sense.

Thank you
Yao Jiewen

From: Brijesh Singh [mailto:brijesh.singh@amd.com]
Sent: Saturday, May 27, 2017 5:07 AM
To: Justen, Jordan L <jordan.l.justen@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>; Fan, Jeff <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

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<mailto:jordan.l.justen@intel.com>>
>> Cc: Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>
>> Reviewed-by: Laszlo Ersek <lersek@redhat.com<mailto: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
>>

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID
  2017-05-26 14:43 ` [PATCH v6 07/17] OvmfPkg: Introduce IoMmuAbsent Protocol GUID Brijesh Singh
@ 2017-05-29  9:07   ` Laszlo Ersek
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29  9:07 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Thomas.Lendacky, leo.duran, Jordan Justen

On 05/26/17 16:43, Brijesh Singh wrote:
> Platforms that optionally provide an IOMMU protocol should do so by
> including a DXE driver (usually called IoMmuDxe) that produces either
> the IOMMU protocol -- if the underlying capabilities are available --,
> or gIoMmuAbsentProtocolGuid, to signal that the IOMMU capability
> detection completed with negative result (i.e., no IOMMU will be
> available in the system).
> 
> In turn, DXE drivers (and library instances) that are supposed to use
> the IOMMU protocol if it is available should add the following to
> their DEPEX:
> 
> gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
> 
> This ensures these client modules will only be dispatched after IOMMU
> detection completes (with positive or negative result).
> 
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Suggested-by: Jordan Justen <jordan.l.justen@intel.com>
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/OvmfPkg.dec | 1 +
>  1 file changed, 1 insertion(+)
> 
> diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
> index 5627be0bab0a..4241af10c3d0 100644
> --- a/OvmfPkg/OvmfPkg.dec
> +++ b/OvmfPkg/OvmfPkg.dec
> @@ -69,6 +69,7 @@ [Protocols]
>    gBlockMmioProtocolGuid              = {0x6b558ce3, 0x69e5, 0x4c67, {0xa6, 0x34, 0xf7, 0xfe, 0x72, 0xad, 0xbe, 0x84}}
>    gXenBusProtocolGuid                 = {0x3d3ca290, 0xb9a5, 0x11e3, {0xb7, 0x5d, 0xb8, 0xac, 0x6f, 0x7d, 0x65, 0xe6}}
>    gXenIoProtocolGuid                  = {0x6efac84f, 0x0ab0, 0x4747, {0x81, 0xbe, 0x85, 0x55, 0x62, 0x59, 0x04, 0x49}}
> +  gIoMmuAbsentProtocolGuid            = {0xf8775d50, 0x8abd, 0x4adf, {0x92, 0xac, 0x85, 0x3e, 0x51, 0xf6, 0xc8, 0xdc}}
>  
>  [PcdsFixedAtBuild]
>    gUefiOvmfPkgTokenSpaceGuid.PcdOvmfPeiMemFvBase|0x0|UINT32|0
> 

Reviewed-by: Laszlo Ersek <lersek@redhat.com>



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib
  2017-05-26 14:43 ` [PATCH v6 08/17] OvmfPkg: Add PlatformHasIoMmuLib Brijesh Singh
@ 2017-05-29  9:19   ` Laszlo Ersek
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29  9:19 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Thomas.Lendacky, leo.duran, Jordan Justen

comments below:

On 05/26/17 16:43, Brijesh Singh wrote:
> Add the shorter-term library instance outlined in the previous patch to
> OvmfPkg, so that we can imbue PciHostBridgeDxe with a protocol dependency
> on gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid.
> 
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf | 37 ++++++++++++++++++++
>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c   | 32 +++++++++++++++++
>  2 files changed, 69 insertions(+)
> 
> diff --git a/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
> new file mode 100644
> index 000000000000..6d97293a3334
> --- /dev/null
> +++ b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
> @@ -0,0 +1,37 @@
> +## @file
> +# A hook-in library for MdeModulePkg/Bus/Pci/PciHostBridgeDxe.
> +#
> +#  Plugging this library instance into PciHostBridgeDxe makes
> +#  EFI_IOMMU_PROTOCOL depend on the platform's dynamic decision whether

(1) s/EFI_IOMMU_PROTOCOL/PciHostBridgeDxe/

> +#  to provide IOMMU implementation (usually through IoMmuDxe driver).
> +#
> +# Copyright (C) 2017, AMD, Inc.

(2) I think you should keep the original Red Hat copyright here as well,
from "EmbeddedPkg/Library/PlatformHasAcpiLib/PlatformHasAcpiLib.inf". (I
think you used that file as basis for this.)

(3) (4) Regarding the C source file below, the same two comments apply.

With those addressed:

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Don't post v7 just for this; I can fix it up at commit, if nothing else
requries a v7.

Thanks
Laszlo

> +#
> +# 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                      = PlatformHasIoMmuLib
> +  FILE_GUID                      = 49b4b018-0558-448b-1e1a-12226342877d
> +  MODULE_TYPE                    = BASE
> +  VERSION_STRING                 = 1.0
> +  LIBRARY_CLASS                  = PlatformHasIoMmuLib|DXE_DRIVER
> +  CONSTRUCTOR                    = PlatformHasIoMmuInitialize
> +
> +[Sources]
> +  PlatformHasIoMmuLib.c
> +
> +[Packages]
> +  MdeModulePkg/MdeModulePkg.dec
> +  MdePkg/MdePkg.dec
> +  OvmfPkg/OvmfPkg.dec
> +
> +[Depex]
> +  gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
> diff --git a/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
> new file mode 100644
> index 000000000000..9ead2637e2c8
> --- /dev/null
> +++ b/OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
> @@ -0,0 +1,32 @@
> +/** @file
> +  A hook-in library for MdeModulePkg/Bus/Pci/PciHostBridgeDxe.
> +
> +  Plugging this library instance into PciHostBridgeDxe makes
> +  EFI_IOMMU_PROTOCOL depend on the platform's dynamic decision whether
> +  to provide IOMMU implementation (usually through IoMmuDxe driver).
> +
> +  Copyright (C) 2017, AMD, Inc.
> +
> +  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 <Base.h>
> +
> +RETURN_STATUS
> +EFIAPI
> +PlatformHasIoMmuInitialize (
> +  VOID
> +  )
> +{
> +  //
> +  // Do nothing, just imbue PciHostBridgeDxe with a protocol dependency on
> +  // gIoMmuAbsentProtocolGuid OR gEdkiiIoMmuProtocolGuid.
> +  //
> +  return RETURN_SUCCESS;
> +}
> 



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver
  2017-05-26 14:43 ` [PATCH v6 09/17] OvmfPkg: Add IoMmuDxe driver Brijesh Singh
@ 2017-05-29  9:28   ` Laszlo Ersek
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29  9:28 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, Jordan Justen, Jiewen Yao, leo.duran

On 05/26/17 16:43, Brijesh Singh wrote:
> The IOMMU protocol driver provides capabilities to set a DMA access
> attribute and methods to allocate, free, map and unmap the DMA memory
> for the PCI Bus devices.
> 
> Due to security reasons all DMA operations inside the SEV guest must
> be performed on shared (i.e unencrypted) pages. The IOMMU protocol
> driver for the SEV guest uses a bounce buffer to map guest DMA buffer
> to shared pages inorder to provide the support for DMA operations inside
> SEV guest.
> 
> IoMmuDxe driver looks for SEV capabilities, if present then it installs
> the real IOMMU protocol otherwise it installs placeholder protocol.
> Currently, PciHostBridgeDxe and QemuFWCfgLib need to know the existance
> of IOMMU protocol. The modules needing to know the existance of IOMMU
> support should add
> 
>   gEdkiiIoMmuProtocolGuid OR gIoMmuAbsentProtocolGuid
> 
> in their depex to ensure that platform IOMMU detection has been performed.
> 
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Suggested-by: Jiewen Yao <jiewen.yao@intel.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
> ---
>  OvmfPkg/OvmfPkgIa32.dsc        |   1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc     |   1 +
>  OvmfPkg/OvmfPkgX64.dsc         |   1 +
>  OvmfPkg/OvmfPkgIa32.fdf        |   1 +
>  OvmfPkg/OvmfPkgIa32X64.fdf     |   1 +
>  OvmfPkg/OvmfPkgX64.fdf         |   1 +
>  OvmfPkg/IoMmuDxe/IoMmuDxe.inf  |  49 +++
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.h |  43 ++
>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.c | 459 ++++++++++++++++++++
>  OvmfPkg/IoMmuDxe/IoMmuDxe.c    |  53 +++
>  10 files changed, 610 insertions(+)

Looks good to me.

Acked-by: Laszlo Ersek <lersek@redhat.com>



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 14/17] OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
  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
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29  9:40 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Thomas.Lendacky, leo.duran, Jordan Justen

On 05/26/17 16:44, Brijesh Singh wrote:
> When SEV is enabled, the DMA must be performed on unencrypted pages.
> So when get asked to perfom FWCFG DMA read or write, we allocate a
> intermediate (bounce buffer) unencrypted buffer and use this buffer
> for DMA read or write.
> 
> 
> 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>
> ---
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxeLib.inf |   7 ++
>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c      | 114 ++++++++++++++++++++
>  2 files changed, 121 insertions(+)

Reviewed-by: Laszlo Ersek <lersek@redhat.com>



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
  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
  0 siblings, 1 reply; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29  9:47 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Thomas.Lendacky, leo.duran, Jordan Justen

On 05/26/17 16:44, Brijesh Singh wrote:
> This patch enables PciHostBridgeDxe driver to use Platform IoMMU detection
> library to ensure that PciHostBridgeDxe is run after platform IoMmuDxe
> driver has checked whether platform need to install IOMMU protocol provider.
> 
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Suggested-by: Laszlo Ersek <lersek@redhat.com>
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> ---
>  OvmfPkg/OvmfPkgIa32.dsc    | 1 +
>  OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
>  OvmfPkg/OvmfPkgX64.dsc     | 1 +
>  3 files changed, 3 insertions(+)
> 
> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
> index fffee6b0610b..7bc2404ca84a 100644
> --- a/OvmfPkg/OvmfPkgIa32.dsc
> +++ b/OvmfPkg/OvmfPkgIa32.dsc
> @@ -626,6 +626,7 @@ [Components]
>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>      <LibraryClasses>
>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>    }
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
> index a7a6c4694bca..e6773084a0f5 100644
> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
> @@ -635,6 +635,7 @@ [Components.X64]
>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>      <LibraryClasses>
>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>    }
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
> index 31145b4bcfad..905ed30232ef 100644
> --- a/OvmfPkg/OvmfPkgX64.dsc
> +++ b/OvmfPkg/OvmfPkgX64.dsc
> @@ -633,6 +633,7 @@ [Components]
>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>      <LibraryClasses>
>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>    }
>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>      <LibraryClasses>
> 

Reviewed-by: Laszlo Ersek <lersek@redhat.com>

Let's wait a bit to see if Jordan has any comments.

I'd also like to run some tests.

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  0 siblings, 1 reply; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29 11:16 UTC (permalink / raw)
  To: Jordan Justen, Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

(looks like I was the one to comment as second reviewer after all :) )

On 05/26/17 23:05, Jordan Justen wrote:
> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>> Changes since v4:
>>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>    dependency support for the dependent modules.
> 
> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
> regarding APRIORI, but I don't think this helped.
> 
> Ideally I would like to see one driver named IoMmuDxe that is *not* in
> APRIORI.

There are two separate goals here:

(1) Make sure that any driver that adds MMIO ranges will automatically
add those ranges with the C bit cleared in the PTEs, without actually
knowing about SEV.

(2) Provide an IOMMU protocol for those drivers that explicitly map /
unmap memory for DMA(-like) transfers.

Goal (2) is covered by the IOMMU protocol, and dependent drivers in
category (2) can be nicely ordered against IoMmuDxe with the OR depex (=
depend on the IOMMU protocol or the placeholder).

Goal (1) is a separate question. For covering goal (1), there are two
options:

(1a) modify all MMIO-adding drivers individually, to clear the C-bit.
(1b) do something general that will affect all MMIO additions at once,
without modifying individual drivers.

(1a) is ugly and it doesn't scale.

For (1b), there are again two possibilities:

(1b1) modify the GCD memory space map gDS services, so they handle SEV
internally,

(1b2) right after we enter the DXE phase (before any MMIO-adding driver
gets a chance to be dispatched), clear the C bit for all NonExistent
ranges (where MMIO might be added later) and for all currently existing
MMIO ranges (which come from the DXE core initialization, according to
MMIO memory descriptor HOBs from PEI).

I don't think we can express "right after we enter the DXE phase"
without an APRIORI entry; DEPEXes don't seem realistic for this.

Option (1b1) could still work, but as far as I remember (I could be
wrong!), Jiewen didn't like that, and he suggested (1b2) as the alternative.

> I think because of QemuFlashFvbServicesRuntimeDxe in APRIORI, we also
> need IoMmuDxe in the APRIORI.

QemuFlashFvbServicesRuntimeDxe adds the flash range as runtime,
uncacheable, system memory to the GCD memory space map (and then
allocates it at once). In practice it is used like MMIO, and therefore
the driver falls under category (1). Consequently, it should be
addressed with:
- either (1a) -- clear the C bit manually,
- or (1b1) -- modify the gDS services --> automatic C-bit clearing,
- or (1b2) -- assign the area with the C-bit pre-cleared.
- (or even (2) -- rework the driver to consume the IOMMU protocol
explicitly.)

Are you suggesting the last option -- rework
QemuFlashFvbServicesRuntimeDxe so that it consumes the IOMMU protocol?

In my opinion, that option is conceptually not much different from (1a)
-- which I don't like --, because it again implements a case-by-case
modification of an MMIO driver. Instead, I prefer SEV to be transparent
to drivers that don't already do *explicit* DMA.

> Hopefully we can figure our how to
> remove QemuFlashFvbServicesRuntimeDxe and then be able to remove
> IoMmuDxe.

The reason why QemuFlashFvbServicesRuntimeDxe is in APRIORI, and the
reason why AmdSevDxe is in APRIORI, are different.

* QemuFlashFvbServicesRuntimeDxe is in APRIORI -- and that's only when
SMM_REQUIRE is FALSE -- because it competes with
EmuVariableFvbRuntimeDxe, and QemuFlashFvbServicesRuntimeDxe takes
priority. EmuVariableFvbRuntimeDxe is only part of the build when
SMM_REQUIRE is false. When SMM_REQUIRE is TRUE, there is no competition,
and QemuFlashFvbServicesRuntimeDxe is not in APRIORI.

* AmdSevDxe is part of APRIORI because it must pre-clear the C bit for
*all* MMIO(-like) drivers.

If you move QemuFlashFvbServicesRuntimeDxe out of APRIORI (for example,
either by defining SMM_REQUIRE, or by inventing a different
serialization vehicle against EmuVariableFvbRuntimeDxe), AmdSevDxe
*still* has to remain in APRIORI, because it still must clear the C bit
for *all* MMIO(-like) drivers.

In my opinion, the current version of the patch set (v6) accurately
reflects option (1b2). And option (1b2) requires APRIORI usage.

If you dislike that, I think we'll have to go back to another option:
(1a), which I dislike; (1b1), which Jiewen dislikes (IIRC); or (2),
which I again dislike for all MMIO drivers that don't already use
explicit DMA.

Thanks
Laszlo

>>  - update debug messages to use gEfiCallerBaseName where applicable.
>>  - fix QemuFwCfgSecLib build errors and simplify SEV support
>>  - update QemuFwCfgDxeLib to assert when failed to locate IOMMU
>>  - update comments "host buffer" to " host buffer"
>>
>> Changes since v3:
>>  - update AmdSevDxe driver to produce IOMMU protocol
>>  - remove BmDmaLib dependency
>>  - update QemuFwCfgLib to use IOMMU protocol to allocate SEV DMA buffer
>>
>> Changes since v2:
>>  - move memory encryption CPUID and MSR definition into UefiCpuPkg
>>  - fix the argument order for SUB instruction in ResetVector and add more
>>    comments
>>  - update PlatformPei to use BaseMemEncryptSevLib
>>  - break the overlong comment lines to 79 chars
>>  - variable aligment and other formating fixes
>>  - split the SEV DMA support patch for QemuFwCfgLib into multiple patches as
>>    recommended by Laszlo
>>  - add AmdSevDxe driver which runs very early in DXE phase and clear the C-bit
>>    from MMIO memory region
>>  - drop 'QemuVideoDxe: Clear C-bit from framebuffer' patch since AmdSevDxe
>>    driver takes care of clearing the C-bit from MMIO region
>>  - Verified that Qemu PFLASH works fine with SEV guest, Found a KVM driver issue
>>    which was causing #PF when PFLASH was enabled. I have submitted patch to
>>    fix it in upstream http://marc.info/?l=kvm&m=149304930814202&w=2
>>
>> Changes since v1:
>>  - bug fixes in OvmfPkg/ResetVector (pointed by Tom Lendacky)
>>  - add SEV CPUID and MSR register definition in standard include file
>>  - remove the MemEncryptLib dependency from PlatformPei. Move AmdSevInitialize()
>>    implementation in local file inside the PlatformPei package
>>  - rename MemCryptSevLib to MemEncryptSevLib and add functions to set or
>>    clear memory encryption attribute on memory region
>>  - integerate SEV support in BmDmaLib
>>  - split QemuFwCfgDxePei.c into QemuFwCfgDxe.c and QemuFwCfgPei.c to
>>    allow building seperate QemuFwCfgLib for Dxe and Pei phase
>>    (recommended by Laszlo Ersek)
>>  - add SEV support in QemuFwCfgLib
>>  - clear the memory encryption attribute from framebuffer memory region
>>
>>
>> TODO:
>> (Will add these features after basic SEV support patches are accepted in upstream)
>>  - add support for DMA operation in QemuFwCfgS3Lib when SEV is enabled
>>  - investigate SMM/SMI support
>>
>> Cc: Jeff Fan <jeff.fan@intel.com>
>> Cc: Liming Gao <liming.gao@intel.com>
>> Cc: Leo Duran <leo.duran@amd.com>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Leo Duran <leo.duran@amd.com>
>> Cc: Jiewen Yao <jiewen.yao@intel.com>
>> Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>>
>> Brijesh Singh (17):
>>   UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
>>   OvmfPkg/ResetVector: Set C-bit when building initial page table
>>   OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
>>   OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
>>   OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
>>   OvmfPkg: Add AmdSevDxe driver
>>   OvmfPkg: Introduce IoMmuAbsent Protocol GUID
>>   OvmfPkg: Add PlatformHasIoMmuLib
>>   OvmfPkg: Add IoMmuDxe driver
>>   OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
>>   OvmfPkg/QemuFwCfgLib: Prepare for SEV support
>>   OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
>>   OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
>>   OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
>>   OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
>>   OvmfPkg/QemuFwCfgLib: Add SEV support
>>   OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
>>
>>  OvmfPkg/OvmfPkg.dec                                                    |   1 +
>>  OvmfPkg/OvmfPkgIa32.dsc                                                |  11 +-
>>  OvmfPkg/OvmfPkgIa32X64.dsc                                             |  12 +-
>>  OvmfPkg/OvmfPkgX64.dsc                                                 |  12 +-
>>  OvmfPkg/OvmfPkgIa32.fdf                                                |   1 +
>>  OvmfPkg/OvmfPkgIa32X64.fdf                                             |   3 +
>>  OvmfPkg/OvmfPkgX64.fdf                                                 |   3 +
>>  OvmfPkg/AmdSevDxe/AmdSevDxe.inf                                        |  43 ++
>>  OvmfPkg/IoMmuDxe/IoMmuDxe.inf                                          |  49 +++
>>  OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf          |  50 +++
>>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf            |  37 ++
>>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} |  15 +-
>>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} |   9 +-
>>  OvmfPkg/PlatformPei/PlatformPei.inf                                    |   3 +
>>  OvmfPkg/Include/Library/MemEncryptSevLib.h                             |  81 ++++
>>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.h                                         |  43 ++
>>  OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h               | 184 ++++++++
>>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h                    |  37 ++
>>  OvmfPkg/PlatformPei/Platform.h                                         |   5 +
>>  UefiCpuPkg/Include/Register/Amd/Cpuid.h                                | 162 +++++++
>>  UefiCpuPkg/Include/Register/Amd/Fam17Msr.h                             |  62 +++
>>  UefiCpuPkg/Include/Register/Amd/Msr.h                                  |  29 ++
>>  OvmfPkg/AmdSevDxe/AmdSevDxe.c                                          |  75 ++++
>>  OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                         | 459 ++++++++++++++++++++
>>  OvmfPkg/IoMmuDxe/IoMmuDxe.c                                            |  53 +++
>>  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 +++++++++++++++++++
>>  OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c              |  32 ++
>>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c                            | 230 ++++++++++
>>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c                            |  67 ++-
>>  OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     |  72 ++-
>>  OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c                            |  57 +++
>>  OvmfPkg/PlatformPei/AmdSev.c                                           |  62 +++
>>  OvmfPkg/PlatformPei/Platform.c                                         |   1 +
>>  OvmfPkg/ResetVector/Ia32/PageTables64.asm                              |  70 ++-
>>  37 files changed, 2703 insertions(+), 24 deletions(-)
>>  create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>>  create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
>>  create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>>  copy OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} (71%)
>>  rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} (80%)
>>  create mode 100644 OvmfPkg/Include/Library/MemEncryptSevLib.h
>>  create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Cpuid.h
>>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
>>  create mode 100644 UefiCpuPkg/Include/Register/Amd/Msr.h
>>  create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.c
>>  create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
>>  create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.c
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>>  create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
>>  create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
>>  create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
>>  rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c} (61%)
>>  create mode 100644 OvmfPkg/PlatformPei/AmdSev.c
>>
>> -- 
>> 2.7.4
>>



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 17/17] OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
  2017-05-29  9:47   ` Laszlo Ersek
@ 2017-05-29 12:13     ` Laszlo Ersek
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-05-29 12:13 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel; +Cc: Thomas.Lendacky, leo.duran, Jordan Justen

On 05/29/17 11:47, Laszlo Ersek wrote:
> On 05/26/17 16:44, Brijesh Singh wrote:
>> This patch enables PciHostBridgeDxe driver to use Platform IoMMU detection
>> library to ensure that PciHostBridgeDxe is run after platform IoMmuDxe
>> driver has checked whether platform need to install IOMMU protocol provider.
>>
>>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Contributed-under: TianoCore Contribution Agreement 1.0
>> Suggested-by: Laszlo Ersek <lersek@redhat.com>
>> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
>> ---
>>  OvmfPkg/OvmfPkgIa32.dsc    | 1 +
>>  OvmfPkg/OvmfPkgIa32X64.dsc | 1 +
>>  OvmfPkg/OvmfPkgX64.dsc     | 1 +
>>  3 files changed, 3 insertions(+)
>>
>> diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc
>> index fffee6b0610b..7bc2404ca84a 100644
>> --- a/OvmfPkg/OvmfPkgIa32.dsc
>> +++ b/OvmfPkg/OvmfPkgIa32.dsc
>> @@ -626,6 +626,7 @@ [Components]
>>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>>      <LibraryClasses>
>>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>>    }
>>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>>      <LibraryClasses>
>> diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc
>> index a7a6c4694bca..e6773084a0f5 100644
>> --- a/OvmfPkg/OvmfPkgIa32X64.dsc
>> +++ b/OvmfPkg/OvmfPkgIa32X64.dsc
>> @@ -635,6 +635,7 @@ [Components.X64]
>>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>>      <LibraryClasses>
>>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>>    }
>>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>>      <LibraryClasses>
>> diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc
>> index 31145b4bcfad..905ed30232ef 100644
>> --- a/OvmfPkg/OvmfPkgX64.dsc
>> +++ b/OvmfPkg/OvmfPkgX64.dsc
>> @@ -633,6 +633,7 @@ [Components]
>>    MdeModulePkg/Bus/Pci/PciHostBridgeDxe/PciHostBridgeDxe.inf {
>>      <LibraryClasses>
>>        PciHostBridgeLib|OvmfPkg/Library/PciHostBridgeLib/PciHostBridgeLib.inf
>> +      NULL|OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>>    }
>>    MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf {
>>      <LibraryClasses>
>>
> 
> Reviewed-by: Laszlo Ersek <lersek@redhat.com>
> 
> Let's wait a bit to see if Jordan has any comments.
> 
> I'd also like to run some tests.

I found no regressions (on my Intel CPU laptop).

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-05-29 11:16   ` Laszlo Ersek
@ 2017-05-29 20:38     ` Jordan Justen
  2017-05-29 21:59       ` Brijesh Singh
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-05-29 20:38 UTC (permalink / raw)
  To: Brijesh Singh, Laszlo Ersek, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

On 2017-05-29 04:16:15, Laszlo Ersek wrote:
> (looks like I was the one to comment as second reviewer after all :) )
> 
> On 05/26/17 23:05, Jordan Justen wrote:
> > On 2017-05-26 07:43:48, Brijesh Singh wrote:
> >> Changes since v4:
> >>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
> >>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
> >>    dependency support for the dependent modules.
> > 
> > I think you split IoMmuDxe out from AmdSevDxe based on my feedback
> > regarding APRIORI, but I don't think this helped.
> > 
> > Ideally I would like to see one driver named IoMmuDxe that is *not* in
> > APRIORI.
> 
> There are two separate goals here:
> 
> (1) Make sure that any driver that adds MMIO ranges will automatically
> add those ranges with the C bit cleared in the PTEs, without actually
> knowing about SEV.

Ok, this sounds reasonable.

The APRIORI method looks like a hack. Why is this not being handled at
the time the page tables are being built, in DxeIpl? Couldn't we
define a platform Page Tables library to allow a platform to somehow
modify the page tables as they are built? Or, maybe just after? This
would also make sure it happens before DXE runs.

-Jordan


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-05-29 20:38     ` Jordan Justen
@ 2017-05-29 21:59       ` Brijesh Singh
  2017-06-01  7:40         ` Jordan Justen
  0 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-05-29 21:59 UTC (permalink / raw)
  To: Jordan Justen, Laszlo Ersek, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao



On 5/29/17 3:38 PM, Jordan Justen wrote:
> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>> (looks like I was the one to comment as second reviewer after all :) )
>>
>> On 05/26/17 23:05, Jordan Justen wrote:
>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>> Changes since v4:
>>>>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>    dependency support for the dependent modules.
>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>> regarding APRIORI, but I don't think this helped.
>>>
>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>> APRIORI.
>> There are two separate goals here:
>>
>> (1) Make sure that any driver that adds MMIO ranges will automatically
>> add those ranges with the C bit cleared in the PTEs, without actually
>> knowing about SEV.
> Ok, this sounds reasonable.
>
> The APRIORI method looks like a hack. Why is this not being handled at
> the time the page tables are being built, in DxeIpl? Couldn't we
> define a platform Page Tables library to allow a platform to somehow
> modify the page tables as they are built? Or, maybe just after? This
> would also make sure it happens before DXE runs.

Before introducing  AmdSevDxe driver, we did proposed patches to clear
the C-bit during the page table creation time. In the first patch [1],
Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
concern was -- typically Dxecore does not do any CPU specific thing
hence we should try to find some alternative approach. In second patch
[2], Leo tried to introduce a new notify protocol to get MMIO add/remove
events. During discussion Jiewen suggested to look into adding a new
platform driver into APRIORI to avoid the need for any modifications
inside the Gcdcore - this seems workable solution which did not require
adding any CPU specific code inside the Gcd.

[1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
[2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-05-29 21:59       ` Brijesh Singh
@ 2017-06-01  7:40         ` Jordan Justen
  2017-06-01  9:10           ` Laszlo Ersek
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-06-01  7:40 UTC (permalink / raw)
  To: Brijesh Singh, Laszlo Ersek, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

On 2017-05-29 14:59:46, Brijesh Singh wrote:
> 
> 
> On 5/29/17 3:38 PM, Jordan Justen wrote:
> > On 2017-05-29 04:16:15, Laszlo Ersek wrote:
> >> (looks like I was the one to comment as second reviewer after all :) )
> >>
> >> On 05/26/17 23:05, Jordan Justen wrote:
> >>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
> >>>> Changes since v4:
> >>>>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
> >>>>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
> >>>>    dependency support for the dependent modules.
> >>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
> >>> regarding APRIORI, but I don't think this helped.
> >>>
> >>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
> >>> APRIORI.
> >> There are two separate goals here:
> >>
> >> (1) Make sure that any driver that adds MMIO ranges will automatically
> >> add those ranges with the C bit cleared in the PTEs, without actually
> >> knowing about SEV.
> > Ok, this sounds reasonable.
> >
> > The APRIORI method looks like a hack. Why is this not being handled at
> > the time the page tables are being built, in DxeIpl? Couldn't we
> > define a platform Page Tables library to allow a platform to somehow
> > modify the page tables as they are built? Or, maybe just after? This
> > would also make sure it happens before DXE runs.
> 
> Before introducing  AmdSevDxe driver, we did proposed patches to clear
> the C-bit during the page table creation time. In the first patch [1],
> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
> concern was -- typically Dxecore does not do any CPU specific thing
> hence we should try to find some alternative approach.

DxeCore doesn't build the page tables. DxeIpl builds them. I agree
that DxeCore is not the right place to handle this. In
https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
Jiewen suggested that DxeIpl could be updated during page table
creation time.

In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
Leo said that DxeIpl won't work because new I/O ranges might be added.
I don't understand this, because isn't DxeIpl and an early APRIORI
entry are roughly equivalent in the boot sequence?

-Jordan

> In second patch
> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
> events. During discussion Jiewen suggested to look into adding a new
> platform driver into APRIORI to avoid the need for any modifications
> inside the Gcdcore - this seems workable solution which did not require
> adding any CPU specific code inside the Gcd.
> 
> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 02/17] OvmfPkg/ResetVector: Set C-bit when building initial page table
  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
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-06-01  8:09 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Brijesh Singh, Laszlo Ersek

On 2017-05-26 07:43:50, Brijesh Singh wrote:
> SEV guest VMs have the concept of private and shared memory. Private
> memory is encrypted with the guest-specific key, while shared memory
> may be encrypted with hypervisor key. Certain types of memory (namely
> instruction pages and guest page tables) are always treated as private
> memory by the hardware. The C-bit in PTE indicate whether the page is
> private or shared. The C-bit position for the PTE can be obtained from
> CPUID Fn8000_001F[EBX].
> 
> When SEV is active, the BIOS is encrypted by the Qemu launch sequence,
> we must set the C-bit when building the page table.
> 
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Tom Lendacky <Thomas.Lendacky@amd.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/ResetVector/Ia32/PageTables64.asm | 70 +++++++++++++++++++-
>  1 file changed, 69 insertions(+), 1 deletion(-)
> 
> diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> index 6201cad1f5dc..3d4b04844cdf 100644
> --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
> @@ -37,9 +37,60 @@ BITS    32
>                         PAGE_READ_WRITE + \
>                         PAGE_PRESENT)
>  
> +; Check if Secure Encrypted Virtualization (SEV) feature is enabled
> +;
> +; If SEV is enabled then EAX will be at least 32
> +; If SEV is disabled then EAX will be zero.
> +;
> +CheckSevFeature:
> +    ; CPUID will clobber EBX, ECX, EDX, save these registers
> +    push  ebx
> +    push  ecx
> +    push  edx

I don't think we have a stack set up in this code, which is why
OneTimeCall/OneTimeCallRet is used. I'm wondering how this is working
at all.

I don't think we have a stack until OvmfPkg/Sec/*/SecEntry.nasm.

More below...

> +
> +    ; Check if we have a valid (0x8000_001F) CPUID leaf
> +    mov       eax, 0x80000000
> +    cpuid
> +
> +    ; This check should fail on Intel or Non SEV AMD CPUs and in future if
> +    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
> +    ; same bit definition.
> +    cmp       eax, 0x8000001f
> +    jl        NoSev
> +
> +    ; Check for memory encryption feature:
> +    ;  CPUID  Fn8000_001F[EAX] - Bit 1
> +    ;
> +    mov       eax,  0x8000001f
> +    cpuid
> +    bt        eax, 1
> +    jnc       NoSev
> +
> +    ; Check if memory encryption is enabled
> +    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
> +    mov       ecx, 0xc0010131
> +    rdmsr
> +    bt        eax, 0
> +    jnc       NoSev
> +
> +    ; Get pte bit position to enable memory encryption
> +    ; CPUID Fn8000_001F[EBX] - Bits 5:0
> +    ;
> +    mov       eax, ebx
> +    and       eax, 0x3f
> +    jmp       SevExit
> +
> +NoSev:
> +    xor       eax, eax
> +
> +SevExit:
> +    pop       edx
> +    pop       ecx
> +    pop       ebx
> +    OneTimeCallRet CheckSevFeature
>  
>  ;
> -; Modified:  EAX, ECX
> +; Modified:  EAX, ECX, EDX

Maybe you can add EBX here as well and call CheckSevFeature earlier?
You'd need to make sure we are not trying to preserve anything in
EBX/EDX in the other VTF-0 code that calls this.

If that gets unworkable, then we could setup a tiny temp stack in RAM
near where we are putting the page tables.

-Jordan

>  ;
>  SetCr3ForPageTables64:
>  
> @@ -60,18 +111,34 @@ clearPageTablesMemoryLoop:
>      mov     dword[ecx * 4 + PT_ADDR (0) - 4], eax
>      loop    clearPageTablesMemoryLoop
>  
> +    OneTimeCall   CheckSevFeature
> +    xor     edx, edx
> +    test    eax, eax
> +    jz      SevNotActive
> +
> +    ; If SEV is enabled, Memory encryption bit is always above 31
> +    sub     eax, 32
> +    bts     edx, eax
> +
> +SevNotActive:
> +
>      ;
>      ; Top level Page Directory Pointers (1 * 512GB entry)
>      ;
>      mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
> +    mov     dword[PT_ADDR (4)], edx
>  
>      ;
>      ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
>      ;
>      mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
> +    mov     dword[PT_ADDR (0x1004)], edx
>      mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
> +    mov     dword[PT_ADDR (0x100C)], edx
>      mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
> +    mov     dword[PT_ADDR (0x1014)], edx
>      mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
> +    mov     dword[PT_ADDR (0x101C)], edx
>  
>      ;
>      ; Page Table Entries (2048 * 2MB entries => 4GB)
> @@ -83,6 +150,7 @@ pageTableEntriesLoop:
>      shl     eax, 21
>      add     eax, PAGE_2M_PDE_ATTR
>      mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
> +    mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
>      loop    pageTableEntriesLoop
>  
>      ;
> -- 
> 2.7.4
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-01  7:40         ` Jordan Justen
@ 2017-06-01  9:10           ` Laszlo Ersek
  2017-06-01 13:48             ` Andrew Fish
  2017-06-05 21:56             ` Brijesh Singh
  0 siblings, 2 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-06-01  9:10 UTC (permalink / raw)
  To: Jordan Justen, Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

On 06/01/17 09:40, Jordan Justen wrote:
> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>
>>
>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>
>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>> Changes since v4:
>>>>>>  - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>    IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>    dependency support for the dependent modules.
>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>> regarding APRIORI, but I don't think this helped.
>>>>>
>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>> APRIORI.
>>>> There are two separate goals here:
>>>>
>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>> knowing about SEV.
>>> Ok, this sounds reasonable.
>>>
>>> The APRIORI method looks like a hack. Why is this not being handled at
>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>> define a platform Page Tables library to allow a platform to somehow
>>> modify the page tables as they are built? Or, maybe just after? This
>>> would also make sure it happens before DXE runs.
>>
>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>> the C-bit during the page table creation time. In the first patch [1],
>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>> concern was -- typically Dxecore does not do any CPU specific thing
>> hence we should try to find some alternative approach.
> 
> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
> that DxeCore is not the right place to handle this. In
> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
> Jiewen suggested that DxeIpl could be updated during page table
> creation time.
> 
> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
> Leo said that DxeIpl won't work because new I/O ranges might be added.
> I don't understand this, because isn't DxeIpl and an early APRIORI
> entry are roughly equivalent in the boot sequence?

I think you are right. I believe a patch for this exact idea hasn't been
posted yet. Jiewen's message that you linked above contains the expression

    always clear SEV mask for MMIO *and all rest*

(emphasis mine), which I think we may have missed *in combination with*
the DxeIpl.

So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
Keep the C bit set for system memory regions. Clear the C bit for MMIO
regions that are known from the HOB list. Also clear the C bit
everywhere else in the address space (known from the CPU HOB) where no
coverage is provided by any memory resource descriptor HOB.

This is going to be harder than the current approach, because:

- The current approach can work off of the GCD memory space map, which
provides explicit NonExistent entries, covering the entire address space
(according to the CPU HOB).

- However, the DxeIpl method would take place before entering DXE, so no
GCD memory space map would be available -- the "NonExistent" entries
would have to be synthesized manually from the address space size (known
from the CPU HOB) and the lack of coverage by memory resource descriptor
HOBs.

Basically, in order to move the current GCD memory space map traversal
from early DXE to late PEI, the memory space map building logic of the
DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
correctly. (The DxeIpl PEIM may already contain very similar code, for
the page table building, which might not be difficult to extend like
this -- I haven't looked.)

Is this what you have in mind?

Thanks
Laszlo

> -Jordan
> 
>> In second patch
>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>> events. During discussion Jiewen suggested to look into adding a new
>> platform driver into APRIORI to avoid the need for any modifications
>> inside the Gcdcore - this seems workable solution which did not require
>> adding any CPU specific code inside the Gcd.
>>
>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 02/17] OvmfPkg/ResetVector: Set C-bit when building initial page table
  2017-06-01  8:09   ` Jordan Justen
@ 2017-06-01 13:43     ` Brijesh Singh
  0 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-06-01 13:43 UTC (permalink / raw)
  To: Jordan Justen, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Laszlo Ersek



On 06/01/2017 03:09 AM, Jordan Justen wrote:
> On 2017-05-26 07:43:50, Brijesh Singh wrote:
>> SEV guest VMs have the concept of private and shared memory. Private
>> memory is encrypted with the guest-specific key, while shared memory
>> may be encrypted with hypervisor key. Certain types of memory (namely
>> instruction pages and guest page tables) are always treated as private
>> memory by the hardware. The C-bit in PTE indicate whether the page is
>> private or shared. The C-bit position for the PTE can be obtained from
>> CPUID Fn8000_001F[EBX].
>>
>> When SEV is active, the BIOS is encrypted by the Qemu launch sequence,
>> we must set the C-bit when building the page table.
>>
>>
>> Cc: Jordan Justen <jordan.l.justen@intel.com>
>> Cc: Laszlo Ersek <lersek@redhat.com>
>> Cc: Tom Lendacky <Thomas.Lendacky@amd.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/ResetVector/Ia32/PageTables64.asm | 70 +++++++++++++++++++-
>>   1 file changed, 69 insertions(+), 1 deletion(-)
>>
>> diff --git a/OvmfPkg/ResetVector/Ia32/PageTables64.asm b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
>> index 6201cad1f5dc..3d4b04844cdf 100644
>> --- a/OvmfPkg/ResetVector/Ia32/PageTables64.asm
>> +++ b/OvmfPkg/ResetVector/Ia32/PageTables64.asm
>> @@ -37,9 +37,60 @@ BITS    32
>>                          PAGE_READ_WRITE + \
>>                          PAGE_PRESENT)
>>   
>> +; Check if Secure Encrypted Virtualization (SEV) feature is enabled
>> +;
>> +; If SEV is enabled then EAX will be at least 32
>> +; If SEV is disabled then EAX will be zero.
>> +;
>> +CheckSevFeature:
>> +    ; CPUID will clobber EBX, ECX, EDX, save these registers
>> +    push  ebx
>> +    push  ecx
>> +    push  edx
> 
> I don't think we have a stack set up in this code, which is why
> OneTimeCall/OneTimeCallRet is used. I'm wondering how this is working
> at all.
> 
> I don't think we have a stack until OvmfPkg/Sec/*/SecEntry.nasm.
> 
> More below...
> 

Thanks for catching this Jordan. I am also wondering why the code has been
working.

>> +
>> +    ; Check if we have a valid (0x8000_001F) CPUID leaf
>> +    mov       eax, 0x80000000
>> +    cpuid
>> +
>> +    ; This check should fail on Intel or Non SEV AMD CPUs and in future if
>> +    ; Intel CPUs supports this CPUID leaf then we are guranteed to have exact
>> +    ; same bit definition.
>> +    cmp       eax, 0x8000001f
>> +    jl        NoSev
>> +
>> +    ; Check for memory encryption feature:
>> +    ;  CPUID  Fn8000_001F[EAX] - Bit 1
>> +    ;
>> +    mov       eax,  0x8000001f
>> +    cpuid
>> +    bt        eax, 1
>> +    jnc       NoSev
>> +
>> +    ; Check if memory encryption is enabled
>> +    ;  MSR_0xC0010131 - Bit 0 (SEV enabled)
>> +    mov       ecx, 0xc0010131
>> +    rdmsr
>> +    bt        eax, 0
>> +    jnc       NoSev
>> +
>> +    ; Get pte bit position to enable memory encryption
>> +    ; CPUID Fn8000_001F[EBX] - Bits 5:0
>> +    ;
>> +    mov       eax, ebx
>> +    and       eax, 0x3f
>> +    jmp       SevExit
>> +
>> +NoSev:
>> +    xor       eax, eax
>> +
>> +SevExit:
>> +    pop       edx
>> +    pop       ecx
>> +    pop       ebx
>> +    OneTimeCallRet CheckSevFeature
>>   
>>   ;
>> -; Modified:  EAX, ECX
>> +; Modified:  EAX, ECX, EDX
> 
> Maybe you can add EBX here as well and call CheckSevFeature earlier?
> You'd need to make sure we are not trying to preserve anything in
> EBX/EDX in the other VTF-0 code that calls this.
> 
> If that gets unworkable, then we could setup a tiny temp stack in RAM
> near where we are putting the page tables.
> 

I looked at the call sequence from VTF-0 and it seems nothing is getting
preserved in EBX/EDX. I should be able remove those push/pop instructions
and move the call CheckSevFeature in start of SetCr3ForPageTables64.

> -Jordan
> 
>>   ;
>>   SetCr3ForPageTables64:
>>   
>> @@ -60,18 +111,34 @@ clearPageTablesMemoryLoop:
>>       mov     dword[ecx * 4 + PT_ADDR (0) - 4], eax
>>       loop    clearPageTablesMemoryLoop
>>   
>> +    OneTimeCall   CheckSevFeature
>> +    xor     edx, edx
>> +    test    eax, eax
>> +    jz      SevNotActive
>> +
>> +    ; If SEV is enabled, Memory encryption bit is always above 31
>> +    sub     eax, 32
>> +    bts     edx, eax
>> +
>> +SevNotActive:
>> +
>>       ;
>>       ; Top level Page Directory Pointers (1 * 512GB entry)
>>       ;
>>       mov     dword[PT_ADDR (0)], PT_ADDR (0x1000) + PAGE_PDP_ATTR
>> +    mov     dword[PT_ADDR (4)], edx
>>   
>>       ;
>>       ; Next level Page Directory Pointers (4 * 1GB entries => 4GB)
>>       ;
>>       mov     dword[PT_ADDR (0x1000)], PT_ADDR (0x2000) + PAGE_PDP_ATTR
>> +    mov     dword[PT_ADDR (0x1004)], edx
>>       mov     dword[PT_ADDR (0x1008)], PT_ADDR (0x3000) + PAGE_PDP_ATTR
>> +    mov     dword[PT_ADDR (0x100C)], edx
>>       mov     dword[PT_ADDR (0x1010)], PT_ADDR (0x4000) + PAGE_PDP_ATTR
>> +    mov     dword[PT_ADDR (0x1014)], edx
>>       mov     dword[PT_ADDR (0x1018)], PT_ADDR (0x5000) + PAGE_PDP_ATTR
>> +    mov     dword[PT_ADDR (0x101C)], edx
>>   
>>       ;
>>       ; Page Table Entries (2048 * 2MB entries => 4GB)
>> @@ -83,6 +150,7 @@ pageTableEntriesLoop:
>>       shl     eax, 21
>>       add     eax, PAGE_2M_PDE_ATTR
>>       mov     [ecx * 8 + PT_ADDR (0x2000 - 8)], eax
>> +    mov     [(ecx * 8 + PT_ADDR (0x2000 - 8)) + 4], edx
>>       loop    pageTableEntriesLoop
>>   
>>       ;
>> -- 
>> 2.7.4
>>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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-05 21:56             ` Brijesh Singh
  1 sibling, 2 replies; 65+ messages in thread
From: Andrew Fish @ 2017-06-01 13:48 UTC (permalink / raw)
  To: Laszlo Ersek
  Cc: Jordan Justen, Brijesh Singh, edk2-devel-01, Thomas.Lendacky,
	leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

Laszlo,

The current design is DXE IPL and gEfiCpuArchProtocolGuid abstract the CPU specifics from the DXE Core. 

https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Gcd/Gcd.c#L866
  if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
    //
    // Call CPU Arch Protocol to attempt to set attributes on the range
    //
    CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
    if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
      if (gCpu == NULL) {
        Status = EFI_NOT_AVAILABLE_YET;
      } else {
        Status = gCpu->SetMemoryAttributes (
                         gCpu,
                         BaseAddress,
                         Length,
                         CpuArchAttributes
                         );
      }
      if (EFI_ERROR (Status)) {
        CoreFreePool (TopEntry);
        CoreFreePool (BottomEntry);
        goto Done;
      }
    }
  }

Maybe the issue is there is an attempt to change attributes too early and they currently get sent to the bit bucket? I guess they could get queued up and replayed after gEfiCpuArchProtocolGuid is preset?

Thanks,

Andrew Fish


> On Jun 1, 2017, at 2:10 AM, Laszlo Ersek <lersek@redhat.com> wrote:
> 
> On 06/01/17 09:40, Jordan Justen wrote:
>> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>> 
>>> 
>>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>> 
>>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>>> Changes since v4:
>>>>>>> - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>>   IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>>   dependency support for the dependent modules.
>>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>>> regarding APRIORI, but I don't think this helped.
>>>>>> 
>>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>>> APRIORI.
>>>>> There are two separate goals here:
>>>>> 
>>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>>> knowing about SEV.
>>>> Ok, this sounds reasonable.
>>>> 
>>>> The APRIORI method looks like a hack. Why is this not being handled at
>>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>>> define a platform Page Tables library to allow a platform to somehow
>>>> modify the page tables as they are built? Or, maybe just after? This
>>>> would also make sure it happens before DXE runs.
>>> 
>>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>>> the C-bit during the page table creation time. In the first patch [1],
>>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>>> concern was -- typically Dxecore does not do any CPU specific thing
>>> hence we should try to find some alternative approach.
>> 
>> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
>> that DxeCore is not the right place to handle this. In
>> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
>> Jiewen suggested that DxeIpl could be updated during page table
>> creation time.
>> 
>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>> I don't understand this, because isn't DxeIpl and an early APRIORI
>> entry are roughly equivalent in the boot sequence?
> 
> I think you are right. I believe a patch for this exact idea hasn't been
> posted yet. Jiewen's message that you linked above contains the expression
> 
>    always clear SEV mask for MMIO *and all rest*
> 
> (emphasis mine), which I think we may have missed *in combination with*
> the DxeIpl.
> 
> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
> Keep the C bit set for system memory regions. Clear the C bit for MMIO
> regions that are known from the HOB list. Also clear the C bit
> everywhere else in the address space (known from the CPU HOB) where no
> coverage is provided by any memory resource descriptor HOB.
> 
> This is going to be harder than the current approach, because:
> 
> - The current approach can work off of the GCD memory space map, which
> provides explicit NonExistent entries, covering the entire address space
> (according to the CPU HOB).
> 
> - However, the DxeIpl method would take place before entering DXE, so no
> GCD memory space map would be available -- the "NonExistent" entries
> would have to be synthesized manually from the address space size (known
> from the CPU HOB) and the lack of coverage by memory resource descriptor
> HOBs.
> 
> Basically, in order to move the current GCD memory space map traversal
> from early DXE to late PEI, the memory space map building logic of the
> DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
> correctly. (The DxeIpl PEIM may already contain very similar code, for
> the page table building, which might not be difficult to extend like
> this -- I haven't looked.)
> 
> Is this what you have in mind?
> 
> Thanks
> Laszlo
> 
>> -Jordan
>> 
>>> In second patch
>>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>>> events. During discussion Jiewen suggested to look into adding a new
>>> platform driver into APRIORI to avoid the need for any modifications
>>> inside the Gcdcore - this seems workable solution which did not require
>>> adding any CPU specific code inside the Gcd.
>>> 
>>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>> 
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-01 13:48             ` Andrew Fish
@ 2017-06-01 14:56               ` Laszlo Ersek
  2017-06-01 15:01               ` Brijesh Singh
  1 sibling, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-06-01 14:56 UTC (permalink / raw)
  To: Andrew Fish
  Cc: Jordan Justen, Brijesh Singh, edk2-devel-01, Thomas.Lendacky,
	leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

On 06/01/17 15:48, Andrew Fish wrote:
> Laszlo,
> 
> The current design is DXE IPL and gEfiCpuArchProtocolGuid abstract the CPU specifics from the DXE Core. 
> 
> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Gcd/Gcd.c#L866
>   if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
>     //
>     // Call CPU Arch Protocol to attempt to set attributes on the range
>     //
>     CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
>     if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
>       if (gCpu == NULL) {
>         Status = EFI_NOT_AVAILABLE_YET;
>       } else {
>         Status = gCpu->SetMemoryAttributes (
>                          gCpu,
>                          BaseAddress,
>                          Length,
>                          CpuArchAttributes
>                          );
>       }
>       if (EFI_ERROR (Status)) {
>         CoreFreePool (TopEntry);
>         CoreFreePool (BottomEntry);
>         goto Done;
>       }
>     }
>   }
> 
> Maybe the issue is there is an attempt to change attributes too early
> and they currently get sent to the bit bucket? I guess they could get
> queued up and replayed after gEfiCpuArchProtocolGuid is preset?
The problem we are facing is not a technical one, the method implemented
in this series works. AIUI we're looking for the best component and best
phase for clearing the C bit for MMIO ranges that are either installed
by the PEI phase (via HOBs) or by gDS->AddMemorySpace() calls in DXE.

One idea was to incorporate the C-bit's management, for both kinds of
MMIO additions, into the DXE Core. (The DXE Core precedes all DXE
drivers, and it processes the memory descriptor HOBs anyway, for
initializing the GCD memory space map.)

If we can push down the C-bit's management to the CPU Arch protocol
implementation, because that's what the DXE Core calls out to, upon
memory space addition, that could likely take care of the
gDS->AddMemorySpace() calls.

Not sure how the other category would be handled via the CPU Arch
protocol though, as a DXE driver directly accessing an MMIO range that
was described in PEI with a HOB could be dispatched before the CPU Arch
protocol becomes available. So acting upon those MMIO HOBs only after
the CPU Arch proto is up could be too late.

Thanks
Laszlo


> 
>> On Jun 1, 2017, at 2:10 AM, Laszlo Ersek <lersek@redhat.com> wrote:
>>
>> On 06/01/17 09:40, Jordan Justen wrote:
>>> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>>>
>>>>
>>>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>>>
>>>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>>>> Changes since v4:
>>>>>>>> - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>>>   IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>>>   dependency support for the dependent modules.
>>>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>>>> regarding APRIORI, but I don't think this helped.
>>>>>>>
>>>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>>>> APRIORI.
>>>>>> There are two separate goals here:
>>>>>>
>>>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>>>> knowing about SEV.
>>>>> Ok, this sounds reasonable.
>>>>>
>>>>> The APRIORI method looks like a hack. Why is this not being handled at
>>>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>>>> define a platform Page Tables library to allow a platform to somehow
>>>>> modify the page tables as they are built? Or, maybe just after? This
>>>>> would also make sure it happens before DXE runs.
>>>>
>>>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>>>> the C-bit during the page table creation time. In the first patch [1],
>>>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>>>> concern was -- typically Dxecore does not do any CPU specific thing
>>>> hence we should try to find some alternative approach.
>>>
>>> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
>>> that DxeCore is not the right place to handle this. In
>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
>>> Jiewen suggested that DxeIpl could be updated during page table
>>> creation time.
>>>
>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>> entry are roughly equivalent in the boot sequence?
>>
>> I think you are right. I believe a patch for this exact idea hasn't been
>> posted yet. Jiewen's message that you linked above contains the expression
>>
>>    always clear SEV mask for MMIO *and all rest*
>>
>> (emphasis mine), which I think we may have missed *in combination with*
>> the DxeIpl.
>>
>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>> Keep the C bit set for system memory regions. Clear the C bit for MMIO
>> regions that are known from the HOB list. Also clear the C bit
>> everywhere else in the address space (known from the CPU HOB) where no
>> coverage is provided by any memory resource descriptor HOB.
>>
>> This is going to be harder than the current approach, because:
>>
>> - The current approach can work off of the GCD memory space map, which
>> provides explicit NonExistent entries, covering the entire address space
>> (according to the CPU HOB).
>>
>> - However, the DxeIpl method would take place before entering DXE, so no
>> GCD memory space map would be available -- the "NonExistent" entries
>> would have to be synthesized manually from the address space size (known
>> from the CPU HOB) and the lack of coverage by memory resource descriptor
>> HOBs.
>>
>> Basically, in order to move the current GCD memory space map traversal
>> from early DXE to late PEI, the memory space map building logic of the
>> DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
>> correctly. (The DxeIpl PEIM may already contain very similar code, for
>> the page table building, which might not be difficult to extend like
>> this -- I haven't looked.)
>>
>> Is this what you have in mind?
>>
>> Thanks
>> Laszlo
>>
>>> -Jordan
>>>
>>>> In second patch
>>>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>>>> events. During discussion Jiewen suggested to look into adding a new
>>>> platform driver into APRIORI to avoid the need for any modifications
>>>> inside the Gcdcore - this seems workable solution which did not require
>>>> adding any CPU specific code inside the Gcd.
>>>>
>>>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel
> 
> 



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  1 sibling, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-06-01 15:01 UTC (permalink / raw)
  To: Andrew Fish, Laszlo Ersek
  Cc: brijesh.singh, Jordan Justen, edk2-devel-01, Thomas.Lendacky,
	leo.duran, Jeff Fan, Liming Gao, Jiewen Yao

Hi Andrew,

The goal is to clear the "C" bit in PTE for all the MMIO areas in the GCD memory
space map. I think Leo looked at SetMemoryAttributes() based on Mike's feedback,
but I believe SetMemoryAttribute may get called on any range without specifying
types (we are interested in MMIO ranges, which are specified in ADD/REMOVE operations).

-Brijesh

On 06/01/2017 08:48 AM, Andrew Fish wrote:
> Laszlo,
> 
> The current design is DXE IPL and gEfiCpuArchProtocolGuid abstract the CPU specifics from the DXE Core.
> 
> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Gcd/Gcd.c#L866
>    if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
>      //
>      // Call CPU Arch Protocol to attempt to set attributes on the range
>      //
>      CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
>      if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
>        if (gCpu == NULL) {
>          Status = EFI_NOT_AVAILABLE_YET;
>        } else {
>          Status = gCpu->SetMemoryAttributes (
>                           gCpu,
>                           BaseAddress,
>                           Length,
>                           CpuArchAttributes
>                           );
>        }
>        if (EFI_ERROR (Status)) {
>          CoreFreePool (TopEntry);
>          CoreFreePool (BottomEntry);
>          goto Done;
>        }
>      }
>    }
> 
> Maybe the issue is there is an attempt to change attributes too early and they currently get sent to the bit bucket? I guess they could get queued up and replayed after gEfiCpuArchProtocolGuid is preset?
> 
> Thanks,
> 
> Andrew Fish
> 
> 
>> On Jun 1, 2017, at 2:10 AM, Laszlo Ersek <lersek@redhat.com <mailto:lersek@redhat.com>> wrote:
>>
>> On 06/01/17 09:40, Jordan Justen wrote:
>>> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>>>
>>>>
>>>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>>>
>>>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>>>> Changes since v4:
>>>>>>>> - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>>>   IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>>>   dependency support for the dependent modules.
>>>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>>>> regarding APRIORI, but I don't think this helped.
>>>>>>>
>>>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>>>> APRIORI.
>>>>>> There are two separate goals here:
>>>>>>
>>>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>>>> knowing about SEV.
>>>>> Ok, this sounds reasonable.
>>>>>
>>>>> The APRIORI method looks like a hack. Why is this not being handled at
>>>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>>>> define a platform Page Tables library to allow a platform to somehow
>>>>> modify the page tables as they are built? Or, maybe just after? This
>>>>> would also make sure it happens before DXE runs.
>>>>
>>>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>>>> the C-bit during the page table creation time. In the first patch [1],
>>>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>>>> concern was -- typically Dxecore does not do any CPU specific thing
>>>> hence we should try to find some alternative approach.
>>>
>>> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
>>> that DxeCore is not the right place to handle this. In
>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
>>> Jiewen suggested that DxeIpl could be updated during page table
>>> creation time.
>>>
>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>> entry are roughly equivalent in the boot sequence?
>>
>> I think you are right. I believe a patch for this exact idea hasn't been
>> posted yet. Jiewen's message that you linked above contains the expression
>>
>>    always clear SEV mask for MMIO *and all rest*
>>
>> (emphasis mine), which I think we may have missed *in combination with*
>> the DxeIpl.
>>
>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>> Keep the C bit set for system memory regions. Clear the C bit for MMIO
>> regions that are known from the HOB list. Also clear the C bit
>> everywhere else in the address space (known from the CPU HOB) where no
>> coverage is provided by any memory resource descriptor HOB.
>>
>> This is going to be harder than the current approach, because:
>>
>> - The current approach can work off of the GCD memory space map, which
>> provides explicit NonExistent entries, covering the entire address space
>> (according to the CPU HOB).
>>
>> - However, the DxeIpl method would take place before entering DXE, so no
>> GCD memory space map would be available -- the "NonExistent" entries
>> would have to be synthesized manually from the address space size (known
>> from the CPU HOB) and the lack of coverage by memory resource descriptor
>> HOBs.
>>
>> Basically, in order to move the current GCD memory space map traversal
>> from early DXE to late PEI, the memory space map building logic of the
>> DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
>> correctly. (The DxeIpl PEIM may already contain very similar code, for
>> the page table building, which might not be difficult to extend like
>> this -- I haven't looked.)
>>
>> Is this what you have in mind?
>>
>> Thanks
>> Laszlo
>>
>>> -Jordan
>>>
>>>> In second patch
>>>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>>>> events. During discussion Jiewen suggested to look into adding a new
>>>> platform driver into APRIORI to avoid the need for any modifications
>>>> inside the Gcdcore - this seems workable solution which did not require
>>>> adding any CPU specific code inside the Gcd.
>>>>
>>>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>
>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-01 15:01               ` Brijesh Singh
@ 2017-06-01 15:37                 ` Andrew Fish
  0 siblings, 0 replies; 65+ messages in thread
From: Andrew Fish @ 2017-06-01 15:37 UTC (permalink / raw)
  To: Brijesh Singh
  Cc: Laszlo Ersek, Thomas.Lendacky, Jordan Justen, edk2-devel-01,
	Liming Gao, leo.duran, Jiewen Yao, Jeff Fan


> On Jun 1, 2017, at 8:01 AM, Brijesh Singh <brijesh.singh@amd.com> wrote:
> 
> Hi Andrew,
> 
> The goal is to clear the "C" bit in PTE for all the MMIO areas in the GCD memory
> space map. I think Leo looked at SetMemoryAttributes() based on Mike's feedback,
> but I believe SetMemoryAttribute may get called on any range without specifying
> types (we are interested in MMIO ranges, which are specified in ADD/REMOVE operations).
> 

Brijesh,

Sorry pre coffee...

I gest I'm trying to ask more generic questions.

1) Should the DXE Core queue GCD_SET_ATTRIBUTES_MEMORY_OPERATIONs so you can update things from PEI, or not require a priori dispatch? 
2) Is there an issue in the GCD implementation or architecture. 

For example I recently ran into an issue use EfiGcdMemoryTypeMemoryMappedIo as it was causing massive amounts of virtual mapping requests to the OS. It looks like by default EfiGcdMemoryTypeMemoryMappedIo sets the EFI_MEMORY_RUNTIME Capability. I'm not exactly sure that is what the PI Spec requires?  It makes sense to me that from EFI MemoryMappedIo things require the EFI_MEMORY_RUNTIME, but for GCD seems like you might have massive ranges of MMIO that need to get mapped, and those regions get owned by the OS at runtime? 

Anyway not trying to derail your solution, or block progress. I just want to make sure we have the conversation as to why this ended up being so hard to make sure we don't have an implementation or spec issue around things GCD. 

PI Spec on EfiGcdMemoryTypeMemoryMappedIo

The GetMemoryMap() implementation must include into the UEFI memory map all GCD map entries of types EfiGcdMemoryTypeReserved and EfiPersistentMemory, and all GCD map entries of type EfiGcdMemoryTypeMemoryMappedIo that have EFI_MEMORY_RUNTIME attribute set.

vs.

The GetMemoryMap() implementation must include all GCD map entries of types EfiGcdMemoryTypeReserved and EfiGcdMemoryTypeMemoryMappedIo into the UEFI memory map.

Thanks,

Andrew Fish

> -Brijesh
> 
> On 06/01/2017 08:48 AM, Andrew Fish wrote:
>> Laszlo,
>> The current design is DXE IPL and gEfiCpuArchProtocolGuid abstract the CPU specifics from the DXE Core.
>> https://github.com/tianocore/edk2/blob/master/MdeModulePkg/Core/Dxe/Gcd/Gcd.c#L866
>>   if (Operation == GCD_SET_ATTRIBUTES_MEMORY_OPERATION) {
>>     //
>>     // Call CPU Arch Protocol to attempt to set attributes on the range
>>     //
>>     CpuArchAttributes = ConverToCpuArchAttributes (Attributes);
>>     if (CpuArchAttributes != INVALID_CPU_ARCH_ATTRIBUTES) {
>>       if (gCpu == NULL) {
>>         Status = EFI_NOT_AVAILABLE_YET;
>>       } else {
>>         Status = gCpu->SetMemoryAttributes (
>>                          gCpu,
>>                          BaseAddress,
>>                          Length,
>>                          CpuArchAttributes
>>                          );
>>       }
>>       if (EFI_ERROR (Status)) {
>>         CoreFreePool (TopEntry);
>>         CoreFreePool (BottomEntry);
>>         goto Done;
>>       }
>>     }
>>   }
>> Maybe the issue is there is an attempt to change attributes too early and they currently get sent to the bit bucket? I guess they could get queued up and replayed after gEfiCpuArchProtocolGuid is preset?
>> Thanks,
>> Andrew Fish
>>> On Jun 1, 2017, at 2:10 AM, Laszlo Ersek <lersek@redhat.com <mailto:lersek@redhat.com> <mailto:lersek@redhat.com <mailto:lersek@redhat.com>>> wrote:
>>> 
>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>>>> 
>>>>> 
>>>>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>>>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>>>> 
>>>>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>>>>> Changes since v4:
>>>>>>>>> - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>>>>  IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>>>>  dependency support for the dependent modules.
>>>>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>>>>> regarding APRIORI, but I don't think this helped.
>>>>>>>> 
>>>>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>>>>> APRIORI.
>>>>>>> There are two separate goals here:
>>>>>>> 
>>>>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>>>>> knowing about SEV.
>>>>>> Ok, this sounds reasonable.
>>>>>> 
>>>>>> The APRIORI method looks like a hack. Why is this not being handled at
>>>>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>>>>> define a platform Page Tables library to allow a platform to somehow
>>>>>> modify the page tables as they are built? Or, maybe just after? This
>>>>>> would also make sure it happens before DXE runs.
>>>>> 
>>>>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>>>>> the C-bit during the page table creation time. In the first patch [1],
>>>>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>>>>> concern was -- typically Dxecore does not do any CPU specific thing
>>>>> hence we should try to find some alternative approach.
>>>> 
>>>> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
>>>> that DxeCore is not the right place to handle this. In
>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
>>>> Jiewen suggested that DxeIpl could be updated during page table
>>>> creation time.
>>>> 
>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>> entry are roughly equivalent in the boot sequence?
>>> 
>>> I think you are right. I believe a patch for this exact idea hasn't been
>>> posted yet. Jiewen's message that you linked above contains the expression
>>> 
>>>   always clear SEV mask for MMIO *and all rest*
>>> 
>>> (emphasis mine), which I think we may have missed *in combination with*
>>> the DxeIpl.
>>> 
>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>> Keep the C bit set for system memory regions. Clear the C bit for MMIO
>>> regions that are known from the HOB list. Also clear the C bit
>>> everywhere else in the address space (known from the CPU HOB) where no
>>> coverage is provided by any memory resource descriptor HOB.
>>> 
>>> This is going to be harder than the current approach, because:
>>> 
>>> - The current approach can work off of the GCD memory space map, which
>>> provides explicit NonExistent entries, covering the entire address space
>>> (according to the CPU HOB).
>>> 
>>> - However, the DxeIpl method would take place before entering DXE, so no
>>> GCD memory space map would be available -- the "NonExistent" entries
>>> would have to be synthesized manually from the address space size (known
>>> from the CPU HOB) and the lack of coverage by memory resource descriptor
>>> HOBs.
>>> 
>>> Basically, in order to move the current GCD memory space map traversal
>>> from early DXE to late PEI, the memory space map building logic of the
>>> DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
>>> correctly. (The DxeIpl PEIM may already contain very similar code, for
>>> the page table building, which might not be difficult to extend like
>>> this -- I haven't looked.)
>>> 
>>> Is this what you have in mind?
>>> 
>>> Thanks
>>> Laszlo
>>> 
>>>> -Jordan
>>>> 
>>>>> In second patch
>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>>>>> events. During discussion Jiewen suggested to look into adding a new
>>>>> platform driver into APRIORI to avoid the need for any modifications
>>>>> inside the Gcdcore - this seems workable solution which did not require
>>>>> adding any CPU specific code inside the Gcd.
>>>>> 
>>>>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>> 
>>> 
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org> <mailto:edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org>>
>>> https://lists.01.org/mailman/listinfo/edk2-devel <https://lists.01.org/mailman/listinfo/edk2-devel>
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org <mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel <https://lists.01.org/mailman/listinfo/edk2-devel>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-01  9:10           ` Laszlo Ersek
  2017-06-01 13:48             ` Andrew Fish
@ 2017-06-05 21:56             ` Brijesh Singh
  2017-06-06  1:12               ` Jordan Justen
  1 sibling, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-06-05 21:56 UTC (permalink / raw)
  To: Laszlo Ersek, Jordan Justen, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Jiewen Yao

Hi Jordan,


On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
> On 06/01/17 09:40, Jordan Justen wrote:
>> On 2017-05-29 14:59:46, Brijesh Singh wrote:
>>>
>>>
>>> On 5/29/17 3:38 PM, Jordan Justen wrote:
>>>> On 2017-05-29 04:16:15, Laszlo Ersek wrote:
>>>>> (looks like I was the one to comment as second reviewer after all :) )
>>>>>
>>>>> On 05/26/17 23:05, Jordan Justen wrote:
>>>>>> On 2017-05-26 07:43:48, Brijesh Singh wrote:
>>>>>>> Changes since v4:
>>>>>>>   - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>>>>>>>     IoMmuDxe driver. And introduce a placeholder protocol to provide the
>>>>>>>     dependency support for the dependent modules.
>>>>>> I think you split IoMmuDxe out from AmdSevDxe based on my feedback
>>>>>> regarding APRIORI, but I don't think this helped.
>>>>>>
>>>>>> Ideally I would like to see one driver named IoMmuDxe that is *not* in
>>>>>> APRIORI.
>>>>> There are two separate goals here:
>>>>>
>>>>> (1) Make sure that any driver that adds MMIO ranges will automatically
>>>>> add those ranges with the C bit cleared in the PTEs, without actually
>>>>> knowing about SEV.
>>>> Ok, this sounds reasonable.
>>>>
>>>> The APRIORI method looks like a hack. Why is this not being handled at
>>>> the time the page tables are being built, in DxeIpl? Couldn't we
>>>> define a platform Page Tables library to allow a platform to somehow
>>>> modify the page tables as they are built? Or, maybe just after? This
>>>> would also make sure it happens before DXE runs.
>>>
>>> Before introducing  AmdSevDxe driver, we did proposed patches to clear
>>> the C-bit during the page table creation time. In the first patch [1],
>>> Leo tried to  teach gcd.c to clear the C-bit from MMIO. IIRC, the main
>>> concern was -- typically Dxecore does not do any CPU specific thing
>>> hence we should try to find some alternative approach.
>>
>> DxeCore doesn't build the page tables. DxeIpl builds them. I agree
>> that DxeCore is not the right place to handle this. In
>> https://lists.01.org/pipermail/edk2-devel/2017-March/008987.html
>> Jiewen suggested that DxeIpl could be updated during page table
>> creation time.
>>
>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>> I don't understand this, because isn't DxeIpl and an early APRIORI
>> entry are roughly equivalent in the boot sequence?
> 
> I think you are right. I believe a patch for this exact idea hasn't been
> posted yet. Jiewen's message that you linked above contains the expression
> 
>      always clear SEV mask for MMIO *and all rest*
> 
> (emphasis mine), which I think we may have missed *in combination with*
> the DxeIpl.
> 
> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
> Keep the C bit set for system memory regions. Clear the C bit for MMIO
> regions that are known from the HOB list. Also clear the C bit
> everywhere else in the address space (known from the CPU HOB) where no
> coverage is provided by any memory resource descriptor HOB.
> 
> This is going to be harder than the current approach, because:
> 
> - The current approach can work off of the GCD memory space map, which
> provides explicit NonExistent entries, covering the entire address space
> (according to the CPU HOB).
> 
> - However, the DxeIpl method would take place before entering DXE, so no
> GCD memory space map would be available -- the "NonExistent" entries
> would have to be synthesized manually from the address space size (known
> from the CPU HOB) and the lack of coverage by memory resource descriptor
> HOBs.
> 
> Basically, in order to move the current GCD memory space map traversal
> from early DXE to late PEI, the memory space map building logic of the
> DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
> correctly. (The DxeIpl PEIM may already contain very similar code, for
> the page table building, which might not be difficult to extend like
> this -- I haven't looked.)
> 
> Is this what you have in mind?
> 

Do you have any further thought on this?

In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to see
if I can invoke a platform dependent library to clear C-bit before DxeMain
finishes its execution. As Laszlo pointed, current approach is using GCD memory
space map to get MMIO and NonExistent entries. I have pushed two patches
in my development branch to show what I have been doing:

1) add a new null DxeGcdCorePlatformHookLib

https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94a920d7ad72d

The library provides a function "DxeGcdCorePlatformHookReady" which can be called
by DxeMain just after it initializes the GcdServices (which will guarantee that
Gcd memory space map is available).

2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
  SEV is detected.

https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba53c95949f659

I've tested the approach and it seems to work. Is this something aligned with your
thinking?


> Thanks
> Laszlo
> 
>> -Jordan
>>
>>> In second patch
>>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
>>> events. During discussion Jiewen suggested to look into adding a new
>>> platform driver into APRIORI to avoid the need for any modifications
>>> inside the Gcdcore - this seems workable solution which did not require
>>> adding any CPU specific code inside the Gcd.
>>>
>>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-05 21:56             ` Brijesh Singh
@ 2017-06-06  1:12               ` Jordan Justen
  2017-06-06  2:08                 ` Zeng, Star
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-06-06  1:12 UTC (permalink / raw)
  To: Brijesh Singh, Laszlo Ersek, edk2-devel, Star Zeng, Eric Dong
  Cc: Thomas.Lendacky, Liming Gao, leo.duran, Jiewen Yao, Jeff Fan

On 2017-06-05 14:56:04, Brijesh Singh wrote:
> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
> > On 06/01/17 09:40, Jordan Justen wrote:
> >> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
> >> Leo said that DxeIpl won't work because new I/O ranges might be added.
> >> I don't understand this, because isn't DxeIpl and an early APRIORI
> >> entry are roughly equivalent in the boot sequence?
> > 
> > I think you are right. I believe a patch for this exact idea hasn't been
> > posted yet. Jiewen's message that you linked above contains the expression
> > 
> >      always clear SEV mask for MMIO *and all rest*
> > 
> > (emphasis mine), which I think we may have missed *in combination with*
> > the DxeIpl.
> > 
> > So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
> > Keep the C bit set for system memory regions. Clear the C bit for MMIO
> > regions that are known from the HOB list. Also clear the C bit
> > everywhere else in the address space (known from the CPU HOB) where no
> > coverage is provided by any memory resource descriptor HOB.
> > 
> > This is going to be harder than the current approach, because:
> > 
> > - The current approach can work off of the GCD memory space map, which
> > provides explicit NonExistent entries, covering the entire address space
> > (according to the CPU HOB).
> > 
> > - However, the DxeIpl method would take place before entering DXE, so no
> > GCD memory space map would be available -- the "NonExistent" entries
> > would have to be synthesized manually from the address space size (known
> > from the CPU HOB) and the lack of coverage by memory resource descriptor
> > HOBs.
> > 
> > Basically, in order to move the current GCD memory space map traversal
> > from early DXE to late PEI, the memory space map building logic of the
> > DXE Core would have to be duplicated in the DxeIpl PEIM. If I understand
> > correctly. (The DxeIpl PEIM may already contain very similar code, for
> > the page table building, which might not be difficult to extend like
> > this -- I haven't looked.)
> > 
> > Is this what you have in mind?
> > 
> 
> Do you have any further thought on this?

Regarding Laszlo's feedback, I'm not convinced that it would be
excessively difficult to accomplish this in DxeIpl. (I'm not saying
that I couldn't be convinced. :)

As far as I can see, this is an architecturally defined AMD feature.
(Is this true, or is BaseMemcryptSevLib actually OVMF specific?)

You've asserted that it should work (SEV would not be detected) with
any Intel processor as well. Therefore, I don't see a good reason that
we shouldn't be able to support it in modules that already have
IA32/X64 specific code. (I'm recalling
881813d7a93d9009c873515b043c41c4554779e4.)

Since DxeIpl builds the IA32/X64 page tables, and you need to modify
the page tables for this feature (correct?), I think we should try to
support the feature there if it is feasible. I can understand the
argument that this doesn't apply to all non-VM platforms, so I think
we could add a PCD which disables this support by default.

I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree
with me though.

> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to see
> if I can invoke a platform dependent library to clear C-bit before DxeMain
> finishes its execution. As Laszlo pointed, current approach is using GCD memory
> space map to get MMIO and NonExistent entries. I have pushed two patches
> in my development branch to show what I have been doing:
> 
> 1) add a new null DxeGcdCorePlatformHookLib
> 
> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94a920d7ad72d
> 
> The library provides a function "DxeGcdCorePlatformHookReady" which can be called
> by DxeMain just after it initializes the GcdServices (which will guarantee that
> Gcd memory space map is available).

Regarding hooking into DxeCore, I don't think it is the best approach,
but it is better than APRIORI. I wonder if the MdeModulePkg owners
could jump in with an opinion. (Hopefully besides just pushing the
problem away via APRIORI.)

-Jordan

> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>   SEV is detected.
> 
> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba53c95949f659
> 
> I've tested the approach and it seems to work. Is this something aligned with your
> thinking?
> 
> 
> > Thanks
> > Laszlo
> > 
> >> -Jordan
> >>
> >>> In second patch
> >>> [2], Leo tried to introduce a new notify protocol to get MMIO add/remove
> >>> events. During discussion Jiewen suggested to look into adding a new
> >>> platform driver into APRIORI to avoid the need for any modifications
> >>> inside the Gcdcore - this seems workable solution which did not require
> >>> adding any CPU specific code inside the Gcd.
> >>>
> >>> [1] https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
> >>> [2] https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
> >>>
> > 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06  1:12               ` Jordan Justen
@ 2017-06-06  2:08                 ` Zeng, Star
  2017-06-06  3:50                   ` Brijesh Singh
  0 siblings, 1 reply; 65+ messages in thread
From: Zeng, Star @ 2017-06-06  2:08 UTC (permalink / raw)
  To: Justen, Jordan L, Brijesh Singh, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric, Yao, Jiewen
  Cc: Thomas.Lendacky@amd.com, Gao, Liming, leo.duran@amd.com,
	Fan, Jeff, Zeng, Star

I was not tracking this thread.
Jiewen will help give comments about the potential change in MdeModulePkg.

Thanks,
Star
-----Original Message-----
From: Justen, Jordan L 
Sent: Tuesday, June 6, 2017 9:12 AM
To: Brijesh Singh <brijesh.singh@amd.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>
Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>; leo.duran@amd.com; Yao, Jiewen <jiewen.yao@intel.com>; Fan, Jeff <jeff.fan@intel.com>
Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)

On 2017-06-05 14:56:04, Brijesh Singh wrote:
> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
> > On 06/01/17 09:40, Jordan Justen wrote:
> >> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
> >> Leo said that DxeIpl won't work because new I/O ranges might be added.
> >> I don't understand this, because isn't DxeIpl and an early APRIORI 
> >> entry are roughly equivalent in the boot sequence?
> > 
> > I think you are right. I believe a patch for this exact idea hasn't 
> > been posted yet. Jiewen's message that you linked above contains the 
> > expression
> > 
> >      always clear SEV mask for MMIO *and all rest*
> > 
> > (emphasis mine), which I think we may have missed *in combination 
> > with* the DxeIpl.
> > 
> > So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
> > Keep the C bit set for system memory regions. Clear the C bit for 
> > MMIO regions that are known from the HOB list. Also clear the C bit 
> > everywhere else in the address space (known from the CPU HOB) where 
> > no coverage is provided by any memory resource descriptor HOB.
> > 
> > This is going to be harder than the current approach, because:
> > 
> > - The current approach can work off of the GCD memory space map, 
> > which provides explicit NonExistent entries, covering the entire 
> > address space (according to the CPU HOB).
> > 
> > - However, the DxeIpl method would take place before entering DXE, 
> > so no GCD memory space map would be available -- the "NonExistent" 
> > entries would have to be synthesized manually from the address space 
> > size (known from the CPU HOB) and the lack of coverage by memory 
> > resource descriptor HOBs.
> > 
> > Basically, in order to move the current GCD memory space map 
> > traversal from early DXE to late PEI, the memory space map building 
> > logic of the DXE Core would have to be duplicated in the DxeIpl 
> > PEIM. If I understand correctly. (The DxeIpl PEIM may already 
> > contain very similar code, for the page table building, which might 
> > not be difficult to extend like this -- I haven't looked.)
> > 
> > Is this what you have in mind?
> > 
> 
> Do you have any further thought on this?

Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)

As far as I can see, this is an architecturally defined AMD feature.
(Is this true, or is BaseMemcryptSevLib actually OVMF specific?)

You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
IA32/X64 specific code. (I'm recalling
881813d7a93d9009c873515b043c41c4554779e4.)

Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.

I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.

> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to 
> see if I can invoke a platform dependent library to clear C-bit before 
> DxeMain finishes its execution. As Laszlo pointed, current approach is 
> using GCD memory space map to get MMIO and NonExistent entries. I have 
> pushed two patches in my development branch to show what I have been doing:
> 
> 1) add a new null DxeGcdCorePlatformHookLib
> 
> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
> a920d7ad72d
> 
> The library provides a function "DxeGcdCorePlatformHookReady" which 
> can be called by DxeMain just after it initializes the GcdServices 
> (which will guarantee that Gcd memory space map is available).

Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)

-Jordan

> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>   SEV is detected.
> 
> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
> 3c95949f659
> 
> I've tested the approach and it seems to work. Is this something 
> aligned with your thinking?
> 
> 
> > Thanks
> > Laszlo
> > 
> >> -Jordan
> >>
> >>> In second patch
> >>> [2], Leo tried to introduce a new notify protocol to get MMIO 
> >>> add/remove events. During discussion Jiewen suggested to look into 
> >>> adding a new platform driver into APRIORI to avoid the need for 
> >>> any modifications inside the Gcdcore - this seems workable 
> >>> solution which did not require adding any CPU specific code inside the Gcd.
> >>>
> >>> [1] 
> >>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
> >>> [2] 
> >>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
> >>>
> > 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06  2:08                 ` Zeng, Star
@ 2017-06-06  3:50                   ` Brijesh Singh
  2017-06-06 14:54                     ` Yao, Jiewen
  0 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-06-06  3:50 UTC (permalink / raw)
  To: Zeng, Star, Justen, Jordan L, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric, Yao, Jiewen
  Cc: Thomas.Lendacky@amd.com, Gao, Liming, leo.duran@amd.com,
	Fan, Jeff

Hi Jordan,


On 6/5/17 9:08 PM, Zeng, Star wrote:
> I was not tracking this thread.
> Jiewen will help give comments about the potential change in MdeModulePkg.
>
> Thanks,
> Star
> -----Original Message-----
> From: Justen, Jordan L 
> Sent: Tuesday, June 6, 2017 9:12 AM
> To: Brijesh Singh <brijesh.singh@amd.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Zeng, Star <star.zeng@intel.com>; Dong, Eric <eric.dong@intel.com>
> Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>; leo.duran@amd.com; Yao, Jiewen <jiewen.yao@intel.com>; Fan, Jeff <jeff.fan@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>
> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>> I don't understand this, because isn't DxeIpl and an early APRIORI 
>>>> entry are roughly equivalent in the boot sequence?
>>> I think you are right. I believe a patch for this exact idea hasn't 
>>> been posted yet. Jiewen's message that you linked above contains the 
>>> expression
>>>
>>>      always clear SEV mask for MMIO *and all rest*
>>>
>>> (emphasis mine), which I think we may have missed *in combination 
>>> with* the DxeIpl.
>>>
>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>> Keep the C bit set for system memory regions. Clear the C bit for 
>>> MMIO regions that are known from the HOB list. Also clear the C bit 
>>> everywhere else in the address space (known from the CPU HOB) where 
>>> no coverage is provided by any memory resource descriptor HOB.
>>>
>>> This is going to be harder than the current approach, because:
>>>
>>> - The current approach can work off of the GCD memory space map, 
>>> which provides explicit NonExistent entries, covering the entire 
>>> address space (according to the CPU HOB).
>>>
>>> - However, the DxeIpl method would take place before entering DXE, 
>>> so no GCD memory space map would be available -- the "NonExistent" 
>>> entries would have to be synthesized manually from the address space 
>>> size (known from the CPU HOB) and the lack of coverage by memory 
>>> resource descriptor HOBs.
>>>
>>> Basically, in order to move the current GCD memory space map 
>>> traversal from early DXE to late PEI, the memory space map building 
>>> logic of the DXE Core would have to be duplicated in the DxeIpl 
>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already 
>>> contain very similar code, for the page table building, which might 
>>> not be difficult to extend like this -- I haven't looked.)
>>>
>>> Is this what you have in mind?
>>>
>> Do you have any further thought on this?
> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>
> As far as I can see, this is an architecturally defined AMD feature.
> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)

Yes, SEV is AMD-V architecture extension and its applicable to
virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
specific).
> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
> IA32/X64 specific code. (I'm recalling
> 881813d7a93d9009c873515b043c41c4554779e4.)
>
> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>
> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.

I am flexible to implement APRIORI or Platform hooks Lib. But one thing
I want to highlight is: I'll prefer clearing C-bit  through
BaseMemEncryptSevLib functions. One of the main reason for doing so - In
future when we add migration support for the SEV guest then we will be
required to notify the unencrypted page range to hypevisor ( through
hypercall). During migration phase, Hypervisor will use this information
to make decision on whether to invoke the SEV firmware to encrypt the
memory region for transport purposes. If clearing C-bit logic is
contained inside BaseMemEncryptSevLib then it will make life much easier.

>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to 
>> see if I can invoke a platform dependent library to clear C-bit before 
>> DxeMain finishes its execution. As Laszlo pointed, current approach is 
>> using GCD memory space map to get MMIO and NonExistent entries. I have 
>> pushed two patches in my development branch to show what I have been doing:
>>
>> 1) add a new null DxeGcdCorePlatformHookLib
>>
>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>> a920d7ad72d
>>
>> The library provides a function "DxeGcdCorePlatformHookReady" which 
>> can be called by DxeMain just after it initializes the GcdServices 
>> (which will guarantee that Gcd memory space map is available).
> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)

Jiewen, any comments ?

> -Jordan
>
>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>   SEV is detected.
>>
>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>> 3c95949f659
>>
>> I've tested the approach and it seems to work. Is this something 
>> aligned with your thinking?
>>
>>
>>> Thanks
>>> Laszlo
>>>
>>>> -Jordan
>>>>
>>>>> In second patch
>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO 
>>>>> add/remove events. During discussion Jiewen suggested to look into 
>>>>> adding a new platform driver into APRIORI to avoid the need for 
>>>>> any modifications inside the Gcdcore - this seems workable 
>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>
>>>>> [1] 
>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>> [2] 
>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org
>> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06  3:50                   ` Brijesh Singh
@ 2017-06-06 14:54                     ` Yao, Jiewen
  2017-06-06 15:24                       ` Andrew Fish
  2017-06-06 18:29                       ` Laszlo Ersek
  0 siblings, 2 replies; 65+ messages in thread
From: Yao, Jiewen @ 2017-06-06 14:54 UTC (permalink / raw)
  To: Brijesh Singh, Zeng, Star, Justen, Jordan L, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric
  Cc: Thomas.Lendacky@amd.com, Gao, Liming, leo.duran@amd.com,
	Fan, Jeff, Yao, Jiewen

Hi
It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below

1)       In DxeIpl, when it builds page table.

2)       In DxeCore

a)         By use CpuArch

b)         By use page table lib

c)         By use a GCD update callback

d)         By use PlatformHook lib

3)       In a standalone AmdSev driver.

Here is my thought:
2.a) is not possible, per Leo’s investigation.
2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.

1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.

If 1) cannot be chosen, I still think 3) is the best idea.
It makes the code very clean by introducing a standalone driver to resolve the problem.
Zero impact on existing platform.
If this feature is not needed, just remove the driver.

I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.

Thank you
Yao Jiewen



From: Brijesh Singh [mailto:brijesh.singh@amd.com]
Sent: Tuesday, June 6, 2017 11:51 AM
To: Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>; leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>
Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)

Hi Jordan,


On 6/5/17 9:08 PM, Zeng, Star wrote:
> I was not tracking this thread.
> Jiewen will help give comments about the potential change in MdeModulePkg.
>
> Thanks,
> Star
> -----Original Message-----
> From: Justen, Jordan L
> Sent: Tuesday, June 6, 2017 9:12 AM
> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>
> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>
> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>> entry are roughly equivalent in the boot sequence?
>>> I think you are right. I believe a patch for this exact idea hasn't
>>> been posted yet. Jiewen's message that you linked above contains the
>>> expression
>>>
>>>      always clear SEV mask for MMIO *and all rest*
>>>
>>> (emphasis mine), which I think we may have missed *in combination
>>> with* the DxeIpl.
>>>
>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>> Keep the C bit set for system memory regions. Clear the C bit for
>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>> everywhere else in the address space (known from the CPU HOB) where
>>> no coverage is provided by any memory resource descriptor HOB.
>>>
>>> This is going to be harder than the current approach, because:
>>>
>>> - The current approach can work off of the GCD memory space map,
>>> which provides explicit NonExistent entries, covering the entire
>>> address space (according to the CPU HOB).
>>>
>>> - However, the DxeIpl method would take place before entering DXE,
>>> so no GCD memory space map would be available -- the "NonExistent"
>>> entries would have to be synthesized manually from the address space
>>> size (known from the CPU HOB) and the lack of coverage by memory
>>> resource descriptor HOBs.
>>>
>>> Basically, in order to move the current GCD memory space map
>>> traversal from early DXE to late PEI, the memory space map building
>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>> contain very similar code, for the page table building, which might
>>> not be difficult to extend like this -- I haven't looked.)
>>>
>>> Is this what you have in mind?
>>>
>> Do you have any further thought on this?
> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>
> As far as I can see, this is an architecturally defined AMD feature.
> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)

Yes, SEV is AMD-V architecture extension and its applicable to
virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
specific).
> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
> IA32/X64 specific code. (I'm recalling
> 881813d7a93d9009c873515b043c41c4554779e4.)
>
> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>
> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.

I am flexible to implement APRIORI or Platform hooks Lib. But one thing
I want to highlight is: I'll prefer clearing C-bit  through
BaseMemEncryptSevLib functions. One of the main reason for doing so - In
future when we add migration support for the SEV guest then we will be
required to notify the unencrypted page range to hypevisor ( through
hypercall). During migration phase, Hypervisor will use this information
to make decision on whether to invoke the SEV firmware to encrypt the
memory region for transport purposes. If clearing C-bit logic is
contained inside BaseMemEncryptSevLib then it will make life much easier.

>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>> see if I can invoke a platform dependent library to clear C-bit before
>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>> using GCD memory space map to get MMIO and NonExistent entries. I have
>> pushed two patches in my development branch to show what I have been doing:
>>
>> 1) add a new null DxeGcdCorePlatformHookLib
>>
>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>> a920d7ad72d
>>
>> The library provides a function "DxeGcdCorePlatformHookReady" which
>> can be called by DxeMain just after it initializes the GcdServices
>> (which will guarantee that Gcd memory space map is available).
> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)

Jiewen, any comments ?

> -Jordan
>
>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>   SEV is detected.
>>
>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>> 3c95949f659
>>
>> I've tested the approach and it seems to work. Is this something
>> aligned with your thinking?
>>
>>
>>> Thanks
>>> Laszlo
>>>
>>>> -Jordan
>>>>
>>>>> In second patch
>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>> any modifications inside the Gcdcore - this seems workable
>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>
>>>>> [1]
>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>> [2]
>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06 14:54                     ` Yao, Jiewen
@ 2017-06-06 15:24                       ` Andrew Fish
  2017-06-06 15:43                         ` Yao, Jiewen
  2017-06-06 18:29                       ` Laszlo Ersek
  1 sibling, 1 reply; 65+ messages in thread
From: Andrew Fish @ 2017-06-06 15:24 UTC (permalink / raw)
  To: Yao, Jiewen
  Cc: Brijesh Singh, Zeng, Star, Jordan Justen, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric, Thomas.Lendacky@amd.com,
	leo.duran@amd.com, Fan, Jeff, Gao, Liming


> On Jun 6, 2017, at 7:54 AM, Yao, Jiewen <jiewen.yao@intel.com> wrote:
> 
> Hi
> It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below
> 
> 1)       In DxeIpl, when it builds page table.
> 
> 2)       In DxeCore
> 
> a)         By use CpuArch
> 
> b)         By use page table lib
> 
> c)         By use a GCD update callback
> 
> d)         By use PlatformHook lib
> 
> 3)       In a standalone AmdSev driver.
> 
> Here is my thought:
> 2.a) is not possible, per Leo’s investigation.
> 2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
> 2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.
> 
> 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.
> 
> If 1) cannot be chosen, I still think 3) is the best idea.
> It makes the code very clean by introducing a standalone driver to resolve the problem.
> Zero impact on existing platform.
> If this feature is not needed, just remove the driver.
> 
> I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.
> 

Jiewen,

I agree that "a priori" is part of the architecture so it is OK to use it, but "a priori" was never really intended as a way to add basic features. it was more for debugging and work arounds. It seems like a feature like this should not require a work around....

'So I think it is OK to accept this patch to get the feature enabled, but we need to look at the GCD implementation and PI architecture to figure out why there is not a cleaner way to add this feature. Maybe we need to change the implementation, and/or the PI Spec?

Thanks,

Andrew Fish

> Thank you
> Yao Jiewen
> 
> 
> 
> From: Brijesh Singh [mailto:brijesh.singh@amd.com]
> Sent: Tuesday, June 6, 2017 11:51 AM
> To: Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>; leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
> 
> Hi Jordan,
> 
> 
> On 6/5/17 9:08 PM, Zeng, Star wrote:
>> I was not tracking this thread.
>> Jiewen will help give comments about the potential change in MdeModulePkg.
>> 
>> Thanks,
>> Star
>> -----Original Message-----
>> From: Justen, Jordan L
>> Sent: Tuesday, June 6, 2017 9:12 AM
>> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>> 
>> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>>> entry are roughly equivalent in the boot sequence?
>>>> I think you are right. I believe a patch for this exact idea hasn't
>>>> been posted yet. Jiewen's message that you linked above contains the
>>>> expression
>>>> 
>>>>     always clear SEV mask for MMIO *and all rest*
>>>> 
>>>> (emphasis mine), which I think we may have missed *in combination
>>>> with* the DxeIpl.
>>>> 
>>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>>> Keep the C bit set for system memory regions. Clear the C bit for
>>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>>> everywhere else in the address space (known from the CPU HOB) where
>>>> no coverage is provided by any memory resource descriptor HOB.
>>>> 
>>>> This is going to be harder than the current approach, because:
>>>> 
>>>> - The current approach can work off of the GCD memory space map,
>>>> which provides explicit NonExistent entries, covering the entire
>>>> address space (according to the CPU HOB).
>>>> 
>>>> - However, the DxeIpl method would take place before entering DXE,
>>>> so no GCD memory space map would be available -- the "NonExistent"
>>>> entries would have to be synthesized manually from the address space
>>>> size (known from the CPU HOB) and the lack of coverage by memory
>>>> resource descriptor HOBs.
>>>> 
>>>> Basically, in order to move the current GCD memory space map
>>>> traversal from early DXE to late PEI, the memory space map building
>>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>>> contain very similar code, for the page table building, which might
>>>> not be difficult to extend like this -- I haven't looked.)
>>>> 
>>>> Is this what you have in mind?
>>>> 
>>> Do you have any further thought on this?
>> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>> 
>> As far as I can see, this is an architecturally defined AMD feature.
>> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
> 
> Yes, SEV is AMD-V architecture extension and its applicable to
> virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
> specific).
>> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
>> IA32/X64 specific code. (I'm recalling
>> 881813d7a93d9009c873515b043c41c4554779e4.)
>> 
>> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>> 
>> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.
> 
> I am flexible to implement APRIORI or Platform hooks Lib. But one thing
> I want to highlight is: I'll prefer clearing C-bit  through
> BaseMemEncryptSevLib functions. One of the main reason for doing so - In
> future when we add migration support for the SEV guest then we will be
> required to notify the unencrypted page range to hypevisor ( through
> hypercall). During migration phase, Hypervisor will use this information
> to make decision on whether to invoke the SEV firmware to encrypt the
> memory region for transport purposes. If clearing C-bit logic is
> contained inside BaseMemEncryptSevLib then it will make life much easier.
> 
>>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>>> see if I can invoke a platform dependent library to clear C-bit before
>>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>>> using GCD memory space map to get MMIO and NonExistent entries. I have
>>> pushed two patches in my development branch to show what I have been doing:
>>> 
>>> 1) add a new null DxeGcdCorePlatformHookLib
>>> 
>>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>>> a920d7ad72d
>>> 
>>> The library provides a function "DxeGcdCorePlatformHookReady" which
>>> can be called by DxeMain just after it initializes the GcdServices
>>> (which will guarantee that Gcd memory space map is available).
>> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)
> 
> Jiewen, any comments ?
> 
>> -Jordan
>> 
>>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>>  SEV is detected.
>>> 
>>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>>> 3c95949f659
>>> 
>>> I've tested the approach and it seems to work. Is this something
>>> aligned with your thinking?
>>> 
>>> 
>>>> Thanks
>>>> Laszlo
>>>> 
>>>>> -Jordan
>>>>> 
>>>>>> In second patch
>>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>>> any modifications inside the Gcdcore - this seems workable
>>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>> 
>>>>>> [1]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>>> [2]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>> 
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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:38                           ` Laszlo Ersek
  0 siblings, 2 replies; 65+ messages in thread
From: Yao, Jiewen @ 2017-06-06 15:43 UTC (permalink / raw)
  To: afish@apple.com
  Cc: Brijesh Singh, Zeng, Star, Justen, Jordan L, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric, Thomas.Lendacky@amd.com,
	leo.duran@amd.com, Fan, Jeff, Gao, Liming, Yao, Jiewen

Hi Andrew
Yes, I agree. If we could figure out a cleaner way to resolve the problem, we should use the cleaner way.



If we really really do not want to use a priori for AmdSec, we can let AmdSec to publish a special protocol, and let the driver depend that protocol, if this driver need add MMIO region.
Because AmdSec is inside of OvmfPkg, this special protocol can be in OvmfPkg.

That is just another option.

Thank you
Yao Jiewen

From: afish@apple.com [mailto:afish@apple.com]
Sent: Tuesday, June 6, 2017 11:25 PM
To: Yao, Jiewen <jiewen.yao@intel.com>
Cc: Brijesh Singh <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Thomas.Lendacky@amd.com; leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>; Gao, Liming <liming.gao@intel.com>
Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)


> On Jun 6, 2017, at 7:54 AM, Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>> wrote:
>
> Hi
> It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below
>
> 1)       In DxeIpl, when it builds page table.
>
> 2)       In DxeCore
>
> a)         By use CpuArch
>
> b)         By use page table lib
>
> c)         By use a GCD update callback
>
> d)         By use PlatformHook lib
>
> 3)       In a standalone AmdSev driver.
>
> Here is my thought:
> 2.a) is not possible, per Leo’s investigation.
> 2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
> 2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.
>
> 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.
>
> If 1) cannot be chosen, I still think 3) is the best idea.
> It makes the code very clean by introducing a standalone driver to resolve the problem.
> Zero impact on existing platform.
> If this feature is not needed, just remove the driver.
>
> I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.
>

Jiewen,

I agree that "a priori" is part of the architecture so it is OK to use it, but "a priori" was never really intended as a way to add basic features. it was more for debugging and work arounds. It seems like a feature like this should not require a work around....

'So I think it is OK to accept this patch to get the feature enabled, but we need to look at the GCD implementation and PI architecture to figure out why there is not a cleaner way to add this feature. Maybe we need to change the implementation, and/or the PI Spec?

Thanks,

Andrew Fish

> Thank you
> Yao Jiewen
>
>
>
> From: Brijesh Singh [mailto:brijesh.singh@amd.com]
> Sent: Tuesday, June 6, 2017 11:51 AM
> To: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>
> Hi Jordan,
>
>
> On 6/5/17 9:08 PM, Zeng, Star wrote:
>> I was not tracking this thread.
>> Jiewen will help give comments about the potential change in MdeModulePkg.
>>
>> Thanks,
>> Star
>> -----Original Message-----
>> From: Justen, Jordan L
>> Sent: Tuesday, June 6, 2017 9:12 AM
>> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com<mailto:brijesh.singh@amd.com%3cmailto:brijesh.singh@amd.com>>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>
>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com%3cmailto:Thomas.Lendacky@amd.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; leo.duran@amd.com<mailto:leo.duran@amd.com<mailto:leo.duran@amd.com%3cmailto:leo.duran@amd.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com<mailto:jeff.fan@intel.com%3cmailto:jeff.fan@intel.com>>>
>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>>
>> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>>> entry are roughly equivalent in the boot sequence?
>>>> I think you are right. I believe a patch for this exact idea hasn't
>>>> been posted yet. Jiewen's message that you linked above contains the
>>>> expression
>>>>
>>>>     always clear SEV mask for MMIO *and all rest*
>>>>
>>>> (emphasis mine), which I think we may have missed *in combination
>>>> with* the DxeIpl.
>>>>
>>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>>> Keep the C bit set for system memory regions. Clear the C bit for
>>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>>> everywhere else in the address space (known from the CPU HOB) where
>>>> no coverage is provided by any memory resource descriptor HOB.
>>>>
>>>> This is going to be harder than the current approach, because:
>>>>
>>>> - The current approach can work off of the GCD memory space map,
>>>> which provides explicit NonExistent entries, covering the entire
>>>> address space (according to the CPU HOB).
>>>>
>>>> - However, the DxeIpl method would take place before entering DXE,
>>>> so no GCD memory space map would be available -- the "NonExistent"
>>>> entries would have to be synthesized manually from the address space
>>>> size (known from the CPU HOB) and the lack of coverage by memory
>>>> resource descriptor HOBs.
>>>>
>>>> Basically, in order to move the current GCD memory space map
>>>> traversal from early DXE to late PEI, the memory space map building
>>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>>> contain very similar code, for the page table building, which might
>>>> not be difficult to extend like this -- I haven't looked.)
>>>>
>>>> Is this what you have in mind?
>>>>
>>> Do you have any further thought on this?
>> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>>
>> As far as I can see, this is an architecturally defined AMD feature.
>> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
>
> Yes, SEV is AMD-V architecture extension and its applicable to
> virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
> specific).
>> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
>> IA32/X64 specific code. (I'm recalling
>> 881813d7a93d9009c873515b043c41c4554779e4.)
>>
>> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>>
>> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.
>
> I am flexible to implement APRIORI or Platform hooks Lib. But one thing
> I want to highlight is: I'll prefer clearing C-bit  through
> BaseMemEncryptSevLib functions. One of the main reason for doing so - In
> future when we add migration support for the SEV guest then we will be
> required to notify the unencrypted page range to hypevisor ( through
> hypercall). During migration phase, Hypervisor will use this information
> to make decision on whether to invoke the SEV firmware to encrypt the
> memory region for transport purposes. If clearing C-bit logic is
> contained inside BaseMemEncryptSevLib then it will make life much easier.
>
>>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>>> see if I can invoke a platform dependent library to clear C-bit before
>>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>>> using GCD memory space map to get MMIO and NonExistent entries. I have
>>> pushed two patches in my development branch to show what I have been doing:
>>>
>>> 1) add a new null DxeGcdCorePlatformHookLib
>>>
>>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>>> a920d7ad72d
>>>
>>> The library provides a function "DxeGcdCorePlatformHookReady" which
>>> can be called by DxeMain just after it initializes the GcdServices
>>> (which will guarantee that Gcd memory space map is available).
>> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)
>
> Jiewen, any comments ?
>
>> -Jordan
>>
>>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>>  SEV is detected.
>>>
>>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>>> 3c95949f659
>>>
>>> I've tested the approach and it seems to work. Is this something
>>> aligned with your thinking?
>>>
>>>
>>>> Thanks
>>>> Laszlo
>>>>
>>>>> -Jordan
>>>>>
>>>>>> In second patch
>>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>>> any modifications inside the Gcdcore - this seems workable
>>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>>
>>>>>> [1]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>>> [2]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>>
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  1 sibling, 1 reply; 65+ messages in thread
From: Duran, Leo @ 2017-06-06 15:54 UTC (permalink / raw)
  To: 'Yao, Jiewen', afish@apple.com
  Cc: Singh, Brijesh, Zeng, Star, Justen, Jordan L, Laszlo Ersek,
	edk2-devel@lists.01.org, Dong, Eric, Lendacky, Thomas, Fan, Jeff,
	Gao, Liming

Thank you all for the feedback… The summary of what I’m hearing is:

1)      For now, use APRIORI in the stand-alone (SEV) driver in OvmfPkg (albeit not as clean as desired, but least intrusive solution.).

2)      Let’s revisit the existing GCD implementation to allow for cleaner of features like this.

Leo.


From: Yao, Jiewen [mailto:jiewen.yao@intel.com]
Sent: Tuesday, June 06, 2017 10:43 AM
To: afish@apple.com
Cc: Singh, Brijesh <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Lendacky, Thomas <Thomas.Lendacky@amd.com>; Duran, Leo <leo.duran@amd.com>; Fan, Jeff <jeff.fan@intel.com>; Gao, Liming <liming.gao@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
Subject: RE: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)

Hi Andrew
Yes, I agree. If we could figure out a cleaner way to resolve the problem, we should use the cleaner way.



If we really really do not want to use a priori for AmdSec, we can let AmdSec to publish a special protocol, and let the driver depend that protocol, if this driver need add MMIO region.
Because AmdSec is inside of OvmfPkg, this special protocol can be in OvmfPkg.

That is just another option.

Thank you
Yao Jiewen

From: afish@apple.com<mailto:afish@apple.com> [mailto:afish@apple.com]
Sent: Tuesday, June 6, 2017 11:25 PM
To: Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
Cc: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>
Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)


> On Jun 6, 2017, at 7:54 AM, Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>> wrote:
>
> Hi
> It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below
>
> 1)       In DxeIpl, when it builds page table.
>
> 2)       In DxeCore
>
> a)         By use CpuArch
>
> b)         By use page table lib
>
> c)         By use a GCD update callback
>
> d)         By use PlatformHook lib
>
> 3)       In a standalone AmdSev driver.
>
> Here is my thought:
> 2.a) is not possible, per Leo’s investigation.
> 2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
> 2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.
>
> 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.
>
> If 1) cannot be chosen, I still think 3) is the best idea.
> It makes the code very clean by introducing a standalone driver to resolve the problem.
> Zero impact on existing platform.
> If this feature is not needed, just remove the driver.
>
> I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.
>

Jiewen,

I agree that "a priori" is part of the architecture so it is OK to use it, but "a priori" was never really intended as a way to add basic features. it was more for debugging and work arounds. It seems like a feature like this should not require a work around....

'So I think it is OK to accept this patch to get the feature enabled, but we need to look at the GCD implementation and PI architecture to figure out why there is not a cleaner way to add this feature. Maybe we need to change the implementation, and/or the PI Spec?

Thanks,

Andrew Fish

> Thank you
> Yao Jiewen
>
>
>
> From: Brijesh Singh [mailto:brijesh.singh@amd.com]
> Sent: Tuesday, June 6, 2017 11:51 AM
> To: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>
> Hi Jordan,
>
>
> On 6/5/17 9:08 PM, Zeng, Star wrote:
>> I was not tracking this thread.
>> Jiewen will help give comments about the potential change in MdeModulePkg.
>>
>> Thanks,
>> Star
>> -----Original Message-----
>> From: Justen, Jordan L
>> Sent: Tuesday, June 6, 2017 9:12 AM
>> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com<mailto:brijesh.singh@amd.com%3cmailto:brijesh.singh@amd.com>>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>
>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com%3cmailto:Thomas.Lendacky@amd.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; leo.duran@amd.com<mailto:leo.duran@amd.com<mailto:leo.duran@amd.com%3cmailto:leo.duran@amd.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com<mailto:jeff.fan@intel.com%3cmailto:jeff.fan@intel.com>>>
>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>>
>> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>>> entry are roughly equivalent in the boot sequence?
>>>> I think you are right. I believe a patch for this exact idea hasn't
>>>> been posted yet. Jiewen's message that you linked above contains the
>>>> expression
>>>>
>>>>     always clear SEV mask for MMIO *and all rest*
>>>>
>>>> (emphasis mine), which I think we may have missed *in combination
>>>> with* the DxeIpl.
>>>>
>>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>>> Keep the C bit set for system memory regions. Clear the C bit for
>>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>>> everywhere else in the address space (known from the CPU HOB) where
>>>> no coverage is provided by any memory resource descriptor HOB.
>>>>
>>>> This is going to be harder than the current approach, because:
>>>>
>>>> - The current approach can work off of the GCD memory space map,
>>>> which provides explicit NonExistent entries, covering the entire
>>>> address space (according to the CPU HOB).
>>>>
>>>> - However, the DxeIpl method would take place before entering DXE,
>>>> so no GCD memory space map would be available -- the "NonExistent"
>>>> entries would have to be synthesized manually from the address space
>>>> size (known from the CPU HOB) and the lack of coverage by memory
>>>> resource descriptor HOBs.
>>>>
>>>> Basically, in order to move the current GCD memory space map
>>>> traversal from early DXE to late PEI, the memory space map building
>>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>>> contain very similar code, for the page table building, which might
>>>> not be difficult to extend like this -- I haven't looked.)
>>>>
>>>> Is this what you have in mind?
>>>>
>>> Do you have any further thought on this?
>> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>>
>> As far as I can see, this is an architecturally defined AMD feature.
>> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
>
> Yes, SEV is AMD-V architecture extension and its applicable to
> virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
> specific).
>> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
>> IA32/X64 specific code. (I'm recalling
>> 881813d7a93d9009c873515b043c41c4554779e4.)
>>
>> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>>
>> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.
>
> I am flexible to implement APRIORI or Platform hooks Lib. But one thing
> I want to highlight is: I'll prefer clearing C-bit  through
> BaseMemEncryptSevLib functions. One of the main reason for doing so - In
> future when we add migration support for the SEV guest then we will be
> required to notify the unencrypted page range to hypevisor ( through
> hypercall). During migration phase, Hypervisor will use this information
> to make decision on whether to invoke the SEV firmware to encrypt the
> memory region for transport purposes. If clearing C-bit logic is
> contained inside BaseMemEncryptSevLib then it will make life much easier.
>
>>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>>> see if I can invoke a platform dependent library to clear C-bit before
>>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>>> using GCD memory space map to get MMIO and NonExistent entries. I have
>>> pushed two patches in my development branch to show what I have been doing:
>>>
>>> 1) add a new null DxeGcdCorePlatformHookLib
>>>
>>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>>> a920d7ad72d
>>>
>>> The library provides a function "DxeGcdCorePlatformHookReady" which
>>> can be called by DxeMain just after it initializes the GcdServices
>>> (which will guarantee that Gcd memory space map is available).
>> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)
>
> Jiewen, any comments ?
>
>> -Jordan
>>
>>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>>  SEV is detected.
>>>
>>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>>> 3c95949f659
>>>
>>> I've tested the approach and it seems to work. Is this something
>>> aligned with your thinking?
>>>
>>>
>>>> Thanks
>>>> Laszlo
>>>>
>>>>> -Jordan
>>>>>
>>>>>> In second patch
>>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>>> any modifications inside the Gcdcore - this seems workable
>>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>>
>>>>>> [1]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>>> [2]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>>
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
>>> https://lists.01.org/mailman/listinfo/edk2-devel
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> https://lists.01.org/mailman/listinfo/edk2-devel

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06 14:54                     ` Yao, Jiewen
  2017-06-06 15:24                       ` Andrew Fish
@ 2017-06-06 18:29                       ` Laszlo Ersek
  2017-06-06 18:57                         ` Duran, Leo
  1 sibling, 1 reply; 65+ messages in thread
From: Laszlo Ersek @ 2017-06-06 18:29 UTC (permalink / raw)
  To: Yao, Jiewen, Brijesh Singh, Zeng, Star, Justen, Jordan L,
	edk2-devel@lists.01.org, Dong, Eric
  Cc: Thomas.Lendacky@amd.com, Gao, Liming, leo.duran@amd.com,
	Fan, Jeff

On 06/06/17 16:54, Yao, Jiewen wrote:
> Hi
> It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below
> 
> 1)       In DxeIpl, when it builds page table.
> 
> 2)       In DxeCore
> 
> a)         By use CpuArch
> 
> b)         By use page table lib
> 
> c)         By use a GCD update callback
> 
> d)         By use PlatformHook lib
> 
> 3)       In a standalone AmdSev driver.
> 
> Here is my thought:
> 2.a) is not possible, per Leo’s investigation.
> 2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
> 2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.
> 
> 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.

I think that implementing the logic in the DXE IPL PEIM will be more
difficult than doing the same somewhere in the DXE phase. But, I
wouldn't oppose the idea. The implementation difficulty is not for me to
overcome: it affects Brijesh and Leo (as the implementors) and the DXE
IPL PEIM maintainers (in review).

NB, Brijesh mentioned up-thread that wherever (= in whichever firmware
phase) they massaged the C-bit, they'd like to use BaseMemEncryptSevLib
for it, because that would help with live migrating VMs. I can't say
off-hand whether the current library instance is appropriate for use in
the DXE IPL PEIM -- for example: repeated memory allocation and freeing
isn't very good for PEIMs, since no freeing occurs in PEI --, so that's
something for Brijesh & Leo to evaluate.

Anyhow, if the DXE IPL PEIM approach can be made work, technically, then
I'm 100% fine with it personally.

Thanks
Laszlo

> 
> If 1) cannot be chosen, I still think 3) is the best idea.
> It makes the code very clean by introducing a standalone driver to resolve the problem.
> Zero impact on existing platform.
> If this feature is not needed, just remove the driver.
> 
> I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.
> 
> Thank you
> Yao Jiewen
> 
> 
> 
> From: Brijesh Singh [mailto:brijesh.singh@amd.com]
> Sent: Tuesday, June 6, 2017 11:51 AM
> To: Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Yao, Jiewen <jiewen.yao@intel.com>
> Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>; leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
> 
> Hi Jordan,
> 
> 
> On 6/5/17 9:08 PM, Zeng, Star wrote:
>> I was not tracking this thread.
>> Jiewen will help give comments about the potential change in MdeModulePkg.
>>
>> Thanks,
>> Star
>> -----Original Message-----
>> From: Justen, Jordan L
>> Sent: Tuesday, June 6, 2017 9:12 AM
>> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>
>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>>
>> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>>> entry are roughly equivalent in the boot sequence?
>>>> I think you are right. I believe a patch for this exact idea hasn't
>>>> been posted yet. Jiewen's message that you linked above contains the
>>>> expression
>>>>
>>>>      always clear SEV mask for MMIO *and all rest*
>>>>
>>>> (emphasis mine), which I think we may have missed *in combination
>>>> with* the DxeIpl.
>>>>
>>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>>> Keep the C bit set for system memory regions. Clear the C bit for
>>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>>> everywhere else in the address space (known from the CPU HOB) where
>>>> no coverage is provided by any memory resource descriptor HOB.
>>>>
>>>> This is going to be harder than the current approach, because:
>>>>
>>>> - The current approach can work off of the GCD memory space map,
>>>> which provides explicit NonExistent entries, covering the entire
>>>> address space (according to the CPU HOB).
>>>>
>>>> - However, the DxeIpl method would take place before entering DXE,
>>>> so no GCD memory space map would be available -- the "NonExistent"
>>>> entries would have to be synthesized manually from the address space
>>>> size (known from the CPU HOB) and the lack of coverage by memory
>>>> resource descriptor HOBs.
>>>>
>>>> Basically, in order to move the current GCD memory space map
>>>> traversal from early DXE to late PEI, the memory space map building
>>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>>> contain very similar code, for the page table building, which might
>>>> not be difficult to extend like this -- I haven't looked.)
>>>>
>>>> Is this what you have in mind?
>>>>
>>> Do you have any further thought on this?
>> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>>
>> As far as I can see, this is an architecturally defined AMD feature.
>> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
> 
> Yes, SEV is AMD-V architecture extension and its applicable to
> virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
> specific).
>> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
>> IA32/X64 specific code. (I'm recalling
>> 881813d7a93d9009c873515b043c41c4554779e4.)
>>
>> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>>
>> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.
> 
> I am flexible to implement APRIORI or Platform hooks Lib. But one thing
> I want to highlight is: I'll prefer clearing C-bit  through
> BaseMemEncryptSevLib functions. One of the main reason for doing so - In
> future when we add migration support for the SEV guest then we will be
> required to notify the unencrypted page range to hypevisor ( through
> hypercall). During migration phase, Hypervisor will use this information
> to make decision on whether to invoke the SEV firmware to encrypt the
> memory region for transport purposes. If clearing C-bit logic is
> contained inside BaseMemEncryptSevLib then it will make life much easier.
> 
>>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>>> see if I can invoke a platform dependent library to clear C-bit before
>>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>>> using GCD memory space map to get MMIO and NonExistent entries. I have
>>> pushed two patches in my development branch to show what I have been doing:
>>>
>>> 1) add a new null DxeGcdCorePlatformHookLib
>>>
>>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>>> a920d7ad72d
>>>
>>> The library provides a function "DxeGcdCorePlatformHookReady" which
>>> can be called by DxeMain just after it initializes the GcdServices
>>> (which will guarantee that Gcd memory space map is available).
>> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)
> 
> Jiewen, any comments ?
> 
>> -Jordan
>>
>>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>>   SEV is detected.
>>>
>>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>>> 3c95949f659
>>>
>>> I've tested the approach and it seems to work. Is this something
>>> aligned with your thinking?
>>>
>>>
>>>> Thanks
>>>> Laszlo
>>>>
>>>>> -Jordan
>>>>>
>>>>>> In second patch
>>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>>> any modifications inside the Gcdcore - this seems workable
>>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>>
>>>>>> [1]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>>> [2]
>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>>
>>> _______________________________________________
>>> edk2-devel mailing list
>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>>> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06 15:43                         ` Yao, Jiewen
  2017-06-06 15:54                           ` Duran, Leo
@ 2017-06-06 18:38                           ` Laszlo Ersek
  1 sibling, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-06-06 18:38 UTC (permalink / raw)
  To: Yao, Jiewen, afish@apple.com
  Cc: Brijesh Singh, Zeng, Star, Justen, Jordan L,
	edk2-devel@lists.01.org, Dong, Eric, Thomas.Lendacky@amd.com,
	leo.duran@amd.com, Fan, Jeff, Gao, Liming

On 06/06/17 17:43, Yao, Jiewen wrote:
> Hi Andrew
> Yes, I agree. If we could figure out a cleaner way to resolve the problem, we should use the cleaner way.
> 
> 
> 
> If we really really do not want to use a priori for AmdSec, we can
> let AmdSec to publish a special protocol, and let the driver depend
> that protocol, if this driver need add MMIO region. Because AmdSec is
> inside of OvmfPkg, this special protocol can be in OvmfPkg.
> 
> That is just another option.
We considered this approach before, and it is something that -- for a
change :) -- *I* happen to dislike.

My issue with this is that it doesn't scale. Assume that in a few months
we'd like to pull another driver from MdeModulePkg into the OVMF binary,
and that QEMU implemented emulation for that device. In virtual machines
without SEV, the driver could just work (we might have to set a few PCDs
for it, but that would be all). For making the driver work in SEV guests
however, we'd have to clone the driver to OvmfPkg, and add code to the
driver to explicitly use the special protocol. Not good. :(

Your suggestion is actually a variant of the IOMMU protocol. The IOMMU
protocol is different however, because PCI physical address space and
CPU physical address space are *already* different, and for this mapping
to work, all drivers that use PCI DMA must *already* use the IOMMU
protocol, even if they run on physical hardware, and even if they live
under MdeModulePkg. Therefore if we provide a SEV-specific IOMMU driver
in OvmfPkg, those PCI DMA drivers in MdeModulePkg will automatically
start using it; no change needed.

However, any drivers under MdeModulePkg (current and future) that use
MMIO directly, without going through PCI DMA, would have to be cloned
and modified in OvmfPkg.

Thanks
Laszlo


> 
> Thank you
> Yao Jiewen
> 
> From: afish@apple.com [mailto:afish@apple.com]
> Sent: Tuesday, June 6, 2017 11:25 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>
> Cc: Brijesh Singh <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>; Justen, Jordan L <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>; edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Thomas.Lendacky@amd.com; leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>; Gao, Liming <liming.gao@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
> 
> 
>> On Jun 6, 2017, at 7:54 AM, Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>> wrote:
>>
>> Hi
>> It takes me some time to read all email below. I believe all of us have a clean understanding on what problem we have now and the possible solutions to clear C bit are below
>>
>> 1)       In DxeIpl, when it builds page table.
>>
>> 2)       In DxeCore
>>
>> a)         By use CpuArch
>>
>> b)         By use page table lib
>>
>> c)         By use a GCD update callback
>>
>> d)         By use PlatformHook lib
>>
>> 3)       In a standalone AmdSev driver.
>>
>> Here is my thought:
>> 2.a) is not possible, per Leo’s investigation.
>> 2.b) is not a good design, because we do not introduce any Cpu Specific thing to DxeCore so far.
>> 2.c) and 2.d) are same. I do not suggest we add a private interface to the core just to support one specific feature.
>>
>> 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is too hard to implement, I am OK.
>>
>> If 1) cannot be chosen, I still think 3) is the best idea.
>> It makes the code very clean by introducing a standalone driver to resolve the problem.
>> Zero impact on existing platform.
>> If this feature is not needed, just remove the driver.
>>
>> I do not see any issue on using a priori, because: A) “a priori” is clearly defined in PI spec, B) “a priori” has already been widely used in current platform in EDKII open source, as well as close source platform.
>>
> 
> Jiewen,
> 
> I agree that "a priori" is part of the architecture so it is OK to use it, but "a priori" was never really intended as a way to add basic features. it was more for debugging and work arounds. It seems like a feature like this should not require a work around....
> 
> 'So I think it is OK to accept this patch to get the feature enabled, but we need to look at the GCD implementation and PI architecture to figure out why there is not a cleaner way to add this feature. Maybe we need to change the implementation, and/or the PI Spec?
> 
> Thanks,
> 
> Andrew Fish
> 
>> Thank you
>> Yao Jiewen
>>
>>
>>
>> From: Brijesh Singh [mailto:brijesh.singh@amd.com]
>> Sent: Tuesday, June 6, 2017 11:51 AM
>> To: Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Justen, Jordan L <jordan.l.justen@intel.com<mailto:jordan.l.justen@intel.com>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>
>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>; leo.duran@amd.com<mailto:leo.duran@amd.com>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>>
>> Hi Jordan,
>>
>>
>> On 6/5/17 9:08 PM, Zeng, Star wrote:
>>> I was not tracking this thread.
>>> Jiewen will help give comments about the potential change in MdeModulePkg.
>>>
>>> Thanks,
>>> Star
>>> -----Original Message-----
>>> From: Justen, Jordan L
>>> Sent: Tuesday, June 6, 2017 9:12 AM
>>> To: Brijesh Singh <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com<mailto:brijesh.singh@amd.com%3cmailto:brijesh.singh@amd.com>>>; Laszlo Ersek <lersek@redhat.com<mailto:lersek@redhat.com<mailto:lersek@redhat.com%3cmailto:lersek@redhat.com>>>; edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>; Zeng, Star <star.zeng@intel.com<mailto:star.zeng@intel.com<mailto:star.zeng@intel.com%3cmailto:star.zeng@intel.com>>>; Dong, Eric <eric.dong@intel.com<mailto:eric.dong@intel.com<mailto:eric.dong@intel.com%3cmailto:eric.dong@intel.com>>>
>>> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com%3cmailto:Thomas.Lendacky@amd.com>>; Gao, Liming <liming.gao@intel.com<mailto:liming.gao@intel.com<mailto:liming.gao@intel.com%3cmailto:liming.gao@intel.com>>>; leo.duran@amd.com<mailto:leo.duran@amd.com<mailto:leo.duran@amd.com%3cmailto:leo.duran@amd.com>>; Yao, Jiewen <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com<mailto:jiewen.yao@intel.com%3cmailto:jiewen.yao@intel.com>>>; Fan, Jeff <jeff.fan@intel.com<mailto:jeff.fan@intel.com<mailto:jeff.fan@intel.com%3cmailto:jeff.fan@intel.com>>>
>>> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
>>>
>>> On 2017-06-05 14:56:04, Brijesh Singh wrote:
>>>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
>>>>> On 06/01/17 09:40, Jordan Justen wrote:
>>>>>> In https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
>>>>>> Leo said that DxeIpl won't work because new I/O ranges might be added.
>>>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
>>>>>> entry are roughly equivalent in the boot sequence?
>>>>> I think you are right. I believe a patch for this exact idea hasn't
>>>>> been posted yet. Jiewen's message that you linked above contains the
>>>>> expression
>>>>>
>>>>>     always clear SEV mask for MMIO *and all rest*
>>>>>
>>>>> (emphasis mine), which I think we may have missed *in combination
>>>>> with* the DxeIpl.
>>>>>
>>>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
>>>>> Keep the C bit set for system memory regions. Clear the C bit for
>>>>> MMIO regions that are known from the HOB list. Also clear the C bit
>>>>> everywhere else in the address space (known from the CPU HOB) where
>>>>> no coverage is provided by any memory resource descriptor HOB.
>>>>>
>>>>> This is going to be harder than the current approach, because:
>>>>>
>>>>> - The current approach can work off of the GCD memory space map,
>>>>> which provides explicit NonExistent entries, covering the entire
>>>>> address space (according to the CPU HOB).
>>>>>
>>>>> - However, the DxeIpl method would take place before entering DXE,
>>>>> so no GCD memory space map would be available -- the "NonExistent"
>>>>> entries would have to be synthesized manually from the address space
>>>>> size (known from the CPU HOB) and the lack of coverage by memory
>>>>> resource descriptor HOBs.
>>>>>
>>>>> Basically, in order to move the current GCD memory space map
>>>>> traversal from early DXE to late PEI, the memory space map building
>>>>> logic of the DXE Core would have to be duplicated in the DxeIpl
>>>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
>>>>> contain very similar code, for the page table building, which might
>>>>> not be difficult to extend like this -- I haven't looked.)
>>>>>
>>>>> Is this what you have in mind?
>>>>>
>>>> Do you have any further thought on this?
>>> Regarding Laszlo's feedback, I'm not convinced that it would be excessively difficult to accomplish this in DxeIpl. (I'm not saying that I couldn't be convinced. :)
>>>
>>> As far as I can see, this is an architecturally defined AMD feature.
>>> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
>>
>> Yes, SEV is AMD-V architecture extension and its applicable to
>> virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
>> specific).
>>> You've asserted that it should work (SEV would not be detected) with any Intel processor as well. Therefore, I don't see a good reason that we shouldn't be able to support it in modules that already have
>>> IA32/X64 specific code. (I'm recalling
>>> 881813d7a93d9009c873515b043c41c4554779e4.)
>>>
>>> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the page tables for this feature (correct?), I think we should try to support the feature there if it is feasible. I can understand the argument that this doesn't apply to all non-VM platforms, so I think we could add a PCD which disables this support by default.
>>>
>>> I don't know that the owners of MdeModulePkg and UefiCpuPkg will agree with me though.
>>
>> I am flexible to implement APRIORI or Platform hooks Lib. But one thing
>> I want to highlight is: I'll prefer clearing C-bit  through
>> BaseMemEncryptSevLib functions. One of the main reason for doing so - In
>> future when we add migration support for the SEV guest then we will be
>> required to notify the unencrypted page range to hypevisor ( through
>> hypercall). During migration phase, Hypervisor will use this information
>> to make decision on whether to invoke the SEV firmware to encrypt the
>> memory region for transport purposes. If clearing C-bit logic is
>> contained inside BaseMemEncryptSevLib then it will make life much easier.
>>
>>>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain to
>>>> see if I can invoke a platform dependent library to clear C-bit before
>>>> DxeMain finishes its execution. As Laszlo pointed, current approach is
>>>> using GCD memory space map to get MMIO and NonExistent entries. I have
>>>> pushed two patches in my development branch to show what I have been doing:
>>>>
>>>> 1) add a new null DxeGcdCorePlatformHookLib
>>>>
>>>> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271a94
>>>> a920d7ad72d
>>>>
>>>> The library provides a function "DxeGcdCorePlatformHookReady" which
>>>> can be called by DxeMain just after it initializes the GcdServices
>>>> (which will guarantee that Gcd memory space map is available).
>>> Regarding hooking into DxeCore, I don't think it is the best approach, but it is better than APRIORI. I wonder if the MdeModulePkg owners could jump in with an opinion. (Hopefully besides just pushing the problem away via APRIORI.)
>>
>> Jiewen, any comments ?
>>
>>> -Jordan
>>>
>>>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-bit when
>>>>  SEV is detected.
>>>>
>>>> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596ba5
>>>> 3c95949f659
>>>>
>>>> I've tested the approach and it seems to work. Is this something
>>>> aligned with your thinking?
>>>>
>>>>
>>>>> Thanks
>>>>> Laszlo
>>>>>
>>>>>> -Jordan
>>>>>>
>>>>>>> In second patch
>>>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
>>>>>>> add/remove events. During discussion Jiewen suggested to look into
>>>>>>> adding a new platform driver into APRIORI to avoid the need for
>>>>>>> any modifications inside the Gcdcore - this seems workable
>>>>>>> solution which did not require adding any CPU specific code inside the Gcd.
>>>>>>>
>>>>>>> [1]
>>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
>>>>>>> [2]
>>>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
>>>>>>>
>>>> _______________________________________________
>>>> edk2-devel mailing list
>>>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org%3cmailto:edk2-devel@lists.01.org>>
>>>> https://lists.01.org/mailman/listinfo/edk2-devel
>> _______________________________________________
>> edk2-devel mailing list
>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
>> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06 15:54                           ` Duran, Leo
@ 2017-06-06 18:39                             ` Laszlo Ersek
  0 siblings, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-06-06 18:39 UTC (permalink / raw)
  To: Duran, Leo, 'Yao, Jiewen', afish@apple.com
  Cc: Singh, Brijesh, Zeng, Star, Justen, Jordan L,
	edk2-devel@lists.01.org, Dong, Eric, Lendacky, Thomas, Fan, Jeff,
	Gao, Liming

On 06/06/17 17:54, Duran, Leo wrote:
> Thank you all for the feedback… The summary of what I’m hearing is:
> 
> 1)      For now, use APRIORI in the stand-alone (SEV) driver in OvmfPkg (albeit not as clean as desired, but least intrusive solution.).
> 
> 2)      Let’s revisit the existing GCD implementation to allow for cleaner of features like this.

Personally I'm OK with this as well.

Thanks
Laszlo


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-06-06 18:29                       ` Laszlo Ersek
@ 2017-06-06 18:57                         ` Duran, Leo
  0 siblings, 0 replies; 65+ messages in thread
From: Duran, Leo @ 2017-06-06 18:57 UTC (permalink / raw)
  To: 'Laszlo Ersek', Yao, Jiewen, Singh, Brijesh, Zeng, Star,
	Justen, Jordan L, edk2-devel@lists.01.org, Dong, Eric
  Cc: Lendacky, Thomas, Gao, Liming, Fan, Jeff

Lazlo, et al,

Calling back from DxeIpl after page tables are created seems like a major hack:
- Duplicates logic already in GCD
- Would need to  pass the page-table root pointer

So, as stated earlier, I'm favor of:  using APRIORI in the interim, and reviewing GCD to support a more correct framework.
Leo.

> -----Original Message-----
> From: Laszlo Ersek [mailto:lersek@redhat.com]
> Sent: Tuesday, June 06, 2017 1:30 PM
> To: Yao, Jiewen <jiewen.yao@intel.com>; Singh, Brijesh
> <brijesh.singh@amd.com>; Zeng, Star <star.zeng@intel.com>; Justen,
> Jordan L <jordan.l.justen@intel.com>; edk2-devel@lists.01.org; Dong, Eric
> <eric.dong@intel.com>
> Cc: Lendacky, Thomas <Thomas.Lendacky@amd.com>; Gao, Liming
> <liming.gao@intel.com>; Duran, Leo <leo.duran@amd.com>; Fan, Jeff
> <jeff.fan@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization
> (AMD)
> 
> On 06/06/17 16:54, Yao, Jiewen wrote:
> > Hi
> > It takes me some time to read all email below. I believe all of us
> > have a clean understanding on what problem we have now and the
> > possible solutions to clear C bit are below
> >
> > 1)       In DxeIpl, when it builds page table.
> >
> > 2)       In DxeCore
> >
> > a)         By use CpuArch
> >
> > b)         By use page table lib
> >
> > c)         By use a GCD update callback
> >
> > d)         By use PlatformHook lib
> >
> > 3)       In a standalone AmdSev driver.
> >
> > Here is my thought:
> > 2.a) is not possible, per Leo’s investigation.
> > 2.b) is not a good design, because we do not introduce any Cpu Specific
> thing to DxeCore so far.
> > 2.c) and 2.d) are same. I do not suggest we add a private interface to the
> core just to support one specific feature.
> >
> > 1) is one possible solution, I suggested before. But if Leo/Laszlo think it is
> too hard to implement, I am OK.
> 
> I think that implementing the logic in the DXE IPL PEIM will be more difficult
> than doing the same somewhere in the DXE phase. But, I wouldn't oppose
> the idea. The implementation difficulty is not for me to
> overcome: it affects Brijesh and Leo (as the implementors) and the DXE IPL
> PEIM maintainers (in review).
> 
> NB, Brijesh mentioned up-thread that wherever (= in whichever firmware
> phase) they massaged the C-bit, they'd like to use BaseMemEncryptSevLib
> for it, because that would help with live migrating VMs. I can't say off-hand
> whether the current library instance is appropriate for use in the DXE IPL
> PEIM -- for example: repeated memory allocation and freeing isn't very good
> for PEIMs, since no freeing occurs in PEI --, so that's something for Brijesh &
> Leo to evaluate.
> 
> Anyhow, if the DXE IPL PEIM approach can be made work, technically, then
> I'm 100% fine with it personally.
> 
> Thanks
> Laszlo
> 
> >
> > If 1) cannot be chosen, I still think 3) is the best idea.
> > It makes the code very clean by introducing a standalone driver to resolve
> the problem.
> > Zero impact on existing platform.
> > If this feature is not needed, just remove the driver.
> >
> > I do not see any issue on using a priori, because: A) “a priori” is clearly
> defined in PI spec, B) “a priori” has already been widely used in current
> platform in EDKII open source, as well as close source platform.
> >
> > Thank you
> > Yao Jiewen
> >
> >
> >
> > From: Brijesh Singh [mailto:brijesh.singh@amd.com]
> > Sent: Tuesday, June 6, 2017 11:51 AM
> > To: Zeng, Star <star.zeng@intel.com>; Justen, Jordan L
> > <jordan.l.justen@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> > edk2-devel@lists.01.org; Dong, Eric <eric.dong@intel.com>; Yao, Jiewen
> > <jiewen.yao@intel.com>
> > Cc: Thomas.Lendacky@amd.com; Gao, Liming <liming.gao@intel.com>;
> > leo.duran@amd.com; Fan, Jeff <jeff.fan@intel.com>
> > Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted
> > Virtualization (AMD)
> >
> > Hi Jordan,
> >
> >
> > On 6/5/17 9:08 PM, Zeng, Star wrote:
> >> I was not tracking this thread.
> >> Jiewen will help give comments about the potential change in
> MdeModulePkg.
> >>
> >> Thanks,
> >> Star
> >> -----Original Message-----
> >> From: Justen, Jordan L
> >> Sent: Tuesday, June 6, 2017 9:12 AM
> >> To: Brijesh Singh
> >> <brijesh.singh@amd.com<mailto:brijesh.singh@amd.com>>; Laszlo Ersek
> >> <lersek@redhat.com<mailto:lersek@redhat.com>>;
> >> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>; Zeng, Star
> >> <star.zeng@intel.com<mailto:star.zeng@intel.com>>; Dong, Eric
> >> <eric.dong@intel.com<mailto:eric.dong@intel.com>>
> >> Cc: Thomas.Lendacky@amd.com<mailto:Thomas.Lendacky@amd.com>;
> Gao,
> >> Liming <liming.gao@intel.com<mailto:liming.gao@intel.com>>;
> >> leo.duran@amd.com<mailto:leo.duran@amd.com>; Yao, Jiewen
> >> <jiewen.yao@intel.com<mailto:jiewen.yao@intel.com>>; Fan, Jeff
> >> <jeff.fan@intel.com<mailto:jeff.fan@intel.com>>
> >> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted
> >> Virtualization (AMD)
> >>
> >> On 2017-06-05 14:56:04, Brijesh Singh wrote:
> >>> On 06/01/2017 04:10 AM, Laszlo Ersek wrote:
> >>>> On 06/01/17 09:40, Jordan Justen wrote:
> >>>>> In
> >>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009883.html
> >>>>> Leo said that DxeIpl won't work because new I/O ranges might be
> added.
> >>>>> I don't understand this, because isn't DxeIpl and an early APRIORI
> >>>>> entry are roughly equivalent in the boot sequence?
> >>>> I think you are right. I believe a patch for this exact idea hasn't
> >>>> been posted yet. Jiewen's message that you linked above contains
> >>>> the expression
> >>>>
> >>>>      always clear SEV mask for MMIO *and all rest*
> >>>>
> >>>> (emphasis mine), which I think we may have missed *in combination
> >>>> with* the DxeIpl.
> >>>>
> >>>> So the idea would be to iterate over all the HOBs in the DxeIpl PEIM.
> >>>> Keep the C bit set for system memory regions. Clear the C bit for
> >>>> MMIO regions that are known from the HOB list. Also clear the C bit
> >>>> everywhere else in the address space (known from the CPU HOB)
> where
> >>>> no coverage is provided by any memory resource descriptor HOB.
> >>>>
> >>>> This is going to be harder than the current approach, because:
> >>>>
> >>>> - The current approach can work off of the GCD memory space map,
> >>>> which provides explicit NonExistent entries, covering the entire
> >>>> address space (according to the CPU HOB).
> >>>>
> >>>> - However, the DxeIpl method would take place before entering DXE,
> >>>> so no GCD memory space map would be available -- the "NonExistent"
> >>>> entries would have to be synthesized manually from the address
> >>>> space size (known from the CPU HOB) and the lack of coverage by
> >>>> memory resource descriptor HOBs.
> >>>>
> >>>> Basically, in order to move the current GCD memory space map
> >>>> traversal from early DXE to late PEI, the memory space map building
> >>>> logic of the DXE Core would have to be duplicated in the DxeIpl
> >>>> PEIM. If I understand correctly. (The DxeIpl PEIM may already
> >>>> contain very similar code, for the page table building, which might
> >>>> not be difficult to extend like this -- I haven't looked.)
> >>>>
> >>>> Is this what you have in mind?
> >>>>
> >>> Do you have any further thought on this?
> >> Regarding Laszlo's feedback, I'm not convinced that it would be
> >> excessively difficult to accomplish this in DxeIpl. (I'm not saying
> >> that I couldn't be convinced. :)
> >>
> >> As far as I can see, this is an architecturally defined AMD feature.
> >> (Is this true, or is BaseMemcryptSevLib actually OVMF specific?)
> >
> > Yes, SEV is AMD-V architecture extension and its applicable to
> > virtualization platform only (we can says BaseMemEncryptSevLib is OVMF
> > specific).
> >> You've asserted that it should work (SEV would not be detected) with
> >> any Intel processor as well. Therefore, I don't see a good reason
> >> that we shouldn't be able to support it in modules that already have
> >> IA32/X64 specific code. (I'm recalling
> >> 881813d7a93d9009c873515b043c41c4554779e4.)
> >>
> >> Since DxeIpl builds the IA32/X64 page tables, and you need to modify the
> page tables for this feature (correct?), I think we should try to support the
> feature there if it is feasible. I can understand the argument that this doesn't
> apply to all non-VM platforms, so I think we could add a PCD which disables
> this support by default.
> >>
> >> I don't know that the owners of MdeModulePkg and UefiCpuPkg will
> agree with me though.
> >
> > I am flexible to implement APRIORI or Platform hooks Lib. But one
> > thing I want to highlight is: I'll prefer clearing C-bit  through
> > BaseMemEncryptSevLib functions. One of the main reason for doing so -
> > In future when we add migration support for the SEV guest then we will
> > be required to notify the unencrypted page range to hypevisor (
> > through hypercall). During migration phase, Hypervisor will use this
> > information to make decision on whether to invoke the SEV firmware to
> > encrypt the memory region for transport purposes. If clearing C-bit
> > logic is contained inside BaseMemEncryptSevLib then it will make life much
> easier.
> >
> >>> In meantime, I have been looking into MdeModule/Core/Dxe/DxeMain
> to
> >>> see if I can invoke a platform dependent library to clear C-bit
> >>> before DxeMain finishes its execution. As Laszlo pointed, current
> >>> approach is using GCD memory space map to get MMIO and NonExistent
> >>> entries. I have pushed two patches in my development branch to show
> what I have been doing:
> >>>
> >>> 1) add a new null DxeGcdCorePlatformHookLib
> >>>
> >>>
> https://github.com/codomania/edk2/commit/171f816376b3b0677cbfb90271
> a
> >>> 94
> >>> a920d7ad72d
> >>>
> >>> The library provides a function "DxeGcdCorePlatformHookReady" which
> >>> can be called by DxeMain just after it initializes the GcdServices
> >>> (which will guarantee that Gcd memory space map is available).
> >> Regarding hooking into DxeCore, I don't think it is the best
> >> approach, but it is better than APRIORI. I wonder if the MdeModulePkg
> >> owners could jump in with an opinion. (Hopefully besides just pushing
> >> the problem away via APRIORI.)
> >
> > Jiewen, any comments ?
> >
> >> -Jordan
> >>
> >>> 2) override DxeGcdCorePlatformHookLib inside the Ovmf to clear the C-
> bit when
> >>>   SEV is detected.
> >>>
> >>>
> https://github.com/codomania/edk2/commit/914ce904ca1b7647c966562596
> b
> >>> a5
> >>> 3c95949f659
> >>>
> >>> I've tested the approach and it seems to work. Is this something
> >>> aligned with your thinking?
> >>>
> >>>
> >>>> Thanks
> >>>> Laszlo
> >>>>
> >>>>> -Jordan
> >>>>>
> >>>>>> In second patch
> >>>>>> [2], Leo tried to introduce a new notify protocol to get MMIO
> >>>>>> add/remove events. During discussion Jiewen suggested to look
> >>>>>> into adding a new platform driver into APRIORI to avoid the need
> >>>>>> for any modifications inside the Gcdcore - this seems workable
> >>>>>> solution which did not require adding any CPU specific code inside
> the Gcd.
> >>>>>>
> >>>>>> [1]
> >>>>>> https://lists.01.org/pipermail/edk2-devel/2017-March/008974.html
> >>>>>> [2]
> >>>>>> https://lists.01.org/pipermail/edk2-devel/2017-April/009852.html
> >>>>>>
> >>> _______________________________________________
> >>> edk2-devel mailing list
> >>> edk2-devel@lists.01.org<mailto:edk2-devel@lists.01.org>
> >>> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-05-26 14:43 [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Brijesh Singh
                   ` (17 preceding siblings ...)
  2017-05-26 21:05 ` [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD) Jordan Justen
@ 2017-07-05 22:31 ` Brijesh Singh
  2017-07-05 23:38   ` Laszlo Ersek
  2017-07-06 16:45   ` Jordan Justen
  18 siblings, 2 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-07-05 22:31 UTC (permalink / raw)
  To: edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Jordan Justen, Laszlo Ersek, Jiewen Yao

Hi Jordan and Laszlo,

Ping.

It has been a while, Do you have any further feedbacks on this series ?
If you want then I can rebase the patches before you commit into upstream repos.

-Brijesh

On 05/26/2017 09:43 AM, Brijesh Singh wrote:
> The patch series provides support for AMD's new Secure Encrypted
> Virtualization (SEV) feature.
> 
> SEV is an extension to the AMD-V architecture which supports running
> multiple VMs under the control of a hypervisor. The SEV feature allows
> the memory contents of a virtual machine (VM) to be transparently encrypted
> with a key unique to the guest VM. The memory controller contains a
> high performance encryption engine which can be programmed with multiple
> keys for use by a different VMs in the system. The programming and
> management of these keys is handled by the AMD Secure Processor firmware
> which exposes a commands for these tasks.
> 
> SEV guest VMs have the concept of private and shared memory.  Private memory is
> encrypted with the guest-specific key, while shared memory may be encrypted
> with hypervisor key.  Certain types of memory (namely instruction pages and
> guest page tables) are always treated as private memory by the hardware.
> For data memory, SEV guest VMs can choose which pages they would like to be
> private. The choice is done using the standard CPU page tables using the C-bit,
> and is fully controlled by the guest. Due to security reasons all the DMA
> operations inside the  guest must be performed on shared pages (C-bit clear).
> Note that since C-bit is only controllable by the guest OS when it is operating
> in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware forces the
> C-bit to a 1.
> 
> The following links provide additional details:
> 
> AMD Memory Encryption whitepaper:
> http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
> 
> AMD64 Architecture Programmer's Manual:
>      http://support.amd.com/TechDocs/24593.pdf
>      SME is section 7.10
>      SEV is section 15.34
> 
> Secure Encrypted Virutualization Key Management:
> http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
> 
> KVM Forum Presentation:
> http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
> 
> [1] http://marc.info/?l=linux-mm&m=148846752931115&w=2
> 
> ---
> 
> Patch series is based on commit aff463c825a3
>   (Vlv2TbltDevicePkg/FvbRuntimeDxe: correct NumOfLba vararg type in EraseBlocks())
> 
> https://github.com/codomania/edk2/tree/v6
> 
> The patch series is tested with OvmfIa32.dsc, OvmfIa32X64.dsc and OvmfX64.dsc.
> Since memory encryption bit is not accessiable when processor is in 32-bit mode
> hence any DMA access in this mode would cause assert. I have also tested the
> suspend and resume path, it seems to be working fine. I still need to work to
> finish adding the SEV Dma support in QemuFwCfgS3Lib package (see TODO).
> 
> Changes since v5:
>   - add placeholder gIoMmuAbsentProtocolGuid
>   - add PlatformHasIoMmuLib
>   - fix indentation
> 
> Changes since v4:
>   - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
>     IoMmuDxe driver. And introduce a placeholder protocol to provide the
>     dependency support for the dependent modules.
>   - update debug messages to use gEfiCallerBaseName where applicable.
>   - fix QemuFwCfgSecLib build errors and simplify SEV support
>   - update QemuFwCfgDxeLib to assert when failed to locate IOMMU
>   - update comments "host buffer" to " host buffer"
> 
> Changes since v3:
>   - update AmdSevDxe driver to produce IOMMU protocol
>   - remove BmDmaLib dependency
>   - update QemuFwCfgLib to use IOMMU protocol to allocate SEV DMA buffer
> 
> Changes since v2:
>   - move memory encryption CPUID and MSR definition into UefiCpuPkg
>   - fix the argument order for SUB instruction in ResetVector and add more
>     comments
>   - update PlatformPei to use BaseMemEncryptSevLib
>   - break the overlong comment lines to 79 chars
>   - variable aligment and other formating fixes
>   - split the SEV DMA support patch for QemuFwCfgLib into multiple patches as
>     recommended by Laszlo
>   - add AmdSevDxe driver which runs very early in DXE phase and clear the C-bit
>     from MMIO memory region
>   - drop 'QemuVideoDxe: Clear C-bit from framebuffer' patch since AmdSevDxe
>     driver takes care of clearing the C-bit from MMIO region
>   - Verified that Qemu PFLASH works fine with SEV guest, Found a KVM driver issue
>     which was causing #PF when PFLASH was enabled. I have submitted patch to
>     fix it in upstream http://marc.info/?l=kvm&m=149304930814202&w=2
> 
> Changes since v1:
>   - bug fixes in OvmfPkg/ResetVector (pointed by Tom Lendacky)
>   - add SEV CPUID and MSR register definition in standard include file
>   - remove the MemEncryptLib dependency from PlatformPei. Move AmdSevInitialize()
>     implementation in local file inside the PlatformPei package
>   - rename MemCryptSevLib to MemEncryptSevLib and add functions to set or
>     clear memory encryption attribute on memory region
>   - integerate SEV support in BmDmaLib
>   - split QemuFwCfgDxePei.c into QemuFwCfgDxe.c and QemuFwCfgPei.c to
>     allow building seperate QemuFwCfgLib for Dxe and Pei phase
>     (recommended by Laszlo Ersek)
>   - add SEV support in QemuFwCfgLib
>   - clear the memory encryption attribute from framebuffer memory region
> 
> 
> TODO:
> (Will add these features after basic SEV support patches are accepted in upstream)
>   - add support for DMA operation in QemuFwCfgS3Lib when SEV is enabled
>   - investigate SMM/SMI support
> 
> Cc: Jeff Fan <jeff.fan@intel.com>
> Cc: Liming Gao <liming.gao@intel.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Laszlo Ersek <lersek@redhat.com>
> Cc: Leo Duran <leo.duran@amd.com>
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> 
> Brijesh Singh (17):
>    UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
>    OvmfPkg/ResetVector: Set C-bit when building initial page table
>    OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
>    OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
>    OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
>    OvmfPkg: Add AmdSevDxe driver
>    OvmfPkg: Introduce IoMmuAbsent Protocol GUID
>    OvmfPkg: Add PlatformHasIoMmuLib
>    OvmfPkg: Add IoMmuDxe driver
>    OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
>    OvmfPkg/QemuFwCfgLib: Prepare for SEV support
>    OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
>    OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
>    OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
>    OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
>    OvmfPkg/QemuFwCfgLib: Add SEV support
>    OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
> 
>   OvmfPkg/OvmfPkg.dec                                                    |   1 +
>   OvmfPkg/OvmfPkgIa32.dsc                                                |  11 +-
>   OvmfPkg/OvmfPkgIa32X64.dsc                                             |  12 +-
>   OvmfPkg/OvmfPkgX64.dsc                                                 |  12 +-
>   OvmfPkg/OvmfPkgIa32.fdf                                                |   1 +
>   OvmfPkg/OvmfPkgIa32X64.fdf                                             |   3 +
>   OvmfPkg/OvmfPkgX64.fdf                                                 |   3 +
>   OvmfPkg/AmdSevDxe/AmdSevDxe.inf                                        |  43 ++
>   OvmfPkg/IoMmuDxe/IoMmuDxe.inf                                          |  49 +++
>   OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf          |  50 +++
>   OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf            |  37 ++
>   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} |  15 +-
>   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} |   9 +-
>   OvmfPkg/PlatformPei/PlatformPei.inf                                    |   3 +
>   OvmfPkg/Include/Library/MemEncryptSevLib.h                             |  81 ++++
>   OvmfPkg/IoMmuDxe/AmdSevIoMmu.h                                         |  43 ++
>   OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h               | 184 ++++++++
>   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h                    |  37 ++
>   OvmfPkg/PlatformPei/Platform.h                                         |   5 +
>   UefiCpuPkg/Include/Register/Amd/Cpuid.h                                | 162 +++++++
>   UefiCpuPkg/Include/Register/Amd/Fam17Msr.h                             |  62 +++
>   UefiCpuPkg/Include/Register/Amd/Msr.h                                  |  29 ++
>   OvmfPkg/AmdSevDxe/AmdSevDxe.c                                          |  75 ++++
>   OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                         | 459 ++++++++++++++++++++
>   OvmfPkg/IoMmuDxe/IoMmuDxe.c                                            |  53 +++
>   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 +++++++++++++++++++
>   OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c              |  32 ++
>   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c                            | 230 ++++++++++
>   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c                            |  67 ++-
>   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     |  72 ++-
>   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c                            |  57 +++
>   OvmfPkg/PlatformPei/AmdSev.c                                           |  62 +++
>   OvmfPkg/PlatformPei/Platform.c                                         |   1 +
>   OvmfPkg/ResetVector/Ia32/PageTables64.asm                              |  70 ++-
>   37 files changed, 2703 insertions(+), 24 deletions(-)
>   create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.inf
>   create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.inf
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
>   create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
>   copy OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} (71%)
>   rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} (80%)
>   create mode 100644 OvmfPkg/Include/Library/MemEncryptSevLib.h
>   create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
>   create mode 100644 UefiCpuPkg/Include/Register/Amd/Cpuid.h
>   create mode 100644 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
>   create mode 100644 UefiCpuPkg/Include/Register/Amd/Msr.h
>   create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.c
>   create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
>   create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.c
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
>   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
>   create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
>   create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
>   rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c} (61%)
>   create mode 100644 OvmfPkg/PlatformPei/AmdSev.c
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  1 sibling, 1 reply; 65+ messages in thread
From: Laszlo Ersek @ 2017-07-05 23:38 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jordan Justen,
	Jiewen Yao

On 07/06/17 00:31, Brijesh Singh wrote:
> Hi Jordan and Laszlo,
> 
> Ping.
> 
> It has been a while, Do you have any further feedbacks on this series ?
> If you want then I can rebase the patches before you commit into
> upstream repos.

>From my side, refreshing the v7 series (posted on 2017-Jun-22) against
current master would be welcome, just to sort out any context
differences that may have crept in meanwhile.

Other than that, I'm ready to merge v7 (and have been ready since my v7
review, posted on 2017-Jun-23).

Thanks,
Laszlo


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-05 23:38   ` Laszlo Ersek
@ 2017-07-06 13:37     ` Brijesh Singh
  0 siblings, 0 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-07-06 13:37 UTC (permalink / raw)
  To: Laszlo Ersek, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Jordan Justen, Jiewen Yao



On 07/05/2017 06:38 PM, Laszlo Ersek wrote:
> On 07/06/17 00:31, Brijesh Singh wrote:
>> Hi Jordan and Laszlo,
>>
>> Ping.
>>
>> It has been a while, Do you have any further feedbacks on this series ?
>> If you want then I can rebase the patches before you commit into
>> upstream repos.
> 
>  From my side, refreshing the v7 series (posted on 2017-Jun-22) against
> current master would be welcome, just to sort out any context
> differences that may have crept in meanwhile.
> 
> Other than that, I'm ready to merge v7 (and have been ready since my v7
> review, posted on 2017-Jun-23).
> 

Thanks Laszlo, I just pulled latest and there was one hunk failure when applying v7 series.
I will send v8 which applies cleanly on top of latest. I also noticed that Jeff Fan has
already applied the first patch (cpuid) from this series and I will drop it in v8.


> Thanks,
> Laszlo
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-05 22:31 ` Brijesh Singh
  2017-07-05 23:38   ` Laszlo Ersek
@ 2017-07-06 16:45   ` Jordan Justen
  2017-07-06 20:11     ` Brijesh Singh
  1 sibling, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-07-06 16:45 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Laszlo Ersek, Jiewen Yao, Michael D Kinney

On 2017-07-05 15:31:20, Brijesh Singh wrote:
> Hi Jordan and Laszlo,
> 
> Ping.
> 
> It has been a while, Do you have any further feedbacks on this series ?
> If you want then I can rebase the patches before you commit into upstream repos.
> 

I'm still dissappointed by the APRIORI usage.

As I understand it, you are also dissatisfied with this approach and
you hope to improve things by somehow hooking into DXE Core. Is that
true? If so, can you create a bugzilla regarding this feature? When
would you plan to work to address that?

I guess with that resolved, you could add an Acked-by from me.

In general, it'd also be nice to move the processor features to more
generic places, although that may be challenging if the next step is
some kind of platform hook from DXE Core. Maybe if the DXE Core calls
out to some protocol or signals an event then a driver in UefiCpuPkg
could handle the protocol implementation to modify the page tables.

-Jordan

> 
> On 05/26/2017 09:43 AM, Brijesh Singh wrote:
> > The patch series provides support for AMD's new Secure Encrypted
> > Virtualization (SEV) feature.
> > 
> > SEV is an extension to the AMD-V architecture which supports running
> > multiple VMs under the control of a hypervisor. The SEV feature allows
> > the memory contents of a virtual machine (VM) to be transparently encrypted
> > with a key unique to the guest VM. The memory controller contains a
> > high performance encryption engine which can be programmed with multiple
> > keys for use by a different VMs in the system. The programming and
> > management of these keys is handled by the AMD Secure Processor firmware
> > which exposes a commands for these tasks.
> > 
> > SEV guest VMs have the concept of private and shared memory.  Private memory is
> > encrypted with the guest-specific key, while shared memory may be encrypted
> > with hypervisor key.  Certain types of memory (namely instruction pages and
> > guest page tables) are always treated as private memory by the hardware.
> > For data memory, SEV guest VMs can choose which pages they would like to be
> > private. The choice is done using the standard CPU page tables using the C-bit,
> > and is fully controlled by the guest. Due to security reasons all the DMA
> > operations inside the  guest must be performed on shared pages (C-bit clear).
> > Note that since C-bit is only controllable by the guest OS when it is operating
> > in 64-bit or 32-bit PAE mode, in all other modes the SEV hardware forces the
> > C-bit to a 1.
> > 
> > The following links provide additional details:
> > 
> > AMD Memory Encryption whitepaper:
> > http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
> > 
> > AMD64 Architecture Programmer's Manual:
> >      http://support.amd.com/TechDocs/24593.pdf
> >      SME is section 7.10
> >      SEV is section 15.34
> > 
> > Secure Encrypted Virutualization Key Management:
> > http://support.amd.com/TechDocs/55766_SEV-KM API_Specification.pdf
> > 
> > KVM Forum Presentation:
> > http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
> > 
> > [1] http://marc.info/?l=linux-mm&m=148846752931115&w=2
> > 
> > ---
> > 
> > Patch series is based on commit aff463c825a3
> >   (Vlv2TbltDevicePkg/FvbRuntimeDxe: correct NumOfLba vararg type in EraseBlocks())
> > 
> > https://github.com/codomania/edk2/tree/v6
> > 
> > The patch series is tested with OvmfIa32.dsc, OvmfIa32X64.dsc and OvmfX64.dsc.
> > Since memory encryption bit is not accessiable when processor is in 32-bit mode
> > hence any DMA access in this mode would cause assert. I have also tested the
> > suspend and resume path, it seems to be working fine. I still need to work to
> > finish adding the SEV Dma support in QemuFwCfgS3Lib package (see TODO).
> > 
> > Changes since v5:
> >   - add placeholder gIoMmuAbsentProtocolGuid
> >   - add PlatformHasIoMmuLib
> >   - fix indentation
> > 
> > Changes since v4:
> >   - decouple IoMmu protocol implementation from AmdSevDxe into a seperate
> >     IoMmuDxe driver. And introduce a placeholder protocol to provide the
> >     dependency support for the dependent modules.
> >   - update debug messages to use gEfiCallerBaseName where applicable.
> >   - fix QemuFwCfgSecLib build errors and simplify SEV support
> >   - update QemuFwCfgDxeLib to assert when failed to locate IOMMU
> >   - update comments "host buffer" to " host buffer"
> > 
> > Changes since v3:
> >   - update AmdSevDxe driver to produce IOMMU protocol
> >   - remove BmDmaLib dependency
> >   - update QemuFwCfgLib to use IOMMU protocol to allocate SEV DMA buffer
> > 
> > Changes since v2:
> >   - move memory encryption CPUID and MSR definition into UefiCpuPkg
> >   - fix the argument order for SUB instruction in ResetVector and add more
> >     comments
> >   - update PlatformPei to use BaseMemEncryptSevLib
> >   - break the overlong comment lines to 79 chars
> >   - variable aligment and other formating fixes
> >   - split the SEV DMA support patch for QemuFwCfgLib into multiple patches as
> >     recommended by Laszlo
> >   - add AmdSevDxe driver which runs very early in DXE phase and clear the C-bit
> >     from MMIO memory region
> >   - drop 'QemuVideoDxe: Clear C-bit from framebuffer' patch since AmdSevDxe
> >     driver takes care of clearing the C-bit from MMIO region
> >   - Verified that Qemu PFLASH works fine with SEV guest, Found a KVM driver issue
> >     which was causing #PF when PFLASH was enabled. I have submitted patch to
> >     fix it in upstream http://marc.info/?l=kvm&m=149304930814202&w=2
> > 
> > Changes since v1:
> >   - bug fixes in OvmfPkg/ResetVector (pointed by Tom Lendacky)
> >   - add SEV CPUID and MSR register definition in standard include file
> >   - remove the MemEncryptLib dependency from PlatformPei. Move AmdSevInitialize()
> >     implementation in local file inside the PlatformPei package
> >   - rename MemCryptSevLib to MemEncryptSevLib and add functions to set or
> >     clear memory encryption attribute on memory region
> >   - integerate SEV support in BmDmaLib
> >   - split QemuFwCfgDxePei.c into QemuFwCfgDxe.c and QemuFwCfgPei.c to
> >     allow building seperate QemuFwCfgLib for Dxe and Pei phase
> >     (recommended by Laszlo Ersek)
> >   - add SEV support in QemuFwCfgLib
> >   - clear the memory encryption attribute from framebuffer memory region
> > 
> > 
> > TODO:
> > (Will add these features after basic SEV support patches are accepted in upstream)
> >   - add support for DMA operation in QemuFwCfgS3Lib when SEV is enabled
> >   - investigate SMM/SMI support
> > 
> > Cc: Jeff Fan <jeff.fan@intel.com>
> > Cc: Liming Gao <liming.gao@intel.com>
> > Cc: Leo Duran <leo.duran@amd.com>
> > Cc: Jordan Justen <jordan.l.justen@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Leo Duran <leo.duran@amd.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Tom Lendacky <Thomas.Lendacky@amd.com>
> > Contributed-under: TianoCore Contribution Agreement 1.0
> > Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
> > 
> > Brijesh Singh (17):
> >    UefiCpuPkg: Define AMD Memory Encryption specific CPUID and MSR
> >    OvmfPkg/ResetVector: Set C-bit when building initial page table
> >    OvmfPkg: Update dsc to use IoLib from BaseIoLibIntrinsicSev.inf
> >    OvmfPkg/BaseMemcryptSevLib: Add SEV helper library
> >    OvmfPkg/PlatformPei: Set memory encryption PCD when SEV is enabled
> >    OvmfPkg: Add AmdSevDxe driver
> >    OvmfPkg: Introduce IoMmuAbsent Protocol GUID
> >    OvmfPkg: Add PlatformHasIoMmuLib
> >    OvmfPkg: Add IoMmuDxe driver
> >    OvmfPkg/QemuFwCfgLib: Provide Pei and Dxe specific library
> >    OvmfPkg/QemuFwCfgLib: Prepare for SEV support
> >    OvmfPkg/QemuFwCfgLib: Implement SEV internal function for SEC phase
> >    OvmfPkg/QemuFwCfgLib: Implement SEV internal functions for PEI phase
> >    OvmfPkg/QemuFwCfgLib: Implement SEV internal function for Dxe phase
> >    OvmfPkg/QemuFwCfgLib: Add option to dynamic alloc FW_CFG_DMA Access
> >    OvmfPkg/QemuFwCfgLib: Add SEV support
> >    OvmfPkg: update PciHostBridgeDxe to use PlatformHasIoMmuLib
> > 
> >   OvmfPkg/OvmfPkg.dec                                                    |   1 +
> >   OvmfPkg/OvmfPkgIa32.dsc                                                |  11 +-
> >   OvmfPkg/OvmfPkgIa32X64.dsc                                             |  12 +-
> >   OvmfPkg/OvmfPkgX64.dsc                                                 |  12 +-
> >   OvmfPkg/OvmfPkgIa32.fdf                                                |   1 +
> >   OvmfPkg/OvmfPkgIa32X64.fdf                                             |   3 +
> >   OvmfPkg/OvmfPkgX64.fdf                                                 |   3 +
> >   OvmfPkg/AmdSevDxe/AmdSevDxe.inf                                        |  43 ++
> >   OvmfPkg/IoMmuDxe/IoMmuDxe.inf                                          |  49 +++
> >   OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf          |  50 +++
> >   OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf            |  37 ++
> >   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} |  15 +-
> >   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} |   9 +-
> >   OvmfPkg/PlatformPei/PlatformPei.inf                                    |   3 +
> >   OvmfPkg/Include/Library/MemEncryptSevLib.h                             |  81 ++++
> >   OvmfPkg/IoMmuDxe/AmdSevIoMmu.h                                         |  43 ++
> >   OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h               | 184 ++++++++
> >   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLibInternal.h                    |  37 ++
> >   OvmfPkg/PlatformPei/Platform.h                                         |   5 +
> >   UefiCpuPkg/Include/Register/Amd/Cpuid.h                                | 162 +++++++
> >   UefiCpuPkg/Include/Register/Amd/Fam17Msr.h                             |  62 +++
> >   UefiCpuPkg/Include/Register/Amd/Msr.h                                  |  29 ++
> >   OvmfPkg/AmdSevDxe/AmdSevDxe.c                                          |  75 ++++
> >   OvmfPkg/IoMmuDxe/AmdSevIoMmu.c                                         | 459 ++++++++++++++++++++
> >   OvmfPkg/IoMmuDxe/IoMmuDxe.c                                            |  53 +++
> >   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 +++++++++++++++++++
> >   OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c              |  32 ++
> >   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c                            | 230 ++++++++++
> >   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgLib.c                            |  67 ++-
> >   OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c}     |  72 ++-
> >   OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgSec.c                            |  57 +++
> >   OvmfPkg/PlatformPei/AmdSev.c                                           |  62 +++
> >   OvmfPkg/PlatformPei/Platform.c                                         |   1 +
> >   OvmfPkg/ResetVector/Ia32/PageTables64.asm                              |  70 ++-
> >   37 files changed, 2703 insertions(+), 24 deletions(-)
> >   create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.inf
> >   create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.inf
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/BaseMemEncryptSevLib.inf
> >   create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.inf
> >   copy OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgDxeLib.inf} (71%)
> >   rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgLib.inf => QemuFwCfgPeiLib.inf} (80%)
> >   create mode 100644 OvmfPkg/Include/Library/MemEncryptSevLib.h
> >   create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.h
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.h
> >   create mode 100644 UefiCpuPkg/Include/Register/Amd/Cpuid.h
> >   create mode 100644 UefiCpuPkg/Include/Register/Amd/Fam17Msr.h
> >   create mode 100644 UefiCpuPkg/Include/Register/Amd/Msr.h
> >   create mode 100644 OvmfPkg/AmdSevDxe/AmdSevDxe.c
> >   create mode 100644 OvmfPkg/IoMmuDxe/AmdSevIoMmu.c
> >   create mode 100644 OvmfPkg/IoMmuDxe/IoMmuDxe.c
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/MemEncryptSevLibInternal.c
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
> >   create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/VirtualMemory.c
> >   create mode 100644 OvmfPkg/Library/PlatformHasIoMmuLib/PlatformHasIoMmuLib.c
> >   create mode 100644 OvmfPkg/Library/QemuFwCfgLib/QemuFwCfgDxe.c
> >   rename OvmfPkg/Library/QemuFwCfgLib/{QemuFwCfgPeiDxe.c => QemuFwCfgPei.c} (61%)
> >   create mode 100644 OvmfPkg/PlatformPei/AmdSev.c
> > 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  0 siblings, 2 replies; 65+ messages in thread
From: Brijesh Singh @ 2017-07-06 20:11 UTC (permalink / raw)
  To: Jordan Justen, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Laszlo Ersek, Jiewen Yao, Michael D Kinney



On 07/06/2017 11:45 AM, Jordan Justen wrote:
> On 2017-07-05 15:31:20, Brijesh Singh wrote:
>> Hi Jordan and Laszlo,
>>
>> Ping.
>>
>> It has been a while, Do you have any further feedbacks on this series ?
>> If you want then I can rebase the patches before you commit into upstream repos.
>>
> 
> I'm still dissappointed by the APRIORI usage.
> 
> As I understand it, you are also dissatisfied with this approach and
> you hope to improve things by somehow hooking into DXE Core. Is that
> true? If so, can you create a bugzilla regarding this feature? When
> would you plan to work to address that?
> 

I think we agree in that this particular use-case has shown the need for re-thinking
the existing GCD interface. However, the problem we are trying to solve with this
patch-set is enabling the SEV feature. As it turns out, we can do so within the
existing GCD framework by simply leveraging the APRIORI hook already in use by OvmfPkg.

In that context, our proposal is that we limit the scope of this patch-set to simply
enabling the SEV feature, and then allow the 'GCD experts' to separately propose updates
to the framework.


> I guess with that resolved, you could add an Acked-by from me.
> 
> In general, it'd also be nice to move the processor features to more
> generic places, although that may be challenging if the next step is
> some kind of platform hook from DXE Core. Maybe if the DXE Core calls
> out to some protocol or signals an event then a driver in UefiCpuPkg
> could handle the protocol implementation to modify the page tables.
> 
> -Jordan
> 
>


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-06 20:11     ` Brijesh Singh
@ 2017-07-06 20:40       ` Laszlo Ersek
  2017-07-06 21:42       ` Jordan Justen
  1 sibling, 0 replies; 65+ messages in thread
From: Laszlo Ersek @ 2017-07-06 20:40 UTC (permalink / raw)
  To: Brijesh Singh, Jordan Justen, edk2-devel
  Cc: Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao, Jiewen Yao,
	Michael D Kinney

On 07/06/17 22:11, Brijesh Singh wrote:
>
>
> On 07/06/2017 11:45 AM, Jordan Justen wrote:
>> On 2017-07-05 15:31:20, Brijesh Singh wrote:
>>> Hi Jordan and Laszlo,
>>>
>>> Ping.
>>>
>>> It has been a while, Do you have any further feedbacks on this
>>> series ? If you want then I can rebase the patches before you commit
>>> into upstream repos.
>>>
>>
>> I'm still dissappointed by the APRIORI usage.
>>
>> As I understand it, you are also dissatisfied with this approach and
>> you hope to improve things by somehow hooking into DXE Core. Is that
>> true? If so, can you create a bugzilla regarding this feature? When
>> would you plan to work to address that?
>>
>
> I think we agree in that this particular use-case has shown the need
> for re-thinking the existing GCD interface. However, the problem we
> are trying to solve with this patch-set is enabling the SEV feature.

I agree.

> As it turns out, we can do so within the existing GCD framework by
> simply leveraging the APRIORI hook already in use by OvmfPkg.

Not just in OvmfPkg. CorebootPayloadPkg, DuetPkg, EmulatorPkg, Nt32Pkg
and Vlv2TbltDevicePkg also use "APRIORI DXE".

See e.g. commit 70420e31a04b ("Nt32Pkg FDF: Move StatusCode Handler run
earlier in DXE phase", 2017-01-20).

> In that context, our proposal is that we limit the scope of this
> patch-set to simply enabling the SEV feature, and then allow the 'GCD
> experts' to separately propose updates to the framework.

I agree. Based on the past discussions, even said experts and edk2
maintainers aren't united on the optimal approach here.

I think filing a BZ (or even a PI spec ticket!) for figuring out the
best scope and location for the platformization of GCD, or for the same
of the page table setup, is justified.

However, I disagree that such a ticket should block this series, or that
Brijesh should prioritize such a ticket after this initial OVMF series
is merged. Brijesh has been handling SEV enablement in other projects as
well, such as KVM, and there's still a whole lot to do after these
initial OVMF patches are merged.

Laszlo


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  1 sibling, 2 replies; 65+ messages in thread
From: Jordan Justen @ 2017-07-06 21:42 UTC (permalink / raw)
  To: Brijesh Singh, edk2-devel
  Cc: brijesh.singh, Thomas.Lendacky, leo.duran, Jeff Fan, Liming Gao,
	Laszlo Ersek, Jiewen Yao, Michael D Kinney

On 2017-07-06 13:11:03, Brijesh Singh wrote:
> 
> 
> On 07/06/2017 11:45 AM, Jordan Justen wrote:
> > On 2017-07-05 15:31:20, Brijesh Singh wrote:
> >> Hi Jordan and Laszlo,
> >>
> >> Ping.
> >>
> >> It has been a while, Do you have any further feedbacks on this series ?
> >> If you want then I can rebase the patches before you commit into upstream repos.
> >>
> > 
> > I'm still dissappointed by the APRIORI usage.
> > 
> > As I understand it, you are also dissatisfied with this approach and
> > you hope to improve things by somehow hooking into DXE Core. Is that
> > true? If so, can you create a bugzilla regarding this feature? When
> > would you plan to work to address that?
> > 
> 
> I think we agree in that this particular use-case has shown the need for re-thinking
> the existing GCD interface. However, the problem we are trying to solve with this
> patch-set is enabling the SEV feature. As it turns out, we can do so within the
> existing GCD framework by simply leveraging the APRIORI hook already in use by OvmfPkg.
> 
> In that context, our proposal is that we limit the scope of this patch-set to simply
> enabling the SEV feature, and then allow the 'GCD experts' to separately propose updates
> to the framework.

This sounds like you don't plan to work on this, but will just leave
it to the 'GCD experts'. Is that right?

I am asking that you file and own a bugzilla for this. You'd obviously
need to work with the package owners though. Unless you drive this, I
don't think anyone will be motivated enough to get it fixed.

-Jordan

> 
> > I guess with that resolved, you could add an Acked-by from me.
> > 
> > In general, it'd also be nice to move the processor features to more
> > generic places, although that may be challenging if the next step is
> > some kind of platform hook from DXE Core. Maybe if the DXE Core calls
> > out to some protocol or signals an event then a driver in UefiCpuPkg
> > could handle the protocol implementation to modify the page tables.
> > 
> > -Jordan
> > 
> >


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-06 21:42       ` Jordan Justen
@ 2017-07-06 21:44         ` Duran, Leo
  2017-07-06 21:46         ` Andrew Fish
  1 sibling, 0 replies; 65+ messages in thread
From: Duran, Leo @ 2017-07-06 21:44 UTC (permalink / raw)
  To: 'Jordan Justen', Singh, Brijesh, edk2-devel@lists.01.org
  Cc: Singh, Brijesh, Lendacky, Thomas, Jeff Fan, Liming Gao,
	Laszlo Ersek, Jiewen Yao, Michael D Kinney

Jordan,

> -----Original Message-----
> From: Jordan Justen [mailto:jordan.l.justen@intel.com]
> Sent: Thursday, July 06, 2017 4:43 PM
> To: Singh, Brijesh <brijesh.singh@amd.com>; edk2-devel@lists.01.org
> Cc: Singh, Brijesh <brijesh.singh@amd.com>; Lendacky, Thomas
> <Thomas.Lendacky@amd.com>; Duran, Leo <leo.duran@amd.com>; Jeff
> Fan <jeff.fan@intel.com>; Liming Gao <liming.gao@intel.com>; Laszlo Ersek
> <lersek@redhat.com>; Jiewen Yao <jiewen.yao@intel.com>; Michael D
> Kinney <michael.d.kinney@intel.com>
> Subject: Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
> 
> On 2017-07-06 13:11:03, Brijesh Singh wrote:
> >
> >
> > On 07/06/2017 11:45 AM, Jordan Justen wrote:
> > > On 2017-07-05 15:31:20, Brijesh Singh wrote:
> > >> Hi Jordan and Laszlo,
> > >>
> > >> Ping.
> > >>
> > >> It has been a while, Do you have any further feedbacks on this series ?
> > >> If you want then I can rebase the patches before you commit into
> upstream repos.
> > >>
> > >
> > > I'm still dissappointed by the APRIORI usage.
> > >
> > > As I understand it, you are also dissatisfied with this approach and
> > > you hope to improve things by somehow hooking into DXE Core. Is that
> > > true? If so, can you create a bugzilla regarding this feature? When
> > > would you plan to work to address that?
> > >
> >
> > I think we agree in that this particular use-case has shown the need
> > for re-thinking the existing GCD interface. However, the problem we
> > are trying to solve with this patch-set is enabling the SEV feature.
> > As it turns out, we can do so within the existing GCD framework by simply
> leveraging the APRIORI hook already in use by OvmfPkg.
> >
> > In that context, our proposal is that we limit the scope of this
> > patch-set to simply enabling the SEV feature, and then allow the 'GCD
> > experts' to separately propose updates to the framework.
> 
> This sounds like you don't plan to work on this, but will just leave it to the
> 'GCD experts'. Is that right?
> 
> I am asking that you file and own a bugzilla for this. You'd obviously need to
> work with the package owners though. Unless you drive this, I don't think
> anyone will be motivated enough to get it fixed.
> 
[Duran, Leo] 
OK, we will file the BZ... But please don't let that keep you from moving these patches forward.
Thanks! :-).

> -Jordan
> 
> >
> > > I guess with that resolved, you could add an Acked-by from me.
> > >
> > > In general, it'd also be nice to move the processor features to more
> > > generic places, although that may be challenging if the next step is
> > > some kind of platform hook from DXE Core. Maybe if the DXE Core
> > > calls out to some protocol or signals an event then a driver in
> > > UefiCpuPkg could handle the protocol implementation to modify the
> page tables.
> > >
> > > -Jordan
> > >
> > >

^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  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
  1 sibling, 1 reply; 65+ messages in thread
From: Andrew Fish @ 2017-07-06 21:46 UTC (permalink / raw)
  To: Jordan Justen
  Cc: Brijesh Singh, edk2-devel-01, Thomas.Lendacky, Liming Gao,
	Leo Duran, Mike Kinney, Jiewen Yao, Laszlo Ersek, Jeff Fan


> On Jul 6, 2017, at 2:42 PM, Jordan Justen <jordan.l.justen@intel.com> wrote:
> 
> On 2017-07-06 13:11:03, Brijesh Singh wrote:
>> 
>> 
>> On 07/06/2017 11:45 AM, Jordan Justen wrote:
>>> On 2017-07-05 15:31:20, Brijesh Singh wrote:
>>>> Hi Jordan and Laszlo,
>>>> 
>>>> Ping.
>>>> 
>>>> It has been a while, Do you have any further feedbacks on this series ?
>>>> If you want then I can rebase the patches before you commit into upstream repos.
>>>> 
>>> 
>>> I'm still dissappointed by the APRIORI usage.
>>> 
>>> As I understand it, you are also dissatisfied with this approach and
>>> you hope to improve things by somehow hooking into DXE Core. Is that
>>> true? If so, can you create a bugzilla regarding this feature? When
>>> would you plan to work to address that?
>>> 
>> 
>> I think we agree in that this particular use-case has shown the need for re-thinking
>> the existing GCD interface. However, the problem we are trying to solve with this
>> patch-set is enabling the SEV feature. As it turns out, we can do so within the
>> existing GCD framework by simply leveraging the APRIORI hook already in use by OvmfPkg.
>> 
>> In that context, our proposal is that we limit the scope of this patch-set to simply
>> enabling the SEV feature, and then allow the 'GCD experts' to separately propose updates
>> to the framework.
> 
> This sounds like you don't plan to work on this, but will just leave
> it to the 'GCD experts'. Is that right?
> 
> I am asking that you file and own a bugzilla for this. You'd obviously
> need to work with the package owners though. Unless you drive this, I
> don't think anyone will be motivated enough to get it fixed.
> 

If some one will make a write up on this mailing list summarizing the issue with the GCD design, and what features are needed I can start a conversation on the PI working group list. 

Thanks,

Andrew Fish

> -Jordan
> 
>> 
>>> I guess with that resolved, you could add an Acked-by from me.
>>> 
>>> In general, it'd also be nice to move the processor features to more
>>> generic places, although that may be challenging if the next step is
>>> some kind of platform hook from DXE Core. Maybe if the DXE Core calls
>>> out to some protocol or signals an event then a driver in UefiCpuPkg
>>> could handle the protocol implementation to modify the page tables.
>>> 
>>> -Jordan
>>> 
>>> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-06 21:46         ` Andrew Fish
@ 2017-07-06 21:49           ` Duran, Leo
  2017-07-07  5:28             ` Jordan Justen
  0 siblings, 1 reply; 65+ messages in thread
From: Duran, Leo @ 2017-07-06 21:49 UTC (permalink / raw)
  To: 'afish@apple.com', Jordan Justen
  Cc: Singh, Brijesh, edk2-devel-01, Lendacky, Thomas, Liming Gao,
	Mike Kinney, Jiewen Yao, Laszlo Ersek, Jeff Fan

Hi Andrew, 

> -----Original Message-----
> From: afish@apple.com [mailto:afish@apple.com]
> Sent: Thursday, July 06, 2017 4:46 PM
> To: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Singh, Brijesh <brijesh.singh@amd.com>; edk2-devel-01 <edk2-
> devel@lists.01.org>; Lendacky, Thomas <Thomas.Lendacky@amd.com>;
> Liming Gao <liming.gao@intel.com>; Duran, Leo <leo.duran@amd.com>;
> Mike Kinney <michael.d.kinney@intel.com>; Jiewen Yao
> <jiewen.yao@intel.com>; Laszlo Ersek <lersek@redhat.com>; Jeff Fan
> <jeff.fan@intel.com>
> Subject: Re: [edk2] [PATCH v6 00/17] x86: Secure Encrypted Virtualization
> (AMD)
> 
> 
> > On Jul 6, 2017, at 2:42 PM, Jordan Justen <jordan.l.justen@intel.com>
> wrote:
> >
> > On 2017-07-06 13:11:03, Brijesh Singh wrote:
> >>
> >>
> >> On 07/06/2017 11:45 AM, Jordan Justen wrote:
> >>> On 2017-07-05 15:31:20, Brijesh Singh wrote:
> >>>> Hi Jordan and Laszlo,
> >>>>
> >>>> Ping.
> >>>>
> >>>> It has been a while, Do you have any further feedbacks on this series ?
> >>>> If you want then I can rebase the patches before you commit into
> upstream repos.
> >>>>
> >>>
> >>> I'm still dissappointed by the APRIORI usage.
> >>>
> >>> As I understand it, you are also dissatisfied with this approach and
> >>> you hope to improve things by somehow hooking into DXE Core. Is that
> >>> true? If so, can you create a bugzilla regarding this feature? When
> >>> would you plan to work to address that?
> >>>
> >>
> >> I think we agree in that this particular use-case has shown the need
> >> for re-thinking the existing GCD interface. However, the problem we
> >> are trying to solve with this patch-set is enabling the SEV feature.
> >> As it turns out, we can do so within the existing GCD framework by simply
> leveraging the APRIORI hook already in use by OvmfPkg.
> >>
> >> In that context, our proposal is that we limit the scope of this
> >> patch-set to simply enabling the SEV feature, and then allow the 'GCD
> >> experts' to separately propose updates to the framework.
> >
> > This sounds like you don't plan to work on this, but will just leave
> > it to the 'GCD experts'. Is that right?
> >
> > I am asking that you file and own a bugzilla for this. You'd obviously
> > need to work with the package owners though. Unless you drive this, I
> > don't think anyone will be motivated enough to get it fixed.
> >
> 
> If some one will make a write up on this mailing list summarizing the issue
> with the GCD design, and what features are needed I can start a
> conversation on the PI working group list.
> 
> Thanks,
> 
> Andrew Fish
[Duran, Leo] 
Excellent proposal, thanks!

How about we do that on a separate thread (maybe with a reference back to this one, if needed for context)?
Basically, we would like these patch-set to move upstream independent of the GCD write-up.

I hope that's reasonable & agreeable by all.
Leo.
> 
> > -Jordan
> >
> >>
> >>> I guess with that resolved, you could add an Acked-by from me.
> >>>
> >>> In general, it'd also be nice to move the processor features to more
> >>> generic places, although that may be challenging if the next step is
> >>> some kind of platform hook from DXE Core. Maybe if the DXE Core
> >>> calls out to some protocol or signals an event then a driver in
> >>> UefiCpuPkg could handle the protocol implementation to modify the
> page tables.
> >>>
> >>> -Jordan
> >>>
> >>>
> > _______________________________________________
> > edk2-devel mailing list
> > edk2-devel@lists.01.org
> > https://lists.01.org/mailman/listinfo/edk2-devel



^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-06 21:49           ` Duran, Leo
@ 2017-07-07  5:28             ` Jordan Justen
  2017-07-07 18:29               ` Brijesh Singh
  0 siblings, 1 reply; 65+ messages in thread
From: Jordan Justen @ 2017-07-07  5:28 UTC (permalink / raw)
  To: 'afish@apple.com', Duran, Leo
  Cc: Singh, Brijesh, edk2-devel-01, Lendacky, Thomas, Liming Gao,
	Mike Kinney, Jiewen Yao, Laszlo Ersek, Jeff Fan

On 2017-07-06 14:49:44, Duran, Leo wrote:
> 
> > -----Original Message-----
> > From: afish@apple.com [mailto:afish@apple.com]
> > Sent: Thursday, July 06, 2017 4:46 PM
> > 
> > > On Jul 6, 2017, at 2:42 PM, Jordan Justen <jordan.l.justen@intel.com>
> > wrote:
> > >
> > > On 2017-07-06 13:11:03, Brijesh Singh wrote:
> > >>
> > >>
> > >> On 07/06/2017 11:45 AM, Jordan Justen wrote:
> > >
> > > I am asking that you file and own a bugzilla for this. You'd obviously
> > > need to work with the package owners though. Unless you drive this, I
> > > don't think anyone will be motivated enough to get it fixed.
> > >
> > 
> > If some one will make a write up on this mailing list summarizing the issue
> > with the GCD design, and what features are needed I can start a
> > conversation on the PI working group list.
> > 
> > Thanks,
> > 
> > Andrew Fish
> [Duran, Leo] 
> Excellent proposal, thanks!
> 
> How about we do that on a separate thread (maybe with a reference back to this one, if needed for context)?
> Basically, we would like these patch-set to move upstream independent of the GCD write-up.

This sounds reasonable, but can you file the bugzilla ticket? I think
it would be fine to add more details to the bugzilla later.

It sounds like it'd be good to note in the ticker that it may require
discussion in the PIWG.

If you document what is needed in the bugzilla, then maybe Andrew can
pull the information from there.

-Jordan


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-07  5:28             ` Jordan Justen
@ 2017-07-07 18:29               ` Brijesh Singh
  2017-07-07 23:10                 ` Jordan Justen
  0 siblings, 1 reply; 65+ messages in thread
From: Brijesh Singh @ 2017-07-07 18:29 UTC (permalink / raw)
  To: Jordan Justen, 'afish@apple.com', Duran, Leo
  Cc: brijesh.singh, edk2-devel-01, Lendacky, Thomas, Liming Gao,
	Mike Kinney, Jiewen Yao, Laszlo Ersek, Jeff Fan

Hi Jordan and Andrew,

On 07/07/2017 12:28 AM, Jordan Justen wrote:
> On 2017-07-06 14:49:44, Duran, Leo wrote:
>>
>>> -----Original Message-----
>>> From: afish@apple.com [mailto:afish@apple.com]
>>> Sent: Thursday, July 06, 2017 4:46 PM
>>>
>>>> On Jul 6, 2017, at 2:42 PM, Jordan Justen <jordan.l.justen@intel.com>
>>> wrote:
>>>>
>>>> On 2017-07-06 13:11:03, Brijesh Singh wrote:
>>>>>
>>>>>
>>>>> On 07/06/2017 11:45 AM, Jordan Justen wrote:
>>>>
>>>> I am asking that you file and own a bugzilla for this. You'd obviously
>>>> need to work with the package owners though. Unless you drive this, I
>>>> don't think anyone will be motivated enough to get it fixed.
>>>>
>>>
>>> If some one will make a write up on this mailing list summarizing the issue
>>> with the GCD design, and what features are needed I can start a
>>> conversation on the PI working group list.
>>>
>>> Thanks,
>>>
>>> Andrew Fish
>> [Duran, Leo]
>> Excellent proposal, thanks!
>>
>> How about we do that on a separate thread (maybe with a reference back to this one, if needed for context)?
>> Basically, we would like these patch-set to move upstream independent of the GCD write-up.
> 
> This sounds reasonable, but can you file the bugzilla ticket? I think
> it would be fine to add more details to the bugzilla later.
> 
> It sounds like it'd be good to note in the ticker that it may require
> discussion in the PIWG.
> 
> If you document what is needed in the bugzilla, then maybe Andrew can
> pull the information from there.
> 

I have created a bugzilla [1]. I have tried to give some background on what we are trying to do.
Lets take the GCD framework discussion on bugzilla (or separate thread).

[1] https://bugzilla.tianocore.org/show_bug.cgi?id=623


> -Jordan
> 


^ permalink raw reply	[flat|nested] 65+ messages in thread

* Re: [PATCH v6 00/17] x86: Secure Encrypted Virtualization (AMD)
  2017-07-07 18:29               ` Brijesh Singh
@ 2017-07-07 23:10                 ` Jordan Justen
  0 siblings, 0 replies; 65+ messages in thread
From: Jordan Justen @ 2017-07-07 23:10 UTC (permalink / raw)
  To: 'afish@apple.com', Duran, Leo, Brijesh Singh
  Cc: Lendacky, Thomas, edk2-devel-01, Liming Gao, Jiewen Yao,
	Mike Kinney, Laszlo Ersek, Jeff Fan

On 2017-07-07 11:29:20, Brijesh Singh wrote:
> I have created a bugzilla [1]. I have tried to give some background on what we are trying to do.
> Lets take the GCD framework discussion on bugzilla (or separate thread).
> 
> [1] https://bugzilla.tianocore.org/show_bug.cgi?id=623
> 

Thanks.

I'll take a final look over v8 and push them. (I'll add
Reviewed-by/Acked-by to more patches.) I expect I should finish within
the next day, or Monday at the latest.

-Jordan


^ permalink raw reply	[flat|nested] 65+ messages in thread

end of thread, other threads:[~2017-07-07 23:08 UTC | newest]

Thread overview: 65+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
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

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox