\r
CPU_MP_DATA *mCpuMpData = NULL;\r
EFI_EVENT mCheckAllApsEvent = NULL;\r
+EFI_EVENT mMpInitExitBootServicesEvent = NULL;\r
volatile BOOLEAN mStopCheckAllApsStatus = TRUE;\r
\r
\r
}\r
}\r
\r
+/**\r
+ Get Protected mode code segment from current GDT table.\r
+\r
+ @returen Protected mode code segment value.\r
+**/\r
+UINT16\r
+GetProtectedModeCS (\r
+ VOID\r
+ )\r
+{\r
+ IA32_DESCRIPTOR GdtrDesc;\r
+ IA32_SEGMENT_DESCRIPTOR *GdtEntry;\r
+ UINTN GdtEntryCount;\r
+ UINT16 Index;\r
+\r
+ Index = (UINT16) -1;\r
+ AsmReadGdtr (&GdtrDesc);\r
+ GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR);\r
+ GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base;\r
+ for (Index = 0; Index < GdtEntryCount; Index++) {\r
+ if (GdtEntry->Bits.L == 0) {\r
+ if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) {\r
+ break;\r
+ }\r
+ }\r
+ GdtEntry++;\r
+ }\r
+ ASSERT (Index != -1);\r
+ return Index * 8;\r
+}\r
+\r
+/**\r
+ Do sync on APs.\r
+\r
+ @param[in, out] Buffer Pointer to private data buffer.\r
+**/\r
+VOID\r
+EFIAPI\r
+RelocateApLoop (\r
+ IN OUT VOID *Buffer\r
+ )\r
+{\r
+ CPU_MP_DATA *CpuMpData;\r
+ BOOLEAN MwaitSupport;\r
+ ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc;\r
+\r
+ CpuMpData = GetCpuMpData ();\r
+ MwaitSupport = IsMwaitSupport ();\r
+ AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) Buffer;\r
+ AsmRelocateApLoopFunc (MwaitSupport, CpuMpData->ApTargetCState, CpuMpData->PmCodeSegment);\r
+ //\r
+ // It should never reach here\r
+ //\r
+ ASSERT (FALSE);\r
+}\r
+\r
+/**\r
+ Callback function for ExitBootServices.\r
+\r
+ @param[in] Event Event whose notification function is being invoked.\r
+ @param[in] Context The pointer to the notification function's context,\r
+ which is implementation-dependent.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+MpInitExitBootServicesCallback (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ CPU_MP_DATA *CpuMpData;\r
+ VOID *ReservedApLoopFunc;\r
+ //\r
+ // Avoid APs access invalid buff data which allocated by BootServices,\r
+ // so we will allocate reserved data for AP loop code.\r
+ //\r
+ CpuMpData = GetCpuMpData ();\r
+ CpuMpData->PmCodeSegment = GetProtectedModeCS ();\r
+ CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode);\r
+ ReservedApLoopFunc = AllocateReservedCopyPool (\r
+ CpuMpData->AddressMap.RelocateApLoopFuncSize,\r
+ CpuMpData->AddressMap.RelocateApLoopFuncAddress\r
+ );\r
+ WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, ReservedApLoopFunc);\r
+ DEBUG ((DEBUG_INFO, "MpInitExitBootServicesCallback() done!\n"));\r
+}\r
+\r
/**\r
Initialize global data for MP support.\r
\r
AP_CHECK_INTERVAL\r
);\r
ASSERT_EFI_ERROR (Status);\r
+ Status = gBS->CreateEvent (\r
+ EVT_SIGNAL_EXIT_BOOT_SERVICES,\r
+ TPL_CALLBACK,\r
+ MpInitExitBootServicesCallback,\r
+ NULL,\r
+ &mMpInitExitBootServicesEvent\r
+ );\r
+ ASSERT_EFI_ERROR (Status);\r
}\r
\r
/**\r