[PATCH v8 12/32] OvmfPkg/PlatformPei: register GHCB gpa for the SEV-SNP guest


Brijesh Singh
 

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

The SEV-SNP guest requires that GHCB GPA must be registered before using.
See the GHCB specification section 2.3.2 for more details.

Cc: Michael Roth <michael.roth@amd.com>
Cc: James Bottomley <jejb@linux.ibm.com>
Cc: Min Xu <min.m.xu@intel.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Jordan Justen <jordan.l.justen@intel.com>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>
Cc: Erdem Aktas <erdemaktas@google.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
---
OvmfPkg/PlatformPei/AmdSev.c | 91 ++++++++++++++++++++++++++++++++++++
1 file changed, 91 insertions(+)

diff --git a/OvmfPkg/PlatformPei/AmdSev.c b/OvmfPkg/PlatformPei/AmdSev.c
index a8bf610022ba..de876fdb478e 100644
--- a/OvmfPkg/PlatformPei/AmdSev.c
+++ b/OvmfPkg/PlatformPei/AmdSev.c
@@ -19,9 +19,93 @@
#include <PiPei.h>
#include <Register/Amd/Msr.h>
#include <Register/Intel/SmramSaveStateMap.h>
+#include <Library/VmgExitLib.h>

#include "Platform.h"

+/**
+ Handle an SEV-SNP/GHCB protocol check failure.
+
+ Notify the hypervisor using the VMGEXIT instruction that the SEV-SNP guest
+ wishes to be terminated.
+
+ @param[in] ReasonCode Reason code to provide to the hypervisor for the
+ termination request.
+
+**/
+STATIC
+VOID
+SevEsProtocolFailure (
+ IN UINT8 ReasonCode
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+
+ //
+ // Use the GHCB MSR Protocol to request termination by the hypervisor
+ //
+ Msr.GhcbPhysicalAddress = 0;
+ Msr.GhcbTerminate.Function = GHCB_INFO_TERMINATE_REQUEST;
+ Msr.GhcbTerminate.ReasonCodeSet = GHCB_TERMINATE_GHCB;
+ Msr.GhcbTerminate.ReasonCode = ReasonCode;
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+ AsmVmgExit ();
+
+ ASSERT (FALSE);
+ CpuDeadLoop ();
+}
+
+/**
+
+ This function can be used to register the GHCB GPA.
+
+ @param[in] Address The physical address to be registered.
+
+**/
+STATIC
+VOID
+GhcbRegister (
+ IN EFI_PHYSICAL_ADDRESS Address
+ )
+{
+ MSR_SEV_ES_GHCB_REGISTER Msr;
+ MSR_SEV_ES_GHCB_REGISTER CurrentMsr;
+ EFI_PHYSICAL_ADDRESS GuestFrameNumber;
+
+ GuestFrameNumber = Address >> EFI_PAGE_SHIFT;
+
+ //
+ // Save the current MSR Value
+ //
+ CurrentMsr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+ //
+ // Use the GHCB MSR Protocol to request to register the GPA.
+ //
+ Msr.GhcbPhysicalAddress = 0;
+ Msr.GhcbGpaRegister.Function = GHCB_INFO_GHCB_GPA_REGISTER_REQUEST;
+ Msr.GhcbGpaRegister.GuestFrameNumber = GuestFrameNumber;
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
+
+ AsmVmgExit ();
+
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
+
+ //
+ // If hypervisor responded with a different GPA than requested then fail.
+ //
+ if ((Msr.GhcbGpaRegister.Function != GHCB_INFO_GHCB_GPA_REGISTER_RESPONSE) ||
+ (Msr.GhcbGpaRegister.GuestFrameNumber != GuestFrameNumber)) {
+ SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
+ }
+
+ //
+ // Restore the MSR
+ //
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, CurrentMsr.GhcbPhysicalAddress);
+}
+
/**

Initialize SEV-ES support if running as an SEV-ES guest.
@@ -109,6 +193,13 @@ AmdSevEsInitialize (
"SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",
(UINT64)GhcbBackupPageCount, GhcbBackupBase));

+ //
+ // SEV-SNP guest requires that GHCB GPA must be registered before using it.
+ //
+ if (MemEncryptSevSnpIsEnabled ()) {
+ GhcbRegister (GhcbBasePa);
+ }
+
AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);

//
--
2.25.1