UefiCpuPkg/DxeMpLib: Allocate new safe stack < 4GB
authorJeff Fan <jeff.fan@intel.com>
Wed, 23 Nov 2016 13:52:24 +0000 (21:52 +0800)
committerJeff Fan <jeff.fan@intel.com>
Mon, 28 Nov 2016 00:56:36 +0000 (08:56 +0800)
For long mode DXE, we will disable paging on AP to protected mode to execute AP
safe loop code in reserved memory range under 4GB. But we forget to allocate
stack for AP under 4GB and AP still are using original AP stack. If original AP
stack is larger than 4GB, it cannot be used after AP is transferred to protected
mode. Besides MwaitSupport == TRUE, AP stack is still required during phase of
disabling paging in long mode DXE.

Moreover, even though AP stack is always under 4GB (a) in Ia32 DXE and (b) with
this patch, after transferring to protected mode from X64 DXE, AP stack
(in BootServiceData) maybe crashed by OS after Exit Boot Service event.

This fix is to allocate reserved memory range under 4GB together with AP safe
loop code. APs will switch to new stack in safe loop code.

Cc: Laszlo Ersek <lersek@redhat.com>
Cc: Feng Tian <feng.tian@intel.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Jeff Fan <jeff.fan@intel.com>
Reviewed-by: Laszlo Ersek <lersek@redhat.com>
Tested-by: Laszlo Ersek <lersek@redhat.com>
UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
UefiCpuPkg/Library/MpInitLib/Ia32/MpFuncs.nasm
UefiCpuPkg/Library/MpInitLib/MpLib.h
UefiCpuPkg/Library/MpInitLib/X64/MpFuncs.nasm

index a0d5eebc9497620efa48b15ee59ae6580b7f09da..5a3b02c26d3acd4a14fce4331038e4278d3246d6 100644 (file)
@@ -18,6 +18,7 @@
 #include <Library/UefiBootServicesTableLib.h>\r
 \r
 #define  AP_CHECK_INTERVAL     (EFI_TIMER_PERIOD_MILLISECONDS (100))\r
+#define  AP_SAFE_STACK_SIZE    128\r
 \r
 CPU_MP_DATA      *mCpuMpData = NULL;\r
 EFI_EVENT        mCheckAllApsEvent = NULL;\r
@@ -25,6 +26,7 @@ EFI_EVENT        mMpInitExitBootServicesEvent = NULL;
 EFI_EVENT        mLegacyBootEvent = NULL;\r
 volatile BOOLEAN mStopCheckAllApsStatus = TRUE;\r
 VOID             *mReservedApLoopFunc = NULL;\r
+UINTN            mReservedTopOfApStack;\r
 \r
 /**\r
   Get the pointer to CPU MP Data structure.\r
@@ -241,11 +243,18 @@ RelocateApLoop (
   CPU_MP_DATA            *CpuMpData;\r
   BOOLEAN                MwaitSupport;\r
   ASM_RELOCATE_AP_LOOP   AsmRelocateApLoopFunc;\r
+  UINTN                  ProcessorNumber;\r
 \r
+  MpInitLibWhoAmI (&ProcessorNumber); \r
   CpuMpData    = GetCpuMpData ();\r
   MwaitSupport = IsMwaitSupport ();\r
   AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc;\r
-  AsmRelocateApLoopFunc (MwaitSupport, CpuMpData->ApTargetCState, CpuMpData->PmCodeSegment);\r
+  AsmRelocateApLoopFunc (\r
+    MwaitSupport,\r
+    CpuMpData->ApTargetCState,\r
+    CpuMpData->PmCodeSegment,\r
+    mReservedTopOfApStack - ProcessorNumber * AP_SAFE_STACK_SIZE\r
+    );\r
   //\r
   // It should never reach here\r
   //\r
@@ -289,6 +298,7 @@ InitMpGlobalData (
 {\r
   EFI_STATUS                 Status;\r
   EFI_PHYSICAL_ADDRESS       Address;\r
+  UINTN                      ApSafeBufferSize;\r
 \r
   SaveCpuMpData (CpuMpData);\r
 \r
@@ -307,16 +317,21 @@ InitMpGlobalData (
   // Allocating it in advance since memory services are not available in\r
   // Exit Boot Services callback function.\r
   //\r
+  ApSafeBufferSize  = CpuMpData->AddressMap.RelocateApLoopFuncSize;\r
+  ApSafeBufferSize += CpuMpData->CpuCount * AP_SAFE_STACK_SIZE;\r
+\r
   Address = BASE_4GB - 1;\r
   Status  = gBS->AllocatePages (\r
                    AllocateMaxAddress,\r
                    EfiReservedMemoryType,\r
-                   EFI_SIZE_TO_PAGES (sizeof (CpuMpData->AddressMap.RelocateApLoopFuncSize)),\r
+                   EFI_SIZE_TO_PAGES (ApSafeBufferSize),\r
                    &Address\r
                    );\r
   ASSERT_EFI_ERROR (Status);\r
   mReservedApLoopFunc = (VOID *) (UINTN) Address;\r
   ASSERT (mReservedApLoopFunc != NULL);\r
+  mReservedTopOfApStack = (UINTN) Address + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ApSafeBufferSize));\r
+  ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);\r
   CopyMem (\r
     mReservedApLoopFunc,\r
     CpuMpData->AddressMap.RelocateApLoopFuncAddress,\r
index 9067f7807098201c539192147eacd1cb72fdda4b..7ab136be4f5d55ed7188ed508dad0f17e2e62b06 100644 (file)
@@ -215,19 +215,26 @@ CProcedureInvoke:
 RendezvousFunnelProcEnd:\r
 \r
 ;-------------------------------------------------------------------------------------\r
-;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack);\r
 ;-------------------------------------------------------------------------------------\r
 global ASM_PFX(AsmRelocateApLoop)\r
 ASM_PFX(AsmRelocateApLoop):\r
 AsmRelocateApLoopStart:\r
-    cmp        byte [esp + 4], 1\r
+    mov        eax, esp\r
+    mov        esp, [eax + 16]     ; TopOfApStack\r
+    push       dword [eax]         ; push return address for stack trace\r
+    push       ebp\r
+    mov        ebp, esp\r
+    mov        ebx, [eax + 8]      ; ApTargetCState\r
+    mov        ecx, [eax + 4]      ; MwaitSupport\r
+    cmp        cl,  1              ; Check mwait-monitor support\r
     jnz        HltLoop\r
 MwaitLoop:\r
     mov        eax, esp\r
     xor        ecx, ecx\r
     xor        edx, edx\r
     monitor\r
-    mov        eax, [esp + 8]    ; Mwait Cx, Target C-State per eax[7:4]\r
+    mov        eax, ebx            ; Mwait Cx, Target C-State per eax[7:4]\r
     shl        eax, 4\r
     mwait\r
     jmp        MwaitLoop\r
index f73a469ae84f5831fb2d1931a3a83412eb149f16..e6dea18428768f7fdc6b03136e4efa268130e65b 100644 (file)
@@ -250,7 +250,8 @@ VOID
 (EFIAPI * ASM_RELOCATE_AP_LOOP) (\r
   IN BOOLEAN                 MwaitSupport,\r
   IN UINTN                   ApTargetCState,\r
-  IN UINTN                   PmCodeSegment\r
+  IN UINTN                   PmCodeSegment,\r
+  IN UINTN                   TopOfApStack\r
   );\r
 \r
 /**\r
index e7e7d8086dd01e989ab6114c983b9abd37d04513..7869970bbb9487e48af300f09dcae9d4d142bdc3 100644 (file)
@@ -222,11 +222,12 @@ CProcedureInvoke:
 RendezvousFunnelProcEnd:\r
 \r
 ;-------------------------------------------------------------------------------------\r
-;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment);\r
+;  AsmRelocateApLoop (MwaitSupport, ApTargetCState, PmCodeSegment, TopOfApStack);\r
 ;-------------------------------------------------------------------------------------\r
 global ASM_PFX(AsmRelocateApLoop)\r
 ASM_PFX(AsmRelocateApLoop):\r
 AsmRelocateApLoopStart:\r
+    mov        rsp, r9\r
     push       rcx\r
     push       rdx\r
 \r