/** * 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; }
/** * Multisocket BSC call to determine the maximum number of steps that any single * processor needs to execute. * * This function loops through all possible socket locations, gathering the number * of power management steps each populated socket requires, and returns the * highest number. * * @param[out] NumSystemSteps Maximum number of system steps required * @param[in] StdHeader Config handle for library and services * */ VOID GetNumberOfSystemPmStepsPtrMulti ( OUT UINT8 *NumSystemSteps, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 NumberOfSteps; UINT32 NumberOfSockets; UINT32 Socket; SYS_PM_TBL_STEP *Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; NumberOfSockets = GetPlatformNumberOfSockets (); *NumSystemSteps = 0; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { GetCpuServicesOfSocket (Socket, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->GetSysPmTableStruct (FamilySpecificServices, (CONST VOID **) &Ignored, &NumberOfSteps, StdHeader); if (NumberOfSteps > *NumSystemSteps) { *NumSystemSteps = NumberOfSteps; } } } }
/** * 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; }
/** * 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; } } } }
/** * 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; }
/** * Performs CPU related initialization at the early entry point * * This function performs a large list of initialization items. These items * include: * * -1 local APIC initialization * -2 MSR table initialization * -3 PCI table initialization * -4 HT Phy PCI table initialization * -5 microcode patch loading * -6 namestring determination/programming * -7 AP initialization * -8 power management initialization * -9 core leveling * * This routine must be run by all cores in the system. Please note that * all APs that enter will never exit. * * @param[in] StdHeader Config handle for library and services * @param[in] PlatformConfig Config handle for platform specific information * * @retval AGESA_SUCCESS * */ AGESA_STATUS AmdCpuEarly ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig ) { UINT8 WaitStatus; UINT8 i; UINT8 StartCore; UINT8 EndCore; UINT32 NodeNum; UINT32 PrimaryCore; UINT32 SocketNum; UINT32 ModuleNum; UINT32 HighCore; UINT32 ApHeapIndex; UINT32 CurrentPerformEarlyFlag; UINT32 TargetApicId; AP_WAIT_FOR_STATUS WaitForStatus; AGESA_STATUS Status; AGESA_STATUS CalledStatus; CPU_SPECIFIC_SERVICES *FamilySpecificServices; AMD_CPU_EARLY_PARAMS CpuEarlyParams; S_PERFORM_EARLY_INIT_ON_CORE *EarlyTableOnCore; Status = AGESA_SUCCESS; CalledStatus = AGESA_SUCCESS; AmdCpuEarlyInitializer (StdHeader, PlatformConfig, &CpuEarlyParams); IDS_OPTION_HOOK (IDS_CPU_Early_Override, &CpuEarlyParams, StdHeader); GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); EarlyTableOnCore = NULL; FamilySpecificServices->GetEarlyInitOnCoreTable (FamilySpecificServices, (CONST S_PERFORM_EARLY_INIT_ON_CORE **)&EarlyTableOnCore, &CpuEarlyParams, StdHeader); if (EarlyTableOnCore != NULL) { GetPerformEarlyFlag (&CurrentPerformEarlyFlag, StdHeader); for (i = 0; EarlyTableOnCore[i].PerformEarlyInitOnCore != NULL; i++) { if ((EarlyTableOnCore[i].PerformEarlyInitFlag & CurrentPerformEarlyFlag) != 0) { IDS_HDT_CONSOLE (CPU_TRACE, " Perform core init step %d\n", i); EarlyTableOnCore[i].PerformEarlyInitOnCore (FamilySpecificServices, &CpuEarlyParams, StdHeader); } } } // B S P C O D E T O I N I T I A L I Z E A Ps // ------------------------------------------------------- // ------------------------------------------------------- // IMPORTANT: Here we determine if we are BSP or AP if (IsBsp (StdHeader, &CalledStatus)) { // Even though the bsc does not need to send itself a heap index, this sequence performs other important initialization. // Use '0' as a dummy heap index value. GetSocketModuleOfNode (0, &SocketNum, &ModuleNum, StdHeader); GetCpuServicesOfSocket (SocketNum, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, 0, StdHeader); FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, StdHeader); // Clear BSP's Status Byte ApUtilWriteControlByte (CORE_ACTIVE, StdHeader); NodeNum = 0; ApHeapIndex = 1; while (NodeNum < MAX_NODES && GetSocketModuleOfNode (NodeNum, &SocketNum, &ModuleNum, StdHeader)) { GetCpuServicesOfSocket (SocketNum, (CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); GetGivenModuleCoreRange (SocketNum, ModuleNum, &PrimaryCore, &HighCore, StdHeader); if (NodeNum == 0) { StartCore = (UINT8) PrimaryCore + 1; } else { StartCore = (UINT8) PrimaryCore; } EndCore = (UINT8) HighCore; for (i = StartCore; i <= EndCore; i++) { FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, ApHeapIndex, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " Launch socket %d core %d\n", SocketNum, i); if (FamilySpecificServices->LaunchApCore (FamilySpecificServices, SocketNum, ModuleNum, i, PrimaryCore, StdHeader)) { IDS_HDT_CONSOLE (CPU_TRACE, " Waiting for socket %d core %d\n", SocketNum, i); GetLocalApicIdForCore (SocketNum, i, &TargetApicId, StdHeader); WaitStatus = CORE_IDLE; WaitForStatus.Status = &WaitStatus; WaitForStatus.NumberOfElements = 1; WaitForStatus.RetryCount = WAIT_INFINITELY; WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY; ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader); ApHeapIndex++; } } NodeNum++; } // B S P P h a s e - 1 E N D IDS_OPTION_HOOK (IDS_BEFORE_PM_INIT, &CpuEarlyParams, StdHeader); AGESA_TESTPOINT (TpProcCpuBeforePMFeatureInit, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " Dispatch CPU features before early power mgmt init\n"); CalledStatus = DispatchCpuFeatures (CPU_FEAT_BEFORE_PM_INIT, PlatformConfig, StdHeader); if (CalledStatus > Status) { Status = CalledStatus; } AGESA_TESTPOINT (TpProcCpuPowerMgmtInit, StdHeader); CalledStatus = PmInitializationAtEarly (&CpuEarlyParams, StdHeader); if (CalledStatus > Status) { Status = CalledStatus; } AGESA_TESTPOINT (TpProcCpuEarlyFeatureInit, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " Dispatch CPU features after early power mgmt init\n"); CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_PM_INIT, PlatformConfig, StdHeader); IDS_OPTION_HOOK (IDS_BEFORE_AP_EARLY_HALT, &CpuEarlyParams, StdHeader); // Sleep all APs IDS_HDT_CONSOLE (CPU_TRACE, " Halting all APs\n"); ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader); } else { ApEntry (StdHeader, &CpuEarlyParams); } if (CalledStatus > Status) { Status = CalledStatus; } return (Status); }
/** * 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; }