+\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
+ GhcbBase = AllocateReservedPages (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
+ );\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 ((\r
+ DEBUG_INFO,\r
+ "SEV-ES is enabled, %lu GHCB pages allocated starting at 0x%p\n",\r
+ (UINT64)GhcbPageCount,\r
+ GhcbBase\r
+ ));\r
+\r
+ //\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
+ GhcbBackupBase = AllocatePages (GhcbBackupPageCount);\r
+ ASSERT (GhcbBackupBase != NULL);\r
+\r
+ GhcbBackupPages = GhcbBackupBase;\r
+ for (PageCount = 1; PageCount < GhcbPageCount; PageCount += 2) {\r
+ SevEsData =\r
+ (SEV_ES_PER_CPU_DATA *)(GhcbBase + EFI_PAGES_TO_SIZE (PageCount));\r
+ SevEsData->GhcbBackupPages = GhcbBackupPages;\r
+\r
+ GhcbBackupPages += EFI_PAGE_SIZE * (VMGEXIT_MAXIMUM_VC_COUNT - 1);\r
+ }\r
+\r
+ DEBUG ((\r
+ DEBUG_INFO,\r
+ "SEV-ES is enabled, %lu GHCB backup pages allocated starting at 0x%p\n",\r
+ (UINT64)GhcbBackupPageCount,\r
+ GhcbBackupBase\r
+ ));\r
+\r
+ AsmWriteMsr64 (MSR_SEV_ES_GHCB, GhcbBasePa);\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
+ // will be read as un-encrypted even though it was created before the C-bit\r
+ // was cleared (encrypted). This will result in a failure to be able to\r
+ // handle the exception.\r
+ //\r
+ AsmReadGdtr (&Gdtr);\r
+\r
+ Gdt = AllocatePages (EFI_SIZE_TO_PAGES ((UINTN)Gdtr.Limit + 1));\r
+ ASSERT (Gdt != NULL);\r
+\r
+ CopyMem (Gdt, (VOID *)Gdtr.Base, Gdtr.Limit + 1);\r
+ Gdtr.Base = (UINTN)Gdt;\r
+ AsmWriteGdtr (&Gdtr);\r