/** * Check to see if the input CPU supports L3 dependent features. * * @param[in] L3FeatureServices L3 Feature family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * * @retval TRUE L3 dependent features are supported. * @retval FALSE L3 dependent features are not supported. * */ BOOLEAN STATIC F10IsL3FeatureSupported ( IN L3_FEATURE_FAMILY_SERVICES *L3FeatureServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig ) { UINT32 Module; UINT32 LocalPciRegister; BOOLEAN IsSupported; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsSupported = FALSE; if (PlatformConfig->PlatformProfile.UseHtAssist) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); if (((NB_CAPS_REGISTER *) &LocalPciRegister)->L3Capable == 1) { IsSupported = TRUE; } break; } } } return IsSupported; }
/** * Multisocket call to determine if the BIOS is responsible for updating the * northbridge operating frequency and voltage. * * This function loops through all possible socket locations, checking whether * any populated sockets require NB COF VID programming. * * @param[in] StdHeader Config handle for library and services * * @retval TRUE BIOS needs to set up NB frequency and voltage * @retval FALSE BIOS does not need to set up NB frequency and voltage * */ BOOLEAN GetSystemNbCofVidUpdateMulti ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 Module; UINT32 Socket; UINT32 NumberOfSockets; BOOLEAN IgnoredBool; BOOLEAN AtLeast1RequiresUpdate; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; NumberOfSockets = GetPlatformNumberOfSockets (); AtLeast1RequiresUpdate = FALSE; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, (UINT8) Socket, Module, &PciAddress, &Ignored)) { break; } } if (FamilySpecificServices->IsNbCofInitNeeded (FamilySpecificServices, &PciAddress, &IgnoredBool, StdHeader)) { AtLeast1RequiresUpdate = TRUE; break; } } } return AtLeast1RequiresUpdate; }
/** * Writes to all nodes on the executing core's socket. * * @param[in] PciAddress The Function and Register to update * @param[in] Mask The bitwise AND mask to apply to the current register value * @param[in] Data The bitwise OR mask to apply to the current register value * @param[in] StdHeader Header for library and services. * */ VOID ModifyCurrSocketPciMulti ( IN PCI_ADDR *PciAddress, IN UINT32 Mask, IN UINT32 Data, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 LocalPciRegister; AGESA_STATUS AgesaStatus; PCI_ADDR Reg; IdentifyCore (StdHeader, &Socket, &Module, &Core, &AgesaStatus); for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &Reg, &AgesaStatus)) { Reg.Address.Function = PciAddress->Address.Function; Reg.Address.Register = PciAddress->Address.Register; LibAmdPciRead (AccessWidth32, Reg, &LocalPciRegister, StdHeader); LocalPciRegister &= Mask; LocalPciRegister |= Data; LibAmdPciWrite (AccessWidth32, Reg, &LocalPciRegister, StdHeader); } } }
/** * Family 15h Kaveri core 0 entry point for performing the necessary steps after * a warm reset has occurred. * * The steps are as follows: * * 1. Temp1=D18F5x170[SwNbPstateLoDis]. * 2. Temp2=D18F5x170[NbPstateDisOnP0]. * 3. Temp3=D18F5x170[NbPstateThreshold]. * 4. Temp4=D18F5x170[NbPstateGnbSlowDis]. * 5. If MSRC001_0070[NbPstate]=0, go to step 6. If MSRC001_0070[NbPstate]=1, go to step 11. * 6. Write 1 to D18F5x170[NbPstateGnbSlowDis]. * 7. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 8. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 9. Set D18F5x170[SwNbPstateLoDis]=1. * 10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. Go to step 15. * 11. Write 1 to D18F5x170[SwNbPstateLoDis]. * 12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. * 13. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 14. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 15. Set D18F5x170[SwNbPstateLoDis]=Temp1, D18F5x170[NbPstateDisOnP0]=Temp2, D18F5x170[NbP- * stateThreshold]=Temp3, and D18F5x170[NbPstateGnbSlowDis]=Temp4. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F15KvPmNbAfterReset ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 TaskedCore; UINT32 Ignored; AP_TASK TaskPtr; AGESA_STATUS IgnoredSts; IDS_HDT_CONSOLE (CPU_TRACE, " F15KvPmNbAfterReset\n"); IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ASSERT (Core == 0); // Launch one core per node. TaskPtr.FuncAddress.PfApTask = F15KvPmNbAfterResetOnCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetGivenModuleCoreRange (Socket, Module, &TaskedCore, &Ignored, StdHeader)) { if (TaskedCore != 0) { ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) TaskedCore, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr); }
/** * Check to see if the input CPU supports HT Assist. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE HT Assist is supported. * @retval FALSE HT Assist cannot be enabled. * */ BOOLEAN STATIC F10IsHtAssistSupported ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; BOOLEAN IsSupported; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsSupported = FALSE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CAPS_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((NB_CAPS_REGISTER *) &PciRegister)->L3Capable == 1) { IsSupported = TRUE; } break; } } return IsSupported; }
/** * Clear EnableCf8ExtCfg on all socket * * Clear F3x8C bit 14 EnableCf8ExtCfg * * @param[in] StdHeader Config handle for library and services * * */ VOID DisableCf8ExtCfg ( IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS AgesaStatus; PCI_ADDR PciAddress; UINT32 Socket; UINT32 Module; UINT32 PciData; UINT32 LegacyPciAccess; ASSERT (IsBsp (StdHeader, &AgesaStatus)); for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = NB_CFG_HIGH_REG; LegacyPciAccess = ((1 << 31) + (PciAddress.Address.Register & 0xFC) + (PciAddress.Address.Function << 8) + (PciAddress.Address.Device << 11) + (PciAddress.Address.Bus << 16) + ((PciAddress.Address.Register & 0xF00) << (24 - 8))); // read from PCI register LibAmdIoWrite (AccessWidth32, IOCF8, &LegacyPciAccess, StdHeader); LibAmdIoRead (AccessWidth32, IOCFC, &PciData, StdHeader); // Disable Cf8ExtCfg PciData &= 0xFFFFBFFF; // write to PCI register LibAmdIoWrite (AccessWidth32, IOCF8, &LegacyPciAccess, StdHeader); LibAmdIoWrite (AccessWidth32, IOCFC, &PciData, StdHeader); } } } }
/** * This routine checks whether any non-coherent links in the system * runs in HT1 mode; used to determine whether certain features * should be disabled when this routine returns TRUE. * * @param[in] StdHeader Standard AMD configuration parameters. * * @retval TRUE One of the non-coherent links in the * system runs in HT1 mode * @retval FALSE None of the non-coherent links in the * system is running in HT1 mode */ BOOLEAN IsNonCoherentHt1 ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINTN Link; UINT32 Socket; UINT32 Module; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; HT_HOST_FEATS HtHostFeats; CPU_SPECIFIC_SERVICES *CpuServices; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, &CpuServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { HtHostFeats.HtHostValue = 0; Link = 0; while (CpuServices->GetNextHtLinkFeatures (CpuServices, &Link, &PciAddress, &HtHostFeats, StdHeader)) { // Return TRUE and exit routine once we find a non-coherent link in HT1 if ((HtHostFeats.HtHostFeatures.NonCoherent == 1) && (HtHostFeats.HtHostFeatures.Ht1 == 1)) { return TRUE; } } } } } } return FALSE; }
/** * Ids Write PCI register to All node * * * @param[in] PciAddress Pci address * @param[in] Highbit High bit position of the field in DWORD * @param[in] Lowbit Low bit position of the field in DWORD * @param[in] Value Pointer to input value * @param[in] StdHeader Standard configuration header * */ VOID IdsLibPciWriteBitsToAllNode ( IN PCI_ADDR PciAddress, IN UINT8 Highbit, IN UINT8 Lowbit, IN UINT32 *Value, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; AGESA_STATUS IgnoreStatus; PCI_ADDR PciAddr; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddr, &IgnoreStatus)) { PciAddr.Address.Function = PciAddress.Address.Function; PciAddr.Address.Register = PciAddress.Address.Register; LibAmdPciWriteBits (PciAddr, Highbit, Lowbit, Value, StdHeader); } } } }
/** * A Family Specific Workaround method, to sync internal node 1 SbiAddr setting. * * @param[in] Data The table data value (unused in this routine) * @param[in] StdHeader Config handle for library and services * *--------------------------------------------------------------------------------------- **/ VOID STATIC F10RevDSyncInternalNode1SbiAddr ( IN UINT32 Data, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 DataOr; UINT32 DataAnd; UINT32 ModuleType; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; UINT32 SyncToModule; AP_MAIL_INFO ApMailboxInfo; UINT32 LocalPciRegister; ApMailboxInfo.Info = 0; GetApMailbox (&ApMailboxInfo.Info, StdHeader); ASSERT (ApMailboxInfo.Fields.Socket < MAX_SOCKETS); ASSERT (ApMailboxInfo.Fields.Module < MAX_DIES); Socket = ApMailboxInfo.Fields.Socket; Module = ApMailboxInfo.Fields.Module; ModuleType = ApMailboxInfo.Fields.ModuleType; // sync is just needed on multinode cpu if (ModuleType != 0) { // check if it is internal node 0 of every socket if (Module == 0) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = 0x1E4; // read internal node 0 F3x1E4[6:4] LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); DataOr = LocalPciRegister & ((UINT32) (7 << 4)); DataAnd = ~(UINT32) (7 << 4); for (SyncToModule = 1; SyncToModule < GetPlatformNumberOfModules (); SyncToModule++) { if (GetPciAddress (StdHeader, Socket, SyncToModule, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = 0x1E4; // sync the other internal node F3x1E4[6:4] LibAmdPciRead (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); LocalPciRegister &= DataAnd; LocalPciRegister |= DataOr; LibAmdPciWrite (AccessWidth32, PciAddress, &LocalPciRegister, StdHeader); } } } } } }
/** * * InitializeCacheFlushOnHaltFeature * * CPU feature leveling. Enable Cpu Cache Flush On Halt Function * * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in,out] StdHeader Pointer to AMD_CONFIG_PARAMS struct. * * @return The most severe status of any family specific service. */ STATIC AGESA_STATUS InitializeCacheFlushOnHaltFeature ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 AndMask; UINT32 OrMask; UINT32 PciRegister; PCI_ADDR PciAddress; PCI_ADDR CfohPciAddress; AGESA_STATUS AgesaStatus; CPU_CFOH_FAMILY_SERVICES *FamilySpecificServices; ASSERT (IsBsp (StdHeader, &AgesaStatus)); FamilySpecificServices = NULL; AndMask = 0xFFFFFFFF; OrMask = 0x00000000; PciRegister = 0; AgesaStatus = AGESA_SUCCESS; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { // Get services for the socket GetFeatureServicesOfSocket (&CacheFlushOnHaltFamilyServiceTable, Socket, (CONST VOID **)&FamilySpecificServices, StdHeader); if (FamilySpecificServices != NULL) { FamilySpecificServices->GetCacheFlushOnHaltRegister (FamilySpecificServices, &CfohPciAddress, &AndMask, &OrMask, StdHeader); // Get the Or Mask value from IDS IDS_OPTION_HOOK (IDS_CACHE_FLUSH_HLT, &OrMask, StdHeader); // Set Cache Flush On Halt register for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { PciAddress.Address.Function = CfohPciAddress.Address.Function; PciAddress.Address.Register = CfohPciAddress.Address.Register; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); PciRegister &= AndMask; PciRegister |= OrMask; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); } } } } } return AgesaStatus; }
/** * Multisocket call to loop through all possible socket locations and Nb Pstates, * comparing the NB frequencies to determine the slowest system and P0 frequency * * @param[in] PlatformConfig Platform profile/build option config structure. * @param[out] MinSysNbFreq NB frequency numerator for the system in MHz * @param[out] MinP0NbFreq NB frequency numerator for P0 in MHz * @param[in] StdHeader Config handle for library and services */ VOID GetMinNbCofMulti ( IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *MinSysNbFreq, OUT UINT32 *MinP0NbFreq, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 CurrMinFreq; UINT32 CurrMaxFreq; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; AGESA_STATUS AgesaStatus; *MinSysNbFreq = 0xFFFFFFFF; *MinP0NbFreq = 0xFFFFFFFF; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Ignored )) { break; } } AgesaStatus = FamilySpecificServices->GetMinMaxNbFrequency (FamilySpecificServices, PlatformConfig, &PciAddress, &CurrMinFreq, &CurrMaxFreq, StdHeader); ASSERT (AgesaStatus == AGESA_SUCCESS); ASSERT ((CurrMinFreq != 0) && (CurrMaxFreq != 0)); // Determine the slowest NB Pmin frequency if (CurrMinFreq < *MinSysNbFreq) { *MinSysNbFreq = CurrMinFreq; } // Determine the slowest NB P0 frequency if (CurrMaxFreq < *MinP0NbFreq) { *MinP0NbFreq = CurrMaxFreq; } } } }
/** * Check to see if the input CPU is running in the optimal configuration. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE HT Assist is running sub-optimally. * @retval FALSE HT Assist is running optimally. * */ STATIC BOOLEAN F10IsNonOptimalConfig ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN IsNonOptimal; BOOLEAN IsMemoryPresent; UINT32 Module; UINT32 PciRegister; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; IsNonOptimal = FALSE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { IsMemoryPresent = FALSE; PciAddress.Address.Function = FUNC_2; PciAddress.Address.Register = DRAM_CFG_HI_REG0; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreqVal == 1) { IsMemoryPresent = TRUE; if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreq < 4) { IsNonOptimal = TRUE; break; } } PciAddress.Address.Register = DRAM_CFG_HI_REG1; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreqVal == 1) { IsMemoryPresent = TRUE; if (((DRAM_CFG_HI_REGISTER *) &PciRegister)->MemClkFreq < 4) { IsNonOptimal = TRUE; break; } } if (!IsMemoryPresent) { IsNonOptimal = TRUE; break; } } } return IsNonOptimal; }
/** * Family 15h Trinity core 0 entry point for performing the necessary steps after * a warm reset has occurred. * * The steps are as follows: * * 1. Temp1=D18F5x170[SwNbPstateLoDis]. * 2. Temp2=D18F5x170[NbPstateDisOnP0]. * 3. Temp3=D18F5x170[NbPstateThreshold]. * 4. Temp4=D18F5x170[NbPstateGnbSlowDis]. * 5. If MSRC001_0070[NbPstate]=0, go to step 6. If MSRC001_0070[NbPstate]=1, go to step 11. * 6. Write 1 to D18F5x170[NbPstateGnbSlowDis]. * 7. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 8. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 9. Set D18F5x170[SwNbPstateLoDis]=1. * 10. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. Go to step 15. * 11. Write 1 to D18F5x170[SwNbPstateLoDis]. * 12. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateHi] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateHi]. * 13. Write 0 to D18F5x170[SwNbPstateLoDis, NbPstateDisOnP0, NbPstateThreshold]. * 14. Wait for D18F5x174[CurNbPstate] = D18F5x170[NbPstateLo] and D18F5x174[CurNbFid, CurNb- * Did]=[NbFid, NbDid] from D18F5x1[6C:60] indexed by D18F5x170[NbPstateLo]. * 15. Set D18F5x170[SwNbPstateLoDis]=Temp1, D18F5x170[NbPstateDisOnP0]=Temp2, D18F5x170[NbP- * stateThreshold]=Temp3, and D18F5x170[NbPstateGnbSlowDis]=Temp4. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] CpuEarlyParamsPtr Service parameters * @param[in] StdHeader Config handle for library and services. * */ VOID F15TnPmNbAfterReset ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Module; UINT32 Core; UINT32 TaskedCore; UINT32 Ignored; AP_TASK TaskPtr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; LOCATE_HEAP_PTR Locate; IDS_HDT_CONSOLE (CPU_TRACE, " F15TnPmNbAfterReset\n"); IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); ASSERT (Core == 0); if (FamilySpecificServices->IsNbPstateEnabled (FamilySpecificServices, &CpuEarlyParamsPtr->PlatformConfig, StdHeader)) { PciAddress.AddressValue = NB_PSTATE_CTRL_PCI_ADDR; Locate.BufferHandle = AMD_CPU_NB_PSTATE_FIXUP_HANDLE; if (HeapLocateBuffer (&Locate, StdHeader) == AGESA_SUCCESS) { LibAmdPciWrite (AccessWidth32, PciAddress, Locate.BufferPtr, StdHeader); } else { ASSERT (FALSE); } } // Launch one core per node. TaskPtr.FuncAddress.PfApTask = F15TnPmNbAfterResetOnCore; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetGivenModuleCoreRange (Socket, Module, &TaskedCore, &Ignored, StdHeader)) { if (TaskedCore != 0) { ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) TaskedCore, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr); }
/** * Hook before the probe filter initialization sequence. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10HookBeforeInit ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; UINT32 PfCtrlRegister; PCI_ADDR PciAddress; CPU_LOGICAL_ID LogicalId; AGESA_STATUS IgnoredStatus; UINT32 PackageType; GetLogicalIdOfSocket (Socket, &LogicalId, StdHeader); PackageType = LibAmdGetPackageType (StdHeader); PciRegister = 0; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFWayNum = 2; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFSubCacheEn = 15; ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFLoIndexHashEn = 1; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = PROBE_FILTER_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PfCtrlRegister, StdHeader); ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFPreferredSORepl = ((PROBE_FILTER_CTRL_REGISTER *) &PfCtrlRegister)->PFPreferredSORepl; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); // Assumption: all socket use the same CPU package. if (((LogicalId.Revision & AMD_F10_D0) != 0) && (PackageType == PACKAGE_TYPE_C32)) { // Apply erratum #384 // Set F2x11C[13:12] = 11b PciAddress.Address.Function = FUNC_2; PciAddress.Address.Register = 0x11C; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); PciRegister |= 0x3000; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); } } } }
/** * * * This function get start end Module according to input ModuleId * * @param[in] ModuleId - 0xFF means all nodes, other value Specifies real NodeId * @param[in,out] StartModule - Point to start Node * @param[in,out] EndModule - Point to end Node * */ VOID IdsGetStartEndModule ( IN UINT8 ModuleId, IN OUT UINT8 *StartModule, IN OUT UINT8 *EndModule ) { if (ModuleId == 0xFF) { *StartModule = 0; *EndModule = (UINT8) (GetPlatformNumberOfSockets () * GetPlatformNumberOfModules () - 1); if (*EndModule > 7) { *EndModule = 7; } } else { *StartModule = ModuleId; *EndModule = ModuleId; } }
/** * Save the current settings of the scrubbers, and disabled them. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] ScrubSettings Location to store current L3 scrubber settings. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10GetL3ScrubCtrl ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN UINT32 ScrubSettings[L3_SCRUBBER_CONTEXT_ARRAY_SIZE], IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 ScrubCtrl; UINT32 ScrubAddr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { ASSERT (Module < L3_SCRUBBER_CONTEXT_ARRAY_SIZE); PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG; LibAmdPciRead (AccessWidth32, PciAddress, &ScrubAddr, StdHeader); PciAddress.Address.Register = SCRUB_RATE_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader); ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->DramScrub = ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub; ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->L3Scrub = ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub; ((F10_SCRUB_CONTEXT *) &ScrubSettings[Module])->Redirect = ((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn; ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->DramScrub = 0; ((SCRUB_RATE_CTRL_REGISTER *) &ScrubCtrl)->L3Scrub = 0; ((DRAM_SCRUB_ADDR_LOW_REGISTER *) &ScrubAddr)->ScrubReDirEn = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubCtrl, StdHeader); PciAddress.Address.Register = DRAM_SCRUB_ADDR_LOW_REG; LibAmdPciWrite (AccessWidth32, PciAddress, &ScrubAddr, StdHeader); } } }
/** * Enable the Probe filter feature. * * @param[in] HtAssistServices HT Assist family services. * @param[in] Socket Processor socket to check. * @param[in] StdHeader Config Handle for library, services. * */ VOID STATIC F10HtAssistInit ( IN HT_ASSIST_FAMILY_SERVICES *HtAssistServices, IN UINT32 Socket, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Module; UINT32 PciRegister; PCI_ADDR PciAddress; AGESA_STATUS IgnoredStatus; for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredStatus)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = L3_CACHE_PARAM_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); ((L3_CACHE_PARAM_REGISTER *) &PciRegister)->L3TagInit = 1; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); do { LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); } while (((L3_CACHE_PARAM_REGISTER *) &PciRegister)->L3TagInit != 0); PciAddress.Address.Register = PROBE_FILTER_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); ((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFMode = 0; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); F10RevDProbeFilterCritical (PciAddress, PciRegister); do { LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); } while (((PROBE_FILTER_CTRL_REGISTER *) &PciRegister)->PFInitDone != 1); IDS_OPTION_HOOK (IDS_HT_ASSIST, &PciAddress, StdHeader); } } }
/** * Multisocket call to determine the frequency that the northbridges must run. * * This function loops through all possible socket locations, comparing the * maximum NB frequencies to determine the slowest. This function also * determines if all coherent NB frequencies are equivalent. * * @param[in] NbPstate NB P-state number to check (0 = fastest) * @param[in] PlatformConfig Platform profile/build option config structure. * @param[out] SystemNbCofNumerator NB frequency numerator for the system in MHz * @param[out] SystemNbCofDenominator NB frequency denominator for the system * @param[out] SystemNbCofsMatch Whether or not all NB frequencies are equivalent * @param[out] NbPstateIsEnabledOnAllCPUs Whether or not NbPstate is valid on all CPUs * @param[in] StdHeader Config handle for library and services * * @retval TRUE At least one processor has NbPstate enabled. * @retval FALSE NbPstate is disabled on all CPUs * */ BOOLEAN GetSystemNbCofMulti ( IN UINT32 NbPstate, IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *SystemNbCofNumerator, OUT UINT32 *SystemNbCofDenominator, OUT BOOLEAN *SystemNbCofsMatch, OUT BOOLEAN *NbPstateIsEnabledOnAllCPUs, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT8 Module; UINT32 CurrentNbCof; UINT32 CurrentDivisor; UINT32 CurrentFreq; UINT32 LowFrequency; UINT32 Ignored32; BOOLEAN FirstCofNotFound; BOOLEAN NbPstateDisabled; BOOLEAN IsNbPstateEnabledOnAny; PCI_ADDR PciAddress; AGESA_STATUS Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; // Find the slowest NB COF in the system & whether or not all are equivalent LowFrequency = 0xFFFFFFFF; *SystemNbCofsMatch = TRUE; *NbPstateIsEnabledOnAllCPUs = FALSE; IsNbPstateEnabledOnAny = FALSE; FirstCofNotFound = TRUE; NbPstateDisabled = FALSE; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &Ignored)) { break; } } if (FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices, PlatformConfig, &PciAddress, NbPstate, &CurrentNbCof, &CurrentDivisor, &Ignored32, StdHeader)) { ASSERT (CurrentDivisor != 0); CurrentFreq = (CurrentNbCof / CurrentDivisor); if (FirstCofNotFound) { *SystemNbCofNumerator = CurrentNbCof; *SystemNbCofDenominator = CurrentDivisor; LowFrequency = CurrentFreq; IsNbPstateEnabledOnAny = TRUE; if (!NbPstateDisabled) { *NbPstateIsEnabledOnAllCPUs = TRUE; } FirstCofNotFound = FALSE; } else { if (CurrentFreq != LowFrequency) { *SystemNbCofsMatch = FALSE; if (CurrentFreq < LowFrequency) { LowFrequency = CurrentFreq; *SystemNbCofNumerator = CurrentNbCof; *SystemNbCofDenominator = CurrentDivisor; } } } } else { NbPstateDisabled = TRUE; *NbPstateIsEnabledOnAllCPUs = FALSE; } } } return IsNbPstateEnabledOnAny; }
/** * Should message-based C1e be enabled * * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @retval TRUE Message-based C1e is supported. * @retval FALSE Message-based C1e cannot be enabled. * */ BOOLEAN STATIC IsMsgBasedC1eFeatureEnabled ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { UINTN Link; UINTN LinkCount; UINT32 Socket; UINT32 Module; BOOLEAN IsEnabled; PCI_ADDR PciAddress; AGESA_STATUS AgesaStatus; HT_HOST_FEATS HtHostFeats; CPU_SPECIFIC_SERVICES *CpuServices; MSG_BASED_C1E_FAMILY_SERVICES *FamilyServices; ASSERT (PlatformConfig->C1eMode < MaxC1eMode); IsEnabled = FALSE; if (PlatformConfig->C1eMode == C1eModeMsgBased) { ASSERT (PlatformConfig->C1ePlatformData < 0x10000); ASSERT (PlatformConfig->C1ePlatformData != 0); if ((PlatformConfig->C1ePlatformData != 0) && (PlatformConfig->C1ePlatformData < 0xFFFE)) { IsEnabled = TRUE; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetFeatureServicesOfSocket (&MsgBasedC1eFamilyServiceTable, Socket, (CONST VOID **)&FamilyServices, StdHeader); if ((FamilyServices == NULL) || !FamilyServices->IsMsgBasedC1eSupported (FamilyServices, Socket, StdHeader)) { IsEnabled = FALSE; break; } else { // If the CPU revision supports message-based C1e, check whether the feature should // be disabled based on the speed of ncHT links (HT1). GetCpuServicesOfSocket (Socket, &CpuServices, StdHeader); for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &AgesaStatus)) { HtHostFeats.HtHostValue = 0; for (LinkCount = 0; LinkCount < 8; LinkCount++) { if (FindHtHostCapability (LinkCount, &PciAddress, StdHeader)) { CpuServices->GetHtLinkFeatures (CpuServices, &Link, &PciAddress, &HtHostFeats, StdHeader); if ((HtHostFeats.HtHostFeatures.NonCoherent == 1) && (HtHostFeats.HtHostFeatures.Ht1 == 1)) { IsEnabled = FALSE; break; } } } } // Exit for (Module = 0; Module < GetPlatformNumberOfModules; Module++) if (!IsEnabled) { break; } } } } // Exit for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) if (!IsEnabled) { break; } } } } return IsEnabled; }
/**-------------------------------------------------------------------------------------- * * PStateLevelingMain * * Description: * This is the common routine for creating the ACPI information tables. * * Parameters: * @param[in,out] *PStateStrucPtr * @param[in] *StdHeader * * @retval AGESA_STATUS * *--------------------------------------------------------------------------------------- **/ AGESA_STATUS PStateLevelingMain ( IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 i; UINT32 k; UINT32 m; UINT32 TotalIterations; UINT32 LogicalSocketCount; UINT32 TempVar_a; UINT32 TempVar_b; UINT32 TempVar_c; UINT32 TempVar_d; UINT32 TempVar_e; UINT32 TempVar_f; PCI_ADDR PciAddress; UINT32 TempFreqArray[20]; UINT32 TempPowerArray[20]; UINT32 TempIddValueArray[20]; UINT32 TempIddDivArray[20]; UINT32 TempSocketPiArray[20]; UINT32 TempSwP0Array[MAX_SOCKETS_SUPPORTED]; BOOLEAN TempFlag1; BOOLEAN TempFlag2; BOOLEAN TempFlag3; BOOLEAN TempFlag4; BOOLEAN AllCoresHaveHtcCapEquToZeroFlag; BOOLEAN AllCoreHaveMaxOnePStateFlag; BOOLEAN PstateMaxValEquToPstateHtcLimitFlag; BOOLEAN AtLeastOneCoreHasPstateHtcLimitEquToOneFlag; BOOLEAN PstateMaxValMinusHtcPstateLimitLessThan2Flag; PSTATE_LEVELING *PStateBufferPtr; PSTATE_LEVELING *PStateBufferPtrTmp; UINT32 MaxPstateInNode; AGESA_STATUS Status; TempFlag1 = FALSE; TempFlag2 = FALSE; TempFlag3 = FALSE; TempFlag4 = FALSE; AllCoresHaveHtcCapEquToZeroFlag = FALSE; AllCoreHaveMaxOnePStateFlag = FALSE; PstateMaxValEquToPstateHtcLimitFlag = FALSE; AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = FALSE; PstateMaxValMinusHtcPstateLimitLessThan2Flag = FALSE; PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc; Status = AGESA_SUCCESS; if (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1) { PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE; PStateBufferPtr[0].InitStruct = 1; return AGESA_UNSUPPORTED; } LogicalSocketCount = PStateStrucPtr->TotalSocketInSystem; ASSERT (LogicalSocketCount <= MAX_SOCKETS_SUPPORTED); // This section of code will execute only for "core 0" i.e. BSP // Read P-States of all the cores. if (PStateBufferPtr[0].InitStruct == 0) { // Determine 'software' P0 indices for each socket for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSwP0Array[i] = (UINT32) (PStateBufferPtrTmp->PStateCoreStruct[0].NumberOfBoostedStates); } // Check if core frequency and power are same across all sockets. TempFlag1 = FALSE; m = TempSwP0Array[0]; for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue != PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue)) { TempFlag1 = TRUE; break; } MaxPstateInNode = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; for (k = TempSwP0Array[i]; k <= MaxPstateInNode; k++, m++) { if ((PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].CoreFreq != PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].CoreFreq) || (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[m].Power != PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].Power)) { TempFlag1 = TRUE; break; // Come out of the inner FOR loop } } if (TempFlag1) { break; // Come out of the outer FOR loop } } if (!TempFlag1) { // No need to do pStateLeveling, or writing to pState MSR registers // if all CPUs have Identical PStates PStateBufferPtr[0].AllCpusHaveIdenticalPStates = TRUE; PStateBufferPtr[0].InitStruct = 1; PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } else { PStateBufferPtr[0].AllCpusHaveIdenticalPStates = FALSE; } // 1_b) & 1_c) TempFlag1 = FALSE; TempFlag2 = FALSE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == TempSwP0Array[i]) { TempFlag1 = TRUE; } else { TempFlag2 = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcCapable == 0) { TempFlag3 = TRUE; } else { TempFlag4 = TRUE; } if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) < 2) { PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { PstateMaxValEquToPstateHtcLimitFlag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) { AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE; } } // Do general setup of flags, that we may use later // Implementation of (1_b) if (TempFlag1 && TempFlag2) { // //Processors with only one enabled P-state (F3xDC[PstateMaxVal]=000b) cannot be mixed in a system with //processors with more than one enabled P-state (F3xDC[PstateMaxVal]!=000b). // PStateBufferPtr[0].InitStruct = 1; PStateBufferPtr[0].CreateAcpiTables = 0; PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } else if (TempFlag1 && !TempFlag2) { // //all processors have only 1 enabled P-state // AllCoreHaveMaxOnePStateFlag = TRUE; PStateBufferPtr[0].OnlyOneEnabledPState = TRUE; } // Processors with F3xE8[HTC_CAPABLE] = 1 can not be // mixed in system with processors with F3xE8[HTC_CAPABLE] = 0. if (TempFlag3 && TempFlag4) { PStateBufferPtr[0].InitStruct = 1; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp[0].CreateAcpiTables = 0; } PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_UNSUPPORTED; } if (TempFlag3) { // //If code run to here means that all processors do not have HTC_CAPABLE. // AllCoresHaveHtcCapEquToZeroFlag = TRUE; } //-------------------------------------------------------------------------------- // S T E P - 2 //-------------------------------------------------------------------------------- // Now run the PState Leveling Algorithm which will create mixed CPU P-State // Tables. // Follow the algorithm in the latest BKDG // ------------------------------------------------------------------------------- // Match P0 CPU COF for all CPU cores to the lowest P0 CPU COF value in the // coherent fabric, and match P0 power for all CPU cores to the highest P0 power // value in the coherent fabric. // 2_a) If all processors have only 1 enabled P-State BIOS must write the // appropriate CpuFid value resulting from the matched CPU COF to all // copies of MSRC001_0070[CpuFid], and exit the sequence (No further // steps are executed) //-------------------------------------------------------------------------------- // Identify the lowest P0 Frequency and maximum P0 Power TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].Power; TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddValue; TempVar_b = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSwP0Array[0]].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power; TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue; TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv; } } // Set P0 Frequency and Power for all CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddValue = TempVar_a; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSwP0Array[i]].IddDiv = TempVar_b; } // 2_a) if (!AllCoreHaveMaxOnePStateFlag) { //-------------------------------------------------------------------------- // STEP - 3 //-------------------------------------------------------------------------- // Match the CPU COF and power for P-states used by HTC. Skip to step 4 // is any processor reports F3xE8[HTC_Capable] = 0; // 3_a) Set F3x64[HtcPstateLimit] = 001b and F3x68[StcPstateLimit] = 001b for // processors with F3x64[HtcPstateLimit] = 000b. // 3_b) Identify the lowest CPU COF for all processors in the P-state // pointed to by [The Hardware Thermal Control (HTC) Register] // F3x64[HtcPstateLimit] // 3_c) Modify the CPU COF pointed to by [The Hardware Thermal Control // (HTC) Register] F3x64[HtcPstateLimit] for all processors to the // previously identified lowest CPU COF value. // 3_d) Identify the highest power for all processors in the P-state // pointed to by [The Hardware Thermal Control (HTC) Register] // F3x64[HtcPstateLimit]. // 3_e) Modify the power pointed to by [The Hardware Thermal Control (HTC) // Register] F3x64[HtcPstateLimit] to the previously identified // highest power value. if (!AllCoresHaveHtcCapEquToZeroFlag) { // 3_a) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 0) { // To Be Done (Set Htc and Stc PstateLimit values) // for this CPU (using PCI address space) for (k = 0; k < (UINT8)GetPlatformNumberOfModules (); k++) { if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, k, &PciAddress, &Status)) { // Set F3x64[HtcPstateLimit] = 001b PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Bits 30:28 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Set F3x68[StcPstateLimit] = 001b PciAddress.Address.Register = SOFTWARE_THERMAL_CTRL_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); // Bits 28:30 TempVar_d = (TempVar_d & 0x8FFFFFFF) | 0x10000000; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); } } // Set LocalBuffer PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit = 1; if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1) < 2) { PstateMaxValMinusHtcPstateLimitLessThan2Flag = TRUE; } if (PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue == 1) { PstateMaxValEquToPstateHtcLimitFlag = TRUE; } } if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit == 1) { AtLeastOneCoreHasPstateHtcLimitEquToOneFlag = TRUE; } } // 3_b) and 3_d) TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit; TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power; TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue; TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = 0; k < 1; k++) { TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power; TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue; TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv; } } } // 3_c) and 3_e) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c; } } // if(AllCoresHaveHtcCapEquToZeroFlag) //-------------------------------------------------------------------------- // STEP - 4 //-------------------------------------------------------------------------- // Match the CPU COF and power for the lowest performance P-state: // 4_a) If F3xDC[PstateMaxVal] = F3x64[HtcPstateLimit] for any processor, // set PstateEn = 0 for all the P-states greater than // F3x64[HtcPstateLimit] for all processors. // 4_b) Identify the lowest CPU COF for all processors in the P-state // pointed to by F3xDC[PstateMaxVal]. // 4_c) Modify the CPU COF for all processors in the P-state pointed to by // F3xDC[PstateMaxVal] to the previously identified lowest CPU COF // value. // 4_d) Identify the highest power for all processors in the P-state // pointed to by F3xDC[PstateMaxVal]. // 4_e) Modify the power for all processors in the P-state pointed to by // F3xDC[PstateMaxVal] to the previously identified highest power // value. // 4_a) if (PstateMaxValEquToPstateHtcLimitFlag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit + 1; for (k = TempVar_b; k <= PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; k++) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } //-------------------------------------------------------------------------- // STEP - 5 //-------------------------------------------------------------------------- // 5_a) Modify F3xDC[PstateMaxVal] to indicate the lowest performance // P-state with PstateEn set for each processor (Step 4 can disable // P-states pointed to by F3xDC[PstateMaxVal]) // Use this value of HtcPstateLimit to program the // F3xDC[pStateMaxValue] TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; TempVar_e <<= 8; // Bits 10:8 for (m = 0; m < (UINT8)GetPlatformNumberOfModules (); m++) { if (GetPciAddress (StdHeader, PStateBufferPtrTmp->SocketNumber, m, &PciAddress, &Status)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = CLOCK_POWER_TIMING_CTRL2_REG; LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_d, StdHeader); TempVar_d = (TempVar_d & 0xFFFFF8FF) | TempVar_e; LibAmdPciWrite (AccessWidth32, PciAddress, &TempVar_d, StdHeader); } }//End of step 5 } }// End of 4_a) // 4_b) and 4_d) TempVar_a = PStateBufferPtr[0].PStateCoreStruct[0].PStateMaxValue; TempVar_d = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq; TempVar_e = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].Power; TempVar_f = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue; TempVar_c = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_b = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; if (TempVar_d > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq) { TempVar_d = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].CoreFreq; } if (TempVar_e < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power) { TempVar_e = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].Power; TempVar_f = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddValue; TempVar_c = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_b].IddDiv; } } // 4_c) and 4_e) for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempVar_a = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].CoreFreq = TempVar_d; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].Power = TempVar_e; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddValue = TempVar_f; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempVar_a].IddDiv = TempVar_c; } //-------------------------------------------------------------------------- // STEP - 6 //-------------------------------------------------------------------------- // Match the CPU COF and power for upper intermediate performance // P-state(s): // Upper intermediate PStates = PStates between (Not including) P0 and // F3x64[HtcPstateLimit] // 6_a) If F3x64[HtcPstateLimit] = 001b for any processor, set PstateEn = 0 // for enabled upper intermediate P-states for all processors with // F3x64[HtcPstateLimit] > 001b and skip the remaining actions for // this numbered step. // 6_b) Define each of the available upper intermediate P-states; for each // processor concurrently evaluate the following loop; when any // processor falls out of the loop (runs out of available upper // intermediate Pstates) all other processors have their remaining // upper intermediate P-states invalidated (PstateEn = 0); // for (i = F3x64[HtcPstateLimit] - 1; i > 0; i--) // - Identify the lowest CPU COF for P(i). // - Identify the highest power for P(i). // - Modify P(i) CPU COF for all processors to the previously // identified lowest CPU COF value. // - Modify P(i) power for all processors to the previously // identified highest power value. // 6_a) if (AtLeastOneCoreHasPstateHtcLimitEquToOneFlag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = TempSwP0Array[i] + 1; k < (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit); k++) { if (PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit > 1) { // Make a function call to clear the // structure values PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } } } } // 6_b) else { // Identify Lowest Frequency and Highest Power TotalIterations = 0; TempFlag1 = TRUE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit - 1; } do { //For first socket, try to find a candidate if (TempSocketPiArray[0] != TempSwP0Array[0]) { while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) { TempSocketPiArray[0] = TempSocketPiArray[0] - 1; if (TempSocketPiArray[0] == TempSwP0Array[0]) { TempFlag1 = FALSE; break; } } } else { TempFlag1 = FALSE; } if (TempFlag1) { TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq; TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv; //Try to find next candidate for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempSocketPiArray[i] != TempSwP0Array[i]) { while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) { TempSocketPiArray[i]--; if (TempSocketPiArray[i] == TempSwP0Array[i]) { TempFlag1 = FALSE; break; } }//end while } else { TempFlag1 = FALSE; } } //end for LogicalSocketCount } if (TempFlag1) { for (i = 0; i < LogicalSocketCount; i++) { // //Compare // CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) { TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq; } if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) { TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv; } } // Modify (Pi) CPU COF and Power for all the CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations]; TempSocketPiArray[i] = TempSocketPiArray[i] - 1; } } else { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (m = TempSocketPiArray[i]; m > TempSwP0Array[i]; m--) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0; } } } TotalIterations++; } while (TempFlag1); } // else //-------------------------------------------------------------------------- // STEP - 7 //-------------------------------------------------------------------------- // Match the CPU COF and power for lower intermediate performance P - state(s) // Lower Intermediate Pstates = Pstates between (not including) // F3x64[HtcPstateLimit] and F3xDC[PstateMaxVal] // 7_a) If F3xDC[PstateMaxVal] - F3x64[HtcPstateLimit] < 2 for any // processor, set PstateEn = 0 for enabled lower intermediate P - states // for all processors with (F3xDC[PstateMaxVal] - // F3x64[HtcPstateLimit] > 1) and skip the remaining actions for this // numbered step. // 7_b) Define each of the available lower intermediate P-states; for each // processor concurrently evaluate the following loop; when any // processor falls out of the loop (runs out of available lower // intermediate Pstates) all other processors have their remaining // lower intermediate P-states invalidated (PstateEn = 0); // for (i = F3xDC[PstateMaxVal]-1; i > F3x64[HtcPstateLimit]; i--) // - Identify the lowest CPU COF for P-states between // (not including) F3x64[HtcPstateLimit] and P(i). // - Identify the highest power for P-states between // (not including) F3x64[HtcPstateLimit] and P(i). // - Modify P(i) CPU COF for all processors to the previously // identified lowest CPU COF value. // - Modify P(i) power for all processors to the previously // identified highest power value. // 7_a) if (PstateMaxValMinusHtcPstateLimitLessThan2Flag) { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (k = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1; k > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; k--) { if ((PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) > 1) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 0; } } } } // 7_b) else { // Identify Lowest Frequency and Highest Power TotalIterations = 0; TempFlag1 = TRUE; for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); TempSocketPiArray[i] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateMaxValue - 1; } do { //For first socket, try to find a candidate if (TempSocketPiArray[0] != PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) { while (PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].PStateEnable == 0) { TempSocketPiArray[0] = TempSocketPiArray[0] - 1; if (TempSocketPiArray[0] == PStateBufferPtr[0].PStateCoreStruct[0].HtcPstateLimit) { TempFlag1 = FALSE; break; } } } else { TempFlag1 = FALSE; } if (TempFlag1) { TempFreqArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].CoreFreq; TempPowerArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtr[0].PStateCoreStruct[0].PStateStruct[TempSocketPiArray[0]].IddDiv; //Try to find next candidate for (i = 1; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempSocketPiArray[i] != PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { while (PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].PStateEnable == 0) { TempSocketPiArray[i]--; if (TempSocketPiArray[i] == PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit) { TempFlag1 = FALSE; break; } }//end while } else { TempFlag1 = FALSE; } } //end for LogicalSocketCount } if (TempFlag1) { for (i = 0; i < LogicalSocketCount; i++) { // //Compare // CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); if (TempFreqArray[TotalIterations] > PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq) { TempFreqArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq; } if (TempPowerArray[TotalIterations] < PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power) { TempPowerArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power; TempIddValueArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue; TempIddDivArray[TotalIterations] = PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv; } } // Modify (Pi) CPU COF and Power for all the CPUs for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].CoreFreq = TempFreqArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].Power = TempPowerArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddValue = TempIddValueArray[TotalIterations]; PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[TempSocketPiArray[i]].IddDiv = TempIddDivArray[TotalIterations]; TempSocketPiArray[i] = TempSocketPiArray[i] - 1; } } else { for (i = 0; i < LogicalSocketCount; i++) { CpuGetPStateLevelStructure (&PStateBufferPtrTmp, PStateStrucPtr, i, StdHeader); for (m = TempSocketPiArray[i]; m > PStateBufferPtrTmp->PStateCoreStruct[0].HtcPstateLimit; m--) { PStateBufferPtrTmp->PStateCoreStruct[0].PStateStruct[m].PStateEnable = 0; } } } TotalIterations++; } while (TempFlag1); } // else } // if(!AllCoreHaveMaxOnePStateFlag) PStateBufferPtr[0].InitStruct = 1; } // CurrentCore // Update the pState MSRs // This can be done only by individual core StartPstateMsrModify (PStateStrucPtr, StdHeader); //---------------------------------------------------------------------------------- // STEP - 8 //---------------------------------------------------------------------------------- // Place all cores into a valid COF and VID configuration corresponding to an // enabled P-state: // 8_a) Select an enabled P-state != to the P-state pointed to by // MSRC001_0063[CurPstate] for each core. // 8_b) Transition all cores to the selected P-states by writing the Control value // from the_PSS object corresponding to the selected P-state to // MSRC001_0062[PstateCmd]. // 8_c) Wait for all cores to report the Status value from the _PSS object // corresponding to the selected P-state in MSRC001_0063[CurPstate]. // PutAllCoreInPState0 (PStateBufferPtr, StdHeader); return AGESA_SUCCESS; }
/** * 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 } }
/** * Save and Restore or Initialize the content of the mailbox registers. * * The registers used for AP mailbox should have the content related to their function * preserved. * * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @return AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC PreserveMailboxes ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { PRESERVE_MAILBOX_FAMILY_SERVICES *FamilySpecificServices; UINT32 Socket; UINT32 Module; PCI_ADDR BaseAddress; PCI_ADDR MailboxRegister; PCI_ADDR *NextRegister; AGESA_STATUS IgnoredStatus; AGESA_STATUS HeapStatus; UINT32 Value; ALLOCATE_HEAP_PARAMS AllocateParams; LOCATE_HEAP_PTR LocateParams; UINT32 RegisterEntryIndex; BaseAddress.AddressValue = ILLEGAL_SBDFO; if (EntryPoint == CPU_FEAT_AFTER_COHERENT_DISCOVERY) { // The save step. Save either the register content or zero (for cold boot, if family specifies that). AllocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; AllocateParams.RequestedBufferSize = (sizeof (UINT32) * (MAX_PRESERVE_REGISTER_ENTRIES * (MAX_SOCKETS * MAX_DIES))); AllocateParams.Persist = HEAP_SYSTEM_MEM; HeapStatus = HeapAllocateBuffer (&AllocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (AllocateParams.BufferPtr != NULL)); LibAmdMemFill (AllocateParams.BufferPtr, 0xFF, AllocateParams.RequestedBufferSize, StdHeader); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); ASSERT (FamilySpecificServices != NULL); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); if (FamilySpecificServices->IsZeroOnCold && (!IsWarmReset (StdHeader))) { Value = 0; } else { MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; LibAmdPciRead (AccessWidth32, MailboxRegister, &Value, StdHeader); } (* (MAILBOX_REGISTER_SAVE_ENTRY) AllocateParams.BufferPtr) [RegisterEntryIndex] = Value; RegisterEntryIndex++; NextRegister++; } } } } } else if ((EntryPoint == CPU_FEAT_INIT_LATE_END) || (EntryPoint == CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) { // The restore step. Just write out the saved content in the buffer. LocateParams.BufferHandle = PRESERVE_MAIL_BOX_HANDLE; HeapStatus = HeapLocateBuffer (&LocateParams, StdHeader); ASSERT ((HeapStatus == AGESA_SUCCESS) && (LocateParams.BufferPtr != NULL)); RegisterEntryIndex = 0; for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) { for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &BaseAddress, &IgnoredStatus)) { GetFeatureServicesOfSocket (&PreserveMailboxFamilyServiceTable, Socket, (const VOID **)&FamilySpecificServices, StdHeader); NextRegister = FamilySpecificServices->RegisterList; while (NextRegister->AddressValue != ILLEGAL_SBDFO) { ASSERT (RegisterEntryIndex < (MAX_PRESERVE_REGISTER_ENTRIES * GetPlatformNumberOfSockets () * GetPlatformNumberOfModules ())); MailboxRegister = BaseAddress; MailboxRegister.Address.Function = NextRegister->Address.Function; MailboxRegister.Address.Register = NextRegister->Address.Register; Value = (* (MAILBOX_REGISTER_SAVE_ENTRY) LocateParams.BufferPtr) [RegisterEntryIndex]; LibAmdPciWrite (AccessWidth32, MailboxRegister, &Value, StdHeader); RegisterEntryIndex++; NextRegister++; } } } } HeapStatus = HeapDeallocateBuffer (PRESERVE_MAIL_BOX_HANDLE, StdHeader); } return AGESA_SUCCESS; }
/** * Core 0 task to enable message-based C1e on a family 10h CPU. * * @param[in] MsgBasedC1eServices Pointer to this CPU's HW C1e family services. * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config Handle for library, services. * * @return AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC F10InitializeMsgBasedC1e ( IN MSG_BASED_C1E_FAMILY_SERVICES *MsgBasedC1eServices, IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 AndMask; UINT32 Core; UINT32 Module; UINT32 OrMask; UINT32 PciRegister; UINT32 Socket; AP_TASK TaskPtr; PCI_ADDR PciAddress; AGESA_STATUS IgnoredSts; if ((EntryPoint & (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) != 0) { // Note that this core 0 does NOT have the ability to launch // any of its cores. Attempting to do so could lead to a system // hang. // Set F3xA0[IdleExitEn] = 1 PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = PW_CTL_MISC_REG; AndMask = 0xFFFFFFFF; OrMask = 0; ((POWER_CTRL_MISC_REGISTER *) &OrMask)->IdleExitEn = 1; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3xA0 // Set F3x188[EnStpGntOnFlushMaskWakeup] = 1 PciAddress.Address.Register = NB_EXT_CFG_LO_REG; OrMask = 0; ((NB_EXT_CFG_LO_REGISTER *) &OrMask)->EnStpGntOnFlushMaskWakeup = 1; ModifyCurrentSocketPci (&PciAddress, AndMask, OrMask, StdHeader); // F3x188 // Set F3xD4[MTC1eEn] = 1, F3xD4[CacheFlushImmOnAllHalt] = 1 // Set F3xD4[StutterScrubEn] = 1 if scrubbing is enabled ((CLK_PWR_TIMING_CTRL_REGISTER *) &AndMask)->StutterScrubEn = 0; OrMask = 0; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->MTC1eEn = 1; ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->CacheFlushImmOnAllHalt = 1; IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts); for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) { if (GetPciAddress (StdHeader, Socket, Module, &PciAddress, &IgnoredSts)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = CPTC0_REG; if (IsDramScrubberEnabled (PciAddress, StdHeader)) { ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->StutterScrubEn = 1; } else { ((CLK_PWR_TIMING_CTRL_REGISTER *) &OrMask)->StutterScrubEn = 0; } LibAmdPciRead (AccessWidth32, PciAddress, &PciRegister, StdHeader); PciRegister &= AndMask; PciRegister |= OrMask; LibAmdPciWrite (AccessWidth32, PciAddress, &PciRegister, StdHeader); } } } else if (EntryPoint == CPU_FEAT_AFTER_PM_INIT) { // At early, this core 0 can launch its subordinate cores. TaskPtr.FuncAddress.PfApTaskI = F10InitializeMsgBasedC1eOnCore; TaskPtr.DataTransfer.DataSizeInDwords = 1; TaskPtr.DataTransfer.DataPtr = &PlatformConfig->C1ePlatformData; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE; ApUtilRunCodeOnAllLocalCoresAtEarly (&TaskPtr, StdHeader, NULL); } return AGESA_SUCCESS; }