// The package level header files this module uses\r
//\r
#include <IndustryStandard/Q35MchIch9.h>\r
+#include <Library/BaseMemoryLib.h>\r
#include <Library/DebugLib.h>\r
#include <Library/HobLib.h>\r
#include <Library/MemEncryptSevLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
#include <Library/PcdLib.h>\r
#include <PiPei.h>\r
#include <Register/Amd/Cpuid.h>\r
+#include <Register/Amd/Msr.h>\r
#include <Register/Cpuid.h>\r
#include <Register/Intel/SmramSaveStateMap.h>\r
\r
VOID\r
)\r
{\r
- RETURN_STATUS PcdStatus;\r
+ VOID *GhcbBase;\r
+ PHYSICAL_ADDRESS GhcbBasePa;\r
+ UINTN GhcbPageCount, PageCount;\r
+ RETURN_STATUS PcdStatus, DecryptStatus;\r
\r
if (!MemEncryptSevEsIsEnabled ()) {\r
return;\r
\r
PcdStatus = PcdSetBoolS (PcdSevEsIsEnabled, TRUE);\r
ASSERT_RETURN_ERROR (PcdStatus);\r
+\r
+ //\r
+ // Allocate GHCB and per-CPU variable pages.\r
+ //\r
+ GhcbPageCount = mMaxCpuCount * 2;\r
+ GhcbBase = AllocatePages (GhcbPageCount);\r
+ ASSERT (GhcbBase != NULL);\r
+\r
+ GhcbBasePa = (PHYSICAL_ADDRESS)(UINTN) GhcbBase;\r
+\r
+ //\r
+ // Each vCPU gets two consecutive pages, the first is the GHCB and the\r
+ // second is the per-CPU variable page. Loop through the allocation and\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
+ TRUE\r
+ );\r
+ ASSERT_RETURN_ERROR (DecryptStatus);\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
+\r
+ DEBUG ((DEBUG_INFO,\r
+ "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",\r
+ (UINT64)GhcbPageCount, GhcbBase));\r
+\r
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\r
}\r
\r
/**\r