+ if (CpuMpData->CpuCount == 1) {\r
+ //\r
+ // If only BSP exists, return\r
+ //\r
+ 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 = 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
+ // allocate this buffer below 4GB due to APs may be transferred to 32bit\r
+ // protected mode on long mode DXE.\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
+ 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
+ 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
+ CpuMpData->AddressMap.RelocateApLoopFuncSize\r
+ );\r
+\r