OvmfPkg/AmdSvsmLib: Add support for the SVSM create/delete vCPU calls

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 AmdSvsmSnpVmsaRmpAdjust() API to perform the proper operation
to update the VMSA attribute.

Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Laszlo Ersek <lersek@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com>
diff --git a/OvmfPkg/Library/AmdSvsmLib/AmdSvsmLib.c b/OvmfPkg/Library/AmdSvsmLib/AmdSvsmLib.c
index fb3fda7..6c79ee7 100644
--- a/OvmfPkg/Library/AmdSvsmLib/AmdSvsmLib.c
+++ b/OvmfPkg/Library/AmdSvsmLib/AmdSvsmLib.c
@@ -378,6 +378,57 @@
 }

 

 /**

+  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

+

+**/

+STATIC

+EFI_STATUS

+SvsmVmsaRmpAdjust (

+  IN SEV_ES_SAVE_AREA  *Vmsa,

+  IN UINT32            ApicId,

+  IN BOOLEAN           SetVmsa

+  )

+{

+  SVSM_CALL_DATA  SvsmCallData;

+  SVSM_FUNCTION   Function;

+  UINTN           Ret;

+

+  SvsmCallData.Caa = (SVSM_CAA *)AmdSvsmSnpGetCaa ();

+

+  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 a native RMPADJUST operation to alter the VMSA setting of a page.

 

   Add or remove the VMSA attribute for a page.

@@ -444,5 +495,6 @@
   IN BOOLEAN           SetVmsa

   )

 {

-  return BaseVmsaRmpAdjust (Vmsa, SetVmsa);

+  return AmdSvsmIsSvsmPresent () ? SvsmVmsaRmpAdjust (Vmsa, ApicId, SetVmsa)

+                                : BaseVmsaRmpAdjust (Vmsa, SetVmsa);

 }