[edk2-devel] [PATCH 08/16] OvmfPkg/CcExitLib: Add support for the SVSM create/delete vCPU calls

Lendacky, Thomas via groups.io posted 16 patches 7 months, 2 weeks ago
There is a newer version of this series
[edk2-devel] [PATCH 08/16] OvmfPkg/CcExitLib: Add support for the SVSM create/delete vCPU calls
Posted by Lendacky, Thomas via groups.io 7 months, 2 weeks ago
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4654

The RMPADJUST instruction is used to alter the VMSA attribute of a page,
but the VMSA attribute can only be changed when running at VMPL0. When
an SVSM is present, use the SVSM_CORE_CREATE_VCPU and SVSM_CORE_DELTE_VCPU
calls to add or remove the VMSA attribute on a page instead of issuing
the RMPADJUST instruction directly.

Implement the CcExitSnpVmsaRmpAdjust() API to perform the proper operation
to update the VMSA attribute.

Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
---
 OvmfPkg/Library/CcExitLib/CcExitSvsm.c | 100 +++++++++++++++++++-
 1 file changed, 99 insertions(+), 1 deletion(-)

diff --git a/OvmfPkg/Library/CcExitLib/CcExitSvsm.c b/OvmfPkg/Library/CcExitLib/CcExitSvsm.c
index 43e0a357efa5..3459338b2033 100644
--- a/OvmfPkg/Library/CcExitLib/CcExitSvsm.c
+++ b/OvmfPkg/Library/CcExitLib/CcExitSvsm.c
@@ -137,6 +137,103 @@ SvsmMsrProtocol (
   return Ret;
 }
 
+/**
+  Perform an RMPADJUST operation to alter the VMSA setting of a page.
+
+  Add or remove the VMSA attribute for a page.
+
+  @param[in]       Vmsa           Pointer to an SEV-ES save area page
+  @param[in]       ApicId         APIC ID associated with the VMSA
+  @param[in]       SetVmsa        Boolean indicator as to whether to set or
+                                  or clear the VMSA setting for the page
+
+  @retval  EFI_SUCCESS            RMPADJUST operation successful
+  @retval  EFI_UNSUPPORTED        Operation is not supported
+  @retval  EFI_INVALID_PARAMETER  RMPADJUST operation failed, an invalid
+                                  parameter was supplied
+
+**/
+EFI_STATUS
+EFIAPI
+SvsmVmsaRmpAdjust (
+  IN SEV_ES_SAVE_AREA  *Vmsa,
+  IN UINT32            ApicId,
+  IN BOOLEAN           SetVmsa
+  )
+{
+  SVSM_CALL_DATA  SvsmCallData;
+  SVSM_FUNCTION   Function;
+  UINTN           Ret;
+
+  SvsmCallData.Caa = SvsmGetCaa ();
+
+  Function.Id.Protocol = 0;
+
+  if (SetVmsa) {
+    Function.Id.CallId = 2;
+
+    SvsmCallData.RaxIn = Function.Uint64;
+    SvsmCallData.RcxIn = (UINT64)(UINTN)Vmsa;
+    SvsmCallData.RdxIn = (UINT64)(UINTN)Vmsa + SIZE_4KB;
+    SvsmCallData.R8In  = ApicId;
+  } else {
+    Function.Id.CallId = 3;
+
+    SvsmCallData.RaxIn = Function.Uint64;
+    SvsmCallData.RcxIn = (UINT64)(UINTN)Vmsa;
+  }
+
+  Ret = SvsmMsrProtocol (&SvsmCallData);
+
+  return (Ret == 0) ? EFI_SUCCESS : EFI_INVALID_PARAMETER;
+}
+
+/**
+  Perform an RMPADJUST operation to alter the VMSA setting of a page.
+
+  Add or remove the VMSA attribute for a page.
+
+  @param[in]       Vmsa           Pointer to an SEV-ES save area page
+  @param[in]       ApicId         APIC ID associated with the VMSA
+  @param[in]       SetVmsa        Boolean indicator as to whether to set or
+                                  or clear the VMSA setting for the page
+
+  @retval  EFI_SUCCESS            RMPADJUST operation successful
+  @retval  EFI_UNSUPPORTED        Operation is not supported
+  @retval  EFI_INVALID_PARAMETER  RMPADJUST operation failed, an invalid
+                                  parameter was supplied
+
+**/
+EFI_STATUS
+EFIAPI
+BaseVmsaRmpAdjust (
+  IN SEV_ES_SAVE_AREA  *Vmsa,
+  IN UINT32            ApicId,
+  IN BOOLEAN           SetVmsa
+  )
+{
+  UINT64  Rdx;
+  UINT32  Ret;
+
+  //
+  // The RMPADJUST instruction is used to set or clear the VMSA bit for a
+  // page. The VMSA change is only made when running at VMPL0 and is ignored
+  // otherwise. If too low a target VMPL is specified, the instruction can
+  // succeed without changing the VMSA bit when not running at VMPL0. Using a
+  // target VMPL level of 1, RMPADJUST will return a FAIL_PERMISSION error if
+  // not running at VMPL0, thus ensuring that the VMSA bit is set appropriately
+  // when no error is returned.
+  //
+  Rdx = 1;
+  if (SetVmsa) {
+    Rdx |= RMPADJUST_VMSA_PAGE_BIT;
+  }
+
+  Ret = AsmRmpAdjust ((UINT64)(UINTN)Vmsa, 0, Rdx);
+
+  return (Ret == 0) ? EFI_SUCCESS : EFI_INVALID_PARAMETER;
+}
+
 /**
   Issue an SVSM request to perform the PVALIDATE instruction.
 
@@ -409,5 +506,6 @@ CcExitSnpVmsaRmpAdjust (
   IN BOOLEAN           SetVmsa
   )
 {
-  return EFI_UNSUPPORTED;
+  return CcExitSnpSvsmPresent () ? SvsmVmsaRmpAdjust (Vmsa, ApicId, SetVmsa)
+                                 : BaseVmsaRmpAdjust (Vmsa, ApicId, SetVmsa);
 }
-- 
2.42.0



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114634): https://edk2.groups.io/g/devel/message/114634
Mute This Topic: https://groups.io/mt/103986458/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-