OvmfPkg/SecMain: register GHCB gpa for the SEV-SNP guest

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>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
This commit is contained in:
Brijesh Singh via groups.io 2021-12-09 11:27:38 +08:00 committed by mergify[bot]
parent d9822304ce
commit 7c3b2892ea
1 changed files with 119 additions and 0 deletions

View File

@ -48,6 +48,104 @@ SevEsProtocolFailure (
CpuDeadLoop ();
}
/**
Determine if SEV-SNP is active.
@retval TRUE SEV-SNP is enabled
@retval FALSE SEV-SNP is not enabled
**/
STATIC
BOOLEAN
SevSnpIsEnabled (
VOID
)
{
MSR_SEV_STATUS_REGISTER Msr;
//
// Read the SEV_STATUS MSR to determine whether SEV-SNP is active.
//
Msr.Uint32 = AsmReadMsr32 (MSR_SEV_STATUS);
//
// Check MSR_0xC0010131 Bit 2 (Sev-Snp Enabled)
//
if (Msr.Bits.SevSnpBit) {
return TRUE;
}
return FALSE;
}
/**
Register the GHCB GPA
*/
STATIC
VOID
SevSnpGhcbRegister (
EFI_PHYSICAL_ADDRESS Address
)
{
MSR_SEV_ES_GHCB_REGISTER Msr;
//
// Use the GHCB MSR Protocol to request to register the GPA.
//
Msr.GhcbPhysicalAddress = Address & ~EFI_PAGE_MASK;
Msr.GhcbGpaRegister.Function = GHCB_INFO_GHCB_GPA_REGISTER_REQUEST;
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.GhcbPhysicalAddress & ~EFI_PAGE_MASK) != Address))
{
SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);
}
}
/**
Verify that Hypervisor supports the SNP feature.
*/
STATIC
BOOLEAN
HypervisorSnpFeatureCheck (
VOID
)
{
MSR_SEV_ES_GHCB_REGISTER Msr;
UINT64 Features;
//
// Use the GHCB MSR Protocol to query the hypervisor capabilities
//
Msr.GhcbPhysicalAddress = 0;
Msr.GhcbHypervisorFeatures.Function = GHCB_HYPERVISOR_FEATURES_REQUEST;
AsmWriteMsr64 (MSR_SEV_ES_GHCB, Msr.GhcbPhysicalAddress);
AsmVmgExit ();
Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);
Features = RShiftU64 (Msr.GhcbPhysicalAddress, 12);
if ((Msr.GhcbHypervisorFeatures.Function != GHCB_HYPERVISOR_FEATURES_RESPONSE) ||
(!(Features & GHCB_HV_FEATURES_SNP)))
{
return FALSE;
}
return TRUE;
}
/**
Validate the SEV-ES/GHCB protocol level.
@ -89,6 +187,27 @@ SevEsProtocolCheck (
SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);
}
//
// We cannot use the MemEncryptSevSnpIsEnabled () because the
// ProcessLibraryConstructorList () is not called yet.
//
if (SevSnpIsEnabled ()) {
//
// Check if hypervisor supports the SNP feature
//
if (!HypervisorSnpFeatureCheck ()) {
SevEsProtocolFailure (GHCB_TERMINATE_GHCB_PROTOCOL);
}
//
// Unlike the SEV-ES guest, the SNP requires that GHCB GPA must be
// registered with the Hypervisor before the use. This can be done
// using the new VMGEXIT defined in the GHCB v2. Register the GPA
// before it is used.
//
SevSnpGhcbRegister ((EFI_PHYSICAL_ADDRESS)(UINTN)FixedPcdGet32 (PcdOvmfSecGhcbBase));
}
//
// SEV-ES protocol checking succeeded, set the initial GHCB address
//