summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLendacky, Thomas via groups.io <thomas.lendacky=amd.com@groups.io>2023-03-29 02:09:24 +0800
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2023-04-01 03:15:51 +0000
commit67a6f414aa0e2a9cac965fcc6d83b6cbd6e893c0 (patch)
treee3570c95c4891bc85f869e7d3c74d6a793bec3b3
parent3323359a811a597b8ee045638c5addd10444402c (diff)
downloadedk2-67a6f414aa0e2a9cac965fcc6d83b6cbd6e893c0.tar.gz
edk2-67a6f414aa0e2a9cac965fcc6d83b6cbd6e893c0.tar.bz2
edk2-67a6f414aa0e2a9cac965fcc6d83b6cbd6e893c0.zip
UefiCpuPkg/MpInitLib: Ensure SEV-SNP VMSA allocations are not 2MB aligned
BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=4353 Due to AMD erratum #1467, an SEV-SNP VMSA should not be 2MB aligned. To work around this issue, allocate two pages instead of one. Because of the way that page allocation is implemented, always try to use the second page. If the second page is not 2MB aligned, free the first page and use the second page. If the second page is 2MB aligned, free the second page and use the first page. Freeing in this way reduces holes in the memory map. Fixes: 06544455d0d4 ("UefiCpuPkg/MpInitLib: Use SEV-SNP AP Creation ...") Signed-off-by: Tom Lendacky <thomas.lendacky@amd.com> Acked-by: Gerd Hoffmann <kraxel@redhat.com> Acked-by: Ray Ni <ray.ni@intel.com>
-rw-r--r--UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c26
1 files changed, 23 insertions, 3 deletions
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
index 509be9b417..c9f0984f41 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
+++ b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
@@ -13,6 +13,8 @@
#include <Register/Amd/Fam17Msr.h>
#include <Register/Amd/Ghcb.h>
+#define _IS_ALIGNED(x, y) (ALIGN_POINTER((x), (y)) == (x))
+
/**
Perform the requested AP Creation action.
@@ -121,6 +123,7 @@ SevSnpCreateSaveArea (
UINT32 ApicId
)
{
+ UINT8 *Pages;
SEV_ES_SAVE_AREA *SaveArea;
IA32_CR0 ApCr0;
IA32_CR0 ResetCr0;
@@ -131,13 +134,30 @@ SevSnpCreateSaveArea (
if (CpuData->SevEsSaveArea == NULL) {
//
- // Allocate a single page for the SEV-ES Save Area and initialize it.
+ // Allocate a page for the SEV-ES Save Area and initialize it. Due to AMD
+ // erratum #1467 (VMSA cannot be on a 2MB boundary), allocate an extra page
+ // to choose from to work around the issue.
//
- SaveArea = AllocateReservedPages (1);
- if (!SaveArea) {
+ Pages = AllocateReservedPages (2);
+ if (!Pages) {
return;
}
+ //
+ // Since page allocation works by allocating downward in the address space,
+ // try to always free the first (lower address) page to limit possible holes
+ // in the memory map. So, if the address of the second page is 2MB aligned,
+ // then use the first page and free the second page. Otherwise, free the
+ // first page and use the second page.
+ //
+ if (_IS_ALIGNED (Pages + EFI_PAGE_SIZE, SIZE_2MB)) {
+ SaveArea = (SEV_ES_SAVE_AREA *)Pages;
+ FreePages (Pages + EFI_PAGE_SIZE, 1);
+ } else {
+ SaveArea = (SEV_ES_SAVE_AREA *)(Pages + EFI_PAGE_SIZE);
+ FreePages (Pages, 1);
+ }
+
CpuData->SevEsSaveArea = SaveArea;
} else {
SaveArea = CpuData->SevEsSaveArea;