/** * Core-level error handler called if any p-states were determined to be out * of range for the mother board. * * This function implements steps 2a-c and 3a-c on each core. * * @param[in] ErrorData Details about the error condition. * @param[in] StdHeader Config handle for library and services. * */ VOID STATIC F10PmPwrCheckCore ( IN VOID *ErrorData, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; UINT8 PsMaxVal; UINT8 DisPsNum; UINT8 CurrentPs; UINT8 EnBsNum; UINT64 LocalMsrRegister; CPU_SPECIFIC_SERVICES *FamilySpecificServices; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); PsMaxVal = (((PWRCHK_ERROR_DATA *) ErrorData)->HwPstateNumber - 1); DisPsNum = (((PWRCHK_ERROR_DATA *) ErrorData)->HwPstateNumber - ((PWRCHK_ERROR_DATA *) ErrorData)->AllowablePstateNumber); EnBsNum = ((PWRCHK_ERROR_DATA *) ErrorData)->NumberofBoostStates; LibAmdMsrRead (MSR_PSTATE_STS, &LocalMsrRegister, StdHeader); CurrentPs = (UINT8) (((PSTATE_STS_MSR *) &LocalMsrRegister)->CurPstate); if (((PWRCHK_ERROR_DATA *) ErrorData)->AllowablePstateNumber == 0) { // Step 1 // Transition to Pstate Max if not there already if ((CurrentPs + EnBsNum) != PsMaxVal) { FamilySpecificServices->TransitionPstate (FamilySpecificServices, (PsMaxVal - EnBsNum), (BOOLEAN) TRUE, StdHeader); } // Step 2 // If Pstate Max is not 000b, copy Pstate max contents to P0 and switch // to P0. This step uses software P-state numbering if (PsMaxVal != 0) { F10PmPwrChkCopyPstate (EnBsNum, PsMaxVal, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) TRUE, StdHeader); } } else { // move remaining P-state register(s) up // Step 1 // Transition to a valid Pstate if current Pstate has been disabled if ((CurrentPs + EnBsNum) < DisPsNum) { FamilySpecificServices->TransitionPstate (FamilySpecificServices, (DisPsNum - EnBsNum), (BOOLEAN) TRUE, StdHeader); CurrentPs = DisPsNum - EnBsNum; } // Step 2 // Move enabled Pstates up and disable the remainder. This step uses software P-state numbering. if (DisPsNum > EnBsNum) { for (i = 0; (i + DisPsNum) <= PsMaxVal; ++i) { F10PmPwrChkCopyPstate ((i + EnBsNum), (i + DisPsNum), StdHeader); } } // Step 3 // Transition to current COF/VID at shifted location CurrentPs = ((CurrentPs + EnBsNum) - DisPsNum); FamilySpecificServices->TransitionPstate (FamilySpecificServices, CurrentPs, (BOOLEAN) TRUE, StdHeader); } i = ((PWRCHK_ERROR_DATA *) ErrorData)->AllowablePstateNumber; if (i == 0) { ++i; } while (i <= PsMaxVal) { FamilySpecificServices->DisablePstate (FamilySpecificServices, i, StdHeader); ++i; } }
/** * Core-level error handler called if any p-states were determined to be out * of range for the mother board. * * This function implements steps 2a-c and 3a-c on each core. * * @param[in] ErrorData Details about the error condition. * @param[in] StdHeader Config handle for library and services. * */ VOID STATIC F15PmPwrCheckCore ( IN VOID *ErrorData, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; UINT8 HwPsMaxVal; UINT8 SwPsMaxVal; UINT8 HwDisPsNum; UINT8 CurrentSwPs; UINT8 PsDisableCount; UINT64 LocalMsrRegister; CPU_SPECIFIC_SERVICES *FamilySpecificServices; if (IsCoreComputeUnitPrimary (FirstCoreIsComputeUnitPrimary, StdHeader)) { // P-state MSRs are shared, so only 1 core per compute unit needs to perform this GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); HwPsMaxVal = (((PWRCHK_ERROR_DATA *) ErrorData)->HwPstateNumber - 1); HwDisPsNum = (((PWRCHK_ERROR_DATA *) ErrorData)->HwPstateNumber - ((PWRCHK_ERROR_DATA *) ErrorData)->AllowablePstateNumber); LibAmdMsrRead (MSR_PSTATE_STS, &LocalMsrRegister, StdHeader); CurrentSwPs = (UINT8) (((PSTATE_STS_MSR *) &LocalMsrRegister)->CurPstate); LibAmdMsrRead (MSR_PSTATE_CURRENT_LIMIT, &LocalMsrRegister, StdHeader); SwPsMaxVal = (UINT8) (((PSTATE_CURLIM_MSR *) &LocalMsrRegister)->PstateMaxVal); PsDisableCount = 0; if (((PWRCHK_ERROR_DATA *) ErrorData)->AllowablePstateNumber == 0) { // All P-States are over the limit. // Step 1 // Transition to Pstate Max if not there already if (CurrentSwPs != SwPsMaxVal) { FamilySpecificServices->TransitionPstate (FamilySpecificServices, SwPsMaxVal, (BOOLEAN) TRUE, StdHeader); } // Step 2 // If Pstate Max is not P0, copy Pstate max contents to P0 and switch // to P0. if (SwPsMaxVal != 0) { F15PmPwrChkCopyPstate (((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfBoostStates, HwPsMaxVal, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) TRUE, StdHeader); } // Disable all SW P-states except P0 PsDisableCount = ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled - 1; } else { // At least one P-State is under the limit & at least one P-State is // over the limit. if (((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfBoostStates > HwDisPsNum) { // A subset of boosted P-states are disabled. Copy the contents of the // highest performance boosted P-state still enabled to the boosted // P-states that have been disabled. for (i = 0; i < HwDisPsNum; i++) { F15PmPwrChkCopyPstate (i, HwDisPsNum, StdHeader); } } else if (((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled != 0) { // Move remaining P-state register(s) up // Step 1 // Transition to a valid Pstate if current Pstate has been disabled if (CurrentSwPs < ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled) { FamilySpecificServices->TransitionPstate (FamilySpecificServices, ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled, (BOOLEAN) TRUE, StdHeader); CurrentSwPs = ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled; } // Step 2 // Move enabled Pstates up and disable the remainder for (i = ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfBoostStates; (i + ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled) <= HwPsMaxVal; i++) { F15PmPwrChkCopyPstate (i, (i + ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled), StdHeader); } // Step 3 // Transition to current COF/VID at shifted location CurrentSwPs = (CurrentSwPs - ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled); FamilySpecificServices->TransitionPstate (FamilySpecificServices, CurrentSwPs, (BOOLEAN) TRUE, StdHeader); // Disable the appropriate number of P-states PsDisableCount = ((PWRCHK_ERROR_DATA *) ErrorData)->NumberOfSwPstatesDisabled; } } // Disable the appropriate P-states if any, starting from HW Pmin for (i = 0; i < PsDisableCount; i++) { FamilySpecificServices->DisablePstate (FamilySpecificServices, (HwPsMaxVal - i), StdHeader); } } }