From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by ml01.01.org (Postfix) with ESMTP id 65C901A1DFF for ; Fri, 29 Jul 2016 11:15:49 -0700 (PDT) Received: from fmsmga001.fm.intel.com ([10.253.24.23]) by fmsmga102.fm.intel.com with ESMTP; 29 Jul 2016 11:15:42 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.28,440,1464678000"; d="scan'208";a="1016339186" Received: from jfan12-desk.ccr.corp.intel.com ([10.239.9.5]) by fmsmga001.fm.intel.com with ESMTP; 29 Jul 2016 11:15:42 -0700 From: Jeff Fan To: edk2-devel@ml01.01.org Cc: Michael Kinney , Feng Tian , Giri P Mudusuru , Laszlo Ersek Date: Sat, 30 Jul 2016 02:14:46 +0800 Message-Id: <1469816112-8200-21-git-send-email-jeff.fan@intel.com> X-Mailer: git-send-email 2.7.4.windows.1 In-Reply-To: <1469816112-8200-1-git-send-email-jeff.fan@intel.com> References: <1469816112-8200-1-git-send-email-jeff.fan@intel.com> Subject: [Patch v4 20/46] UefiCpuPkg/MpInitLib: Add ApCFunction() executed by assembly code 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: Fri, 29 Jul 2016 18:15:49 -0000 ApCFunction() is the first C function executed from AP reset vector. When APs waken up at the first time, it will sync BSP's MTRR setting and load microcode on APs and collect APs' BIST information. When AP tasked finished, it will place APs it one loop specified by ApLoopMode. 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 | 198 +++++++++++++++++++++++++++++++++++ UefiCpuPkg/Library/MpInitLib/MpLib.h | 2 + 2 files changed, 200 insertions(+) diff --git a/UefiCpuPkg/Library/MpInitLib/MpLib.c b/UefiCpuPkg/Library/MpInitLib/MpLib.c index 90ede9c..bbf48f6 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.c +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.c @@ -179,6 +179,59 @@ GetApLoopMode ( return ApLoopMode; } + +/** + Do sync on APs. + + @param[in, out] Buffer Pointer to private data buffer. +**/ +VOID +EFIAPI +ApInitializeSync ( + IN OUT VOID *Buffer + ) +{ + CPU_MP_DATA *CpuMpData; + + CpuMpData = (CPU_MP_DATA *) Buffer; + // + // Sync BSP's MTRR table to AP + // + MtrrSetAllMtrrs (&CpuMpData->MtrrTable); + // + // Load microcode on AP + // + MicrocodeDetect (CpuMpData); +} + +/** + Find the current Processor number by APIC ID. + + @param[in] CpuMpData Pointer to PEI CPU MP Data + @param[in] ProcessorNumber Return the pocessor number found + + @retval EFI_SUCCESS ProcessorNumber is found and returned. + @retval EFI_NOT_FOUND ProcessorNumber is not found. +**/ +EFI_STATUS +GetProcessorNumber ( + IN CPU_MP_DATA *CpuMpData, + OUT UINTN *ProcessorNumber + ) +{ + UINTN TotalProcessorNumber; + UINTN Index; + + TotalProcessorNumber = CpuMpData->CpuCount; + for (Index = 0; Index < TotalProcessorNumber; Index ++) { + if (CpuMpData->CpuData[Index].ApicId == GetApicId ()) { + *ProcessorNumber = Index; + return EFI_SUCCESS; + } + } + return EFI_NOT_FOUND; +} + /* Initialize CPU AP Data when AP is wakeup at the first time. @@ -214,6 +267,151 @@ InitializeApData ( } /** + This function will be called from AP reset code if BSP uses WakeUpAP. + + @param[in] ExchangeInfo Pointer to the MP exchange info buffer + @param[in] NumApsExecuting Number of current executing AP +**/ +VOID +EFIAPI +ApCFunction ( + IN MP_CPU_EXCHANGE_INFO *ExchangeInfo, + IN UINTN NumApsExecuting + ) +{ + CPU_MP_DATA *CpuMpData; + UINTN ProcessorNumber; + EFI_AP_PROCEDURE Procedure; + VOID *Parameter; + UINT32 BistData; + volatile UINT32 *ApStartupSignalBuffer; + + // + // AP finished assembly code and begin to execute C code + // + CpuMpData = ExchangeInfo->CpuMpData; + + ProgramVirtualWireMode (); + + while (TRUE) { + if (CpuMpData->InitFlag == ApInitConfig) { + // + // Add CPU number + // + InterlockedIncrement ((UINT32 *) &CpuMpData->CpuCount); + ProcessorNumber = NumApsExecuting; + // + // This is first time AP wakeup, get BIST information from AP stack + // + BistData = *(UINT32 *) (CpuMpData->Buffer + ProcessorNumber * CpuMpData->CpuApStackSize - sizeof (UINTN)); + // + // Do some AP initialize sync + // + ApInitializeSync (CpuMpData); + // + // Sync BSP's Control registers to APs + // + RestoreVolatileRegisters (&CpuMpData->CpuData[0].VolatileRegisters, FALSE); + InitializeApData (CpuMpData, ProcessorNumber, BistData); + ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; + } else { + // + // Execute AP function if AP is ready + // + GetProcessorNumber (CpuMpData, &ProcessorNumber); + // + // Clear AP start-up signal when AP waken up + // + ApStartupSignalBuffer = CpuMpData->CpuData[ProcessorNumber].StartupApSignal; + InterlockedCompareExchange32 ( + (UINT32 *) ApStartupSignalBuffer, + WAKEUP_AP_SIGNAL, + 0 + ); + if (CpuMpData->ApLoopMode == ApInHltLoop) { + // + // Restore AP's volatile registers saved + // + RestoreVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters, TRUE); + } + + if (GetApState (&CpuMpData->CpuData[ProcessorNumber]) == CpuStateReady) { + Procedure = (EFI_AP_PROCEDURE)CpuMpData->CpuData[ProcessorNumber].ApFunction; + Parameter = (VOID *) CpuMpData->CpuData[ProcessorNumber].ApFunctionArgument; + if (Procedure != NULL) { + SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateBusy); + // + // Invoke AP function here + // + Procedure (Parameter); + // + // Re-get the CPU APICID and Initial APICID + // + CpuMpData->CpuData[ProcessorNumber].ApicId = GetApicId (); + CpuMpData->CpuData[ProcessorNumber].InitialApicId = GetInitialApicId (); + } + SetApState (&CpuMpData->CpuData[ProcessorNumber], CpuStateFinished); + } + } + + // + // AP finished executing C code + // + InterlockedIncrement ((UINT32 *) &CpuMpData->FinishedCount); + + // + // Place AP is specified loop mode + // + if (CpuMpData->ApLoopMode == ApInHltLoop) { + // + // Save AP volatile registers + // + SaveVolatileRegisters (&CpuMpData->CpuData[ProcessorNumber].VolatileRegisters); + // + // Place AP in HLT-loop + // + while (TRUE) { + DisableInterrupts (); + CpuSleep (); + CpuPause (); + } + } + while (TRUE) { + DisableInterrupts (); + if (CpuMpData->ApLoopMode == ApInMwaitLoop) { + // + // Place AP in MWAIT-loop + // + AsmMonitor ((UINTN) ApStartupSignalBuffer, 0, 0); + if (*ApStartupSignalBuffer != WAKEUP_AP_SIGNAL) { + // + // Check AP start-up signal again. + // If AP start-up signal is not set, place AP into + // the specified C-state + // + AsmMwait (CpuMpData->ApTargetCState << 4, 0); + } + } else if (CpuMpData->ApLoopMode == ApInRunLoop) { + // + // Place AP in Run-loop + // + CpuPause (); + } else { + ASSERT (FALSE); + } + + // + // If AP start-up signal is written, AP is waken up + // otherwise place AP in loop again + // + if (*ApStartupSignalBuffer == WAKEUP_AP_SIGNAL) { + break; + } + } + } +} + +/** 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 81fea02..363867a 100644 --- a/UefiCpuPkg/Library/MpInitLib/MpLib.h +++ b/UefiCpuPkg/Library/MpInitLib/MpLib.h @@ -35,6 +35,8 @@ #include #include +#define WAKEUP_AP_SIGNAL SIGNATURE_32 ('S', 'T', 'A', 'P') + typedef enum { ApInHltLoop = 1, ApInMwaitLoop = 2, -- 2.7.4.windows.1