[edk2-devel] [PATCH 1/4] Revert "UefiCpuPkg: Has APs in 64 bit long-mode before booting to OS."

Yuanhao Xie yuanhao.xie at intel.com
Mon Jan 9 03:37:21 UTC 2023


This reverts commit 73ccde8f6d04a246377cabaed2875e69d4b6b719 since it
results in a hang of the IA32 processor and needs further clean-up.

Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=4234
Cc: Eric Dong <eric.dong at intel.com>
Cc: Ray Ni <ray.ni at intel.com>
Cc: Rahul Kumar <rahul1.kumar at intel.com>
Cc: Gerd Hoffmann <kraxel at redhat.com>
Signed-off-by: Yuanhao Xie <yuanhao.xie at intel.com>
---
 UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf |   7 +-
 UefiCpuPkg/Library/MpInitLib/DxeMpLib.c       |  84 +++++----
 .../Library/MpInitLib/Ia32/CreatePageTable.c  |  27 ---
 UefiCpuPkg/Library/MpInitLib/MpLib.h          |  19 +-
 .../Library/MpInitLib/X64/CreatePageTable.c   |  75 --------
 UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm | 171 +++++++++++++++---
 UefiCpuPkg/UefiCpuPkg.dsc                     |   1 -
 7 files changed, 200 insertions(+), 184 deletions(-)
 delete mode 100644 UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c
 delete mode 100644 UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c

diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
index 8c8b81d933..cd07de3a3c 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
@@ -1,7 +1,7 @@
 ## @file
 #  MP Initialize Library instance for DXE driver.
 #
-#  Copyright (c) 2016 - 2022, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2016 - 2021, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -24,11 +24,9 @@
 [Sources.IA32]
   Ia32/AmdSev.c
   Ia32/MpFuncs.nasm
-  Ia32/CreatePageTable.c
 
 [Sources.X64]
   X64/AmdSev.c
-  X64/CreatePageTable.c
   X64/MpFuncs.nasm
 
 [Sources.common]
@@ -59,9 +57,6 @@
   CcExitLib
   MicrocodeLib
 
-[LibraryClasses.X64]
-  CpuPageTableLib
-
 [Protocols]
   gEfiTimerArchProtocolGuid                     ## SOMETIMES_CONSUMES
 
diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
index beab06a5b1..445e0853d2 100644
--- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
+++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
@@ -28,7 +28,6 @@ volatile BOOLEAN  mStopCheckAllApsStatus       = TRUE;
 VOID              *mReservedApLoopFunc         = NULL;
 UINTN             mReservedTopOfApStack;
 volatile UINT32   mNumberToFinish = 0;
-UINTN             mApPageTable;
 
 //
 // Begin wakeup buffer allocation below 0x88000
@@ -408,9 +407,12 @@ RelocateApLoop (
     AsmRelocateApLoopFunc (
       MwaitSupport,
       CpuMpData->ApTargetCState,
+      CpuMpData->PmCodeSegment,
       StackStart - ProcessorNumber * AP_SAFE_STACK_SIZE,
       (UINTN)&mNumberToFinish,
-      mApPageTable
+      CpuMpData->Pm16CodeSegment,
+      CpuMpData->SevEsAPBuffer,
+      CpuMpData->WakeupBuffer
       );
   }
 
@@ -475,6 +477,7 @@ InitMpGlobalData (
   )
 {
   EFI_STATUS                       Status;
+  EFI_PHYSICAL_ADDRESS             Address;
   UINTN                            ApSafeBufferSize;
   UINTN                            Index;
   EFI_GCD_MEMORY_SPACE_DESCRIPTOR  MemDesc;
@@ -542,45 +545,60 @@ InitMpGlobalData (
   // Allocating it in advance since memory services are not available in
   // Exit Boot Services callback function.
   //
-  // +------------+
-  // | Ap Loop    |
-  // +------------+
-  // | Stack * N  |
-  // +------------+ (low address)
-  //
   ApSafeBufferSize = EFI_PAGES_TO_SIZE (
                        EFI_SIZE_TO_PAGES (
-                         CpuMpData->CpuCount * AP_SAFE_STACK_SIZE
-                         + CpuMpData->AddressMap.RelocateApLoopFuncSize
+                         CpuMpData->AddressMap.RelocateApLoopFuncSize
                          )
                        );
+  Address = BASE_4GB - 1;
+  Status  = gBS->AllocatePages (
+                   AllocateMaxAddress,
+                   EfiReservedMemoryType,
+                   EFI_SIZE_TO_PAGES (ApSafeBufferSize),
+                   &Address
+                   );
+  ASSERT_EFI_ERROR (Status);
 
-  mReservedTopOfApStack = (UINTN)AllocateReservedPages (EFI_SIZE_TO_PAGES (ApSafeBufferSize));
-  ASSERT (mReservedTopOfApStack != 0);
-  ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
-  ASSERT ((AP_SAFE_STACK_SIZE & (CPU_STACK_ALIGNMENT - 1)) == 0);
-
-  mReservedApLoopFunc = (VOID *)(mReservedTopOfApStack + CpuMpData->CpuCount * AP_SAFE_STACK_SIZE);
-  if (StandardSignatureIsAuthenticAMD ()) {
-    CopyMem (
-      mReservedApLoopFunc,
-      CpuMpData->AddressMap.RelocateApLoopFuncAddressAmd,
-      CpuMpData->AddressMap.RelocateApLoopFuncSizeAmd
-      );
-  } else {
-    CopyMem (
-      mReservedApLoopFunc,
-      CpuMpData->AddressMap.RelocateApLoopFuncAddress,
-      CpuMpData->AddressMap.RelocateApLoopFuncSize
-      );
+  mReservedApLoopFunc = (VOID *)(UINTN)Address;
+  ASSERT (mReservedApLoopFunc != NULL);
 
-    mApPageTable = CreatePageTable (
-                     mReservedTopOfApStack,
-                     ApSafeBufferSize
-                     );
+  //
+  // Make sure that the buffer memory is executable if NX protection is enabled
+  // for EfiReservedMemoryType.
+  //
+  // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD
+  //       service.
+  //
+  Status = gDS->GetMemorySpaceDescriptor (Address, &MemDesc);
+  if (!EFI_ERROR (Status)) {
+    gDS->SetMemorySpaceAttributes (
+           Address,
+           ApSafeBufferSize,
+           MemDesc.Attributes & (~EFI_MEMORY_XP)
+           );
   }
 
-  mReservedTopOfApStack += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE;
+  ApSafeBufferSize = EFI_PAGES_TO_SIZE (
+                       EFI_SIZE_TO_PAGES (
+                         CpuMpData->CpuCount * AP_SAFE_STACK_SIZE
+                         )
+                       );
+  Address = BASE_4GB - 1;
+  Status  = gBS->AllocatePages (
+                   AllocateMaxAddress,
+                   EfiReservedMemoryType,
+                   EFI_SIZE_TO_PAGES (ApSafeBufferSize),
+                   &Address
+                   );
+  ASSERT_EFI_ERROR (Status);
+
+  mReservedTopOfApStack = (UINTN)Address + ApSafeBufferSize;
+  ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);
+  CopyMem (
+    mReservedApLoopFunc,
+    CpuMpData->AddressMap.RelocateApLoopFuncAddress,
+    CpuMpData->AddressMap.RelocateApLoopFuncSize
+    );
 
   Status = gBS->CreateEvent (
                   EVT_TIMER | EVT_NOTIFY_SIGNAL,
diff --git a/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c
deleted file mode 100644
index 525885b77d..0000000000
--- a/UefiCpuPkg/Library/MpInitLib/Ia32/CreatePageTable.c
+++ /dev/null
@@ -1,27 +0,0 @@
-/** @file
-  Function to create page talbe.
-  Only create page table for x64, and leave the CreatePageTable empty for Ia32.
-
-  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-
-/**
-  Only create page table for x64, and leave the CreatePageTable empty for Ia32.
-
-  @param[in]      LinearAddress  The start of the linear address range.
-  @param[in]      Length         The length of the linear address range.
-
-  @return The page table to be created.
-**/
-UINTN
-CreatePageTable (
-  IN UINTN  Address,
-  IN UINTN  Length
-  )
-{
-  return 0;
-}
diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h
index 13d515c2df..1102003a93 100644
--- a/UefiCpuPkg/Library/MpInitLib/MpLib.h
+++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h
@@ -392,9 +392,12 @@ typedef
 (EFIAPI *ASM_RELOCATE_AP_LOOP)(
   IN BOOLEAN                 MwaitSupport,
   IN UINTN                   ApTargetCState,
+  IN UINTN                   PmCodeSegment,
   IN UINTN                   TopOfApStack,
   IN UINTN                   NumberToFinish,
-  IN UINTN                   Cr3
+  IN UINTN                   Pm16CodeSegment,
+  IN UINTN                   SevEsAPJumpTable,
+  IN UINTN                   WakeupBuffer
   );
 
 /**
@@ -509,20 +512,6 @@ WakeUpAP (
   IN BOOLEAN           WakeUpDisabledAps
   );
 
-/**
-  Create 1:1 mapping page table in reserved memory to map the specified address range.
-
-  @param[in]      LinearAddress  The start of the linear address range.
-  @param[in]      Length         The length of the linear address range.
-
-  @return The page table to be created.
-**/
-UINTN
-CreatePageTable (
-  IN UINTN  Address,
-  IN UINTN  Length
-  );
-
 /**
   Initialize global data for MP support.
 
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c b/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c
deleted file mode 100644
index 548ef3f2c8..0000000000
--- a/UefiCpuPkg/Library/MpInitLib/X64/CreatePageTable.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/** @file
-  Function to create page talbe.
-  Only create page table for x64, and leave the CreatePageTable empty for Ia32.
-
-  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
-  SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-#include <Library/CpuPageTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Base.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/DebugLib.h>
-
-/**
-  Create 1:1 mapping page table in reserved memory to map the specified address range.
-
-  @param[in]      LinearAddress  The start of the linear address range.
-  @param[in]      Length         The length of the linear address range.
-
-  @return The page table to be created.
-**/
-UINTN
-CreatePageTable (
-  IN UINTN  Address,
-  IN UINTN  Length
-  )
-{
-  EFI_STATUS  Status;
-  VOID        *PageTableBuffer;
-  UINTN       PageTableBufferSize;
-  UINTN       PageTable;
-
-  IA32_MAP_ATTRIBUTE  MapAttribute;
-  IA32_MAP_ATTRIBUTE  MapMask;
-
-  MapAttribute.Uint64         = Address;
-  MapAttribute.Bits.Present   = 1;
-  MapAttribute.Bits.ReadWrite = 1;
-
-  MapMask.Bits.PageTableBaseAddress = 1;
-  MapMask.Bits.Present              = 1;
-  MapMask.Bits.ReadWrite            = 1;
-
-  PageTable           = 0;
-  PageTableBufferSize = 0;
-
-  Status = PageTableMap (
-             &PageTable,
-             Paging4Level,
-             NULL,
-             &PageTableBufferSize,
-             Address,
-             Length,
-             &MapAttribute,
-             &MapMask
-             );
-  ASSERT (Status == EFI_BUFFER_TOO_SMALL);
-  DEBUG ((DEBUG_INFO, "AP Page Table Buffer Size = %x\n", PageTableBufferSize));
-
-  PageTableBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (PageTableBufferSize));
-  ASSERT (PageTableBuffer != NULL);
-  Status = PageTableMap (
-             &PageTable,
-             Paging4Level,
-             PageTableBuffer,
-             &PageTableBufferSize,
-             Address,
-             Length,
-             &MapAttribute,
-             &MapMask
-             );
-  ASSERT_EFI_ERROR (Status);
-  return PageTable;
-}
diff --git a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
index 8ae287dd8d..39c3e8606a 100644
--- a/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
+++ b/UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm
@@ -279,42 +279,120 @@ CProcedureInvoke:
 RendezvousFunnelProcEnd:
 
 ;-------------------------------------------------------------------------------------
-;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, TopOfApStack, CountTofinish, Cr3);
-;  This function is called during the finalizaiton of Mp initialization before booting
-;  to OS, and aim to put Aps either in Mwait or HLT.
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack, CountTofinish, Pm16CodeSegment, SevEsAPJumpTable, WakeupBuffer);
 ;-------------------------------------------------------------------------------------
-; +----------------+
-; | Cr3            |  rsp+40
-; +----------------+
-; | CountTofinish  |  r9
-; +----------------+
-; | TopOfApStack   |  r8
-; +----------------+
-; | ApTargetCState |  rdx
-; +----------------+
-; | MwaitSupport   |  rcx
-; +----------------+
-; | the return     |
-; +----------------+ low address
-
 AsmRelocateApLoopStart:
-    mov        rax, r9           ; CountTofinish
+BITS 64
+    cmp        qword [rsp + 56], 0  ; SevEsAPJumpTable
+    je         NoSevEs
+
+    ;
+    ; Perform some SEV-ES related setup before leaving 64-bit mode
+    ;
+    push       rcx
+    push       rdx
+
+    ;
+    ; Get the RDX reset value using CPUID
+    ;
+    mov        rax, 1
+    cpuid
+    mov        rsi, rax          ; Save off the reset value for RDX
+
+    ;
+    ; Prepare the GHCB for the AP_HLT_LOOP VMGEXIT call
+    ;   - Must be done while in 64-bit long mode so that writes to
+    ;     the GHCB memory will be unencrypted.
+    ;   - No NAE events can be generated once this is set otherwise
+    ;     the AP_RESET_HOLD SW_EXITCODE will be overwritten.
+    ;
+    mov        rcx, 0xc0010130
+    rdmsr                        ; Retrieve current GHCB address
+    shl        rdx, 32
+    or         rdx, rax
+
+    mov        rdi, rdx
+    xor        rax, rax
+    mov        rcx, 0x800
+    shr        rcx, 3
+    rep stosq                    ; Clear the GHCB
+
+    mov        rax, 0x80000004   ; VMGEXIT AP_RESET_HOLD
+    mov        [rdx + 0x390], rax
+    mov        rax, 114          ; Set SwExitCode valid bit
+    bts        [rdx + 0x3f0], rax
+    inc        rax               ; Set SwExitInfo1 valid bit
+    bts        [rdx + 0x3f0], rax
+    inc        rax               ; Set SwExitInfo2 valid bit
+    bts        [rdx + 0x3f0], rax
+
+    pop        rdx
+    pop        rcx
+
+NoSevEs:
+    cli                          ; Disable interrupt before switching to 32-bit mode
+    mov        rax, [rsp + 40]   ; CountTofinish
     lock dec   dword [rax]       ; (*CountTofinish)--
 
-    mov        rax, [rsp + 40]    ; Cr3
-    ; Do not push on old stack, since old stack is not mapped
-    ; in the page table pointed by cr3
-    mov        cr3, rax
-    mov        rsp, r8            ; TopOfApStack
+    mov        r10, [rsp + 48]   ; Pm16CodeSegment
+    mov        rax, [rsp + 56]   ; SevEsAPJumpTable
+    mov        rbx, [rsp + 64]   ; WakeupBuffer
+    mov        rsp, r9           ; TopOfApStack
+
+    push       rax               ; Save SevEsAPJumpTable
+    push       rbx               ; Save WakeupBuffer
+    push       r10               ; Save Pm16CodeSegment
+    push       rcx               ; Save MwaitSupport
+    push       rdx               ; Save ApTargetCState
+
+    lea        rax, [PmEntry]    ; rax <- The start address of transition code
+
+    push       r8
+    push       rax
+
+    ;
+    ; Clear R8 - R15, for reset, before going into 32-bit mode
+    ;
+    xor        r8, r8
+    xor        r9, r9
+    xor        r10, r10
+    xor        r11, r11
+    xor        r12, r12
+    xor        r13, r13
+    xor        r14, r14
+    xor        r15, r15
+
+    ;
+    ; Far return into 32-bit mode
+    ;
+    retfq
+
+BITS 32
+PmEntry:
+    mov        eax, cr0
+    btr        eax, 31           ; Clear CR0.PG
+    mov        cr0, eax          ; Disable paging and caches
+
+    mov        ecx, 0xc0000080
+    rdmsr
+    and        ah, ~ 1           ; Clear LME
+    wrmsr
+    mov        eax, cr4
+    and        al, ~ (1 << 5)    ; Clear PAE
+    mov        cr4, eax
+
+    pop        edx
+    add        esp, 4
+    pop        ecx,
+    add        esp, 4
 
 MwaitCheck:
     cmp        cl, 1              ; Check mwait-monitor support
     jnz        HltLoop
-    mov        rbx, rdx           ; Save C-State to ebx
-
+    mov        ebx, edx           ; Save C-State to ebx
 MwaitLoop:
     cli
-    mov        rax, rsp           ; Set Monitor Address
+    mov        eax, esp           ; Set Monitor Address
     xor        ecx, ecx           ; ecx = 0
     xor        edx, edx           ; edx = 0
     monitor
@@ -324,10 +402,49 @@ MwaitLoop:
     jmp        MwaitLoop
 
 HltLoop:
+    pop        edx                ; PM16CodeSegment
+    add        esp, 4
+    pop        ebx                ; WakeupBuffer
+    add        esp, 4
+    pop        eax                ; SevEsAPJumpTable
+    add        esp, 4
+    cmp        eax, 0             ; Check for SEV-ES
+    je         DoHlt
+
+    cli
+    ;
+    ; SEV-ES is enabled, use VMGEXIT (GHCB information already
+    ; set by caller)
+    ;
+BITS 64
+    rep        vmmcall
+BITS 32
+
+    ;
+    ; Back from VMGEXIT AP_HLT_LOOP
+    ;   Push the FLAGS/CS/IP values to use
+    ;
+    push       word 0x0002        ; EFLAGS
+    xor        ecx, ecx
+    mov        cx, [eax + 2]      ; CS
+    push       cx
+    mov        cx, [eax]          ; IP
+    push       cx
+    push       word 0x0000        ; For alignment, will be discarded
+
+    push       edx
+    push       ebx
+
+    mov        edx, esi           ; Restore RDX reset value
+
+    retf
+
+DoHlt:
     cli
     hlt
-    jmp        HltLoop
+    jmp        DoHlt
 
+BITS 64
 AsmRelocateApLoopEnd:
 
 ;-------------------------------------------------------------------------------------
diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc
index 781acedfc5..f9a46089d2 100644
--- a/UefiCpuPkg/UefiCpuPkg.dsc
+++ b/UefiCpuPkg/UefiCpuPkg.dsc
@@ -94,7 +94,6 @@
   MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
   HobLib|MdePkg/Library/DxeHobLib/DxeHobLib.inf
   CpuExceptionHandlerLib|UefiCpuPkg/Library/CpuExceptionHandlerLib/DxeCpuExceptionHandlerLib.inf
-  CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf
   MpInitLib|UefiCpuPkg/Library/MpInitLib/DxeMpInitLib.inf
   RegisterCpuFeaturesLib|UefiCpuPkg/Library/RegisterCpuFeaturesLib/DxeRegisterCpuFeaturesLib.inf
   CpuCacheInfoLib|UefiCpuPkg/Library/CpuCacheInfoLib/DxeCpuCacheInfoLib.inf
-- 
2.36.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#98164): https://edk2.groups.io/g/devel/message/98164
Mute This Topic: https://groups.io/mt/96145515/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list