]> git.proxmox.com Git - mirror_edk2.git/blobdiff - UefiCpuPkg/Library/MpInitLib/DxeMpLib.c
UefiCpuPkg: Clean up source files
[mirror_edk2.git] / UefiCpuPkg / Library / MpInitLib / DxeMpLib.c
index 479f8189f6553f21347f5eef7b3f5823a0ae413b..d82e9aea45c0c0a4bfc607c691b7f23350606068 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   MP initialize support functions for DXE phase.\r
 \r
-  Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2016 - 2018, Intel Corporation. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -17,6 +17,7 @@
 #include <Library/UefiLib.h>\r
 #include <Library/UefiBootServicesTableLib.h>\r
 #include <Library/DebugAgentLib.h>\r
+#include <Library/DxeServicesTableLib.h>\r
 \r
 #include <Protocol/Timer.h>\r
 \r
@@ -112,6 +113,40 @@ GetWakeupBuffer (
   return (UINTN) StartAddress;\r
 }\r
 \r
+/**\r
+  Get available EfiBootServicesCode memory below 4GB by specified size.\r
+\r
+  This buffer is required to safely transfer AP from real address mode to\r
+  protected mode or long mode, due to the fact that the buffer returned by\r
+  GetWakeupBuffer() may be marked as non-executable.\r
+\r
+  @param[in] BufferSize   Wakeup transition buffer size.\r
+\r
+  @retval other   Return wakeup transition buffer address below 4GB.\r
+  @retval 0       Cannot find free memory below 4GB.\r
+**/\r
+UINTN\r
+GetModeTransitionBuffer (\r
+  IN UINTN                BufferSize\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  EFI_PHYSICAL_ADDRESS    StartAddress;\r
+\r
+  StartAddress = BASE_4GB - 1;\r
+  Status = gBS->AllocatePages (\r
+                  AllocateMaxAddress,\r
+                  EfiBootServicesCode,\r
+                  EFI_SIZE_TO_PAGES (BufferSize),\r
+                  &StartAddress\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    StartAddress = 0;\r
+  }\r
+\r
+  return (UINTN)StartAddress;\r
+}\r
+\r
 /**\r
   Checks APs status and updates APs status if needed.\r
 \r
@@ -233,7 +268,7 @@ RelocateApLoop (
   ASM_RELOCATE_AP_LOOP   AsmRelocateApLoopFunc;\r
   UINTN                  ProcessorNumber;\r
 \r
-  MpInitLibWhoAmI (&ProcessorNumber); \r
+  MpInitLibWhoAmI (&ProcessorNumber);\r
   CpuMpData    = GetCpuMpData ();\r
   MwaitSupport = IsMwaitSupport ();\r
   AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) mReservedApLoopFunc;\r
@@ -288,9 +323,13 @@ InitMpGlobalData (
   IN CPU_MP_DATA               *CpuMpData\r
   )\r
 {\r
-  EFI_STATUS                 Status;\r
-  EFI_PHYSICAL_ADDRESS       Address;\r
-  UINTN                      ApSafeBufferSize;\r
+  EFI_STATUS                          Status;\r
+  EFI_PHYSICAL_ADDRESS                Address;\r
+  UINTN                               ApSafeBufferSize;\r
+  UINTN                               Index;\r
+  EFI_GCD_MEMORY_SPACE_DESCRIPTOR     MemDesc;\r
+  UINTN                               StackBase;\r
+  CPU_INFO_IN_HOB                     *CpuInfoInHob;\r
 \r
   SaveCpuMpData (CpuMpData);\r
 \r
@@ -301,6 +340,46 @@ InitMpGlobalData (
     return;\r
   }\r
 \r
+  if (PcdGetBool (PcdCpuStackGuard)) {\r
+    //\r
+    // One extra page at the bottom of the stack is needed for Guard page.\r
+    //\r
+    if (CpuMpData->CpuApStackSize <= EFI_PAGE_SIZE) {\r
+      DEBUG ((DEBUG_ERROR, "PcdCpuApStackSize is not big enough for Stack Guard!\n"));\r
+      ASSERT (FALSE);\r
+    }\r
+\r
+    //\r
+    // DXE will reuse stack allocated for APs at PEI phase if it's available.\r
+    // Let's check it here.\r
+    //\r
+    // Note: BSP's stack guard is set at DxeIpl phase. But for the sake of\r
+    // BSP/AP exchange, stack guard for ApTopOfStack of cpu 0 will still be\r
+    // set here.\r
+    //\r
+    CpuInfoInHob = (CPU_INFO_IN_HOB *)(UINTN)CpuMpData->CpuInfoInHob;\r
+    for (Index = 0; Index < CpuMpData->CpuCount; ++Index) {\r
+      if (CpuInfoInHob != NULL && CpuInfoInHob[Index].ApTopOfStack != 0) {\r
+        StackBase = (UINTN)CpuInfoInHob[Index].ApTopOfStack - CpuMpData->CpuApStackSize;\r
+      } else {\r
+        StackBase = CpuMpData->Buffer + Index * CpuMpData->CpuApStackSize;\r
+      }\r
+\r
+      Status = gDS->GetMemorySpaceDescriptor (StackBase, &MemDesc);\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      Status = gDS->SetMemorySpaceAttributes (\r
+                      StackBase,\r
+                      EFI_PAGES_TO_SIZE (1),\r
+                      MemDesc.Attributes | EFI_MEMORY_RP\r
+                      );\r
+      ASSERT_EFI_ERROR (Status);\r
+\r
+      DEBUG ((DEBUG_INFO, "Stack Guard set at %lx [cpu%lu]!\n",\r
+              (UINT64)StackBase, (UINT64)Index));\r
+    }\r
+  }\r
+\r
   //\r
   // Avoid APs access invalid buffer data which allocated by BootServices,\r
   // so we will allocate reserved data for AP loop code. We also need to\r
@@ -309,9 +388,9 @@ 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
+  ApSafeBufferSize  = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (\r
+                        CpuMpData->AddressMap.RelocateApLoopFuncSize\r
+                        ));\r
   Address = BASE_4GB - 1;\r
   Status  = gBS->AllocatePages (\r
                    AllocateMaxAddress,\r
@@ -320,9 +399,39 @@ InitMpGlobalData (
                    &Address\r
                    );\r
   ASSERT_EFI_ERROR (Status);\r
+\r
   mReservedApLoopFunc = (VOID *) (UINTN) Address;\r
   ASSERT (mReservedApLoopFunc != NULL);\r
-  mReservedTopOfApStack = (UINTN) Address + EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (ApSafeBufferSize));\r
+\r
+  //\r
+  // Make sure that the buffer memory is executable if NX protection is enabled\r
+  // for EfiReservedMemoryType.\r
+  //\r
+  // TODO: Check EFI_MEMORY_XP bit set or not once it's available in DXE GCD\r
+  //       service.\r
+  //\r
+  Status = gDS->GetMemorySpaceDescriptor (Address, &MemDesc);\r
+  if (!EFI_ERROR (Status)) {\r
+    gDS->SetMemorySpaceAttributes (\r
+           Address,\r
+           ApSafeBufferSize,\r
+           MemDesc.Attributes & (~EFI_MEMORY_XP)\r
+           );\r
+  }\r
+\r
+  ApSafeBufferSize = EFI_PAGES_TO_SIZE (EFI_SIZE_TO_PAGES (\r
+                       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 (ApSafeBufferSize),\r
+                   &Address\r
+                   );\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
+  mReservedTopOfApStack = (UINTN) Address + ApSafeBufferSize;\r
   ASSERT ((mReservedTopOfApStack & (UINTN)(CPU_STACK_ALIGNMENT - 1)) == 0);\r
   CopyMem (\r
     mReservedApLoopFunc,\r