/** @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
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
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
// 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
&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