On 3/28/23 13:09, Lendacky, Thomas via groups.io wrote:
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.lenda...@amd.com>
---
  UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c | 26 ++++++++++++++++++++---
  1 file changed, 23 insertions(+), 3 deletions(-)

diff --git a/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c 
b/UefiCpuPkg/Library/MpInitLib/X64/AmdSev.c
index 509be9b41757..c9f0984f41a2 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))

I haven't seen any movement on Gerd's series to create common macros for alignment checks, but can't wait forever. So here I use an underscore in front of IS_ALIGNED() so that there won't be a conflict either before or after Gerd's series is applied. Once Gerd's series is applied, I can go back and submit another patch to use the new macros.

Thanks,
Tom

+
  /**
    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;


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#102060): https://edk2.groups.io/g/devel/message/102060
Mute This Topic: https://groups.io/mt/97912195/21656
Group Owner: devel+ow...@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to