/** * * FeatureLeveling * * CPU feature leveling. Set least common features set of all CPUs * * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. * */ VOID FeatureLeveling ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; UINT32 Socket; UINT32 Core; UINT32 NumberOfSockets; UINT32 NumberOfCores; BOOLEAN *FirstTime; BOOLEAN *NeedLeveling; AGESA_STATUS IgnoredSts; CPU_FEATURES_LIST *globalCpuFeatureList; AP_TASK TaskPtr; ASSERT (IsBsp (StdHeader, &IgnoredSts)); GetGlobalCpuFeatureListAddress ((UINT64 **) &globalCpuFeatureList, StdHeader); FirstTime = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST)); NeedLeveling = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST) + sizeof (BOOLEAN)); *FirstTime = TRUE; *NeedLeveling = FALSE; LibAmdMemFill (globalCpuFeatureList, 0xFF, sizeof (CPU_FEATURES_LIST), StdHeader); IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); TaskPtr.FuncAddress.PfApTaskI = SaveFeatures; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (CPU_FEATURES_LIST); TaskPtr.ExeFlags = WAIT_FOR_CORE; TaskPtr.DataTransfer.DataPtr = globalCpuFeatureList; TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { if (Socket != BscSocket) { ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL); if (*NeedLeveling) { TaskPtr.FuncAddress.PfApTaskI = WriteFeatures; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != BscSocket) || (Core != BscCoreNum)) { ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, &TaskPtr, StdHeader); } } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL); } }
/** * IDS function force all cores run specific task after amdinitpost * * * @param[in] ApLateTaskPtr The Pointer of IDSAPLATETASK. * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS. * * @retval AGESA_SUCCESS Success * @retval AGESA_ERROR meet some error * **/ AGESA_STATUS IdsAgesaRunFcnOnAllCoresLate ( IN IDSAPLATETASK *ApLateTaskPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AP_EXE_PARAMS LaunchApParams; AGESA_STATUS Status; //init AgesaRunFcnOnAp parameters Status = AGESA_SUCCESS; LaunchApParams.FunctionNumber = IDS_LATE_RUN_AP_TASK_ID; LaunchApParams.RelatedBlockLength = SIZE_IN_DWORDS (IDSAPLATETASK); LaunchApParams.RelatedDataBlock = ApLateTaskPtr; LaunchApParams.StdHeader = *StdHeader; Status = RunLateApTaskOnAllAPs (&LaunchApParams, StdHeader); //do it on Bsp Status = ApLateTaskPtr->ApTask (ApLateTaskPtr->ApTaskPara, StdHeader); return Status; }
/** * IDS function for ap run specific task after amdinitpost * * * @param[in] ApicIdOfCore apic id of specific AP * @param[in] ApLateTaskPtr The Pointer of IDSAPLATETASK. * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS. * * @retval AGESA_SUCCESS Success * @retval AGESA_ERROR meet some error * **/ AGESA_STATUS IdsAgesaRunFcnOnApLate ( IN UINTN ApicIdOfCore, IN IDSAPLATETASK *ApLateTaskPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS Status; AP_EXE_PARAMS LaunchApParams; //init AgesaRunFcnOnAp parameters LaunchApParams.FunctionNumber = IDS_LATE_RUN_AP_TASK_ID; LaunchApParams.RelatedBlockLength = SIZE_IN_DWORDS (IDSAPLATETASK); LaunchApParams.RelatedDataBlock = ApLateTaskPtr; LaunchApParams.StdHeader = *StdHeader; AGESA_TESTPOINT (TpIfBeforeRunApFromIds, StdHeader); Status = AgesaRunFcnOnAp ((UINTN) ApicIdOfCore, &LaunchApParams); AGESA_TESTPOINT (TpIfAfterRunApFromIds, StdHeader); return Status; }
/** *--------------------------------------------------------------------------------------- * * PutAllCoreInPState0 * * Description: * This function will put core pstate to p0. * * Parameters: * @param[in,out] *PStateBufferPtr * @param[in] *StdHeader * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- **/ AGESA_STATUS PutAllCoreInPState0 ( IN OUT PSTATE_LEVELING *PStateBufferPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { AP_TASK TaskPtr; UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; UINT32 Core; UINT32 Socket; UINT32 NumberOfSockets; UINT32 NumberOfCores; AGESA_STATUS IgnoredSts; TaskPtr.FuncAddress.PfApTaskI = PutCoreInPState0; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PSTATE_LEVELING); TaskPtr.ExeFlags = WAIT_FOR_CORE; TaskPtr.DataTransfer.DataPtr = PStateBufferPtr; TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY; IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); PutCoreInPState0 (PStateBufferPtr, StdHeader); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != (UINT32) BscSocket) || (Core != (UINT32) BscCoreNum)) { ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader); } } } } return AGESA_SUCCESS; }
/** * * * BSC task to run Core0 task at early, must only run on BSC * * @param[in] Socket - Socket which run the task * @param[in] Core - Core which run the task * @param[in] ApTask - Task for AP * @param[in,out] StdHeader - The Pointer of AGESA Header * */ VOID IdsRunCodeOnCoreEarly ( IN UINT8 Socket, IN UINT8 Core, IN AP_TASK* ApTask, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 BscSocket; UINT32 BscCoreNum; UINT32 IgnoredModule; AGESA_STATUS IgnoredSts; AP_TASK Core0Task; IDS_EARLY_AP_TASK IdsEarlyTask; IdentifyCore (StdHeader, &BscSocket, &IgnoredModule, &BscCoreNum, &IgnoredSts); ASSERT (~((Socket == BscSocket) && (Core == BscCoreNum))); if ((Socket == BscSocket) || (Core == 0)) { ApUtilRunCodeOnSocketCore (Socket, Core, ApTask, StdHeader); } else { //Init IDS_EARLY_AP_TASK for Core 0 IdsEarlyTask.Ap_Task0.ApTask = *ApTask; IdsEarlyTask.Ap_Task0.Core = Core; //Init Parameter buffer, Target core can't get the parameter from pointer, which point to Host Core memory space ASSERT ((ApTask->DataTransfer.DataSizeInDwords * sizeof (UINT32)) <= IDS_EARLY_AP_TASK_PARA_NUM); LibAmdMemCopy (&IdsEarlyTask.Parameters[0], ApTask->DataTransfer.DataPtr, sizeof (UINT32) * ApTask->DataTransfer.DataSizeInDwords, StdHeader); if ((ApTask->DataTransfer.DataSizeInDwords * sizeof (UINT32)) <= IDS_EARLY_AP_TASK_PARA_NUM) { //Lauch Core0 1st Core0Task.FuncAddress.PfApTaskI = (PF_AP_TASK_I)IdsCmnTaskCore0Early; Core0Task.ExeFlags = WAIT_FOR_CORE; Core0Task.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (IDS_EARLY_AP_TASK0) + ApTask->DataTransfer.DataSizeInDwords; Core0Task.DataTransfer.DataPtr = &IdsEarlyTask; Core0Task.DataTransfer.DataTransferFlags = 0; ApUtilRunCodeOnSocketCore (Socket, 0, &Core0Task, StdHeader); } } }
/** * Multisocket call to determine the most severe AGESA_STATUS return value after * processing the power management initialization tables. * * This function loops through all possible socket locations, collecting any * power management initialization errors that may have occurred. These errors * are transferred from the core 0s of the socket in which the errors occurred * to the BSC's heap. The BSC's heap is then searched for the most severe error * that occurred, and returns it. This function must be called by the BSC only. * * @param[in] StdHeader Config handle for library and services * * @return The most severe error code from power management init * */ AGESA_STATUS GetEarlyPmErrorsMulti ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT16 i; UINT32 BscSocket; UINT32 BscModule; UINT32 BscCoreNum; UINT32 Socket; UINT32 NumberOfSockets; AP_TASK TaskPtr; AGESA_EVENT EventLogEntry; AGESA_STATUS ReturnCode; AGESA_STATUS DummyStatus; ASSERT (IsBsp (StdHeader, &ReturnCode)); ReturnCode = AGESA_SUCCESS; EventLogEntry.EventClass = AGESA_SUCCESS; EventLogEntry.EventInfo = 0; EventLogEntry.DataParam1 = 0; EventLogEntry.DataParam2 = 0; EventLogEntry.DataParam3 = 0; EventLogEntry.DataParam4 = 0; NumberOfSockets = GetPlatformNumberOfSockets (); IdentifyCore (StdHeader, &BscSocket, &BscModule, &BscCoreNum, &DummyStatus); TaskPtr.FuncAddress.PfApTaskI = GetNextEvent; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (AGESA_EVENT); TaskPtr.DataTransfer.DataPtr = &EventLogEntry; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE | RETURN_PARAMS; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (Socket != BscSocket) { if (IsProcessorPresent (Socket, StdHeader)) { do { ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8) 0, &TaskPtr, StdHeader); if ((EventLogEntry.EventInfo & CPU_EVENT_PM_EVENT_MASK) == CPU_EVENT_PM_EVENT_CLASS) { PutEventLog ( EventLogEntry.EventClass, EventLogEntry.EventInfo, EventLogEntry.DataParam1, EventLogEntry.DataParam2, EventLogEntry.DataParam3, EventLogEntry.DataParam4, StdHeader ); } } while (EventLogEntry.EventInfo != 0); } } } for (i = 0; PeekEventLog (&EventLogEntry, i, StdHeader); i++) { if ((EventLogEntry.EventInfo & CPU_EVENT_PM_EVENT_MASK) == CPU_EVENT_PM_EVENT_CLASS) { if (EventLogEntry.EventClass > ReturnCode) { ReturnCode = EventLogEntry.EventClass; } } } return (ReturnCode); }
/** * Family 10h core 0 entry point for performing the family 10h Processor- * Systemboard Power Delivery Check. * * The steps are as follows: * 1. Starting with P0, loop through all P-states until a passing state is * found. A passing state is one in which the current required by the * CPU is less than the maximum amount of current that the system can * provide to the CPU. If P0 is under the limit, no further action is * necessary. * 2. If at least one P-State is under the limit & at least one P-State is * over the limit, the BIOS must: * a. If the processor's current P-State is disabled by the power check, * then the BIOS must request a transition to an enabled P-state * using MSRC001_0062[PstateCmd] and wait for MSRC001_0063[CurPstate] * to reflect the new value. * b. Copy the contents of the enabled P-state MSRs to the highest * performance P-state locations. * c. Request a P-state transition to the P-state MSR containing the * COF/VID values currently applied. * d. On revision E systems with CPUID Fn8000_0007[CPB]=1, if P0 is disabled then * program F4x15C[BoostSrc]=0. This step uses hardware P-state numbering. * e. Adjust the following P-state parameters affected by the P-state * MSR copy by subtracting the number of P-states that are disabled * by the power check. * 1. F3x64[HtcPstateLimit] * 2. F3x68[StcPstateLimit] * 3. F3xDC[PstateMaxVal] * 3. If all P-States are over the limit, the BIOS must: * a. If the processor's current P-State is !=F3xDC[PstateMaxVal], then * write F3xDC[PstateMaxVal] to MSRC001_0062[PstateCmd] and wait for * MSRC001_0063[CurPstate] to reflect the new value. * b. If F3xDC[PstateMaxVal]!= 000b, copy the contents of the P-state * MSR pointed to by F3xDC[PstateMaxVal] to MSRC001_0064 and set * MSRC001_0064[PstateEn] * c. Write 000b to MSRC001_0062[PstateCmd] and wait for MSRC001_0063 * [CurPstate] to reflect the new value. * d. Adjust the following P-state parameters to zero on revision D and earlier processors. * On revision E processors adjust the following fields to F4x15C[NumBoostStates]: * 1. F3x64[HtcPstateLimit] * 2. F3x68[StcPstateLimit] * 3. F3xDC[PstateMaxVal] * e. For revision E systems with CPUID Fn8000_0007[CPB]=1, program F4x15C[BoostSrc]=0. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParams Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F10PmPwrCheck ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 DisPsNum; UINT8 PsMaxVal; UINT8 Pstate; UINT32 ProcIddMax; UINT32 LocalPciRegister; UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 AndMask; UINT32 OrMask; UINT32 PstateLimit; PCI_ADDR PciAddress; UINT64 LocalMsrRegister; AP_TASK TaskPtr; AGESA_STATUS IgnoredSts; PWRCHK_ERROR_DATA ErrorData; // get the socket number IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ErrorData.SocketNumber = (UINT8)Socket; ASSERT (Core == 0); // get the Max P-state value for (PsMaxVal = NM_PS_REG - 1; PsMaxVal != 0; --PsMaxVal) { LibAmdMsrRead (PS_REG_BASE + PsMaxVal, &LocalMsrRegister, StdHeader); if (((PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1) { break; } } ErrorData.HwPstateNumber = (UINT8) (PsMaxVal + 1); DisPsNum = 0; for (Pstate = 0; Pstate < ErrorData.HwPstateNumber; Pstate++) { if (FamilySpecificServices->GetProcIddMax (FamilySpecificServices, Pstate, &ProcIddMax, StdHeader)) { if (ProcIddMax > CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].CurrentLimit) { // Add to event log the Pstate that exceeded the current limit PutEventLog (AGESA_WARNING, CPU_EVENT_PM_PSTATE_OVERCURRENT, Socket, Pstate, 0, 0, StdHeader); DisPsNum++; } else { break; } } } // If all P-state registers are disabled, move P[PsMaxVal] to P0 // and transition to P0, then wait for CurPstate = 0 ErrorData.AllowablePstateNumber = ((PsMaxVal + 1) - DisPsNum); // We only need to log this event on the BSC if (ErrorData.AllowablePstateNumber == 0) { PutEventLog (AGESA_FATAL, CPU_EVENT_PM_ALL_PSTATE_OVERCURRENT, Socket, 0, 0, 0, StdHeader); } if (DisPsNum != 0) { GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); // Check if CPB is supported. if yes, get the number of boost states. ErrorData.NumberofBoostStates = F10GetNumberOfBoostedPstatesOnCore (StdHeader); TaskPtr.FuncAddress.PfApTaskI = F10PmPwrCheckCore; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PWRCHK_ERROR_DATA); TaskPtr.DataTransfer.DataPtr = &ErrorData; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, CpuEarlyParams); // Final Step 1 // For revision E systems with CPUID Fn8000_0007[CPB]=1, if P0 is disabled then // program F4x15C[BoostSrc]=0. This step uses hardware P-state numbering. if (ErrorData.NumberofBoostStates == 1) { PciAddress.Address.Function = FUNC_4; PciAddress.Address.Register = CPB_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); ((CPB_CTRL_REGISTER *) &LocalPciRegister)->BoostSrc = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } // Final Step 2 // F3x64[HtPstatelimit] -= disPsNum // F3x68[StcPstateLimit]-= disPsNum // F3xDC[PstateMaxVal]-= disPsNum PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = HTC_REG; AndMask = 0xFFFFFFFF; ((HTC_REGISTER *) &AndMask)->HtcPstateLimit = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3x64 PstateLimit = ((HTC_REGISTER *) &LocalPciRegister)->HtcPstateLimit; if (ErrorData.AllowablePstateNumber != 0) { if (PstateLimit > DisPsNum) { PstateLimit -= DisPsNum; ((HTC_REGISTER *) &OrMask)->HtcPstateLimit = PstateLimit; } } else { ((HTC_REGISTER *) &OrMask)->HtcPstateLimit = ErrorData.NumberofBoostStates; } ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3x64 PciAddress.Address.Register = STC_REG; AndMask = 0xFFFFFFFF; ((STC_REGISTER *) &AndMask)->StcPstateLimit = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3x68 PstateLimit = ((STC_REGISTER *) &LocalPciRegister)->StcPstateLimit; if (ErrorData.AllowablePstateNumber != 0) { if (PstateLimit > DisPsNum) { PstateLimit -= DisPsNum; ((STC_REGISTER *) &OrMask)->StcPstateLimit = PstateLimit; } } else { ((STC_REGISTER *) &OrMask)->StcPstateLimit = ErrorData.NumberofBoostStates; } ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3x68 PciAddress.Address.Register = CPTC2_REG; AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &AndMask)->PstateMaxVal = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3xDC PstateLimit = ((CLK_PWR_TIMING_CTRL2_REGISTER *) &LocalPciRegister)->PstateMaxVal; if (ErrorData.AllowablePstateNumber != 0) { if (PstateLimit > DisPsNum) { PstateLimit -= DisPsNum; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->PstateMaxVal = PstateLimit; } } else { ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->PstateMaxVal = ErrorData.NumberofBoostStates; } ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3xDC // Now that P0 has changed, recalculate VSSlamTime F10ProgramVSSlamTimeOnSocket (&PciAddress, CpuEarlyParams, StdHeader); } }
/** * Family 15h core 0 entry point for performing the family 15h Processor- * Systemboard Power Delivery Check. * * The steps are as follows: * 1. Starting with P0, loop through all P-states until a passing state is * found. A passing state is one in which the current required by the * CPU is less than the maximum amount of current that the system can * provide to the CPU. If P0 is under the limit, no further action is * necessary. * 2. If at least one P-State is under the limit & at least one P-State is * over the limit, the BIOS must: * a. If the processor's current P-State is disabled by the power check, * then the BIOS must request a transition to an enabled P-state * using MSRC001_0062[PstateCmd] and wait for MSRC001_0063[CurPstate] * to reflect the new value. * b. Copy the contents of the enabled P-state MSRs to the highest * performance P-state locations. * c. Request a P-state transition to the P-state MSR containing the * COF/VID values currently applied. * d. If a subset of boosted P-states are disabled, then copy the contents * of the highest performance boosted P-state still enabled to the * boosted P-states that have been disabled. * e. If all boosted P-states are disabled, then program D18F4x15C[BoostSrc] * to zero. * f. Adjust the following P-state parameters affected by the P-state * MSR copy by subtracting the number of P-states that are disabled * by the power check. * 1. F3x64[HtcPstateLimit] * 2. F3x68[SwPstateLimit] * 3. F3xDC[PstateMaxVal] * 3. If all P-States are over the limit, the BIOS must: * a. If the processor's current P-State is !=F3xDC[PstateMaxVal], then * write F3xDC[PstateMaxVal] to MSRC001_0062[PstateCmd] and wait for * MSRC001_0063[CurPstate] to reflect the new value. * b. If MSRC001_0061[PstateMaxVal]!=000b, copy the contents of the P-state * MSR pointed to by F3xDC[PstateMaxVal] to the software P0 MSR. * Write 000b to MSRC001_0062[PstateCmd] and wait for MSRC001_0063 * [CurPstate] to reflect the new value. * c. Adjust the following P-state parameters to zero: * 1. F3x64[HtcPstateLimit] * 2. F3x68[SwPstateLimit] * 3. F3xDC[PstateMaxVal] * d. Program D18F4x15C[BoostSrc] to zero. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParams Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F15PmPwrCheck ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 DisPsNum; UINT8 PsMaxVal; UINT8 Pstate; UINT32 ProcIddMax; UINT32 LocalPciRegister; UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 AndMask; UINT32 OrMask; UINT32 PstateLimit; PCI_ADDR PciAddress; UINT64 LocalMsrRegister; AP_TASK TaskPtr; AGESA_STATUS IgnoredSts; PWRCHK_ERROR_DATA ErrorData; UINT32 NumModules; UINT32 HighCore; UINT32 LowCore; UINT32 ModuleIndex; // get the socket number IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ErrorData.SocketNumber = (UINT8) Socket; ASSERT (Core == 0); // get the Max P-state value for (PsMaxVal = NM_PS_REG - 1; PsMaxVal != 0; --PsMaxVal) { LibAmdMsrRead (PS_REG_BASE + PsMaxVal, &LocalMsrRegister, StdHeader); if (((F15_PSTATE_MSR *) &LocalMsrRegister)->PsEnable == 1) { break; } } ErrorData.HwPstateNumber = (UINT8) (PsMaxVal + 1); // Starting with P0, loop through all P-states until a passing state is // found. A passing state is one in which the current required by the // CPU is less than the maximum amount of current that the system can // provide to the CPU. If P0 is under the limit, no further action is // necessary. DisPsNum = 0; for (Pstate = 0; Pstate < ErrorData.HwPstateNumber; Pstate++) { if (FamilySpecificServices->GetProcIddMax (FamilySpecificServices, Pstate, &ProcIddMax, StdHeader)) { if (ProcIddMax > CpuEarlyParams->PlatformConfig.VrmProperties[CoreVrm].CurrentLimit) { // Add to event log the Pstate that exceeded the current limit PutEventLog (AGESA_WARNING, CPU_EVENT_PM_PSTATE_OVERCURRENT, Socket, Pstate, 0, 0, StdHeader); DisPsNum++; } else { break; } } } ErrorData.AllowablePstateNumber = ((PsMaxVal + 1) - DisPsNum); if (ErrorData.AllowablePstateNumber == 0) { PutEventLog (AGESA_FATAL, CPU_EVENT_PM_ALL_PSTATE_OVERCURRENT, Socket, 0, 0, 0, StdHeader); } if (DisPsNum != 0) { GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); PciAddress.Address.Function = FUNC_4; PciAddress.Address.Register = CPB_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F4x15C ErrorData.NumberOfBoostStates = (UINT8) ((F15_CPB_CTRL_REGISTER *) &LocalPciRegister)->NumBoostStates; if (DisPsNum >= ErrorData.NumberOfBoostStates) { // If all boosted P-states are disabled, then program D18F4x15C[BoostSrc] to zero. AndMask = 0xFFFFFFFF; ((F15_CPB_CTRL_REGISTER *) &AndMask)->BoostSrc = 0; OrMask = 0x00000000; OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F4x15C // Update the result of isFeatureEnabled in heap. UpdateFeatureStatusInHeap (CoreBoost, FALSE, StdHeader); ErrorData.NumberOfSwPstatesDisabled = DisPsNum - ErrorData.NumberOfBoostStates; } else { ErrorData.NumberOfSwPstatesDisabled = 0; } NumModules = GetPlatformNumberOfModules (); // Only execute this loop if this is an MCM. if (NumModules > 1) { // Since the P-State MSRs are shared across a // node, we only need to set one core in the node for the modified number of supported p-states // to be reported across all of the cores in the module. TaskPtr.FuncAddress.PfApTaskI = F15PmPwrCheckCore; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (PWRCHK_ERROR_DATA); TaskPtr.DataTransfer.DataPtr = &ErrorData; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; for (ModuleIndex = 0; ModuleIndex < NumModules; ModuleIndex++) { // Execute the P-State reduction code on the module's primary core only. // Skip this code for the BSC's module. if (ModuleIndex != Module) { if (GetGivenModuleCoreRange (Socket, ModuleIndex, &LowCore, &HighCore, StdHeader)) { ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)LowCore, &TaskPtr, StdHeader); } } } } // Path for SCM and the BSC F15PmPwrCheckCore (&ErrorData, StdHeader); // Final Step // F3x64[HtPstatelimit] -= disPsNum // F3x68[SwPstateLimit] -= disPsNum // F3xDC[PstateMaxVal] -= disPsNum PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = HTC_REG; AndMask = 0xFFFFFFFF; ((HTC_REGISTER *) &AndMask)->HtcPstateLimit = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3x64 PstateLimit = ((HTC_REGISTER *) &LocalPciRegister)->HtcPstateLimit; if (PstateLimit > ErrorData.NumberOfSwPstatesDisabled) { PstateLimit -= ErrorData.NumberOfSwPstatesDisabled; ((HTC_REGISTER *) &OrMask)->HtcPstateLimit = PstateLimit; } OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3x64 PciAddress.Address.Register = SW_PS_LIMIT_REG; AndMask = 0xFFFFFFFF; ((SW_PS_LIMIT_REGISTER *) &AndMask)->SwPstateLimit = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3x68 PstateLimit = ((SW_PS_LIMIT_REGISTER *) &LocalPciRegister)->SwPstateLimit; if (PstateLimit > ErrorData.NumberOfSwPstatesDisabled) { PstateLimit -= ErrorData.NumberOfSwPstatesDisabled; ((SW_PS_LIMIT_REGISTER *) &OrMask)->SwPstateLimit = PstateLimit; } OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3x68 PciAddress.Address.Register = CPTC2_REG; AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &AndMask)->PstateMaxVal = 0; OrMask = 0x00000000; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); // F3xDC PstateLimit = ((CLK_PWR_TIMING_CTRL2_REGISTER *) &LocalPciRegister)->PstateMaxVal; if (PstateLimit > ErrorData.NumberOfSwPstatesDisabled) { PstateLimit -= ErrorData.NumberOfSwPstatesDisabled; ((CLK_PWR_TIMING_CTRL2_REGISTER *) &OrMask)->PstateMaxVal = PstateLimit; } OptionMultiSocketConfiguration.ModifyCurrSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3xDC } }
/** * Family 10h core 0 entry point for performing the "Northbridge COF and * VID Configuration" algorithm. * * The steps are as follows: * 1. Determine if the algorithm is necessary by checking if all NB FIDs * match in the coherent fabric. If so, check to see if NbCofVidUpdate * is zero for all CPUs. If that is also true, no further steps are * necessary. If not + cold reset, proceed to step 2. If not + warm * reset, proceed to step 8. * 2. Determine NewNbVid & NewNbFid. * 3. Copy Startup Pstate settings to P0/P1 MSRs on all local cores. * 4. Copy NewNbVid to P0 NbVid on all local cores. * 5. Transition to P1 on all local cores. * 6. Transition to P0 on local core 0 only. * 7. Copy NewNbFid to F3xD4[NbFid], set NbFidEn, and issue a warm reset. * 8. Update all enabled Pstate MSRs' NbVids according to NbVidUpdateAll * on all local cores. * 9. Transition to Startup Pstate on all local cores. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service related parameters (unused). * @param[in] StdHeader Config handle for library and services. * */ VOID F10PmNbCofVidInit ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN PerformNbCofVidCfg; BOOLEAN SystemNbCofsMatch; UINT8 NewNbFid; UINT8 NewNbVid; UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 SystemNbCof; UINT32 AndMask; UINT32 OrMask; UINT32 Ignored; UINT32 NewNbVoltage; WARM_RESET_REQUEST Request; AP_TASK TaskPtr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; NB_COF_VID_INIT_WARM FunctionData; PerformNbCofVidCfg = TRUE; OptionMultiSocketConfiguration.GetSystemNbCof (&SystemNbCof, &SystemNbCofsMatch, StdHeader); if (SystemNbCofsMatch) { if (!OptionMultiSocketConfiguration.GetSystemNbCofVidUpdate (StdHeader)) { PerformNbCofVidCfg = FALSE; } } if (PerformNbCofVidCfg) { // get the local node ID IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts); ASSERT (Core == 0); // get NewNbVid FamilySpecificServices->GetNbFrequency (FamilySpecificServices, &PciAddress, &Ignored, &NewNbVoltage, StdHeader); ASSERT (((1550000 - NewNbVoltage) % 12500) == 0); NewNbVid = (UINT8) ((1550000 - NewNbVoltage) / 12500); ASSERT (NewNbVid < 0x80); if (!(IsWarmReset (StdHeader))) { // determine NewNbFid NewNbFid = (UINT8) ((SystemNbCof / 200) - 4); TaskPtr.FuncAddress.PfApTaskI = PmNbCofVidInitP0P1Core; TaskPtr.DataTransfer.DataSizeInDwords = 1; TaskPtr.DataTransfer.DataPtr = &NewNbVid; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = 0; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, CpuEarlyParamsPtr); // Transition core 0 to P0 and wait for change to complete FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) TRUE, StdHeader); PciAddress.Address.Register = CPTC0_REG; AndMask = 0xFFFFFFFF; ((CLK_PWR_TIMING_CTRL_REGISTER *) &AndMask)->NbFid = 0; OrMask = 0x00000000; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->NbFid = NewNbFid; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->NbFidEn = 1; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // warm reset request FamilySpecificServices->GetWarmResetFlag (FamilySpecificServices, StdHeader, &Request); Request.RequestBit = TRUE; FamilySpecificServices->SetWarmResetFlag (FamilySpecificServices, StdHeader, &Request); } else { // warm reset path FunctionData.NewNbVid = NewNbVid; FamilySpecificServices->IsNbCofInitNeeded (FamilySpecificServices, &PciAddress, &FunctionData.NbVidUpdateAll, StdHeader); TaskPtr.FuncAddress.PfApTaskI = PmNbCofVidInitWarmCore; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (NB_COF_VID_INIT_WARM); TaskPtr.DataTransfer.DataPtr = &FunctionData; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, CpuEarlyParamsPtr); } } // skip whole algorithm }