#include <Library/MemEncryptSevLib.h>\r
#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
+#include <Pi/PrePiHob.h>\r
#include <PiPei.h>\r
#include <Register/Amd/Msr.h>\r
#include <Register/Intel/SmramSaveStateMap.h>\r
-#include <Library/VmgExitLib.h>\r
+#include <Library/CcExitLib.h>\r
#include <ConfidentialComputingGuestAttr.h>\r
\r
#include "Platform.h"\r
\r
+STATIC\r
+UINT64\r
+GetHypervisorFeature (\r
+ VOID\r
+ );\r
+\r
/**\r
Initialize SEV-SNP support if running as an SEV-SNP guest.\r
\r
{\r
EFI_PEI_HOB_POINTERS Hob;\r
EFI_HOB_RESOURCE_DESCRIPTOR *ResourceHob;\r
+ UINT64 HvFeatures;\r
+ EFI_STATUS PcdStatus;\r
\r
if (!MemEncryptSevSnpIsEnabled ()) {\r
return;\r
}\r
\r
+ //\r
+ // Query the hypervisor feature using the CcExitVmgExit and set the value in the\r
+ // hypervisor features PCD.\r
+ //\r
+ HvFeatures = GetHypervisorFeature ();\r
+ PcdStatus = PcdSet64S (PcdGhcbHypervisorFeatures, HvFeatures);\r
+ ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
//\r
// Iterate through the system RAM and validate it.\r
//\r
ResourceHob = Hob.ResourceDescriptor;\r
\r
if (ResourceHob->ResourceType == EFI_RESOURCE_SYSTEM_MEMORY) {\r
+ if (ResourceHob->PhysicalStart >= SIZE_4GB) {\r
+ ResourceHob->ResourceType = BZ3937_EFI_RESOURCE_MEMORY_UNACCEPTED;\r
+ continue;\r
+ }\r
+\r
MemEncryptSevSnpPreValidateSystemRam (\r
ResourceHob->PhysicalStart,\r
EFI_SIZE_TO_PAGES ((UINTN)ResourceHob->ResourceLength)\r
CpuDeadLoop ();\r
}\r
\r
+/**\r
+ Get the hypervisor features bitmap\r
+\r
+**/\r
+STATIC\r
+UINT64\r
+GetHypervisorFeature (\r
+ VOID\r
+ )\r
+{\r
+ UINT64 Status;\r
+ GHCB *Ghcb;\r
+ MSR_SEV_ES_GHCB_REGISTER Msr;\r
+ BOOLEAN InterruptState;\r
+ UINT64 Features;\r
+\r
+ Msr.GhcbPhysicalAddress = AsmReadMsr64 (MSR_SEV_ES_GHCB);\r
+ Ghcb = Msr.Ghcb;\r
+\r
+ //\r
+ // Initialize the GHCB\r
+ //\r
+ CcExitVmgInit (Ghcb, &InterruptState);\r
+\r
+ //\r
+ // Query the Hypervisor Features.\r
+ //\r
+ Status = CcExitVmgExit (Ghcb, SVM_EXIT_HYPERVISOR_FEATURES, 0, 0);\r
+ if ((Status != 0)) {\r
+ SevEsProtocolFailure (GHCB_TERMINATE_GHCB_GENERAL);\r
+ }\r
+\r
+ Features = Ghcb->SaveArea.SwExitInfo2;\r
+\r
+ CcExitVmgDone (Ghcb, InterruptState);\r
+\r
+ return Features;\r
+}\r
+\r
/**\r
\r
This function can be used to register the GHCB GPA.\r
STATIC\r
VOID\r
AmdSevEsInitialize (\r
- VOID\r
+ IN EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
)\r
{\r
UINT8 *GhcbBase;\r
UINTN GhcbBackupPageCount;\r
SEV_ES_PER_CPU_DATA *SevEsData;\r
UINTN PageCount;\r
- RETURN_STATUS PcdStatus, DecryptStatus;\r
+ RETURN_STATUS Status;\r
IA32_DESCRIPTOR Gdtr;\r
VOID *Gdt;\r
\r
return;\r
}\r
\r
- PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
+ Status = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);\r
+ ASSERT_RETURN_ERROR (Status);\r
\r
//\r
// Allocate GHCB and per-CPU variable pages.\r
// Since the pages must survive across the UEFI to OS transition\r
// make them reserved.\r
//\r
- GhcbPageCount = mMaxCpuCount * 2;\r
+ GhcbPageCount = PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber * 2;\r
GhcbBase = AllocateReservedPages (GhcbPageCount);\r
ASSERT (GhcbBase != NULL);\r
\r
// only clear the encryption mask for the GHCB pages.\r
//\r
for (PageCount = 0; PageCount < GhcbPageCount; PageCount += 2) {\r
- DecryptStatus = MemEncryptSevClearPageEncMask (\r
- 0,\r
- GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),\r
- 1\r
- );\r
- ASSERT_RETURN_ERROR (DecryptStatus);\r
+ Status = MemEncryptSevClearPageEncMask (\r
+ 0,\r
+ GhcbBasePa + EFI_PAGES_TO_SIZE (PageCount),\r
+ 1\r
+ );\r
+ ASSERT_RETURN_ERROR (Status);\r
}\r
\r
ZeroMem (GhcbBase, EFI_PAGES_TO_SIZE (GhcbPageCount));\r
\r
- PcdStatus = PcdSet64S (PcdGhcbBase, GhcbBasePa);\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
- PcdStatus = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));\r
- ASSERT_RETURN_ERROR (PcdStatus);\r
+ Status = PcdSet64S (PcdGhcbBase, GhcbBasePa);\r
+ ASSERT_RETURN_ERROR (Status);\r
+ Status = PcdSet64S (PcdGhcbSize, EFI_PAGES_TO_SIZE (GhcbPageCount));\r
+ ASSERT_RETURN_ERROR (Status);\r
\r
DEBUG ((\r
DEBUG_INFO,\r
// Allocate #VC recursion backup pages. The number of backup pages needed is\r
// one less than the maximum VC count.\r
//\r
- GhcbBackupPageCount = mMaxCpuCount * (VMGEXIT_MAXIMUM_VC_COUNT - 1);\r
+ GhcbBackupPageCount = PlatformInfoHob->PcdCpuMaxLogicalProcessorNumber * (VMGEXIT_MAXIMUM_VC_COUNT - 1);\r
GhcbBackupBase = AllocatePages (GhcbBackupPageCount);\r
ASSERT (GhcbBackupBase != NULL);\r
\r
\r
AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\r
\r
+ //\r
+ // Now that the PEI GHCB is set up, the SEC GHCB page is no longer necessary\r
+ // to keep shared. Later, it is exposed to the OS as EfiConventionalMemory, so\r
+ // it needs to be marked private. The size of the region is hardcoded in\r
+ // OvmfPkg/ResetVector/ResetVector.nasmb in the definition of\r
+ // SNP_SEC_MEM_BASE_DESC_2.\r
+ //\r
+ Status = MemEncryptSevSetPageEncMask (\r
+ 0, // Cr3 -- use system Cr3\r
+ FixedPcdGet32 (PcdOvmfSecGhcbBase), // BaseAddress\r
+ 1 // NumPages\r
+ );\r
+ ASSERT_RETURN_ERROR (Status);\r
+\r
//\r
// The SEV support will clear the C-bit from non-RAM areas. The early GDT\r
// lives in a non-RAM area, so when an exception occurs (like a #VC) the GDT\r
**/\r
VOID\r
AmdSevInitialize (\r
- VOID\r
+ IN OUT EFI_HOB_PLATFORM_INFO *PlatformInfoHob\r
)\r
{\r
UINT64 EncryptionMask;\r
// until after re-encryption, in order to prevent an information leak to the\r
// hypervisor.\r
//\r
- if (FeaturePcdGet (PcdSmmSmramRequire) && (mBootMode != BOOT_ON_S3_RESUME)) {\r
+ if (PlatformInfoHob->SmmSmramRequire && (PlatformInfoHob->BootMode != BOOT_ON_S3_RESUME)) {\r
RETURN_STATUS LocateMapStatus;\r
UINTN MapPagesBase;\r
UINTN MapPagesCount;\r
);\r
ASSERT_RETURN_ERROR (LocateMapStatus);\r
\r
- if (mQ35SmramAtDefaultSmbase) {\r
+ if (PlatformInfoHob->Q35SmramAtDefaultSmbase) {\r
//\r
// The initial SMRAM Save State Map has been covered as part of a larger\r
// reserved memory allocation in InitializeRamRegions().\r
//\r
// Check and perform SEV-ES initialization if required.\r
//\r
- AmdSevEsInitialize ();\r
+ AmdSevEsInitialize (PlatformInfoHob);\r
\r
//\r
// Set the Confidential computing attr PCD to communicate which SEV\r
\r
ASSERT_RETURN_ERROR (PcdStatus);\r
}\r
+\r
+/**\r
+ The function performs SEV specific region initialization.\r
+\r
+ **/\r
+VOID\r
+SevInitializeRam (\r
+ VOID\r
+ )\r
+{\r
+ if (MemEncryptSevSnpIsEnabled ()) {\r
+ //\r
+ // If SEV-SNP is enabled, reserve the Secrets and CPUID memory area.\r
+ //\r
+ // This memory range is given to the PSP by the hypervisor to populate\r
+ // the information used during the SNP VM boots, and it need to persist\r
+ // across the kexec boots. Mark it as EfiReservedMemoryType so that\r
+ // the guest firmware and OS does not use it as a system memory.\r
+ //\r
+ BuildMemoryAllocationHob (\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfSnpSecretsBase),\r
+ (UINT64)(UINTN)PcdGet32 (PcdOvmfSnpSecretsSize),\r
+ EfiReservedMemoryType\r
+ );\r
+ BuildMemoryAllocationHob (\r
+ (EFI_PHYSICAL_ADDRESS)(UINTN)PcdGet32 (PcdOvmfCpuidBase),\r
+ (UINT64)(UINTN)PcdGet32 (PcdOvmfCpuidSize),\r
+ EfiReservedMemoryType\r
+ );\r
+ }\r
+}\r