diff --git a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c index 1043becf4c..42d320ff8a 100644 --- a/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/DxeMpLib.c @@ -21,6 +21,7 @@ CPU_MP_DATA *mCpuMpData = NULL; EFI_EVENT mCheckAllApsEvent = NULL; +EFI_EVENT mMpInitExitBootServicesEvent = NULL; volatile BOOLEAN mStopCheckAllApsStatus = TRUE; @@ -185,6 +186,94 @@ CheckApsStatus ( } } +/** + Get Protected mode code segment from current GDT table. + + @returen Protected mode code segment value. +**/ +UINT16 +GetProtectedModeCS ( + VOID + ) +{ + IA32_DESCRIPTOR GdtrDesc; + IA32_SEGMENT_DESCRIPTOR *GdtEntry; + UINTN GdtEntryCount; + UINT16 Index; + + Index = (UINT16) -1; + AsmReadGdtr (&GdtrDesc); + GdtEntryCount = (GdtrDesc.Limit + 1) / sizeof (IA32_SEGMENT_DESCRIPTOR); + GdtEntry = (IA32_SEGMENT_DESCRIPTOR *) GdtrDesc.Base; + for (Index = 0; Index < GdtEntryCount; Index++) { + if (GdtEntry->Bits.L == 0) { + if (GdtEntry->Bits.Type > 8 && GdtEntry->Bits.L == 0) { + break; + } + } + GdtEntry++; + } + ASSERT (Index != -1); + return Index * 8; +} + +/** + Do sync on APs. + + @param[in, out] Buffer Pointer to private data buffer. +**/ +VOID +EFIAPI +RelocateApLoop ( + IN OUT VOID *Buffer + ) +{ + CPU_MP_DATA *CpuMpData; + BOOLEAN MwaitSupport; + ASM_RELOCATE_AP_LOOP AsmRelocateApLoopFunc; + + CpuMpData = GetCpuMpData (); + MwaitSupport = IsMwaitSupport (); + AsmRelocateApLoopFunc = (ASM_RELOCATE_AP_LOOP) (UINTN) Buffer; + AsmRelocateApLoopFunc (MwaitSupport, CpuMpData->ApTargetCState, CpuMpData->PmCodeSegment); + // + // It should never reach here + // + ASSERT (FALSE); +} + +/** + Callback function for ExitBootServices. + + @param[in] Event Event whose notification function is being invoked. + @param[in] Context The pointer to the notification function's context, + which is implementation-dependent. + +**/ +VOID +EFIAPI +MpInitExitBootServicesCallback ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + CPU_MP_DATA *CpuMpData; + VOID *ReservedApLoopFunc; + // + // Avoid APs access invalid buff data which allocated by BootServices, + // so we will allocate reserved data for AP loop code. + // + CpuMpData = GetCpuMpData (); + CpuMpData->PmCodeSegment = GetProtectedModeCS (); + CpuMpData->ApLoopMode = PcdGet8 (PcdCpuApLoopMode); + ReservedApLoopFunc = AllocateReservedCopyPool ( + CpuMpData->AddressMap.RelocateApLoopFuncSize, + CpuMpData->AddressMap.RelocateApLoopFuncAddress + ); + WakeUpAP (CpuMpData, TRUE, 0, RelocateApLoop, ReservedApLoopFunc); + DEBUG ((DEBUG_INFO, "MpInitExitBootServicesCallback() done!\n")); +} + /** Initialize global data for MP support. @@ -217,6 +306,14 @@ InitMpGlobalData ( AP_CHECK_INTERVAL ); ASSERT_EFI_ERROR (Status); + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + MpInitExitBootServicesCallback, + NULL, + &mMpInitExitBootServicesEvent + ); + ASSERT_EFI_ERROR (Status); } /** diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 06af7cc15b..e53deb449d 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -519,6 +519,17 @@ MicrocodeDetect ( IN CPU_MP_DATA *CpuMpData ); +/** + Detect whether Mwait-monitor feature is supported. + + @retval TRUE Mwait-monitor feature is supported. + @retval FALSE Mwait-monitor feature is not supported. +**/ +BOOLEAN +IsMwaitSupport ( + VOID + ); + /** Notify function on End Of PEI PPI.