From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by ml01.01.org (Postfix) with ESMTP id 57D0B1A1E9E for ; Tue, 2 Aug 2016 02:00:22 -0700 (PDT) Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga101.fm.intel.com with ESMTP; 02 Aug 2016 02:00:22 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,459,1464678000"; d="scan'208";a="743019244" Received: from jfan12-desk.ccr.corp.intel.com ([10.239.9.5]) by FMSMGA003.fm.intel.com with ESMTP; 02 Aug 2016 02:00:21 -0700 From: Jeff Fan To: edk2-devel@lists.01.org Cc: Michael Kinney , Feng Tian , Giri P Mudusuru , Laszlo Ersek Date: Tue, 2 Aug 2016 16:59:22 +0800 Message-Id: <1470128388-17960-23-git-send-email-jeff.fan@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1470128388-17960-1-git-send-email-jeff.fan@intel.com> References: <1470128388-17960-1-git-send-email-jeff.fan@intel.com> Subject: [Patch v5 22/48] UefiCpuPkg/MpInitLib: Add WakeUpAP() X-BeenThere: edk2-devel@lists.01.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: EDK II Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 02 Aug 2016 09:00:22 -0000 WakeUpAP() is used to wakeup APs per current ApLoopMode and make sure APs wake up successfully. Cc: Michael Kinney Cc: Feng Tian Cc: Giri P Mudusuru Cc: Laszlo Ersek Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jeff Fan --- UefiCpuPkg/Library/MpInitLib/MpLib.c | 121 +++++++++++++++++++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 19 ++++++ 2 files changed, 140 insertions(+) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index d081111..de169e6 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -448,6 +448,29 @@ ApWakeupFunction ( } /** + Wait for AP wakeup and write AP start-up signal till AP is waken up. + + @param[in] ApStartupSignalBuffer Pointer to AP wakeup signal +**/ +VOID +WaitApWakeup ( + IN volatile UINT32 *ApStartupSignalBuffer + ) +{ + // + // If AP is waken up, StartupApSignal should be cleared. + // Otherwise, write StartupApSignal again till AP waken up. + // + while (InterlockedCompareExchange32 ( + (UINT32 *) ApStartupSignalBuffer, + WAKEUP_AP_SIGNAL, + WAKEUP_AP_SIGNAL + ) != 0) { + CpuPause (); + } +} + +/** This function will fill the exchange info structure. @param[in] CpuMpData Pointer to CPU MP Data @@ -486,6 +509,104 @@ FillExchangeInfoData ( } /** + This function will be called by BSP to wakeup AP. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] Broadcast TRUE: Send broadcast IPI to all APs + FALSE: Send IPI to AP by ApicId + @param[in] ProcessorNumber The handle number of specified processor + @param[in] Procedure The function to be invoked by AP + @param[in] ProcedureArgument The argument to be passed into AP function +**/ +VOID +WakeUpAP ( + IN CPU_MP_DATA *CpuMpData, + IN BOOLEAN Broadcast, + IN UINTN ProcessorNumber, + IN EFI_AP_PROCEDURE Procedure, OPTIONAL + IN VOID *ProcedureArgument OPTIONAL + ) +{ + volatile MP_CPU_EXCHANGE_INFO *ExchangeInfo; + UINTN Index; + CPU_AP_DATA *CpuData; + BOOLEAN ResetVectorRequired; + + CpuMpData->FinishedCount = 0; + ResetVectorRequired = FALSE; + + if (CpuMpData->ApLoopMode == ApInHltLoop || + CpuMpData->InitFlag != ApInitDone) { + ResetVectorRequired = TRUE; + AllocateResetVector (CpuMpData); + FillExchangeInfoData (CpuMpData); + } else if (CpuMpData->ApLoopMode == ApInMwaitLoop) { + // + // Get AP target C-state each time when waking up AP, + // for it maybe updated by platform again + // + CpuMpData->ApTargetCState = PcdGet8 (PcdCpuApTargetCstate); + } + + ExchangeInfo = CpuMpData->MpCpuExchangeInfo; + + if (Broadcast) { + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { + if (Index != CpuMpData->BspNumber) { + CpuData = &CpuMpData->CpuData[Index]; + CpuData->ApFunction = (UINTN) Procedure; + CpuData->ApFunctionArgument = (UINTN) ProcedureArgument; + SetApState (CpuData, CpuStateReady); + if (CpuMpData->InitFlag != ApInitConfig) { + *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL; + } + } + } + if (ResetVectorRequired) { + // + // Wakeup all APs + // + SendInitSipiSipiAllExcludingSelf ((UINT32) ExchangeInfo->BufferStart); + } + if (CpuMpData->InitFlag != ApInitConfig) { + // + // Wait all APs waken up if this is not the 1st broadcast of SIPI + // + for (Index = 0; Index < CpuMpData->CpuCount; Index++) { + CpuData = &CpuMpData->CpuData[Index]; + if (Index != CpuMpData->BspNumber) { + WaitApWakeup (CpuData->StartupApSignal); + } + } + } + } else { + CpuData = &CpuMpData->CpuData[ProcessorNumber]; + CpuData->ApFunction = (UINTN) Procedure; + CpuData->ApFunctionArgument = (UINTN) ProcedureArgument; + SetApState (CpuData, CpuStateReady); + // + // Wakeup specified AP + // + ASSERT (CpuMpData->InitFlag != ApInitConfig); + *(UINT32 *) CpuData->StartupApSignal = WAKEUP_AP_SIGNAL; + if (ResetVectorRequired) { + SendInitSipiSipi ( + CpuData->ApicId, + (UINT32) ExchangeInfo->BufferStart + ); + } + // + // Wait specified AP waken up + // + WaitApWakeup (CpuData->StartupApSignal); + } + + if (ResetVectorRequired) { + FreeResetVector (CpuMpData); + } +} + +/** MP Initialize Library initialization. This service will allocate AP reset vector and wakeup all APs to do APs diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.h b/UefiCpuPkg/Library/MpInitLib/MpLib.h index 72a35ef..84e0970 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -283,6 +283,25 @@ FreeResetVector ( ); /** + This function will be called by BSP to wakeup AP. + + @param[in] CpuMpData Pointer to CPU MP Data + @param[in] Broadcast TRUE: Send broadcast IPI to all APs + FALSE: Send IPI to AP by ApicId + @param[in] ProcessorNumber The handle number of specified processor + @param[in] Procedure The function to be invoked by AP + @param[in] ProcedureArgument The argument to be passed into AP function +**/ +VOID +WakeUpAP ( + IN CPU_MP_DATA *CpuMpData, + IN BOOLEAN Broadcast, + IN UINTN ProcessorNumber, + IN EFI_AP_PROCEDURE Procedure, OPTIONAL + IN VOID *ProcedureArgument OPTIONAL + ); + +/** Initialize global data for MP support. @param[in] CpuMpData The pointer to CPU MP Data structure. -- 2.7.4.windows.1