public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v8 0/6] SEV Live Migration support for OVMF.
@ 2022-04-05 17:28 Ashish Kalra
  2022-04-05 17:30 ` [PATCH v8 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature Ashish Kalra
                   ` (5 more replies)
  0 siblings, 6 replies; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:28 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3467

By default all the SEV guest memory regions are considered encrypted,
if a guest changes the encryption attribute of the page (e.g mark a
page as decrypted) then notify hypervisor. Hypervisor will need to
track the unencrypted pages. The information will be used during
guest live migration, guest page migration and guest debugging.

The patch-set detects if it is running under KVM hypervisor and then
checks for SEV live migration feature support via KVM_FEATURE_CPUID,
if detected setup a new UEFI enviroment variable to indicate OVMF
support for SEV live migration.

This environment variable is created by UEFI but consumed by the
(guest) linux kernel. This is actually part of a 3-way negotiation
of the live migration feature between hypervisor, guest OVMF and
guest kernel. Host indicates support for live migration, which is
detected by OVMF and correspondingly OVMF sets this SetLiveMigrationEnabled
UEFI variable, which is read by the guest kernel and it indicates
to the guest kernel that both host and OVMF support and have
enabled the live migration feature.

A branch containing these patches is available here:
https://github.com/ashkalra/edk2-1/tree/sev_live_migration_v5_23

Changes since v7:
 - Rebase to master

Changes since v6:
 - Move KvmDetectSevLiveMigrationFeature() function in a new header
   file PeiDxeMemEncryptSevLibInternal.h as this function is
   only used internally.
 - Code Style fixes.
 - More descriptive comments for use of SetLiveMigrationEnabled
   UEFI variable.

Changes since v5:
 - Split first patch into three components, one patch for the
   MemEncryptSevLiveMigrationIsEnabled() API, one patch for the
   SetMemoryEncDecHypercall3() API, one patch to make use of the
   SetMemoryEncDecHypercall3() API. 
 - Fix patch subject, in code and patch comments and 
   additionally add relevant comments.
 - Replace SetMemoryEncDecHypercall3() API's Status argument
   with a boolean IsEncrypted argument and corresponding fixes
   to users of this API call.
 - Fix AsciiStrCmp() usage in KVM hypervisor detection code.

Changes since v4:
 - Remove MemEncryptHypercallLib Library and add support to issue
   hypercall in the BaseMemEncryptSevLib library itself.
 - For SEV-ES, make the VC handler hypercall aware by comparing
   the hypercall number and add the additional register values
   in the GHCB.
 - Fix comments in the hypercall API interface.
 - The encryption bit is set/clear on the smallest page size, hence
   use the 4k page size in MAP_GPA_RANGE hypercall.
 - Make the hypercall expect the guest physical address to be
   page-aligned.
 - Add KVM live migration feature flag check in BaseMemEncryptSevLib
   library similar to how BaseMemEncryptSevLib does for the
   MemEncryptSevIsEnabled() and check it before invoking HC. Also
   export the MemEncryptSevLiveMigrationIsEnabled() function as 
   part of the library.
 - Add error handling on hypercall return, on failure, return error
   code to caller which potentially will cause an assert() and
   terminate the boot.
 
Changes since v3:
 - Fix all DSC files under OvmfPkg except X64 to add support for 
   BaseMemEncryptLib and add NULL instance of BaseMemEncryptLib
   for 32 bit platforms.
 - Add the MemEncryptHypercallLib-related files to Maintainers.txt,
   in section "OvmfPkg: Confidential Computing".
 - Add support for the new KVM_HC_MAP_GPA_RANGE hypercall interface.
 - Add patch for SEV live migration support.

Changes since v2:
 - GHCB_BASE setup during reset-vector as decrypted is marked explicitly
   in the hypervisor page encryption bitmap after setting the 
   PcdSevEsIsEnabled PCD.

Changes since v1:
 - Mark GHCB_BASE setup during reset-vector as decrypted explicitly in
   the hypervisor page encryption bitmap.
 - Resending the series with correct shallow threading.

Ashish Kalra (6):
  OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature.
  OvmfPkg/BaseMemEncryptLib: Hypercall API for page encryption state
    change
  OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change
    hypercall
  OvmfPkg/VmgExitLib: Encryption state change hypercall support in VC
    handler
  OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall
  OvmfPkg/AmdSevDxe: Add support for SEV live migration.

 OvmfPkg/AmdSevDxe/AmdSevDxe.c                 | 67 +++++++++++++++++++
 OvmfPkg/AmdSevDxe/AmdSevDxe.inf               |  4 ++
 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h    | 20 ++++++
 OvmfPkg/Include/Library/MemEncryptSevLib.h    | 64 ++++++++++++++++++
 .../DxeMemEncryptSevLib.inf                   |  1 +
 .../DxeMemEncryptSevLibInternal.c             | 49 ++++++++++++--
 .../Ia32/MemEncryptSevLib.c                   | 27 ++++++++
 .../PeiDxeMemEncryptSevLibInternal.c          | 58 ++++++++++++++++
 .../PeiDxeMemEncryptSevLibInternal.h          | 31 +++++++++
 .../PeiMemEncryptSevLib.inf                   |  1 +
 .../PeiMemEncryptSevLibInternal.c             | 42 ++++++++++++
 .../SecMemEncryptSevLibInternal.c             | 38 +++++++++++
 .../X64/AsmHelperStub.nasm                    | 33 +++++++++
 .../X64/MemEncryptSevLib.c                    | 66 ++++++++++++++++++
 .../X64/PeiDxeVirtualMemory.c                 | 16 +++++
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 13 ++++
 OvmfPkg/OvmfPkg.dec                           |  1 +
 OvmfPkg/PlatformPei/AmdSev.c                  | 11 +++
 18 files changed, 538 insertions(+), 4 deletions(-)
 create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm

-- 
2.25.1


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

* [PATCH v8 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature.
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
@ 2022-04-05 17:30 ` Ashish Kalra
  2022-04-05 17:31 ` [PATCH v8 2/6] OvmfPkg/BaseMemEncryptLib: Hypercall API for page encryption state change Ashish Kalra
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:30 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Add support to check if we are running inside KVM HVM and
KVM HVM supports SEV Live Migration feature.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h    | 12 ++++
 .../DxeMemEncryptSevLibInternal.c             | 49 ++++++++++++++--
 .../PeiDxeMemEncryptSevLibInternal.c          | 58 +++++++++++++++++++
 .../PeiDxeMemEncryptSevLibInternal.h          | 31 ++++++++++
 .../PeiMemEncryptSevLibInternal.c             | 42 ++++++++++++++
 .../SecMemEncryptSevLibInternal.c             | 18 ++++++
 6 files changed, 206 insertions(+), 4 deletions(-)
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index 4fa9c0d700..babec60df4 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -83,6 +83,18 @@ MemEncryptSevIsEnabled (
   VOID
   );
 
+/**
+  Returns a boolean to indicate whether SEV live migration is enabled.
+
+  @retval TRUE           SEV live migration is enabled
+  @retval FALSE          SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+  VOID
+  );
+
 /**
   This function clears memory encryption bit for the memory region specified by
   BaseAddress and NumPages from the current page table context.
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
index 4aba0075b9..d80ebe2fac 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLibInternal.c
@@ -18,10 +18,14 @@
 #include <Uefi/UefiBaseType.h>
 #include <ConfidentialComputingGuestAttr.h>
 
-STATIC UINT64   mCurrentAttr            = 0;
-STATIC BOOLEAN  mCurrentAttrRead        = FALSE;
-STATIC UINT64   mSevEncryptionMask      = 0;
-STATIC BOOLEAN  mSevEncryptionMaskSaved = FALSE;
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
+STATIC UINT64   mCurrentAttr                   = 0;
+STATIC BOOLEAN  mCurrentAttrRead               = FALSE;
+STATIC UINT64   mSevEncryptionMask             = 0;
+STATIC BOOLEAN  mSevEncryptionMaskSaved        = FALSE;
+STATIC BOOLEAN  mSevLiveMigrationStatus        = FALSE;
+STATIC BOOLEAN  mSevLiveMigrationStatusChecked = FALSE;
 
 /**
   The function check if the specified Attr is set.
@@ -111,6 +115,24 @@ MemEncryptSevSnpIsEnabled (
   return ConfidentialComputingGuestHas (CCAttrAmdSevSnp);
 }
 
+/**
+  Figures out if we are running inside KVM HVM and
+  KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature (
+  VOID
+  )
+{
+  if (KvmDetectSevLiveMigrationFeature ()) {
+    mSevLiveMigrationStatus = TRUE;
+  }
+
+  mSevLiveMigrationStatusChecked = TRUE;
+}
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
@@ -141,6 +163,25 @@ MemEncryptSevIsEnabled (
   return ConfidentialComputingGuestHas (CCAttrAmdSev);
 }
 
+/**
+  Returns a boolean to indicate whether SEV live migration is enabled.
+
+  @retval TRUE           SEV live migration is enabled
+  @retval FALSE          SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+  VOID
+  )
+{
+  if (!mSevLiveMigrationStatusChecked) {
+    InternalDetectSevLiveMigrationFeature ();
+  }
+
+  return mSevLiveMigrationStatus;
+}
+
 /**
   Returns the SEV encryption mask.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
index 78ea16ae06..868392f7e2 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.c
@@ -16,6 +16,8 @@
 #include <Register/SmramSaveStateMap.h>
 #include <Uefi/UefiBaseType.h>
 
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
 /**
   Locate the page range that covers the initial (pre-SMBASE-relocation) SMRAM
   Save State Map.
@@ -61,3 +63,59 @@ MemEncryptSevLocateInitialSmramSaveStateMapPages (
 
   return RETURN_SUCCESS;
 }
+
+/**
+  Figures out if we are running inside KVM HVM and
+  KVM HVM supports SEV Live Migration feature.
+
+  @retval TRUE           SEV live migration is supported.
+  @retval FALSE          SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature (
+  VOID
+  )
+{
+  CHAR8   Signature[13];
+  UINT32  mKvmLeaf;
+  UINT32  RegEax;
+  UINT32  RegEbx;
+  UINT32  RegEcx;
+  UINT32  RegEdx;
+
+  Signature[12] = '\0';
+  for (mKvmLeaf = 0x40000000; mKvmLeaf < 0x40010000; mKvmLeaf += 0x100) {
+    AsmCpuid (
+      mKvmLeaf,
+      NULL,
+      (UINT32 *)&Signature[0],
+      (UINT32 *)&Signature[4],
+      (UINT32 *)&Signature[8]
+      );
+
+    if (AsciiStrCmp (Signature, "KVMKVMKVM") == 0) {
+      DEBUG ((
+        DEBUG_INFO,
+        "%a: KVM Detected, signature = %a\n",
+        __FUNCTION__,
+        Signature
+        ));
+
+      RegEax = mKvmLeaf + 1;
+      RegEcx = 0;
+      AsmCpuid (mKvmLeaf + 1, &RegEax, &RegEbx, &RegEcx, &RegEdx);
+      if ((RegEax & KVM_FEATURE_MIGRATION_CONTROL) != 0) {
+        DEBUG ((
+          DEBUG_INFO,
+          "%a: SEV Live Migration feature supported\n",
+          __FUNCTION__
+          ));
+
+        return TRUE;
+      }
+    }
+  }
+
+  return FALSE;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
new file mode 100644
index 0000000000..b0ef053cd9
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiDxeMemEncryptSevLibInternal.h
@@ -0,0 +1,31 @@
+/** @file
+
+  Secure Encrypted Virtualization (SEV) library helper function
+
+  Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
+#define PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
+
+#include <Library/BaseLib.h>
+
+#define KVM_FEATURE_MIGRATION_CONTROL  BIT17
+
+/**
+  Figures out if we are running inside KVM HVM and
+  KVM HVM supports SEV Live Migration feature.
+
+  @retval TRUE           SEV live migration is supported.
+  @retval FALSE          SEV live migration is not supported.
+**/
+BOOLEAN
+EFIAPI
+KvmDetectSevLiveMigrationFeature (
+  VOID
+  );
+
+#endif // PEI_DXE_MEM_ENCRYPT_SEV_LIB_INTERNAL_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
index 3f8f91a5da..72bd6e98f8 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLibInternal.c
@@ -17,6 +17,11 @@
 #include <Register/Cpuid.h>
 #include <Uefi/UefiBaseType.h>
 
+#include "PeiDxeMemEncryptSevLibInternal.h"
+
+STATIC BOOLEAN  mSevLiveMigrationStatus        = FALSE;
+STATIC BOOLEAN  mSevLiveMigrationStatusChecked = FALSE;
+
 /**
    Read the workarea to determine whether SEV is enabled. If enabled,
    then return the SevEsWorkArea pointer.
@@ -83,6 +88,24 @@ MemEncryptSevSnpIsEnabled (
   return Msr.Bits.SevSnpBit ? TRUE : FALSE;
 }
 
+/**
+  Figures out if we are running inside KVM HVM and
+  KVM HVM supports SEV Live Migration feature.
+**/
+STATIC
+VOID
+EFIAPI
+InternalDetectSevLiveMigrationFeature (
+  VOID
+  )
+{
+  if (KvmDetectSevLiveMigrationFeature ()) {
+    mSevLiveMigrationStatus = TRUE;
+  }
+
+  mSevLiveMigrationStatusChecked = TRUE;
+}
+
 /**
   Returns a boolean to indicate whether SEV-ES is enabled.
 
@@ -121,6 +144,25 @@ MemEncryptSevIsEnabled (
   return Msr.Bits.SevBit ? TRUE : FALSE;
 }
 
+/**
+  Returns a boolean to indicate whether SEV live migration is enabled.
+
+  @retval TRUE           SEV live migration is enabled
+  @retval FALSE          SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+  VOID
+  )
+{
+  if (!mSevLiveMigrationStatusChecked) {
+    InternalDetectSevLiveMigrationFeature ();
+  }
+
+  return mSevLiveMigrationStatus;
+}
+
 /**
   Returns the SEV encryption mask.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index 80aceba01b..b05dbec02e 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -121,6 +121,24 @@ MemEncryptSevIsEnabled (
   return Msr.Bits.SevBit ? TRUE : FALSE;
 }
 
+/**
+  Returns a boolean to indicate whether SEV live migration is enabled.
+
+  @retval TRUE           SEV live migration is enabled
+  @retval FALSE          SEV live migration is not enabled
+**/
+BOOLEAN
+EFIAPI
+MemEncryptSevLiveMigrationIsEnabled (
+  VOID
+  )
+{
+  //
+  // Not used in SEC phase.
+  //
+  return FALSE;
+}
+
 /**
   Returns the SEV encryption mask.
 
-- 
2.25.1


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

* [PATCH v8 2/6] OvmfPkg/BaseMemEncryptLib: Hypercall API for page encryption state change
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
  2022-04-05 17:30 ` [PATCH v8 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature Ashish Kalra
@ 2022-04-05 17:31 ` Ashish Kalra
  2022-04-05 17:32 ` [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall Ashish Kalra
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:31 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Add API to issue hypercall on page encryption state change.

By default all the SEV guest memory regions are considered encrypted,
if a guest changes the encryption attribute of the page (e.g mark a
page as decrypted) then notify hypervisor. Hypervisor will need to
track the unencrypted pages. The information will be used during
guest live migration, guest page migration and guest debugging.

This hypercall is used to notify hypervisor when the page's
encryption state changes.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 OvmfPkg/Include/Library/MemEncryptSevLib.h    | 52 +++++++++++++++
 .../DxeMemEncryptSevLib.inf                   |  1 +
 .../Ia32/MemEncryptSevLib.c                   | 27 ++++++++
 .../PeiMemEncryptSevLib.inf                   |  1 +
 .../SecMemEncryptSevLibInternal.c             | 20 ++++++
 .../X64/AsmHelperStub.nasm                    | 33 ++++++++++
 .../X64/MemEncryptSevLib.c                    | 66 +++++++++++++++++++
 7 files changed, 200 insertions(+)
 create mode 100644 OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm

diff --git a/OvmfPkg/Include/Library/MemEncryptSevLib.h b/OvmfPkg/Include/Library/MemEncryptSevLib.h
index babec60df4..b60496c26f 100644
--- a/OvmfPkg/Include/Library/MemEncryptSevLib.h
+++ b/OvmfPkg/Include/Library/MemEncryptSevLib.h
@@ -240,4 +240,56 @@ MemEncryptSevSnpPreValidateSystemRam (
   IN UINTN             NumPages
   );
 
+/**
+ This hypercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in]   PhysicalAddress       The physical address that is the start address
+                                    of a memory region.
+ @param[in]   Pages                 Number of pages in memory region.
+ @param[in]   IsEncrypted           Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS             Hypercall returned success.
+ @retval RETURN_UNSUPPORTED         Hypercall not supported.
+ @retval RETURN_NO_MAPPING          Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+  IN  UINTN    PhysicalAddress,
+  IN  UINTN    Pages,
+  IN  BOOLEAN  IsEncrypted
+  );
+
+#define KVM_HC_MAP_GPA_RANGE          12
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_4K  0
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_2M  BIT0
+#define KVM_MAP_GPA_RANGE_PAGE_SZ_1G  BIT1
+#define KVM_MAP_GPA_RANGE_ENC_STATE(n)  ((n) << 4)
+#define KVM_MAP_GPA_RANGE_ENCRYPTED  KVM_MAP_GPA_RANGE_ENC_STATE(1)
+#define KVM_MAP_GPA_RANGE_DECRYPTED  KVM_MAP_GPA_RANGE_ENC_STATE(0)
+
+/**
+ Interface exposed by the ASM implementation of the core hypercall
+
+ @param[in]   HypercallNum          KVM_HC_MAP_GPA_RANGE hypercall.
+ @param[in]   PhysicalAddress       The physical address that is the start address
+                                    of a memory region.
+ @param[in]   Pages                 Number of pages in memory region.
+ @param[in]   Attributes            Bits 3:0 - preferred page size encoding,
+                                    0 = 4kb, 1 = 2mb, 2 = 1gb, etc...
+                                    Bit  4 - plaintext = 0, encrypted = 1
+                                    Bits 63:5 - reserved (must be zero)
+
+  @retval Hypercall returned status.
+**/
+UINTN
+EFIAPI
+SetMemoryEncDecHypercall3AsmStub (
+  IN  UINTN  HypercallNum,
+  IN  UINTN  PhysicalAddress,
+  IN  UINTN  Pages,
+  IN  UINTN  Attributes
+  );
+
 #endif // _MEM_ENCRYPT_SEV_LIB_H_
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
index 35b7d519d9..af7d2059a2 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/DxeMemEncryptSevLib.inf
@@ -40,6 +40,7 @@
   X64/SnpPageStateChangeInternal.c
   X64/VirtualMemory.c
   X64/VirtualMemory.h
+  X64/AsmHelperStub.nasm
 
 [Sources.IA32]
   Ia32/MemEncryptSevLib.c
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
index f92299fc77..c1c10a61c4 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/Ia32/MemEncryptSevLib.c
@@ -153,3 +153,30 @@ MemEncryptSevSnpPreValidateSystemRam (
 {
   ASSERT (FALSE);
 }
+
+/**
+ This hyercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in]   PhysicalAddress       The physical address that is the start address
+                                    of a memory region.
+ @param[in]   Pages                 Number of Pages in the memory region.
+ @param[in]   IsEncrypted           Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS             Hypercall returned success.
+ @retval RETURN_UNSUPPORTED         Hypercall not supported.
+ @retval RETURN_NO_MAPPING          Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+  IN  UINTN    PhysicalAddress,
+  IN  UINTN    Pages,
+  IN  BOOLEAN  IsEncrypted
+  )
+{
+  //
+  // Memory encryption bit is not accessible in 32-bit mode
+  //
+  return RETURN_UNSUPPORTED;
+}
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
index 714da33237..e28008d26b 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/PeiMemEncryptSevLib.inf
@@ -40,6 +40,7 @@
   X64/SnpPageStateChangeInternal.c
   X64/VirtualMemory.c
   X64/VirtualMemory.h
+  X64/AsmHelperStub.nasm
 
 [Sources.IA32]
   Ia32/MemEncryptSevLib.c
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
index b05dbec02e..d7504ea9e7 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/SecMemEncryptSevLibInternal.c
@@ -139,6 +139,26 @@ MemEncryptSevLiveMigrationIsEnabled (
   return FALSE;
 }
 
+/**
+  Interface exposed by the ASM implementation of the core hypercall
+
+  @retval Hypercall returned status.
+**/
+UINTN
+EFIAPI
+SetMemoryEncDecHypercall3AsmStub (
+  IN  UINTN  HypercallNum,
+  IN  UINTN  PhysicalAddress,
+  IN  UINTN  Pages,
+  IN  UINTN  Attributes
+  )
+{
+  //
+  // Not used in SEC phase.
+  //
+  return RETURN_UNSUPPORTED;
+}
+
 /**
   Returns the SEV encryption mask.
 
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm
new file mode 100644
index 0000000000..0ec35dd9b6
--- /dev/null
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/AsmHelperStub.nasm
@@ -0,0 +1,33 @@
+/** @file
+
+  ASM helper stub to invoke hypercall
+
+  Copyright (c) 2021, AMD Incorporated. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+DEFAULT REL
+SECTION .text
+
+; UINTN
+; EFIAPI
+; SetMemoryEncDecHypercall3AsmStub (
+;   IN UINTN HypercallNum,
+;   IN UINTN Arg1,
+;   IN UINTN Arg2,
+;   IN UINTN Arg3
+;   );
+global ASM_PFX(SetMemoryEncDecHypercall3AsmStub)
+ASM_PFX(SetMemoryEncDecHypercall3AsmStub):
+  ; UEFI calling conventions require RBX to
+  ; be nonvolatile/callee-saved.
+  push rbx
+  mov rax, rcx    ; Copy HypercallNumber to rax
+  mov rbx, rdx    ; Copy Arg1 to the register expected by KVM
+  mov rcx, r8     ; Copy Arg2 to register expected by KVM
+  mov rdx, r9     ; Copy Arg3 to register expected by KVM
+  vmmcall         ; Call VMMCALL
+  pop rbx
+  ret
diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
index e7c703bb9a..a64ff2a5e6 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/MemEncryptSevLib.c
@@ -142,3 +142,69 @@ MemEncryptSevClearMmioPageEncMask (
            EFI_PAGES_TO_SIZE (NumPages)
            );
 }
+
+/**
+ This hyercall is used to notify hypervisor when the page's encryption
+ state changes.
+
+ @param[in]   PhysicalAddress       The physical address that is the start address
+                                    of a memory region.
+ @param[in]   Pages                 Number of Pages in the memory region.
+ @param[in]   IsEncrypted           Encrypted or Decrypted.
+
+ @retval RETURN_SUCCESS             Hypercall returned success.
+ @retval RETURN_UNSUPPORTED         Hypercall not supported.
+ @retval RETURN_NO_MAPPING          Hypercall returned error.
+**/
+RETURN_STATUS
+EFIAPI
+SetMemoryEncDecHypercall3 (
+  IN  UINTN    PhysicalAddress,
+  IN  UINTN    Pages,
+  IN  BOOLEAN  IsEncrypted
+  )
+{
+  RETURN_STATUS  Ret;
+  UINTN          Error;
+  UINTN          EncryptState;
+
+  Ret = RETURN_UNSUPPORTED;
+
+  if (MemEncryptSevLiveMigrationIsEnabled ()) {
+    Ret = RETURN_SUCCESS;
+    //
+    // The encryption bit is set/clear on the smallest page size, hence
+    // use the 4k page size in MAP_GPA_RANGE hypercall below.
+    //
+    // Also, when the GCD map is being walked and the c-bit being cleared
+    // from MMIO and NonExistent memory spaces, the physical address
+    // range being passed may not be page-aligned and adding an assert
+    // here prevents booting. Hence, rounding it down when calling
+    // SetMemoryEncDecHypercall3AsmStub below.
+    //
+
+    EncryptState = IsEncrypted ? KVM_MAP_GPA_RANGE_ENCRYPTED :
+                   KVM_MAP_GPA_RANGE_DECRYPTED;
+
+    Error = SetMemoryEncDecHypercall3AsmStub (
+              KVM_HC_MAP_GPA_RANGE,
+              PhysicalAddress & ~EFI_PAGE_MASK,
+              Pages,
+              KVM_MAP_GPA_RANGE_PAGE_SZ_4K | EncryptState
+              );
+
+    if (Error != 0) {
+      DEBUG ((
+        DEBUG_ERROR,
+        "SetMemoryEncDecHypercall3 failed, Phys = %x, Pages = %d, Err = %Ld\n",
+        PhysicalAddress,
+        Pages,
+        (INT64)Error
+        ));
+
+      Ret = RETURN_NO_MAPPING;
+    }
+  }
+
+  return Ret;
+}
-- 
2.25.1


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

* [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
  2022-04-05 17:30 ` [PATCH v8 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature Ashish Kalra
  2022-04-05 17:31 ` [PATCH v8 2/6] OvmfPkg/BaseMemEncryptLib: Hypercall API for page encryption state change Ashish Kalra
@ 2022-04-05 17:32 ` Ashish Kalra
  2022-06-07  8:38   ` [edk2-devel] " nikunj
  2022-04-05 17:32 ` [PATCH v8 4/6] OvmfPkg/VmgExitLib: Encryption state change hypercall support in VC handler Ashish Kalra
                   ` (2 subsequent siblings)
  5 siblings, 1 reply; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:32 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Invoke the hypercall API to notify hypervisor when the page's
encryption state changes.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 .../X64/PeiDxeVirtualMemory.c                    | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
index b9c0a5b25a..b8478dd948 100644
--- a/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
+++ b/OvmfPkg/Library/BaseMemEncryptSevLib/X64/PeiDxeVirtualMemory.c
@@ -701,6 +701,7 @@ SetMemoryEncDec (
   UINT64                          PgTableMask;
   UINT64                          AddressEncMask;
   BOOLEAN                         IsWpEnabled;
+  BOOLEAN                         CBitChanged;
   UINTN                           OrigLength;
   RETURN_STATUS                   Status;
 
@@ -769,6 +770,7 @@ SetMemoryEncDec (
   // Save the specified length and physical address (we need it later).
   //
   OrigLength          = Length;
+  CBitChanged         = FALSE;
   OrigPhysicalAddress = PhysicalAddress;
 
   while (Length != 0) {
@@ -829,6 +831,7 @@ SetMemoryEncDec (
           ));
         PhysicalAddress += BIT30;
         Length          -= BIT30;
+        CBitChanged      = TRUE;
       } else {
         //
         // We must split the page
@@ -884,6 +887,7 @@ SetMemoryEncDec (
           SetOrClearCBit (&PageDirectory2MEntry->Uint64, Mode);
           PhysicalAddress += BIT21;
           Length          -= BIT21;
+          CBitChanged      = TRUE;
         } else {
           //
           // We must split up this page into 4K pages
@@ -927,6 +931,7 @@ SetMemoryEncDec (
         SetOrClearCBit (&PageTableEntry->Uint64, Mode);
         PhysicalAddress += EFI_PAGE_SIZE;
         Length          -= EFI_PAGE_SIZE;
+        CBitChanged      = TRUE;
       }
     }
   }
@@ -959,6 +964,17 @@ SetMemoryEncDec (
       );
   }
 
+  //
+  // Notify Hypervisor on C-bit status
+  //
+  if (CBitChanged) {
+    Status = SetMemoryEncDecHypercall3 (
+               OrigPhysicalAddress,
+               EFI_SIZE_TO_PAGES (OrigLength),
+               (Mode == SetCBit) ? TRUE : FALSE
+               );
+  }
+
 Done:
   //
   // Restore page table write protection, if any.
-- 
2.25.1


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

* [PATCH v8 4/6] OvmfPkg/VmgExitLib: Encryption state change hypercall support in VC handler
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
                   ` (2 preceding siblings ...)
  2022-04-05 17:32 ` [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall Ashish Kalra
@ 2022-04-05 17:32 ` Ashish Kalra
  2022-04-05 17:32 ` [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall Ashish Kalra
  2022-04-05 17:33 ` [PATCH v8 6/6] OvmfPkg/AmdSevDxe: Add support for SEV live migration Ashish Kalra
  5 siblings, 0 replies; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:32 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Make the #VC handler aware of the page encryption state
change hypercall by adding support to check KVM_HC_MAP_GPA_RANGE
hypercall and add the additional register values used by
hypercall in the GHCB.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
index a4393dffbd..ee213ae2cb 100644
--- a/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
+++ b/OvmfPkg/Library/VmgExitLib/VmgExitVcHandler.c
@@ -1211,6 +1211,19 @@ VmmCallExit (
   Ghcb->SaveArea.Cpl = (UINT8)(Regs->Cs & 0x3);
   VmgSetOffsetValid (Ghcb, GhcbCpl);
 
+  if (Regs->Rax == KVM_HC_MAP_GPA_RANGE) {
+    //
+    // KVM_HC_MAP_GPA_RANGE hypercall requires these
+    // extra registers.
+    //
+    Ghcb->SaveArea.Rbx = Regs->Rbx;
+    VmgSetOffsetValid (Ghcb, GhcbRbx);
+    Ghcb->SaveArea.Rcx = Regs->Rcx;
+    VmgSetOffsetValid (Ghcb, GhcbRcx);
+    Ghcb->SaveArea.Rdx = Regs->Rdx;
+    VmgSetOffsetValid (Ghcb, GhcbRdx);
+  }
+
   Status = VmgExit (Ghcb, SVM_EXIT_VMMCALL, 0, 0);
   if (Status != 0) {
     return Status;
-- 
2.25.1


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

* [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
                   ` (3 preceding siblings ...)
  2022-04-05 17:32 ` [PATCH v8 4/6] OvmfPkg/VmgExitLib: Encryption state change hypercall support in VC handler Ashish Kalra
@ 2022-04-05 17:32 ` Ashish Kalra
  2022-05-31 15:42   ` [edk2-devel] " Nikunj A. Dadhania
  2022-04-05 17:33 ` [PATCH v8 6/6] OvmfPkg/AmdSevDxe: Add support for SEV live migration Ashish Kalra
  5 siblings, 1 reply; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:32 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Mark the SEC GHCB page (that is mapped as unencrypted in
ResetVector code) in the hypervisor's guest page encryption
state tracking.

Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index 385562b44c..cd96fc23bd 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -223,6 +223,17 @@ AmdSevEsInitialize (
   PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
   ASSERT_RETURN_ERROR (PcdStatus);
 
+  //
+  // The SEC Ghcb setup during reset-vector needs to be marked as
+  // decrypted in the hypervisor's guest page encryption state
+  // tracking.
+  //
+  SetMemoryEncDecHypercall3 (
+    FixedPcdGet32 (PcdOvmfSecGhcbBase),
+    EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdOvmfSecGhcbSize)),
+    FALSE
+    );
+
   //
   // Allocate GHCB and per-CPU variable pages.
   //   Since the pages must survive across the UEFI to OS transition
-- 
2.25.1


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

* [PATCH v8 6/6] OvmfPkg/AmdSevDxe: Add support for SEV live migration.
  2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
                   ` (4 preceding siblings ...)
  2022-04-05 17:32 ` [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall Ashish Kalra
@ 2022-04-05 17:33 ` Ashish Kalra
  5 siblings, 0 replies; 11+ messages in thread
From: Ashish Kalra @ 2022-04-05 17:33 UTC (permalink / raw)
  To: devel
  Cc: dovmurik, brijesh.singh, tobin, Thomas.Lendacky, jejb, dgilbert,
	lersek, jordan.l.justen, ard.biesheuvel

From: Ashish Kalra <ashish.kalra@amd.com>

Check for SEV live migration feature support, if detected
setup a new UEFI enviroment variable to indicate OVMF
support for SEV live migration.

This environment variable is created by UEFI but consumed
by the (guest) linux kernel. This is actually part of a
3-way negotiation of the live migration feature between
hypervisor, guest OVMF and guest kernel. Host indicates
support for live migration, which is detected by OVMF
and correspondingly OVMF sets this SetLiveMigrationEnabled
UEFI variable, which is read by the guest kernel and it
indicates to the guest kernel that both host and OVMF
support and have enabled the live migration feature.

The new runtime UEFI environment variable is set via the
notification function registered for the
EFI_END_OF_DXE_EVENT_GROUP_GUID event in AmdSevDxe driver.

AmdSevDxe module is an apriori driver so it gets loaded between PEI
and DXE phases and the SetVariable call will fail at the driver's
entry point as the Variable DXE module is still not loaded yet.
So we need to wait for an event notification which is signaled
after the Variable DXE module is loaded, hence, using the
EndOfDxe event notification to make this call.

Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
---
 OvmfPkg/AmdSevDxe/AmdSevDxe.c              | 67 ++++++++++++++++++++++
 OvmfPkg/AmdSevDxe/AmdSevDxe.inf            |  4 ++
 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h | 20 +++++++
 OvmfPkg/OvmfPkg.dec                        |  1 +
 4 files changed, 92 insertions(+)
 create mode 100644 OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h

diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.c b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
index 662d3c4ccb..1453d68d81 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.c
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.c
@@ -15,10 +15,13 @@
 #include <Library/BaseMemoryLib.h>
 #include <Library/DebugLib.h>
 #include <Library/DxeServicesTableLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
 #include <Library/MemEncryptSevLib.h>
 #include <Library/MemoryAllocationLib.h>
 #include <Library/UefiBootServicesTableLib.h>
 #include <Guid/ConfidentialComputingSevSnpBlob.h>
+#include <Guid/AmdSevMemEncryptLib.h>
+#include <Guid/EventGroup.h>
 #include <Library/PcdLib.h>
 
 STATIC CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION  mSnpBootDxeTable = {
@@ -31,6 +34,39 @@ STATIC CONFIDENTIAL_COMPUTING_SNP_BLOB_LOCATION  mSnpBootDxeTable = {
   FixedPcdGet32 (PcdOvmfCpuidSize),
 };
 
+STATIC
+VOID
+EFIAPI
+AmdSevDxeOnEndOfDxe (
+  IN EFI_EVENT  Event,
+  IN VOID       *EventToSignal
+  )
+{
+  EFI_STATUS  Status;
+  BOOLEAN     SevLiveMigrationEnabled;
+
+  SevLiveMigrationEnabled = MemEncryptSevLiveMigrationIsEnabled ();
+
+  if (SevLiveMigrationEnabled) {
+    Status = gRT->SetVariable (
+                    L"SevLiveMigrationEnabled",
+                    &gAmdSevMemEncryptGuid,
+                    EFI_VARIABLE_NON_VOLATILE |
+                    EFI_VARIABLE_BOOTSERVICE_ACCESS |
+                    EFI_VARIABLE_RUNTIME_ACCESS,
+                    sizeof SevLiveMigrationEnabled,
+                    &SevLiveMigrationEnabled
+                    );
+
+    DEBUG ((
+      DEBUG_INFO,
+      "%a: Setting SevLiveMigrationEnabled variable, status = %lx\n",
+      __FUNCTION__,
+      Status
+      ));
+  }
+}
+
 EFI_STATUS
 EFIAPI
 AmdSevDxeEntryPoint (
@@ -42,6 +78,7 @@ AmdSevDxeEntryPoint (
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  *AllDescMap;
   UINTN                            NumEntries;
   UINTN                            Index;
+  EFI_EVENT                        Event;
 
   //
   // Do nothing when SEV is not enabled
@@ -158,5 +195,35 @@ AmdSevDxeEntryPoint (
                   );
   }
 
+  //
+  // AmdSevDxe module is an apriori driver so it gets loaded between PEI
+  // and DXE phases and the SetVariable call will fail at the driver's
+  // entry point as the Variable DXE module is still not loaded yet.
+  // So we need to wait for an event notification which is signaled
+  // after the Variable DXE module is loaded, hence, using the
+  // EndOfDxe event notification to make this call.
+  //
+  // Register EFI_END_OF_DXE_EVENT_GROUP_GUID event.
+  // The notification function sets the runtime variable indicating OVMF
+  // support for SEV live migration.
+  //
+  Status = gBS->CreateEventEx (
+                  EVT_NOTIFY_SIGNAL,
+                  TPL_CALLBACK,
+                  AmdSevDxeOnEndOfDxe,
+                  NULL,
+                  &gEfiEndOfDxeEventGroupGuid,
+                  &Event
+                  );
+
+  if (EFI_ERROR (Status)) {
+    DEBUG ((
+      DEBUG_ERROR,
+      "%a: CreateEventEx(): %r\n",
+      __FUNCTION__,
+      Status
+      ));
+  }
+
   return EFI_SUCCESS;
 }
diff --git a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
index 9acf860cf2..42f8af0d0d 100644
--- a/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
+++ b/OvmfPkg/AmdSevDxe/AmdSevDxe.inf
@@ -52,3 +52,7 @@
 
 [Pcd]
   gUefiOvmfPkgTokenSpaceGuid.PcdOvmfHostBridgePciDevId
+
+[Guids]
+  gAmdSevMemEncryptGuid
+  gEfiEndOfDxeEventGroupGuid         ## CONSUMES   ## Event
diff --git a/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
new file mode 100644
index 0000000000..62d22e79a9
--- /dev/null
+++ b/OvmfPkg/Include/Guid/AmdSevMemEncryptLib.h
@@ -0,0 +1,20 @@
+/** @file
+
+  AMD Memory Encryption GUID, define a new GUID for defining
+  new UEFI environment variables assocaiated with SEV Memory Encryption.
+
+  Copyright (c) 2021, AMD Inc. All rights reserved.<BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef __AMD_SEV_MEMENCRYPT_LIB_H__
+#define __AMD_SEV_MEMENCRYPT_LIB_H__
+
+#define AMD_SEV_MEMENCRYPT_GUID \
+{0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}}
+
+extern EFI_GUID  gAmdSevMemEncryptGuid;
+
+#endif
diff --git a/OvmfPkg/OvmfPkg.dec b/OvmfPkg/OvmfPkg.dec
index b9ca441202..0f415f24db 100644
--- a/OvmfPkg/OvmfPkg.dec
+++ b/OvmfPkg/OvmfPkg.dec
@@ -142,6 +142,7 @@
   gConfidentialComputingSecretGuid      = {0xadf956ad, 0xe98c, 0x484c, {0xae, 0x11, 0xb5, 0x1c, 0x7d, 0x33, 0x64, 0x47}}
   gConfidentialComputingSevSnpBlobGuid  = {0x067b1f5f, 0xcf26, 0x44c5, {0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42}}
   gUefiOvmfPkgPlatformInfoGuid          = {0xdec9b486, 0x1f16, 0x47c7, {0x8f, 0x68, 0xdf, 0x1a, 0x41, 0x88, 0x8b, 0xa5}}
+  gAmdSevMemEncryptGuid                 = {0x0cf29b71, 0x9e51, 0x433a, {0xa3, 0xb7, 0x81, 0xf3, 0xab, 0x16, 0xb8, 0x75}}
 
 [Ppis]
   # PPI whose presence in the PPI database signals that the TPM base address
-- 
2.25.1


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

* Re: [edk2-devel] [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall
  2022-04-05 17:32 ` [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall Ashish Kalra
@ 2022-05-31 15:42   ` Nikunj A. Dadhania
  0 siblings, 0 replies; 11+ messages in thread
From: Nikunj A. Dadhania @ 2022-05-31 15:42 UTC (permalink / raw)
  To: devel, ashish.kalra
  Cc: dovmurik, tobin, Thomas.Lendacky, jejb, dgilbert, lersek,
	jordan.l.justen, ard.biesheuvel, nikunj

Hi Ashish,

I missed the v8 and replied on v7.

On 4/5/2022 11:02 PM, Ashish Kalra via groups.io wrote:
> From: Ashish Kalra <ashish.kalra@amd.com>
> 
> Mark the SEC GHCB page (that is mapped as unencrypted in
> ResetVector code) in the hypervisor's guest page encryption
> state tracking.
> 
> Cc: Jordan Justen <jordan.l.justen@intel.com>
> Cc: Ard Biesheuvel <ard.biesheuvel@arm.com>
> Signed-off-by: Ashish Kalra <ashish.kalra@amd.com>
> ---
>  OvmfPkg/PlatformPei/AmdSev.c | 11 +++++++++++
>  1 file changed, 11 insertions(+)
> 
> diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
> index 385562b44c..cd96fc23bd 100644
> --- a/OvmfPkg/PlatformPei/AmdSev.c
> +++ b/OvmfPkg/PlatformPei/AmdSev.c
> @@ -223,6 +223,17 @@ AmdSevEsInitialize (
>    PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);
> 
>    ASSERT_RETURN_ERROR (PcdStatus);
> 
>  
> 
> +  //
> +  // The SEC Ghcb setup during reset-vector needs to be marked as
> +  // decrypted in the hypervisor's guest page encryption state
> +  // tracking.
> +  //
> +  SetMemoryEncDecHypercall3 (
> +    FixedPcdGet32 (PcdOvmfSecGhcbBase),
> +    EFI_SIZE_TO_PAGES (FixedPcdGet32 (PcdOvmfSecGhcbSize)),
> +    FALSE
> +    );
> +

PcdOvmfSecGhcbSize is set to 2 pages (8192 bytes). AFAIU, only first page 
needs to be change to shared, second page should be kept private.

>    //
>    // Allocate GHCB and per-CPU variable pages.
>    //   Since the pages must survive across the UEFI to OS transition
> 

Regards
Nikunj

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

* Re: [edk2-devel] [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall
  2022-04-05 17:32 ` [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall Ashish Kalra
@ 2022-06-07  8:38   ` nikunj
  2022-06-07 17:28     ` Ashish Kalra
  0 siblings, 1 reply; 11+ messages in thread
From: nikunj @ 2022-06-07  8:38 UTC (permalink / raw)
  To: Ashish Kalra, devel

[-- Attachment #1: Type: text/plain, Size: 789 bytes --]

Hi Ashish,

For case with latest OVMF and older qemu that does not enable live migrations,
SetMemoryEncDecHypercall3() returns RETURN_UNSUPPORTED, which is correct.
But then its actually treated as an error and OVMF sees an assert. This is a valid usecase
and OVMF should move ahead without live migration and HC_MAP_GPA_RANGE.
....

> + //
> + // Notify Hypervisor on C-bit status
> + //
> + if (CBitChanged) {

Should we call the SetMemoryEncDecHypercall() only if migration is enabled like below?

if (CBitChanged && MemEncryptSevLiveMigrationIsEnabled () {

> + Status = SetMemoryEncDecHypercall3 (
> + OrigPhysicalAddress,
> + EFI_SIZE_TO_PAGES (OrigLength),
> + (Mode == SetCBit) ? TRUE : FALSE
> + );
> + }
> +
> ...
>
> return Status;

Regards
Nikunj

[-- Attachment #2: Type: text/html, Size: 2060 bytes --]

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

* Re: [edk2-devel] [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall
  2022-06-07  8:38   ` [edk2-devel] " nikunj
@ 2022-06-07 17:28     ` Ashish Kalra
  2022-06-08 13:22       ` nikunj
  0 siblings, 1 reply; 11+ messages in thread
From: Ashish Kalra @ 2022-06-07 17:28 UTC (permalink / raw)
  To: Dadhania, Nikunj, devel@edk2.groups.io

[-- Attachment #1: Type: text/plain, Size: 1344 bytes --]

[AMD Official Use Only - General]

Hello Nikunj,

Yes we can move MemEncryptSevLiveMigrationIsEnabled() check here before calling SetMemoryEncDecHypercall3()
but then we also need to remove the same check from inside SetMemoryEncDecHypercall3() function.

Thanks,
Ashish

From: nikunj via groups.io <nikunj=amd.com@groups.io>
Sent: Tuesday, June 7, 2022 3:39 AM
To: Kalra, Ashish <Ashish.Kalra@amd.com>; devel@edk2.groups.io
Subject: Re: [edk2-devel] [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall

Hi Ashish,

For case with latest OVMF and older qemu that does not enable live migrations,
SetMemoryEncDecHypercall3() returns RETURN_UNSUPPORTED, which is correct.
But then its actually treated as an error and OVMF sees an assert. This is a valid usecase
and OVMF should move ahead without live migration and HC_MAP_GPA_RANGE.
....

> + //
> + // Notify Hypervisor on C-bit status
> + //
> + if (CBitChanged) {

Should we call the SetMemoryEncDecHypercall() only if migration is enabled like below?

if (CBitChanged && MemEncryptSevLiveMigrationIsEnabled () {

> + Status = SetMemoryEncDecHypercall3 (
> + OrigPhysicalAddress,
> + EFI_SIZE_TO_PAGES (OrigLength),
> + (Mode == SetCBit) ? TRUE : FALSE
> + );
> + }
> +
> ...
>
> return Status;

Regards
Nikunj

[-- Attachment #2: Type: text/html, Size: 3926 bytes --]

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

* Re: [edk2-devel] [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall
  2022-06-07 17:28     ` Ashish Kalra
@ 2022-06-08 13:22       ` nikunj
  0 siblings, 0 replies; 11+ messages in thread
From: nikunj @ 2022-06-08 13:22 UTC (permalink / raw)
  To: Kalra, Ashish, devel@edk2.groups.io; +Cc: nikunj

Hi Ashish,

On 6/7/2022 10:58 PM, Kalra, Ashish wrote:
> 
> Hello Nikunj,
> 
> Yes we can move MemEncryptSevLiveMigrationIsEnabled() check here before calling SetMemoryEncDecHypercall3()
> 
> but then we also need to remove the same check from inside SetMemoryEncDecHypercall3() function.

Sure, and we will have to check this at all places that are calling SetMemoryEncDecHypercall3()

Regards
Nikunj

>  
> 
> Thanks,
> 
> Ashish
> 
>  
> 
> *From:* nikunj via groups.io <nikunj=amd.com@groups.io>
> *Sent:* Tuesday, June 7, 2022 3:39 AM
> *To:* Kalra, Ashish <Ashish.Kalra@amd.com>; devel@edk2.groups.io
> *Subject:* Re: [edk2-devel] [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall
> 
>  
> 
> Hi Ashish,
> 
> For case with latest OVMF and older qemu that does not enable live migrations,
> SetMemoryEncDecHypercall3() returns RETURN_UNSUPPORTED, which is correct.
> But then its actually treated as an error and OVMF sees an assert. This is a valid usecase
> and OVMF should move ahead without live migration and HC_MAP_GPA_RANGE.
> ....
> 
>> + //
>> + // Notify Hypervisor on C-bit status
>> + //
>> + if (CBitChanged) {
> 
> Should we call the SetMemoryEncDecHypercall() only if migration is enabled like below?
> 
> if (CBitChanged && MemEncryptSevLiveMigrationIsEnabled () {
> 
>> + Status = SetMemoryEncDecHypercall3 (
>> + OrigPhysicalAddress,
>> + EFI_SIZE_TO_PAGES (OrigLength),
>> + (Mode == SetCBit) ? TRUE : FALSE
>> + );
>> + }
>> +
>> ...
>>
>> return Status;
> 
> Regards
> Nikunj
> 

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

end of thread, other threads:[~2022-06-08 13:22 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-04-05 17:28 [PATCH v8 0/6] SEV Live Migration support for OVMF Ashish Kalra
2022-04-05 17:30 ` [PATCH v8 1/6] OvmfPkg/BaseMemEncryptLib: Detect SEV live migration feature Ashish Kalra
2022-04-05 17:31 ` [PATCH v8 2/6] OvmfPkg/BaseMemEncryptLib: Hypercall API for page encryption state change Ashish Kalra
2022-04-05 17:32 ` [PATCH v8 3/6] OvmfPkg/BaseMemEncryptLib: Invoke page encryption state change hypercall Ashish Kalra
2022-06-07  8:38   ` [edk2-devel] " nikunj
2022-06-07 17:28     ` Ashish Kalra
2022-06-08 13:22       ` nikunj
2022-04-05 17:32 ` [PATCH v8 4/6] OvmfPkg/VmgExitLib: Encryption state change hypercall support in VC handler Ashish Kalra
2022-04-05 17:32 ` [PATCH v8 5/6] OvmfPkg/PlatformPei: Mark SEC GHCB page as unencrypted via hypercall Ashish Kalra
2022-05-31 15:42   ` [edk2-devel] " Nikunj A. Dadhania
2022-04-05 17:33 ` [PATCH v8 6/6] OvmfPkg/AmdSevDxe: Add support for SEV live migration Ashish Kalra

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