/** * Determines the base address of the executing core's heap. * * This function uses the executing core's socket/core numbers to determine * where it's heap should be located. * * @param[in] StdHeader Config handle for library and services. * * @return A pointer to the executing core's heap. * */ UINT64 STATIC HeapGetCurrentBase ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 SystemCoreNumber; UINT64 ReturnPtr; AGESA_STATUS IgnoredStatus; CPU_SPECIFIC_SERVICES *FamilyServices; if (IsBsp (StdHeader, &IgnoredStatus)) { ReturnPtr = AMD_HEAP_START_ADDRESS; } else { GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader); ASSERT (FamilyServices != NULL); SystemCoreNumber = FamilyServices->GetApCoreNumber (FamilyServices, StdHeader); ASSERT (SystemCoreNumber != 0); ASSERT (SystemCoreNumber < 64); ReturnPtr = ((SystemCoreNumber * AMD_HEAP_SIZE_PER_CORE) + AMD_HEAP_START_ADDRESS); } ASSERT (ReturnPtr <= ((AMD_HEAP_REGION_END_ADDRESS + 1) - AMD_HEAP_SIZE_PER_CORE)); return ReturnPtr; }
/** * Single socket call to determine the frequency that the northbridges must run. * * This function simply returns the executing core's NB frequency, and that all * 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 GetSystemNbCofSingle ( 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 Ignored; PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); *SystemNbCofsMatch = TRUE; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); *NbPstateIsEnabledOnAllCPUs = FamilySpecificServices->GetNbPstateInfo (FamilySpecificServices, PlatformConfig, &PciAddress, NbPstate, SystemNbCofNumerator, SystemNbCofDenominator, &Ignored, StdHeader); return *NbPstateIsEnabledOnAllCPUs; }
BOOLEAN STATIC MemConstructRemoteNBBlockHY ( IN OUT MEM_NB_BLOCK *NBPtr, IN DIE_STRUCT *MCTPtr, IN MEM_FEAT_BLOCK_NB *FeatPtr ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; NBPtr->MCTPtr = MCTPtr; NBPtr->PciAddr.AddressValue = MCTPtr->PciAddr.AddressValue; MemNInitNBDataHy (NBPtr); FeatPtr->InitCPG (NBPtr); NBPtr->FeatPtr = FeatPtr; FeatPtr->InitHwRxEn (NBPtr); MemNSwitchDCTNb (NBPtr, 0); //---------------------------------------------------------------------------- // Get TSC rate of the this AP //---------------------------------------------------------------------------- GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &NBPtr->MemPtr->StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &NBPtr->MemPtr->TscRate, &NBPtr->MemPtr->StdHeader); return TRUE; }
/** * Get the number of P-State to support * * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS. * * @retval num The number of P-State to support. * **/ UINT8 IdsGetNumPstatesFamCommon ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT8 pstatesnum; UINT8 i; UINT32 IddVal; UINT32 IddDiv; BOOLEAN PStateEnabled; UINT32 TempVar_c; CPU_SPECIFIC_SERVICES *FamilySpecificServices; pstatesnum = 0; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetPstateMaxState (FamilySpecificServices, &TempVar_c, StdHeader); for (i = 0; i <= TempVar_c; i++) { // Check if PState is enabled FamilySpecificServices->GetPstateRegisterInfo (FamilySpecificServices, (UINT32) i, &PStateEnabled, &IddVal, &IddDiv, StdHeader); if (PStateEnabled) { pstatesnum++; } } return pstatesnum; }
/** * This function will get the CPU register warm reset bits. * * Note: This function will be called by UEFI BIOS's * The UEFI wrapper code should register this function, to be called back later point * in time, before the wrapper code does warm reset. * * @param[in] StdHeader Config handle for library and services * @param[out] Request Indicate warm reset status * *--------------------------------------------------------------------------------------- **/ VOID GetWarmResetFlag ( IN AMD_CONFIG_PARAMS *StdHeader, OUT WARM_RESET_REQUEST *Request ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetWarmResetFlag (FamilySpecificServices, StdHeader, Request); switch (StdHeader->Func) { case AMD_INIT_RESET: Request->PostStage = (UINT8) WR_STATE_RESET; break; case AMD_INIT_EARLY: Request->PostStage = (UINT8) WR_STATE_EARLY; break; case AMD_INIT_POST: // Fall through to default case default: Request->PostStage = (UINT8) WR_STATE_POST; break; } }
/** * Output Test Point function . * * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval AGESA_SUCCESS Success to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * @retval AGESA_ERROR Fail to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * **/ AGESA_STATUS IdsPerfAnalyseTimestamp ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT32 TscRateInMhz; CPU_SPECIFIC_SERVICES *FamilySpecificServices; IDS_CALLOUT_STRUCT IdsCalloutData; AGESA_STATUS Status; PERFREGBACKUP PerfReg; UINT32 CR4reg; UINT64 SMsr; LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status != AGESA_SUCCESS) { return status; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRateInMhz, StdHeader); ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->TscInMhz = TscRateInMhz; ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->Version = IDS_PERF_VERSION; IdsCalloutData.IdsNvPtr = NULL; IdsCalloutData.StdHeader = *StdHeader; IdsCalloutData.Reserved = 0; Status = AgesaGetIdsData (IDS_CALLOUT_GET_PERF_BUFFER, &IdsCalloutData); //Check if Platform BIOS provide a buffer to copy if ((Status == AGESA_SUCCESS) && (IdsCalloutData.Reserved != 0)) { LibAmdMemCopy ((VOID *)IdsCalloutData.Reserved, LocateHeapStructPtr.BufferPtr, sizeof (TP_Perf_STRUCT), StdHeader); } else { //No platform performance buffer provide, use the default HDTOUT output if (AmdIdsHdtOutSupport () == FALSE) { //Init break point IdsPerfSaveReg (&PerfReg, StdHeader); LibAmdMsrRead (0xC001100A, (UINT64 *)&SMsr, StdHeader); SMsr |= 1; LibAmdMsrWrite (0xC001100A, (UINT64 *)&SMsr, StdHeader); LibAmdWriteCpuReg (DR2_REG, 0x99cc); LibAmdWriteCpuReg (DR7_REG, 0x02000420); LibAmdReadCpuReg (CR4_REG, &CR4reg); LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3)); IdsPerfHdtOut (1, (UINT32) (UINT64) LocateHeapStructPtr.BufferPtr, StdHeader); IdsPerfRestoreReg (&PerfReg, StdHeader); } } return status; }
/** * Single socket BSC call to determine the maximum number of steps that any single * processor needs to execute. * * This function simply returns the number of steps that the BSC needs. * * @param[out] NumSystemSteps Maximum number of system steps required * @param[in] StdHeader Config handle for library and services * */ VOID GetNumberOfSystemPmStepsPtrSingle ( OUT UINT8 *NumSystemSteps, IN AMD_CONFIG_PARAMS *StdHeader ) { SYS_PM_TBL_STEP *Ignored; CPU_SPECIFIC_SERVICES *FamilySpecificServices; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetSysPmTableStruct (FamilySpecificServices, (CONST VOID **) &Ignored, NumSystemSteps, StdHeader); }
/** * Transitions the executing core to the desired P-state. * * This function implements the AMD_CPU_EARLY_PARAMS.MemInitPState parameter, and is * run by all system cores. * * @param[in] StdHeader Config handle for library and services * @param[in] CpuEarlyParamsPtr Required input parameters for early CPU initialization * */ VOID STATIC GoToMemInitPstateCore ( IN AMD_CONFIG_PARAMS *StdHeader, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, CpuEarlyParamsPtr->MemInitPState, (BOOLEAN) FALSE, StdHeader); }
/** * This function will set the CPU register warm reset bits. * * Note: This function will be called by UEFI BIOS's * The UEFI wrapper code should register this function, to be called back later point * in time, before the wrapper code does warm reset. * * @param[in] StdHeader Config handle for library and services * @param[in] Request Indicate warm reset status * *--------------------------------------------------------------------------------------- **/ VOID SetWarmResetFlag ( IN AMD_CONFIG_PARAMS *StdHeader, IN WARM_RESET_REQUEST *Request ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->SetWarmResetFlag (FamilySpecificServices, StdHeader, Request); }
/** * * WriteFeatures * * Write out least common features set of all CPUs * * @param[in,out] cpuFeatureListPtr - Pointer to CPU Feature List. * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. * */ VOID STATIC WriteFeatures ( IN OUT VOID *cpuFeatureListPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->WriteFeatures (FamilySpecificServices, cpuFeatureListPtr, StdHeader); }
/** * Single socket call to determine if the BIOS is responsible for updating the * northbridge operating frequency and voltage. * * This function simply returns whether or not the executing core needs 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 GetSystemNbCofVidUpdateSingle ( IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN Ignored; PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); return (FamilySpecificServices->IsNbCofInitNeeded (FamilySpecificServices, &PciAddress, &Ignored, StdHeader)); }
/** * IDS Backend Function for Target Pstate * * * @param[in,out] DataPtr The Pointer of AMD_CPU_EARLY_PARAMS. * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS. * @param[in] IdsNvPtr The Pointer of NV Table. * * @retval IDS_SUCCESS Backend function is called successfully. * @retval IDS_UNSUPPORTED No Backend function is found. * **/ IDS_STATUS IdsSubTargetPstate ( IN OUT VOID *DataPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader, IN IDS_NV_ITEM *IdsNvPtr ) { IDS_STATUS tarpst; CPU_SPECIFIC_SERVICES *FamilySpecificServices; IDS_NV_READ_SKIP (tarpst, AGESA_IDS_NV_TARGET_PSTATE, IdsNvPtr) { GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) tarpst, (BOOLEAN) FALSE, StdHeader); }
/** * Performs the next step in the executing core 0's family specific power * management table. * * This function determines if the input step is valid, and invokes the power * management step if appropriate. This must be run by processor core 0s only. * * @param[in] Step Zero based step number * @param[in] StdHeader Config handle for library and services * @param[in] CpuEarlyParamsPtr Required input parameters for early CPU initialization * */ VOID STATIC PerformThisPmStep ( IN VOID *Step, IN AMD_CONFIG_PARAMS *StdHeader, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr ) { UINT8 MyNumberOfSteps; UINT32 ExeResetFlags; SYS_PM_TBL_STEP *FamilyTablePtr; CPU_SPECIFIC_SERVICES *FamilySpecificServices; BOOLEAN ThisIsWarmReset; BOOLEAN NoResetLimit; BOOLEAN NotConflictResetLimit; BOOLEAN WarmResetOnly; BOOLEAN ColdResetOnly; GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->GetSysPmTableStruct (FamilySpecificServices, (CONST VOID **) &FamilyTablePtr, &MyNumberOfSteps, StdHeader); if (*(UINT8 *)Step < MyNumberOfSteps) { if (FamilyTablePtr[*(UINT8 *)Step].FuncPtr != NULL) { ExeResetFlags = FamilyTablePtr[*(UINT8 *)Step].ExeFlags & (PM_EXEFLAGS_COLD_ONLY | PM_EXEFLAGS_WARM_ONLY); ThisIsWarmReset = IsWarmReset (StdHeader); NoResetLimit = (ExeResetFlags == 0) ? TRUE : FALSE; NotConflictResetLimit = (BOOLEAN) (ExeResetFlags != (PM_EXEFLAGS_COLD_ONLY | PM_EXEFLAGS_WARM_ONLY)); WarmResetOnly = (BOOLEAN) ((ExeResetFlags & PM_EXEFLAGS_WARM_ONLY) == PM_EXEFLAGS_WARM_ONLY); ColdResetOnly = (BOOLEAN) ((ExeResetFlags & PM_EXEFLAGS_COLD_ONLY) == PM_EXEFLAGS_COLD_ONLY); IDS_HDT_CONSOLE (CPU_TRACE, " \tIsWarmReset = %d.\n", ThisIsWarmReset); IDS_HDT_CONSOLE (CPU_TRACE, " \tNoResetLimit = %d\n", NoResetLimit); IDS_HDT_CONSOLE (CPU_TRACE, " \tNotConflictResetLimit = %d\n", NotConflictResetLimit); IDS_HDT_CONSOLE (CPU_TRACE, " \tWarmResetOnly = %d\n", WarmResetOnly); IDS_HDT_CONSOLE (CPU_TRACE, " \tColdResetOnly = %d\n", ColdResetOnly); ASSERT (NotConflictResetLimit); if (NoResetLimit || (NotConflictResetLimit && ((WarmResetOnly && ThisIsWarmReset) || (ColdResetOnly && !ThisIsWarmReset)))) { FamilyTablePtr[*(UINT8 *)Step].FuncPtr (FamilySpecificServices, CpuEarlyParamsPtr, StdHeader); } else { IDS_HDT_CONSOLE (CPU_TRACE, " \t\tThis PM init step was skipped!\n"); } } } }
/** * Single socket call to loop through all Nb Pstates, comparing the NB frequencies * to determine the slowest in the system. This routine also returns the NB 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 GetMinNbCofSingle ( IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *MinSysNbFreq, OUT UINT32 *MinP0NbFreq, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **) &FamilySpecificServices, StdHeader); FamilySpecificServices->GetMinMaxNbFrequency (FamilySpecificServices, PlatformConfig, &PciAddress, MinSysNbFreq, MinP0NbFreq, StdHeader); }
/** * Cold reset support routine for F10PmNbCofVidInit. * * This function implements steps 3, 4, & 5 on each core. * * @param[in] NewNbVid NewNbVid determined by core 0 in step 2. * @param[in] StdHeader Config handle for library and services. * */ VOID STATIC PmNbCofVidInitP0P1Core ( IN VOID *NewNbVid, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 MsrAddress; UINT64 MsrRegister; CPU_SPECIFIC_SERVICES *FamilySpecificServices = NULL; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); LibAmdMsrRead (MSR_COFVID_STS, &MsrRegister, StdHeader); MsrAddress = (UINT32) ((((COFVID_STS_MSR *) &MsrRegister)->StartupPstate) + PS_REG_BASE); LibAmdMsrRead (MsrAddress, &MsrRegister, StdHeader); LibAmdMsrWrite ((UINT32) (PS_REG_BASE + 1), &MsrRegister, StdHeader); ((PSTATE_MSR *) &MsrRegister)->NbVid = *(UINT8 *) NewNbVid; LibAmdMsrWrite (PS_REG_BASE, &MsrRegister, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 1, (BOOLEAN) FALSE, StdHeader); }
VOID MemFS3Wait10ns ( IN UINT32 Count, IN OUT MEM_DATA_STRUCT *MemPtr ) { UINT32 TscRate; UINT64 TargetTsc; UINT64 CurrentTsc; CPU_SPECIFIC_SERVICES *FamilySpecificServices; ASSERT (Count <= 1000000); GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &MemPtr->StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRate, &MemPtr->StdHeader); LibAmdMsrRead (TSC, &CurrentTsc, &MemPtr->StdHeader); TargetTsc = CurrentTsc + ((Count * TscRate + 99) / 100); do { LibAmdMsrRead (TSC, &CurrentTsc, &MemPtr->StdHeader); } while (CurrentTsc < TargetTsc); }
/** * Entry point for enabling Power Status Indicator * * This function must be run after all P-State routines have been executed * * @param[in] PsiServices The current CPU's family services. * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config handle for library and services. * * @retval AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC F16MlInitializePsi ( IN PSI_FAMILY_SERVICES *PsiServices, IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; if ((EntryPoint & (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) != 0) { GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); // Configure PsiVid F16MlPmVrmLowPowerModeEnable (FamilySpecificServices, PlatformConfig, PciAddress, StdHeader); } return AGESA_SUCCESS; }
/** *--------------------------------------------------------------------------------------- * * PutCoreInPState0 * * Description: * This function will take the CPU core into P0 * * Parameters: * @param[in] *PStateBuffer * @param[in] *StdHeader * * @retval VOID * *--------------------------------------------------------------------------------------- **/ VOID STATIC PutCoreInPState0 ( IN VOID *PStateBuffer, IN AMD_CONFIG_PARAMS *StdHeader ) { CPU_SPECIFIC_SERVICES *FamilySpecificServices; PSTATE_LEVELING *PStateBufferPtr; PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer; if ((PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_1 ) || (PStateBufferPtr[0].SetPState0 == PSTATE_FLAG_2)) { return; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) 0, (BOOLEAN) FALSE, StdHeader); }
/** * Output Test Point function . * * @param[in,out] StdHeader The Pointer of Standard Header. * * @retval AGESA_SUCCESS Success to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * @retval AGESA_ERROR Fail to get the pointer of IDS_CHECK_POINT_PERF_HANDLE. * **/ AGESA_STATUS IdsPerfAnalyseTimestamp ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; LOCATE_HEAP_PTR LocateHeapStructPtr; UINT32 TscRateInMhz; CPU_SPECIFIC_SERVICES *FamilySpecificServices; PERFREGBACKUP PerfReg; UINT32 CR4reg; UINT64 SMsr; LocateHeapStructPtr.BufferHandle = IDS_CHECK_POINT_PERF_HANDLE; LocateHeapStructPtr.BufferPtr = NULL; status = HeapLocateBuffer (&LocateHeapStructPtr, StdHeader); if (status != AGESA_SUCCESS) { return status; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRateInMhz, StdHeader); ((TP_Perf_STRUCT *) (LocateHeapStructPtr.BufferPtr)) ->TscInMhz = TscRateInMhz; //Init break point IdsPerfSaveReg (&PerfReg, StdHeader); LibAmdMsrRead (0xC001100A, (UINT64 *)&SMsr, StdHeader); SMsr |= 1; LibAmdMsrWrite (0xC001100A, (UINT64 *)&SMsr, StdHeader); LibAmdWriteCpuReg (DR0_REG, 0x8899); LibAmdWriteCpuReg (DR7_REG, 0x00020402); LibAmdReadCpuReg (CR4_REG, &CR4reg); LibAmdWriteCpuReg (CR4_REG, CR4reg | ((UINT32)1 << 3)); IdsPerfHdtOut (1, (UINT32) LocateHeapStructPtr.BufferPtr, StdHeader); IdsPerfRestoreReg (&PerfReg, StdHeader); return status; }
/** * Single socket call to loop through all Nb Pstates, comparing the NB frequencies * to determine the slowest in the system. This routine also returns the NB 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 GetMinNbCofSingle ( IN PLATFORM_CONFIGURATION *PlatformConfig, OUT UINT32 *MinSysNbFreq, OUT UINT32 *MinP0NbFreq, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; AGESA_STATUS AgesaStatus; PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); AgesaStatus = FamilySpecificServices->GetMinMaxNbFrequency (FamilySpecificServices, PlatformConfig, &PciAddress, MinSysNbFreq, MinP0NbFreq, StdHeader); ASSERT (AgesaStatus == AGESA_SUCCESS); ASSERT ((MinSysNbFreq != 0) && (MinP0NbFreq != 0)); }
/** * Determines the base address of the executing core's heap. * * This function uses the executing core's socket/core numbers to determine * where it's heap should be located. * * @param[in] StdHeader Config handle for library and services. * * @return A pointer to the executing core's heap. * */ UINT64 STATIC HeapGetCurrentBase ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 SystemCoreNumber; UINT64 ReturnPtr; UINTN FcnData; AGESA_STATUS IgnoredStatus; AGESA_REBASE_PARAMS HeapRebaseParams; CPU_SPECIFIC_SERVICES *FamilyServices; HeapRebaseParams.HeapAddress = AMD_HEAP_START_ADDRESS; HeapRebaseParams.StdHeader = *StdHeader; FcnData = 0; AgesaHeapRebase (FcnData, &HeapRebaseParams); if (IsBsp (StdHeader, &IgnoredStatus)) { ReturnPtr = HeapRebaseParams.HeapAddress; } else { GetCpuServicesOfCurrentCore (&FamilyServices, StdHeader); ASSERT (FamilyServices != NULL); SystemCoreNumber = FamilyServices->GetApCoreNumber (FamilyServices, StdHeader); ASSERT (SystemCoreNumber != 0); ASSERT (SystemCoreNumber < 64); ReturnPtr = ((SystemCoreNumber * AMD_HEAP_SIZE_PER_CORE) + HeapRebaseParams.HeapAddress); } // Normally, HeapRebaseParams.HeapAddress = AMD_HEAP_START_ADDRESS // But due to SecureS3, HeapAddress would be changed during run-time // So below checking for ReturnPtr needs to be run only if HeapRebaseParams.HeapAddress = AMD_HEAP_START_ADDRESS if (HeapRebaseParams.HeapAddress == AMD_HEAP_START_ADDRESS) { ASSERT (ReturnPtr <= ((AMD_HEAP_REGION_END_ADDRESS + 1) - AMD_HEAP_SIZE_PER_CORE)); } return ReturnPtr; }
/** * Is this boot a warm reset? * * This function reads the CPU register warm reset bit that is preserved after a warm reset. * Which in fact gets set before issuing warm reset. We just use the BSP's register always. * * @param[in] StdHeader Config handle for library and services * * @retval TRUE Warm Reset * @retval FALSE Not Warm Reset * */ BOOLEAN IsWarmReset ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 PostStage; WARM_RESET_REQUEST Request; BOOLEAN WarmReset; CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; switch (StdHeader->Func) { case AMD_INIT_RESET: PostStage = WR_STATE_RESET; break; case AMD_INIT_EARLY: PostStage = WR_STATE_EARLY; break; case AMD_INIT_POST: default: PostStage = WR_STATE_POST; break; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetWarmResetFlag (FamilySpecificServices, StdHeader, &Request); if (Request.StateBits >= PostStage) { WarmReset = TRUE; } else { WarmReset = FALSE; } return WarmReset; }
/** * Warm reset support routine for F10PmNbCofVidInit. * * This function implements steps 8 & 9 on each core. * * @param[in] FunctionData Contains NewNbVid determined by core 0 in step * 2, and NbVidUpdateAll. * @param[in] StdHeader Config handle for library and services. * */ VOID STATIC PmNbCofVidInitWarmCore ( IN VOID *FunctionData, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 MsrAddress; UINT64 MsrRegister; CPU_SPECIFIC_SERVICES *FamilySpecificServices; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); for (MsrAddress = PS_REG_BASE; MsrAddress <= PS_MAX_REG; MsrAddress++) { LibAmdMsrRead (MsrAddress, &MsrRegister, StdHeader); if (((PSTATE_MSR *) &MsrRegister)->PsEnable == 1) { if ((((PSTATE_MSR *) &MsrRegister)->NbDid == 0) || ((NB_COF_VID_INIT_WARM *) FunctionData)->NbVidUpdateAll) { ((PSTATE_MSR *) &MsrRegister)->NbVid = ((NB_COF_VID_INIT_WARM *) FunctionData)->NewNbVid; LibAmdMsrWrite (MsrAddress, &MsrRegister, StdHeader); } } } LibAmdMsrRead (MSR_COFVID_STS, &MsrRegister, StdHeader); FamilySpecificServices->TransitionPstate (FamilySpecificServices, (UINT8) (((COFVID_STS_MSR *) &MsrRegister)->StartupPstate), (BOOLEAN) FALSE, StdHeader); }
/** * Performs the next step in the executing core 0's family specific power * management table. * * This function determines if the input step is valid, and invokes the power * management step if appropriate. This must be run by processor core 0s only. * * @param[in] Step Zero based step number * @param[in] StdHeader Config handle for library and services * @param[in] CpuEarlyParamsPtr Required input parameters for early CPU initialization * */ VOID STATIC PerformThisPmStep ( IN VOID *Step, IN AMD_CONFIG_PARAMS *StdHeader, IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr ) { UINT8 MyNumberOfSteps; SYS_PM_TBL_STEP *FamilyTablePtr; CPU_SPECIFIC_SERVICES *FamilySpecificServices; GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetSysPmTableStruct (FamilySpecificServices, &FamilyTablePtr, &MyNumberOfSteps, StdHeader); if (*(UINT8 *)Step < MyNumberOfSteps) { if (FamilyTablePtr[*(UINT8 *)Step].FuncPtr != NULL) { if (!(BOOLEAN) (FamilyTablePtr[*(UINT8 *)Step].ExeFlags & PM_EXEFLAGS_WARM_ONLY) || IsWarmReset (StdHeader)) { FamilyTablePtr[*(UINT8 *)Step].FuncPtr (FamilySpecificServices, CpuEarlyParamsPtr, StdHeader); } } } }
/** * Entry point for enabling Power Status Indicator * * This function must be run after all P-State routines have been executed * * @param[in] PsiServices The current CPU's family services. * @param[in] EntryPoint Timepoint designator. * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Config handle for library and services. * * @retval AGESA_SUCCESS Always succeeds. * */ AGESA_STATUS STATIC F15CzInitializePsi ( IN PSI_FAMILY_SERVICES *PsiServices, IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilySpecificServices; UINT32 HwPstateMaxVal; F15_CZ_CLK_PWR_TIMING_CTRL2_REGISTER ClkPwrTimingCtrl2; UINT32 CoreVrmLowPowerThreshold; UINT32 Pstate; UINT32 PstateCurrent; UINT32 NextPstateCurrent; PSTATE_MSR PstateMsr; UINT32 CurrentVid; UINT32 PreviousVid; NB_PSTATE_REGISTER NbPstateReg; NB_PSTATE_CTRL_REGISTER NbPsCtrl; UINT32 NbVrmLowPowerThreshold; UINT32 NbPstate; UINT32 NbPstateMaxVal; UINT32 NbPstateCurrent; UINT32 NextNbPstateCurrent; UINT32 PreviousNbVid; UINT32 CurrentNbVid; SMUSVI_MISC_VID_STATUS_REGISTER SmuSviMiscVidStatus; SMUSVI_POWER_CONTROL_MISC_REGISTER SmuSviPowerCtrlMisc; if ((EntryPoint & (CPU_FEAT_AFTER_POST_MTRR_SYNC | CPU_FEAT_AFTER_RESUME_MTRR_SYNC)) != 0) { // Configure PsiVid GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **) &FamilySpecificServices, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " F15CzPmVrmLowPowerModeEnable\n"); if (PlatformConfig->VrmProperties[CoreVrm].LowPowerThreshold != 0) { // Set up PSI0_L for VDD CoreVrmLowPowerThreshold = PlatformConfig->VrmProperties[CoreVrm].LowPowerThreshold; IDS_HDT_CONSOLE (CPU_TRACE, " Core VRM - LowPowerThreshold: %d \n", CoreVrmLowPowerThreshold); PreviousVid = 0xFF; PciAddress.AddressValue = CPTC2_PCI_ADDR; LibAmdPciRead (AccessWidth32, PciAddress, &ClkPwrTimingCtrl2, StdHeader); HwPstateMaxVal = ClkPwrTimingCtrl2.HwPstateMaxVal; IDS_HDT_CONSOLE (CPU_TRACE, " HwPstateMaxVal %d\n", HwPstateMaxVal); for (Pstate = 0; Pstate <= HwPstateMaxVal; Pstate++) { // Check only valid P-state if (FamilySpecificServices->GetProcIddMax (FamilySpecificServices, (UINT8) Pstate, &PstateCurrent, StdHeader) != TRUE) { continue; } LibAmdMsrRead ((UINT32) (Pstate + PS_REG_BASE), (UINT64 *) &PstateMsr, StdHeader); CurrentVid = (UINT32) PstateMsr.CpuVid; if (Pstate == HwPstateMaxVal) { NextPstateCurrent = 0; } else { // Check P-state from P1 to HwPstateMaxVal if (FamilySpecificServices->GetProcIddMax (FamilySpecificServices, (UINT8) (Pstate + 1), &NextPstateCurrent, StdHeader) != TRUE) { continue; } } if ((PstateCurrent <= CoreVrmLowPowerThreshold) && (NextPstateCurrent <= CoreVrmLowPowerThreshold) && (CurrentVid != PreviousVid)) { // Program PsiVid and PsiVidEn if PSI state is found and stop searching. GnbLibPciIndirectRead (MAKE_SBDFO (0, 0, 0, 0, 0xB8), SMUSVI_POWER_CONTROL_MISC, AccessWidth32, &SmuSviPowerCtrlMisc, StdHeader); SmuSviPowerCtrlMisc.PSIVID = CurrentVid; SmuSviPowerCtrlMisc.PSIVIDEN = 1; GnbLibPciIndirectWrite (MAKE_SBDFO (0, 0, 0, 0, 0xB8), SMUSVI_POWER_CONTROL_MISC, AccessWidth32, &SmuSviPowerCtrlMisc, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " PsiVid is enabled at P-state %d. PsiVid: %d\n", Pstate, CurrentVid); break; } else { PreviousVid = CurrentVid; } } } if (PlatformConfig->VrmProperties[NbVrm].LowPowerThreshold != 0) { // Set up NBPSI0_L for VDDNB NbVrmLowPowerThreshold = PlatformConfig->VrmProperties[NbVrm].LowPowerThreshold; IDS_HDT_CONSOLE (CPU_TRACE, " NB VRM - LowPowerThreshold: %d\n", NbVrmLowPowerThreshold); PreviousNbVid = 0xFF; PciAddress.AddressValue = NB_PSTATE_CTRL_PCI_ADDR; LibAmdPciRead (AccessWidth32, PciAddress, &NbPsCtrl, StdHeader); NbPstateMaxVal = NbPsCtrl.NbPstateMaxVal; ASSERT (NbPstateMaxVal < NM_NB_PS_REG); IDS_HDT_CONSOLE (CPU_TRACE, " NbPstateMaxVal %d\n", NbPstateMaxVal); for (NbPstate = 0; NbPstate <= NbPstateMaxVal; NbPstate++) { // Check only valid NB P-state if (FamilySpecificServices->GetNbIddMax (FamilySpecificServices, (UINT8) NbPstate, &NbPstateCurrent, StdHeader) != TRUE) { continue; } PciAddress.Address.Register = (NB_PSTATE_0 + (sizeof (NB_PSTATE_REGISTER) * NbPstate)); LibAmdPciRead (AccessWidth32, PciAddress, &NbPstateReg, StdHeader); CurrentNbVid = (UINT32) GetF15CzNbVid (&NbPstateReg); if (NbPstate == NbPstateMaxVal) { NextNbPstateCurrent = 0; } else { // Check only valid NB P-state if (FamilySpecificServices->GetNbIddMax (FamilySpecificServices, (UINT8) (NbPstate + 1), &NextNbPstateCurrent, StdHeader) != TRUE) { continue; } } if ((NbPstateCurrent <= NbVrmLowPowerThreshold) && (NextNbPstateCurrent <= NbVrmLowPowerThreshold) && (CurrentNbVid != PreviousNbVid)) { // Program NbPsi0Vid and NbPsi0VidEn if PSI state is found and stop searching. GnbLibPciIndirectRead (MAKE_SBDFO (0, 0, 0, 0, 0xB8), SMUSVI_MISC_VID_STATUS, AccessWidth32, &SmuSviMiscVidStatus, StdHeader); SmuSviMiscVidStatus.NB_PSI_VID = CurrentNbVid; SmuSviMiscVidStatus.NB_PSI_VID_EN = 1; GnbLibPciIndirectWrite (MAKE_SBDFO (0, 0, 0, 0, 0xB8), SMUSVI_MISC_VID_STATUS, AccessWidth32, &SmuSviMiscVidStatus, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " NbPsi0Vid is enabled at NB P-state %d. NbPsi0Vid: %d\n", NbPstate, CurrentNbVid); break; } else { PreviousNbVid = CurrentNbVid; } } } } return AGESA_SUCCESS; }
/** * * It will create the ACPI tale of WHEA and return the pointer to the table. * * @param[in, out] StdHeader Standard Head Pointer * @param[in, out] WheaMcePtr Point to Whea Hest Mce table * @param[in, out] WheaCmcPtr Point to Whea Hest Cmc table * * @retval UINT32 AGESA_STATUS */ AGESA_STATUS GetAcpiWheaMain ( IN OUT AMD_CONFIG_PARAMS *StdHeader, IN OUT VOID **WheaMcePtr, IN OUT VOID **WheaCmcPtr ) { UINT8 BankNum; UINT8 Entries; UINT16 HestMceTableSize; UINT16 HestCmcTableSize; UINT64 MsrData; AMD_HEST_MCE_TABLE *HestMceTablePtr; AMD_HEST_CMC_TABLE *HestCmcTablePtr; AMD_HEST_BANK *HestBankPtr; AMD_WHEA_INIT_DATA *WheaInitDataPtr; ALLOCATE_HEAP_PARAMS AllocParams; CPU_SPECIFIC_SERVICES *FamilySpecificServices; FamilySpecificServices = NULL; IDS_HDT_CONSOLE (CPU_TRACE, " WHEA is created\n"); // step 1: calculate Hest table size LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader); BankNum = (UINT8) (((MSR_MCG_CAP_STRUCT *) (&MsrData))->Count); if (BankNum == 0) { return AGESA_ERROR; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetWheaInitData (FamilySpecificServices, &WheaInitDataPtr, &Entries, StdHeader); ASSERT (WheaInitDataPtr->HestBankNum <= BankNum); HestMceTableSize = sizeof (AMD_HEST_MCE_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK); HestCmcTableSize = sizeof (AMD_HEST_CMC_TABLE) + WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK); HestMceTablePtr = (AMD_HEST_MCE_TABLE *) *WheaMcePtr; HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) *WheaCmcPtr; // step 2: allocate a buffer by callback function if ((HestMceTablePtr == NULL) || (HestCmcTablePtr == NULL)) { AllocParams.RequestedBufferSize = (UINT32) (HestMceTableSize + HestCmcTableSize); AllocParams.BufferHandle = AMD_WHEA_BUFFER_HANDLE; AllocParams.Persist = HEAP_SYSTEM_MEM; AGESA_TESTPOINT (TpProcCpuBeforeAllocateWheaBuffer, StdHeader); if (HeapAllocateBuffer (&AllocParams, StdHeader) != AGESA_SUCCESS) { return AGESA_ERROR; } AGESA_TESTPOINT (TpProcCpuAfterAllocateWheaBuffer, StdHeader); HestMceTablePtr = (AMD_HEST_MCE_TABLE *) AllocParams.BufferPtr; HestCmcTablePtr = (AMD_HEST_CMC_TABLE *) ((UINT8 *) (HestMceTablePtr + 1) + (WheaInitDataPtr->HestBankNum * sizeof (AMD_HEST_BANK))); } // step 3: fill in Hest MCE table HestMceTablePtr->TblLength = HestMceTableSize; HestMceTablePtr->GlobCapInitDataLSD = WheaInitDataPtr->GlobCapInitDataLSD; HestMceTablePtr->GlobCapInitDataMSD = WheaInitDataPtr->GlobCapInitDataMSD; HestMceTablePtr->GlobCtrlInitDataLSD = WheaInitDataPtr->GlobCtrlInitDataLSD; HestMceTablePtr->GlobCtrlInitDataMSD = WheaInitDataPtr->GlobCtrlInitDataMSD; HestMceTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum; HestBankPtr = (AMD_HEST_BANK *) (HestMceTablePtr + 1); CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr); // step 4: fill in Hest CMC table HestCmcTablePtr->NumHWBanks = WheaInitDataPtr->HestBankNum; HestCmcTablePtr->TblLength = HestCmcTableSize; HestBankPtr = (AMD_HEST_BANK *) (HestCmcTablePtr + 1); CreateHestBank (HestBankPtr, WheaInitDataPtr->HestBankNum, WheaInitDataPtr); // step 5: fill in the incoming structure *WheaMcePtr = HestMceTablePtr; *WheaCmcPtr = HestCmcTablePtr; return (AGESA_SUCCESS); }
/** * * * This function is the main memory configuration function for DR DDR3 * * Requirements: * * Run-Time Requirements: * 1. Complete Hypertransport Bus Configuration * 2. AmdMemInitDataStructDef must be run to set default values * 3. MSR bit to allow access to high PCI regs set on all nodes * 4. BSP in Big Real Mode * 5. Stack available * 6. MCG_CTL=-1, MC4_EN=0 for all CPUs * 7. MCi_STS from shutdown/warm reset recorded (if desired) prior to entry * 8. All var MTRRs reset to zero * 9. State of NB_CFG.DisDatMsk set properly on all CPUs * * @param[in,out] *MemPtr - Pointer to the MEM_DATA_STRUCT * * @return AGESA_STATUS * - AGESA_ALERT * - AGESA_FATAL * - AGESA_SUCCESS * - AGESA_WARNING */ AGESA_STATUS AmdMemAuto ( IN OUT MEM_DATA_STRUCT *MemPtr ) { MEM_SHARED_DATA mmSharedData; MEM_MAIN_DATA_BLOCK mmData; MEM_NB_BLOCK *NBPtr; MEM_TECH_BLOCK *TechPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; AGESA_STATUS Retval; UINT8 i; UINT8 Die; UINT8 DieCount; UINT8 Tab; CPU_SPECIFIC_SERVICES *FamilySpecificServices; ASSERT (MemPtr != NULL); AGESA_TESTPOINT (TpProcMemAmdMemAuto, &MemPtr->StdHeader); IDS_HDT_CONSOLE (MEM_FLOW, "MEM PARAMS:\n"); IDS_HDT_CONSOLE (MEM_FLOW, "\tBottomIo : %04x\n", MemPtr->ParameterListPtr->BottomIo); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemHoleRemap : %d\n", MemPtr->ParameterListPtr->MemHoleRemapping); IDS_HDT_CONSOLE (MEM_FLOW, "\tLimitBelow1TB : %d\n", MemPtr->ParameterListPtr->LimitMemoryToBelow1Tb); IDS_HDT_CONSOLE (MEM_FLOW, "\tUserTimingMode : %d\n", MemPtr->ParameterListPtr->UserTimingMode); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClockValue : %d\n", MemPtr->ParameterListPtr->MemClockValue); IDS_HDT_CONSOLE (MEM_FLOW, "\tBankIntlv : %d\n", MemPtr->ParameterListPtr->EnableBankIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tNodeIntlv : %d\n", MemPtr->ParameterListPtr->EnableNodeIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tChannelIntlv : %d\n", MemPtr->ParameterListPtr->EnableChannelIntlv); IDS_HDT_CONSOLE (MEM_FLOW, "\tEccFeature : %d\n", MemPtr->ParameterListPtr->EnableEccFeature); IDS_HDT_CONSOLE (MEM_FLOW, "\tPowerDown : %d\n", MemPtr->ParameterListPtr->EnablePowerDown); IDS_HDT_CONSOLE (MEM_FLOW, "\tOnLineSpare : %d\n", MemPtr->ParameterListPtr->EnableOnLineSpareCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tParity : %d\n", MemPtr->ParameterListPtr->EnableParity); IDS_HDT_CONSOLE (MEM_FLOW, "\tBankSwizzle : %d\n", MemPtr->ParameterListPtr->EnableBankSwizzle); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemClr : %d\n", MemPtr->ParameterListPtr->EnableMemClr); IDS_HDT_CONSOLE (MEM_FLOW, "\tUmaMode : %d\n", MemPtr->ParameterListPtr->UmaMode); IDS_HDT_CONSOLE (MEM_FLOW, "\tUmaSize : %d\n", MemPtr->ParameterListPtr->UmaSize); IDS_HDT_CONSOLE (MEM_FLOW, "\tMemRestoreCtl : %d\n", MemPtr->ParameterListPtr->MemRestoreCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tSaveMemContextCtl : %d\n", MemPtr->ParameterListPtr->SaveMemContextCtl); IDS_HDT_CONSOLE (MEM_FLOW, "\tExternalVrefCtl : %d\n", MemPtr->ParameterListPtr->ExternalVrefCtl ); IDS_HDT_CONSOLE (MEM_FLOW, "\tForceTrainMode : %d\n\n", MemPtr->ParameterListPtr->ForceTrainMode ); //---------------------------------------------------------------------------- // Get TSC rate, which will be used later in Wait10ns routine //---------------------------------------------------------------------------- GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, &MemPtr->StdHeader); FamilySpecificServices->GetTscRate (FamilySpecificServices, &MemPtr->TscRate, &MemPtr->StdHeader); //---------------------------------------------------------------------------- // Read In SPD Data //---------------------------------------------------------------------------- AGESA_TESTPOINT (TpProcMemBeforeSpdProcessing, &MemPtr->StdHeader); MemSPDDataProcess (MemPtr); //---------------------------------------------------------------- // Initialize Main Data Block //---------------------------------------------------------------- mmData.MemPtr = MemPtr; mmData.mmSharedPtr = &mmSharedData; LibAmdMemFill (&mmSharedData, 0, sizeof (mmSharedData), &MemPtr->StdHeader); mmSharedData.DimmExcludeFlag = NORMAL; mmSharedData.NodeIntlv.IsValid = FALSE; //---------------------------------------------------------------- // Discover populated CPUs // //---------------------------------------------------------------- Retval = MemSocketScan (&mmData); if (Retval == AGESA_FATAL) { return Retval; } DieCount = mmData.DieCount; //---------------------------------------------------------------- // // Allocate Memory for NB and Tech Blocks // // NBPtr[Die]----+ // | // V // +---+---+---+---+---+---+---+---+ // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | NB Blocks // +---+---+---+---+---+---+---+---+ // | | | | | | | | // | | | | | | | | // v v v v v v v v // +---+---+---+---+---+---+---+---+ // | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | Tech Blocks // +---+---+---+---+---+---+---+---+ // // //---------------------------------------------------------------- AllocHeapParams.RequestedBufferSize = (DieCount * (sizeof (MEM_NB_BLOCK) + sizeof (MEM_TECH_BLOCK))); AllocHeapParams.BufferHandle = AMD_MEM_AUTO_HANDLE; AllocHeapParams.Persist = HEAP_LOCAL_CACHE; if (AGESA_SUCCESS != HeapAllocateBuffer (&AllocHeapParams, &MemPtr->StdHeader)) { ASSERT(FALSE); // NB and Tech Block Heap allocate error return AGESA_FATAL; } NBPtr = (MEM_NB_BLOCK *)AllocHeapParams.BufferPtr; TechPtr = (MEM_TECH_BLOCK *) (&NBPtr[DieCount]); mmData.NBPtr = NBPtr; mmData.TechPtr = TechPtr; //---------------------------------------------------------------- // Create NB Blocks // //---------------------------------------------------------------- for (Die = 0 ; Die < DieCount ; Die++ ) { i = 0; while (memNBInstalled[i].MemConstructNBBlock != 0) { if (memNBInstalled[i].MemConstructNBBlock (&NBPtr[Die], MemPtr, memNBInstalled[i].MemFeatBlock, &mmSharedData, Die) == TRUE) { break; } i++; } // Couldn't find a NB which supported this family if (memNBInstalled[i].MemConstructNBBlock == 0) { return AGESA_FATAL; } } //---------------------------------------------------------------- // Create Technology Blocks // //---------------------------------------------------------------- for (Die = 0 ; Die < DieCount ; Die++ ) { i = 0; while (memTechInstalled[i] != NULL) { if (memTechInstalled[i] (&TechPtr[Die], &NBPtr[Die])) { NBPtr[Die].TechPtr = &TechPtr[Die]; break; } i++; } // Couldn't find a Tech block which supported this family if (memTechInstalled[i] == NULL) { return AGESA_FATAL; } } //---------------------------------------------------------------- // // MEMORY INITIALIZATION TASKS // //---------------------------------------------------------------- i = 0; while (memFlowControlInstalled[i] != NULL) { Retval = memFlowControlInstalled[i] (&mmData); if (MemPtr->IsFlowControlSupported == TRUE) { break; } i++; } //---------------------------------------------------------------- // Deallocate NB register tables //---------------------------------------------------------------- for (Tab = 0; Tab < NumberOfNbRegTables; Tab++) { HeapDeallocateBuffer (GENERATE_MEM_HANDLE (ALLOC_NB_REG_TABLE, Tab, 0, 0), &MemPtr->StdHeader); } //---------------------------------------------------------------- // Check for errors and return //---------------------------------------------------------------- AGESA_TESTPOINT (TpProcMemEnd, &MemPtr->StdHeader); for (Die = 0; Die < DieCount; Die++) { if (NBPtr[Die].MCTPtr->ErrCode > Retval) { Retval = NBPtr[Die].MCTPtr->ErrCode; } } return Retval; }
/** * 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); }
/** * This function initializes the heap for each CPU core. * * Check for already initialized. If not, determine offset of local heap in CAS and * setup initial heap markers and bookkeeping status. Also create an initial event log. * * @param[in] StdHeader Handle of Header for calling lib functions and services. * * @retval AGESA_SUCCESS This core's heap is initialized * @retval AGESA_FATAL This core's heap cannot be initialized due to any reasons below: * - current processor family cannot be identified. * */ AGESA_STATUS HeapManagerInit ( IN AMD_CONFIG_PARAMS *StdHeader ) { // First Time Initialization // Note: First 16 bytes of buffer is reserved for Heap Manager use UINT16 HeapAlreadyInitSizeDword; UINT32 HeapAlreadyRead; UINT8 L2LineSize; UINT8 *HeapBufferPtr; UINT8 *HeapInitPtr; UINT32 *HeapDataPtr; UINT64 MsrData; UINT64 MsrMask; UINT8 Ignored; CPUID_DATA CpuId; BUFFER_NODE *FreeSpaceNode; CACHE_INFO *CacheInfoPtr; CPU_SPECIFIC_SERVICES *FamilySpecificServices; CPU_LOGICAL_ID CpuFamilyRevision; // Check whether this is a known processor family. GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader); if ((CpuFamilyRevision.Family == 0) && (CpuFamilyRevision.Revision == 0)) { IDS_ERROR_TRAP; return AGESA_FATAL; } GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader); FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader); HeapBufferPtr = (UINT8 *) StdHeader->HeapBasePtr; // Check whether the heap manager is already initialized LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrData, StdHeader); if (!IsSecureS3 (StdHeader)) { if (MsrData == (CacheInfoPtr->VariableMtrrMask & AMD_HEAP_MTRR_MASK)) { LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader); if ((MsrData & CacheInfoPtr->HeapBaseMask) == ((UINT64) (UINTN) HeapBufferPtr & CacheInfoPtr->HeapBaseMask)) { if (((HEAP_MANAGER *) HeapBufferPtr)->Signature == HEAP_SIGNATURE_VALID) { // This is not a bug, there are multiple premem basic entry points, // and each will call heap init to make sure create struct will succeed. // If that is later deemed a problem, there needs to be a reasonable test // for the calling code to make to determine if it needs to init heap or not. // In the mean time, add this to the event log PutEventLog (AGESA_SUCCESS, CPU_ERROR_HEAP_IS_ALREADY_INITIALIZED, 0, 0, 0, 0, StdHeader); return AGESA_SUCCESS; } } } // Set variable MTRR base and mask MsrData = ((UINT64) (UINTN) HeapBufferPtr & CacheInfoPtr->HeapBaseMask); MsrMask = CacheInfoPtr->VariableMtrrHeapMask & AMD_HEAP_MTRR_MASK; MsrData |= 0x06; LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_BASE, &MsrData, StdHeader); LibAmdMsrWrite (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrMask, StdHeader); // Set top of memory to a temp value LibAmdMsrRead (TOP_MEM, &MsrData, StdHeader); if (AMD_TEMP_TOM > MsrData) { MsrData = (UINT64) (AMD_TEMP_TOM); LibAmdMsrWrite (TOP_MEM, &MsrData, StdHeader); } } // Enable variable MTTRs LibAmdMsrRead (SYS_CFG, &MsrData, StdHeader); MsrData |= AMD_VAR_MTRR_ENABLE_BIT; LibAmdMsrWrite (SYS_CFG, &MsrData, StdHeader); // Initialize Heap Space // BIOS may store to a line only after it has been allocated by a load LibAmdCpuidRead (AMD_CPUID_L2L3Cache_L2TLB, &CpuId, StdHeader); L2LineSize = (UINT8) (CpuId.ECX_Reg); HeapInitPtr = HeapBufferPtr ; for (HeapAlreadyRead = 0; HeapAlreadyRead < AMD_HEAP_SIZE_PER_CORE; (HeapAlreadyRead = HeapAlreadyRead + L2LineSize)) { Ignored = *HeapInitPtr; HeapInitPtr += L2LineSize; } HeapDataPtr = (UINT32 *) HeapBufferPtr; for (HeapAlreadyInitSizeDword = 0; HeapAlreadyInitSizeDword < AMD_HEAP_SIZE_DWORD_PER_CORE; HeapAlreadyInitSizeDword++) { *HeapDataPtr = 0; HeapDataPtr++; } // Note: We are reserving the first 16 bytes for Heap Manager use // UsedSize indicates the size of heap spaced is used for HEAP_MANAGER, BUFFER_NODE, // Pad for 16-byte alignment, buffer data, and IDS SENTINEL. // FirstActiveBufferOffset is initalized as invalid heap offset, AMD_HEAP_INVALID_HEAP_OFFSET. // FirstFreeSpaceOffset is initalized as the byte right after HEAP_MANAGER header. // Then we set Signature of HEAP_MANAGER header as valid, HEAP_SIGNATURE_VALID. ((HEAP_MANAGER*) HeapBufferPtr)->UsedSize = sizeof (HEAP_MANAGER); ((HEAP_MANAGER*) HeapBufferPtr)->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET; ((HEAP_MANAGER*) HeapBufferPtr)->FirstFreeSpaceOffset = sizeof (HEAP_MANAGER); ((HEAP_MANAGER*) HeapBufferPtr)->Signature = HEAP_SIGNATURE_VALID; // Create free space link FreeSpaceNode = (BUFFER_NODE *) (HeapBufferPtr + sizeof (HEAP_MANAGER)); FreeSpaceNode->BufferSize = AMD_HEAP_SIZE_PER_CORE - sizeof (HEAP_MANAGER) - sizeof (BUFFER_NODE); FreeSpaceNode->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; StdHeader->HeapStatus = HEAP_LOCAL_CACHE; EventLogInitialization (StdHeader); return AGESA_SUCCESS; }
/** * Returns the family specific properties of the cache, and its usage. * * @CpuServiceMethod{::F_CPU_GET_FAMILY_SPECIFIC_ARRAY}. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[out] CacheInfoPtr Points to the cache info properties on exit. * @param[out] NumberOfElements Will be one to indicate one entry. * @param[in] StdHeader Header for library and services. * */ VOID GetF15CacheInfo ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, OUT CONST VOID **CacheInfoPtr, OUT UINT8 *NumberOfElements, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Enabled; UINT32 DualCore; UINT32 Node; PCI_ADDR PciAddress; CPU_SPECIFIC_SERVICES *FamilyServices; AP_MAILBOXES ApMailboxes; CORE_PAIR_MAP *CorePairMap; AGESA_STATUS IgnoredStatus; if (!IsBsp (StdHeader, &IgnoredStatus)) { GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader); ASSERT (FamilyServices != NULL); FamilyServices->GetApMailboxFromHardware (FamilyServices, &ApMailboxes, StdHeader); Node = ApMailboxes.ApMailInfo.Fields.Node; // Since pre-heap, get compute unit status from hardware, using mailbox info. PciAddress.AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0); PciAddress.Address.Device = PciAddress.Address.Device + Node; PciAddress.Address.Function = FUNC_5; PciAddress.Address.Register = COMPUTE_UNIT_STATUS; LibAmdPciReadBits (PciAddress, 3, 0, &Enabled, StdHeader); LibAmdPciReadBits (PciAddress, 19, 16, &DualCore, StdHeader); // Find the core to compute unit mapping for this node. CorePairMap = FamilyServices->CorePairMap; if ((Enabled != 0) && (CorePairMap != NULL)) { while (CorePairMap->Enabled != 0xFF) { if ((Enabled == CorePairMap->Enabled) && (DualCore == CorePairMap->DualCore)) { break; } CorePairMap++; } // The assert is for finding a processor configured in a way the core pair map doesn't support. ASSERT (CorePairMap->Enabled != 0xFF); switch (CorePairMap->Mapping) { case AllCoresMapping: // No cores are sharing a compute unit *CacheInfoPtr = &CpuF15CacheInfo; break; case EvenCoresMapping: // Cores are paired into compute units *CacheInfoPtr = &CpuF15CacheInfoCP; break; default: ASSERT (FALSE); } } } else { // the BSC is always just the first slice, we could return either one. Return the non for safest. *CacheInfoPtr = &CpuF15CacheInfo; } *NumberOfElements = 1; }