/** * Multisocket BSC call to start all system core 0s to perform a standard AP_TASK. * * This function loops through all possible socket locations, starting core 0 of * each populated socket to perform the passed in AP_TASK. After starting all * other core 0s, the BSC will perform the AP_TASK as well. This must be run by * the system BSC only. * * @param[in] TaskPtr Function descriptor * @param[in] StdHeader Config handle for library and services * @param[in] ConfigParams AMD entry point's CPU parameter structure * */ VOID RunCodeOnAllSystemCore0sMulti ( IN AP_TASK *TaskPtr, IN AMD_CONFIG_PARAMS *StdHeader, IN VOID *ConfigParams ) { UINT32 BscSocket; UINT32 BscModule; UINT32 BscCoreNum; UINT8 Socket; UINT32 NumberOfSockets; AGESA_STATUS DummyStatus; ASSERT (IsBsp (StdHeader, &DummyStatus)); NumberOfSockets = GetPlatformNumberOfSockets (); IdentifyCore (StdHeader, &BscSocket, &BscModule, &BscCoreNum, &DummyStatus); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (Socket != BscSocket) { if (IsProcessorPresent (Socket, StdHeader)) { ApUtilRunCodeOnSocketCore (Socket, 0, TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (TaskPtr, StdHeader, ConfigParams); }
/** * 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); } } } }
/** * * FeatureLeveling * * CPU feature leveling. Set least common features set of all CPUs * * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. * */ VOID FeatureLeveling ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; UINT32 Socket; UINT32 Core; UINT32 NumberOfSockets; UINT32 NumberOfCores; BOOLEAN *FirstTime; BOOLEAN *NeedLeveling; AGESA_STATUS IgnoredSts; CPU_FEATURES_LIST *globalCpuFeatureList; AP_TASK TaskPtr; ASSERT (IsBsp (StdHeader, &IgnoredSts)); GetGlobalCpuFeatureListAddress ((UINT64 **) &globalCpuFeatureList, StdHeader); FirstTime = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST)); NeedLeveling = (BOOLEAN *) ((UINT8 *) globalCpuFeatureList + sizeof (CPU_FEATURES_LIST) + sizeof (BOOLEAN)); *FirstTime = TRUE; *NeedLeveling = FALSE; LibAmdMemFill (globalCpuFeatureList, 0xFF, sizeof (CPU_FEATURES_LIST), StdHeader); IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); TaskPtr.FuncAddress.PfApTaskI = SaveFeatures; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (CPU_FEATURES_LIST); TaskPtr.ExeFlags = WAIT_FOR_CORE; TaskPtr.DataTransfer.DataPtr = globalCpuFeatureList; TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { if (Socket != BscSocket) { ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader); } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL); if (*NeedLeveling) { TaskPtr.FuncAddress.PfApTaskI = WriteFeatures; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != BscSocket) || (Core != BscCoreNum)) { ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, &TaskPtr, StdHeader); } } } } ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL); } }
/** * 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; }
/** * * HeapGetBaseAddressInTempMem * * This function gets heap base address in HEAP_TEMP_MEM phase * * @param[in] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. * * @retval UINT64 - Heap base address in HEAP_TEMP_MEM phase * */ UINT64 HeapGetBaseAddressInTempMem ( IN AMD_CONFIG_PARAMS *StdHeader ) { EFI_PEI_SERVICES **PeiServices; EFI_PEI_HOB_POINTERS Hob; AGESA_STATUS IgnoredStatus; UINT64 BaseAddress; BaseAddress = UserOptions.CfgHeapDramAddress; if (IsBsp (StdHeader, &IgnoredStatus) && (StdHeader->HeapStatus != HEAP_LOCAL_CACHE)) { PeiServices = (EFI_PEI_SERVICES **) StdHeader->ImageBasePtr; // // Retrieve the new Heap Manager base in HOB and update StdHeader // (*PeiServices)->GetHobList (PeiServices, &Hob.Raw); while (!END_OF_HOB_LIST (Hob)) { if (Hob.Header->HobType == EFI_HOB_TYPE_GUID_EXTENSION && CompareGuid ( &Hob.Guid->Name, &gAmdHeapHobGuid)) { BaseAddress = (UINT64) (VOID *) (Hob.Raw + sizeof (EFI_HOB_GENERIC_HEADER) + sizeof (EFI_GUID)); break; } Hob.Raw = GET_NEXT_HOB (Hob); } } return BaseAddress; }
/** * Dispatches all features needing to perform some initialization at * this time point. * * This routine searches the feature table for features needing to * run at this time point, and invokes them. * * @param[in] EntryPoint Timepoint designator * @param[in] PlatformConfig Contains the runtime modifiable feature input data. * @param[in] StdHeader Standard AMD configuration parameters. * * @return The most severe status of any called service. */ AGESA_STATUS DispatchCpuFeatures ( IN UINT64 EntryPoint, IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { UINTN i; AGESA_STATUS AgesaStatus; AGESA_STATUS CalledStatus; AGESA_STATUS IgnoredStatus; AgesaStatus = AGESA_SUCCESS; if (IsBsp (StdHeader, &IgnoredStatus)) { for (i = 0; SupportedCpuFeatureList[i] != NULL; i++) { if ((SupportedCpuFeatureList[i]->EntryPoint & EntryPoint) != 0) { if (SupportedCpuFeatureList[i]->IsEnabled (PlatformConfig, StdHeader)) { CalledStatus = SupportedCpuFeatureList[i]->InitializeFeature (EntryPoint, PlatformConfig, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } } } } } return AgesaStatus; }
/** * * This function checks the status of BIST and places the error status in the event log * if there are any errors * * @param[in] StdHeader Header for library and services * * @retval AGESA_SUCCESS No BIST errors have been logged. * @retval AGESA_ALERT BIST errors have been detected and added to the * event log. */ AGESA_STATUS CheckBistStatus ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 Socket; UINT32 Core; UINT32 BscSocket; UINT32 BscCoreNum; UINT32 NumberOfSockets; UINT32 NumberOfCores; UINT32 Ignored; UINT32 ReturnCode; AGESA_STATUS IgnoredSts; AGESA_STATUS AgesaStatus; AP_TASK TaskPtr; // Make sure that Standard Header is valid ASSERT (StdHeader != NULL); ASSERT (IsBsp (StdHeader, &IgnoredSts)); AgesaStatus = AGESA_SUCCESS; // Get the BscSocket, BscCoreNum and NumberOfSockets in the system IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); // Setup TaskPtr struct to execute routine on APs TaskPtr.FuncAddress.PfApTaskO = GetBistResults; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.ExeFlags = TASK_HAS_OUTPUT | WAIT_FOR_CORE; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != BscSocket) || (Core != BscCoreNum)) { ReturnCode = ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, &TaskPtr, StdHeader); } else { ReturnCode = TaskPtr.FuncAddress.PfApTaskO (StdHeader); } // If BIST value is non-zero, add to BSP's event log if (ReturnCode != 0) { IDS_HDT_CONSOLE (CPU_TRACE, " BIST failure: socket %d core %d, status = 0x%x\n", Socket, Core, ReturnCode); AgesaStatus = AGESA_ALERT; PutEventLog (AGESA_ALERT, CPU_EVENT_BIST_ERROR, ReturnCode, Socket, Core, 0, StdHeader); } } } } return AgesaStatus; }
/** * * 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; }
/** * Init GNB at Early before CPU * * * * @param[in,out] EarlyParamsPtr Pointer to early configuration params. * @retval Initialization status. */ AGESA_STATUS GnbInitAtEarlier ( IN OUT AMD_EARLY_PARAMS *EarlyParamsPtr ) { AGESA_STATUS Status; // Only run code on BSP if (IsBsp (&EarlyParamsPtr->StdHeader, &Status)) { Status = GnbLibDispatchFeatures (&GnbEarlierFeatureTable[0], &EarlyParamsPtr->StdHeader); } return Status; }
/** * * Exit function for HDT out Function of S3 Resume * * Restore debug register and Deallocate heap, and will also fire a HDTOUT * Command to let hdtout script do corresponding things. * * @param[in,out] StdHeader The Pointer of AGESA Header * **/ VOID AmdIdsHdtOutS3Exit ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS AgesaStatus; if (AmdIdsHdtOutSupport ()) { //Ap debug print exit have been done at the end of AmdInitResume, so we only BSP at here AmdIdsHdtOutExitCoreTask (NULL, StdHeader); if (IsBsp (StdHeader, &AgesaStatus)) { HeapDeallocateBuffer (IDS_HDT_OUT_BUFFER_HANDLE, StdHeader); } } }
/** * Ids code for parse IDS feat table. * * Feat table in IDS is used to decribe the IDS support feat and its according family,handler. * * @param[in] PIdsFeatTbl point to Ids Feat table * @param[in] IdsOption IDS indicator value, see @ref AGESA_IDS_OPTION * @param[in,out] DataPtr Data pointer. * @param[in] IdsNvPtr Ids Nvram pointer. * @param[in,out] StdHeader The Pointer of AMD_CONFIG_PARAMS. * * @retval IDS_SUCCESS Backend function is called successfully. * @retval IDS_UNSUPPORTED No Backend function is found. **/ IDS_STATUS IdsParseFeatTbl ( IN AGESA_IDS_OPTION IdsOption, IN CONST IDS_FEAT_STRUCT * PIdsFeatTbl[], IN OUT VOID *DataPtr, IN IDS_NV_ITEM *IdsNvPtr, IN OUT AMD_CONFIG_PARAMS *StdHeader ) { UINT16 i; AGESA_STATUS Tmpsts; CPU_LOGICAL_ID CpuLogicalId; BOOLEAN No_Check_Bsp; CONST IDS_FEAT_STRUCT *PIdsFeat; IDS_STATUS ReturnFlag; IDS_STATUS status; status = IDS_SUCCESS; ReturnFlag = IDS_SUCCESS; for (i = 0; PIdsFeatTbl[i] != NULL; i++) { PIdsFeat = PIdsFeatTbl[i]; //Does specified IdsOption reached if (PIdsFeat->IdsOption == IdsOption) { //check if bsp only if (PIdsFeat->IsBsp) { No_Check_Bsp = 0; } else { No_Check_Bsp = 1; } if (No_Check_Bsp || IsBsp (StdHeader, &Tmpsts)) { //Does Family Match required GetLogicalIdOfCurrentCore (&CpuLogicalId, StdHeader); if ((CpuLogicalId.Family) & (PIdsFeat->CpuFamily)) { //Excute the code for specific Ids Feat status = PIdsFeat->pf_idsoption (DataPtr, StdHeader, IdsNvPtr); if (status != IDS_SUCCESS) { ReturnFlag = status; } } } } } return ReturnFlag; }
/** * * Run code on every AP in the system. * * @param[in] ApParams AP task pointer. * @param[in] StdHeader Handle to config for library and services * * @return The most severe AGESA_STATUS returned by an AP. * */ AGESA_STATUS RunLateApTaskOnAllAPs ( IN AP_EXE_PARAMS *ApParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 NumberOfSockets; UINT32 NumberOfCores; UINT8 Socket; UINT8 Core; UINT8 ApicId; UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; AGESA_STATUS CalledStatus; AGESA_STATUS IgnoredStatus; AGESA_STATUS AgesaStatus; ASSERT (IsBsp (StdHeader, &IgnoredStatus)); AgesaStatus = AGESA_SUCCESS; IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredStatus); NumberOfSockets = GetPlatformNumberOfSockets (); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) { for (Core = 0; Core < NumberOfCores; Core++) { if ((Socket != BscSocket) || (Core != BscCoreNum)) { GetApicId (StdHeader, Socket, Core, &ApicId, &IgnoredStatus); AGESA_TESTPOINT (TpIfBeforeRunApFromAllAps, StdHeader); CalledStatus = AgesaRunFcnOnAp ((UINTN) ApicId, ApParams); AGESA_TESTPOINT (TpIfAfterRunApFromAllAps, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } } } } } return AgesaStatus; }
/** * Single socket call to determine the most severe AGESA_STATUS return value after * processing the power management initialization tables. * * This function searches the event log for the most severe error and returns * the status code. This function must be called by the BSC only. * * @param[in] StdHeader Config handle for library and services * * @return The most severe error code from power management init * */ AGESA_STATUS GetEarlyPmErrorsSingle ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT16 i; AGESA_EVENT EventLogEntry; AGESA_STATUS ReturnCode; ASSERT (IsBsp (StdHeader, &ReturnCode)); ReturnCode = AGESA_SUCCESS; for (i = 0; PeekEventLog (&EventLogEntry, i, StdHeader); i++) { if ((EventLogEntry.EventInfo & CPU_EVENT_PM_EVENT_MASK) == CPU_EVENT_PM_EVENT_CLASS) { if (EventLogEntry.EventClass > ReturnCode) { ReturnCode = EventLogEntry.EventClass; } } } return (ReturnCode); }
/** * * Run code on core 0 of every socket in the system. * * @param[in] ApParams AP task pointer. * @param[in] StdHeader Handle to config for library and services * * @return The most severe AGESA_STATUS returned by an AP. * */ AGESA_STATUS RunLateApTaskOnAllCore0s ( IN AP_EXE_PARAMS *ApParams, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 NumberOfSockets; UINT8 Socket; UINT8 ApicId; UINT32 BscSocket; UINT32 IgnoredModule; UINT32 IgnoredCore; AGESA_STATUS CalledStatus; AGESA_STATUS IgnoredStatus; AGESA_STATUS AgesaStatus; ASSERT (IsBsp (StdHeader, &IgnoredStatus)); AgesaStatus = AGESA_SUCCESS; IdentifyCore (StdHeader, &BscSocket, &IgnoredModule, &IgnoredCore, &IgnoredStatus); NumberOfSockets = GetPlatformNumberOfSockets (); for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (IsProcessorPresent (Socket, StdHeader)) { if (Socket != BscSocket) { GetApicId (StdHeader, Socket, 0, &ApicId, &IgnoredStatus); AGESA_TESTPOINT (TpIfBeforeRunApFromAllCore0s, StdHeader); CalledStatus = AgesaRunFcnOnAp ((UINTN) ApicId, ApParams); AGESA_TESTPOINT (TpIfAfterRunApFromAllCore0s, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } } } } return AgesaStatus; }
/** Break the other processor by send IPI. @param[in] CurrentProcessorIndex Current processor index value. **/ VOID HaltOtherProcessors ( IN UINT32 CurrentProcessorIndex ) { DebugAgentMsgPrint (DEBUG_AGENT_INFO, "processor[%x]:Try to halt other processors.\n", CurrentProcessorIndex); if (!IsBsp (CurrentProcessorIndex)) { SetIpiSentByApFlag (TRUE);; } mDebugMpContext.BreakAtCpuIndex = CurrentProcessorIndex; // // Set the debug viewpoint to the current breaking CPU. // SetDebugViewPoint (CurrentProcessorIndex); // // Send fixed IPI to other processors. // SendFixedIpiAllExcludingSelf (DEBUG_TIMER_VECTOR); }
/** * 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; }
/** * * CopyHeapToTempRamAtPost * * This function copies BSP heap content to RAM * * @param[in,out] StdHeader - Pointer to AMD_CONFIG_PARAMS struct. * * @retval AGESA_STATUS * */ AGESA_STATUS CopyHeapToTempRamAtPost ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { EFI_PEI_SERVICES **PeiServices; EFI_STATUS Status; UINT32 SizeOfHeapNode; UINT32 HeapBaseInCache; UINT8 *HeapBaseInTempMem; UINT8 *Source; UINT8 *Destination; UINT8 AlignTo16ByteInCache; UINT32 SizeOfNodeData; UINT32 TotalSize; UINT32 HeapInCacheOffset; HEAP_MANAGER *HeapManagerInCache; BUFFER_NODE *HeapInCache; HEAP_MANAGER *HeapManagerInTempMem; BUFFER_NODE *HeapInTempMem; BUFFER_NODE *EndNodeInTempMem; // // Only BSP is expected to run this routine // if (IsBsp (StdHeader)) { if (StdHeader->HeapStatus != HEAP_LOCAL_CACHE) { // // System memory range is out of PEI, we don't have to copy any thing into HOB. // return AGESA_UNSUPPORTED; } PeiServices = (EFI_PEI_SERVICES **) StdHeader->ImageBasePtr; Status = EFI_SUCCESS; HeapInCache = NULL; HeapManagerInCache = NULL; SizeOfHeapNode = 0; TotalSize = sizeof (HEAP_MANAGER); SizeOfNodeData = 0; // Heap in cache variables HeapBaseInCache = (UINT32) StdHeader->HeapBasePtr; HeapManagerInCache = (HEAP_MANAGER *) HeapBaseInCache; HeapInCacheOffset = HeapManagerInCache->FirstActiveBufferOffset; HeapInCache = (BUFFER_NODE*) (HeapBaseInCache + HeapInCacheOffset); // Heap in temp buffer variables HeapBaseInTempMem = (UINT8 *) GLOBAL_CPU_UEFI_HOB_LIST_TEMP_ADDR; HeapManagerInTempMem = (HEAP_MANAGER *) HeapBaseInTempMem; HeapInTempMem = (BUFFER_NODE *) (HeapBaseInTempMem + TotalSize); EndNodeInTempMem = HeapInTempMem; // // Calculate the whole size of heap that need to transferred. // while (HeapInCacheOffset != AMD_HEAP_INVALID_HEAP_OFFSET) { // // Copy nodes that will persist in system memory // if (HeapInCache->Persist > HEAP_LOCAL_CACHE) { AlignTo16ByteInCache = HeapInCache->PadSize; SizeOfNodeData = HeapInCache->BufferSize - AlignTo16ByteInCache; SizeOfHeapNode = SizeOfNodeData + sizeof (BUFFER_NODE); TotalSize += SizeOfHeapNode; // // Copy heap in cache with 16-byte alignment to temp buffer compactly. // Source = (UINT8 *) HeapInCache + sizeof (BUFFER_NODE) + AlignTo16ByteInCache; Destination = (UINT8 *) HeapInTempMem + sizeof (BUFFER_NODE); LibAmdMemCopy (HeapInTempMem, HeapInCache, sizeof (BUFFER_NODE), StdHeader); LibAmdMemCopy (Destination, Source, SizeOfNodeData, StdHeader); // // Fix buffer size in temp memory which has no 16-byte alignment. // Next node offset is the total size used. // HeapInTempMem->BufferSize = SizeOfNodeData; HeapInTempMem->OffsetOfNextNode = TotalSize; HeapInTempMem->PadSize = 0; EndNodeInTempMem = HeapInTempMem; HeapInTempMem = (BUFFER_NODE *) (HeapBaseInTempMem + TotalSize); } // // Point to the next buffer node // HeapInCacheOffset = HeapInCache->OffsetOfNextNode; HeapInCache = (BUFFER_NODE *) (HeapBaseInCache + HeapInCacheOffset); } // // Finalize new heap manager in temp memory // No free space node is reserved for temp memory. // HeapManagerInTempMem->FirstFreeSpaceOffset = AMD_HEAP_INVALID_HEAP_OFFSET; if (TotalSize == sizeof (HEAP_MANAGER)) { HeapManagerInTempMem->UsedSize = sizeof (HEAP_MANAGER); HeapManagerInTempMem->FirstActiveBufferOffset = AMD_HEAP_INVALID_HEAP_OFFSET; } else { HeapManagerInTempMem->UsedSize = TotalSize; HeapManagerInTempMem->FirstActiveBufferOffset = sizeof (HEAP_MANAGER); // // Last Node has no next node. // EndNodeInTempMem->OffsetOfNextNode = AMD_HEAP_INVALID_HEAP_OFFSET; } HeapManagerInCache->Signature = HEAP_SIGNATURE_INVALID; HeapManagerInTempMem->Signature = HEAP_SIGNATURE_VALID; // // Start to copy data into UEFI HOB. // Status = PeiBuildHobGuidData (PeiServices, &gAmdHeapHobGuid, HeapBaseInTempMem, (UINTN) TotalSize); if (EFI_ERROR (Status)) { return AGESA_ERROR; } // // Update StdHeader with new heap status and base address // StdHeader->HeapStatus = HEAP_TEMP_MEM; StdHeader->HeapBasePtr = HeapGetBaseAddressInTempMem (StdHeader); } return AGESA_SUCCESS; }
/** * 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. Initialize a couple heap items * all cores need, for convenience. Currently these are caching the AP mailbox info and * 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; AGESA_STATUS IgnoredSts; 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 ((CONST CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader); FamilySpecificServices->GetCacheInfo (FamilySpecificServices, (CONST VOID **) &CacheInfoPtr, &Ignored, StdHeader); HeapBufferPtr = (UINT8 *)(UINTN) StdHeader->HeapBasePtr; // Check whether the heap manager is already initialized LibAmdMsrRead (AMD_MTRR_VARIABLE_HEAP_MASK, &MsrData, 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 MsrData = (UINT64) (AMD_TEMP_TOM); LibAmdMsrWrite (TOP_MEM, &MsrData, StdHeader); // Enable variable MTRRs 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; if (!IsBsp (StdHeader, &IgnoredSts)) { // The BSP's hardware mailbox has not been initialized, so only APs // can do this at this point. CacheApMailbox (StdHeader); } EventLogInitialization (StdHeader); return AGESA_SUCCESS; }
/** * 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); }
/** * * Initial function for HDT out Function. * * Init required Debug register & heap, and will also fire a HDTOUT * Command to let hdtout script do corresponding things. * * @param[in,out] StdHeader The Pointer of AGESA Header * **/ VOID AmdIdsHdtOutInit ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { ALLOCATE_HEAP_PARAMS AllocHeapParams; HDTOUT_HEADER HdtoutHeader; UINT8 Persist; AGESA_STATUS IgnoreSts; HDTOUT_HEADER *pHdtoutHeader; IDS_FUNCLIST_EXTERN (); if (AmdIdsHdtOutSupport ()) { AmdIdsHdtOutRegisterInit (StdHeader); // Initialize HDTOUT Header HdtoutHeader.Signature = HDTOUT_HEADER_SIGNATURE; HdtoutHeader.Version = HDTOUT_VERSION; HdtoutHeader.BufferSize = HDTOUT_DEFAULT_BUFFER_SIZE; HdtoutHeader.DataIndex = 0; HdtoutHeader.PrintCtrl = HDTOUT_PRINTCTRL_ON; HdtoutHeader.NumBreakpointUnit = 0; HdtoutHeader.FuncListAddr = (UINTN)IDS_FUNCLIST_ADDR; HdtoutHeader.StatusStr[0] = 0; HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON; HdtoutHeader.EnableMask = 0; HdtoutHeader.ConsoleFilter = IDS_DEBUG_PRINT_MASK; // Trigger HDTOUT breakpoint to get inputs from script IdsOutPort (HDTOUT_INIT, (UINTN) &HdtoutHeader, 0); // Disable AP HDTOUT if set BspOnlyFlag if (HdtoutHeader.BspOnlyFlag == HDTOUT_BSP_ONLY) { if (!IsBsp (StdHeader, &IgnoreSts)) { AmdIdsHdtOutRegisterRestore (StdHeader); return; } } // Convert legacy EnableMask to new ConsoleFilter HdtoutHeader.ConsoleFilter |= HdtoutHeader.EnableMask; // Disable the buffer if the size is not large enough if (HdtoutHeader.BufferSize < 128) { HdtoutHeader.BufferSize = 0; HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_OFF; } else { HdtoutHeader.OutBufferMode = HDTOUT_BUFFER_MODE_ON; } // Check if Hdtout header have been initialed, if so it must 2nd time come here if (AmdIdsHdtoutGetHeader (&pHdtoutHeader, StdHeader)) { Persist = HEAP_SYSTEM_MEM; } else { Persist = HEAP_LOCAL_CACHE; } // Allocate heap do { AllocHeapParams.RequestedBufferSize = HdtoutHeader.BufferSize + sizeof (HdtoutHeader) - 2; AllocHeapParams.BufferHandle = IDS_HDT_OUT_BUFFER_HANDLE; AllocHeapParams.Persist = Persist; if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) { break; } else { IdsOutPort (HDTOUT_ERROR, HDTOUT_ERROR_HEAP_ALLOCATION, AllocHeapParams.RequestedBufferSize); HdtoutHeader.BufferSize -= 256; } } while ((HdtoutHeader.BufferSize & 0x8000) == 0); // If the buffer have been successfully allocated? if ((HdtoutHeader.BufferSize & 0x8000) == 0) { LibAmdWriteCpuReg (DR3_REG, (UINTN)AllocHeapParams.BufferPtr); LibAmdMemCopy (AllocHeapParams.BufferPtr, &HdtoutHeader, sizeof (HdtoutHeader) - 2, StdHeader); } else { /// Clear DR3_REG IdsOutPort ((UINT32)HDTOUT_ERROR, (UINT32)HDTOUT_ERROR_HEAP_AllOCATE_FAIL, (UINT32)IDS_DEBUG_PRINT_MASK); LibAmdWriteCpuReg (DR3_REG, 0); } } }
/** * 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; }
/** * Multisocket call to determine the most severe AGESA_STATUS return value after * processing the power management initialization tables. * * This function loops through all possible socket locations, collecting any * power management initialization errors that may have occurred. These errors * are transferred from the core 0s of the socket in which the errors occurred * to the BSC's heap. The BSC's heap is then searched for the most severe error * that occurred, and returns it. This function must be called by the BSC only. * * @param[in] StdHeader Config handle for library and services * * @return The most severe error code from power management init * */ AGESA_STATUS GetEarlyPmErrorsMulti ( IN AMD_CONFIG_PARAMS *StdHeader ) { UINT16 i; UINT32 BscSocket; UINT32 BscModule; UINT32 BscCoreNum; UINT32 Socket; UINT32 NumberOfSockets; AP_TASK TaskPtr; AGESA_EVENT EventLogEntry; AGESA_STATUS ReturnCode; AGESA_STATUS DummyStatus; ASSERT (IsBsp (StdHeader, &ReturnCode)); ReturnCode = AGESA_SUCCESS; EventLogEntry.EventClass = AGESA_SUCCESS; EventLogEntry.EventInfo = 0; EventLogEntry.DataParam1 = 0; EventLogEntry.DataParam2 = 0; EventLogEntry.DataParam3 = 0; EventLogEntry.DataParam4 = 0; NumberOfSockets = GetPlatformNumberOfSockets (); IdentifyCore (StdHeader, &BscSocket, &BscModule, &BscCoreNum, &DummyStatus); TaskPtr.FuncAddress.PfApTaskI = GetNextEvent; TaskPtr.DataTransfer.DataSizeInDwords = SIZE_IN_DWORDS (AGESA_EVENT); TaskPtr.DataTransfer.DataPtr = &EventLogEntry; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.ExeFlags = WAIT_FOR_CORE | RETURN_PARAMS; for (Socket = 0; Socket < NumberOfSockets; Socket++) { if (Socket != BscSocket) { if (IsProcessorPresent (Socket, StdHeader)) { do { ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8) 0, &TaskPtr, StdHeader); if ((EventLogEntry.EventInfo & CPU_EVENT_PM_EVENT_MASK) == CPU_EVENT_PM_EVENT_CLASS) { PutEventLog ( EventLogEntry.EventClass, EventLogEntry.EventInfo, EventLogEntry.DataParam1, EventLogEntry.DataParam2, EventLogEntry.DataParam3, EventLogEntry.DataParam4, StdHeader ); } } while (EventLogEntry.EventInfo != 0); } } } for (i = 0; PeekEventLog (&EventLogEntry, i, StdHeader); i++) { if ((EventLogEntry.EventInfo & CPU_EVENT_PM_EVENT_MASK) == CPU_EVENT_PM_EVENT_CLASS) { if (EventLogEntry.EventClass > ReturnCode) { ReturnCode = EventLogEntry.EventClass; } } } return (ReturnCode); }
/** * North bridge bufer allocation for Family14h ON. * * This function programs North bridge buffer allocation registers and provides * hook routine for override at AmdInitEarly. * * @param[in] FamilyServices The current Family Specific Services. * @param[in] EarlyParams Service parameters. * @param[in] StdHeader Config handle for library and services. * */ VOID F14NbBufferAllocationAtEarly ( IN CPU_SPECIFIC_SERVICES *FamilyServices, IN AMD_CPU_EARLY_PARAMS *EarlyParams, IN AMD_CONFIG_PARAMS *StdHeader ) { //Buffer allocations cannot be decreased through software, so move these register setting from register table //to here to make IDS easy override NB_BUFFER_ALLOCATION NbBufAllocation; PCI_ADDR PciAddr; AGESA_STATUS Ignored; if (IsBsp (StdHeader, &Ignored)) { PciAddr.AddressValue = MAKE_SBDFO (0, 0, 24, FUNC_3, D18F3x6C_ADDRESS); LibAmdPciRead (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x6C.Value, StdHeader); PciAddr.Address.Register = D18F3x74_ADDRESS; LibAmdPciRead (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x74.Value, StdHeader); PciAddr.Address.Register = D18F3x7C_ADDRESS; LibAmdPciRead (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x7C.Value, StdHeader); PciAddr.Address.Register = D18F3x17C_ADDRESS; LibAmdPciRead (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x17C.Value, StdHeader); //Recommend value for NB buffer allocation // D18F3x6C - Upstream Data Buffer Count // bits[3:0] UpLoPreqDBC = 0x0E // bits[7:4] UpLoNpReqDBC = 1 // bits[11:8] UpLoRespDBC = 1 // bits[19:16] UpHiPreqDBC = 0 // bits[23:20] UpHiNpReqDBC = 0 NbBufAllocation.D18F3x6C.Field.UpLoPreqDBC = 0x0E; NbBufAllocation.D18F3x6C.Field.UpLoNpreqDBC = 1; NbBufAllocation.D18F3x6C.Field.UpLoRespDBC = 1; NbBufAllocation.D18F3x6C.Field.UpHiPreqDBC = 0; NbBufAllocation.D18F3x6C.Field.UpHiNpreqDBC = 0; // D18F3x74 - Upstream Command Buffer Count // bits[3:0] UpLoPreqCBC = 7 // bits[7:4] UpLoNpreqCBC = 9 // bits[11:8] UpLoRespCBC = 8 // bits[19:16] UpHiPreqCBC = 0 // bits[23:20] UpHiNpreqCBC = 0 NbBufAllocation.D18F3x74.Field.UpLoPreqCBC = 7; NbBufAllocation.D18F3x74.Field.UpLoNpreqCBC = 9; NbBufAllocation.D18F3x74.Field.UpLoRespCBC = 8; NbBufAllocation.D18F3x74.Field.UpHiPreqCBC = 0; NbBufAllocation.D18F3x74.Field.UpHiNpreqCBC = 0; // D18F3x7C - In-Flight Queue Buffer Allocation // bits[5:0] CpuBC = 1 // bits[13:8] LoPriPBC = 1 // bits[21:16] LoPriNPBC = 1 // bits[29:24] FreePoolBC = 0x19 NbBufAllocation.D18F3x7C.Field.CpuBC = 1; NbBufAllocation.D18F3x7C.Field.LoPriPBC = 1; NbBufAllocation.D18F3x7C.Field.LoPriNPBC = 1; NbBufAllocation.D18F3x7C.Field.FreePoolBC = 0x19; // D18F3x17C - In-Flight Queue Extended Buffer Allocation // bits[5:0] HiPriPBC = 0 // bits[13:8] HiPriNPBC = 0 NbBufAllocation.D18F3x17C.Field.HiPriPBC = 0; NbBufAllocation.D18F3x17C.Field.HiPriNPBC = 0; IDS_OPTION_HOOK (IDS_NBBUFFERALLOCATIONATEARLY, &NbBufAllocation, StdHeader); PciAddr.AddressValue = MAKE_SBDFO (0, 0, 24, FUNC_3, D18F3x6C_ADDRESS); LibAmdPciWrite (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x6C.Value, StdHeader); PciAddr.Address.Register = D18F3x74_ADDRESS; LibAmdPciWrite (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x74.Value, StdHeader); PciAddr.Address.Register = D18F3x7C_ADDRESS; LibAmdPciWrite (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x7C.Value, StdHeader); PciAddr.Address.Register = D18F3x17C_ADDRESS; LibAmdPciWrite (AccessWidth32, PciAddr, &NbBufAllocation.D18F3x17C.Value, StdHeader); } }
/** * Main entry point for the AMD_INIT_RESET function. * * This entry point is responsible for establishing the HT links to the program * ROM and for performing basic processor initialization. * * @param[in,out] ResetParams Required input parameters for the AMD_INIT_RESET * entry point. * * @return Aggregated status across all internal AMD reset calls invoked. * */ AGESA_STATUS AmdInitReset ( IN OUT AMD_RESET_PARAMS *ResetParams ) { AGESA_STATUS AgesaStatus; AGESA_STATUS CalledAgesaStatus; WARM_RESET_REQUEST Request; UINT8 PrevRequestBit; UINT8 PrevStateBits; AgesaStatus = AGESA_SUCCESS; // Setup ROM execution cache CalledAgesaStatus = AllocateExecutionCache (&ResetParams->StdHeader, &ResetParams->CacheRegion[0]); if (CalledAgesaStatus > AgesaStatus) { AgesaStatus = CalledAgesaStatus; } // IDS_EXTENDED_HOOK (IDS_INIT_RESET_BEFORE, NULL, NULL, &ResetParams->StdHeader); // Init Debug Print function IDS_HDT_CONSOLE_INIT (&ResetParams->StdHeader); IDS_HDT_CONSOLE (MAIN_FLOW, "\nAmdInitReset: Start\n\n"); IDS_HDT_CONSOLE (MAIN_FLOW, "\n*** %s ***\n\n", (CHAR8 *)&UserOptions.VersionString); AGESA_TESTPOINT (TpIfAmdInitResetEntry, &ResetParams->StdHeader); ASSERT (ResetParams != NULL); PrevRequestBit = FALSE; PrevStateBits = WR_STATE_COLD; if (IsBsp (&ResetParams->StdHeader, &AgesaStatus)) { CalledAgesaStatus = BldoptFchFunction.InitReset (ResetParams); AgesaStatus = (CalledAgesaStatus > AgesaStatus) ? CalledAgesaStatus : AgesaStatus; } // If a previously requested warm reset cannot be triggered in the // current stage, store the previous state of request and reset the // request struct to the current post stage GetWarmResetFlag (&ResetParams->StdHeader, &Request); if (Request.RequestBit == TRUE) { if (Request.StateBits >= Request.PostStage) { PrevRequestBit = Request.RequestBit; PrevStateBits = Request.StateBits; Request.RequestBit = FALSE; Request.StateBits = Request.PostStage - 1; SetWarmResetFlag (&ResetParams->StdHeader, &Request); } } // Initialize the PCI MMIO access mechanism InitializePciMmio (&ResetParams->StdHeader); // Initialize Hyper Transport Registers if (HtOptionInitReset.HtInitReset != NULL) { IDS_HDT_CONSOLE (MAIN_FLOW, "HtInitReset: Start\n"); CalledAgesaStatus = HtOptionInitReset.HtInitReset (&ResetParams->StdHeader, &ResetParams->HtConfig); IDS_HDT_CONSOLE (MAIN_FLOW, "HtInitReset: End\n"); if (CalledAgesaStatus > AgesaStatus) { AgesaStatus = CalledAgesaStatus; } } // Warm Reset, should be at the end of AmdInitReset GetWarmResetFlag (&ResetParams->StdHeader, &Request); // If a warm reset is requested in the current post stage, trigger the // warm reset and ignore the previous request if (Request.RequestBit == TRUE) { if (Request.StateBits < Request.PostStage) { AgesaDoReset (WARM_RESET_WHENEVER, &ResetParams->StdHeader); } } else { // Otherwise, if there's a previous request, restore it // so that the subsequent post stage can trigger the warm reset if (PrevRequestBit == TRUE) { Request.RequestBit = PrevRequestBit; Request.StateBits = PrevStateBits; SetWarmResetFlag (&ResetParams->StdHeader, &Request); } } // Check for Cache As Ram Corruption IDS_CAR_CORRUPTION_CHECK (&ResetParams->StdHeader); IDS_HDT_CONSOLE (MAIN_FLOW, "\nAmdInitReset: End\n\n"); AGESA_TESTPOINT (TpIfAmdInitResetExit, &ResetParams->StdHeader); return AgesaStatus; }
AGESA_STATUS AmdIdsCtrlInitialize ( IN OUT AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS status; AGESA_STATUS IgnoreStatus; UINT16 NvTblSize; UINT16 i; IDS_NV_ITEM IdsNvTable[IDS_NUM_NV_ITEM]; IDS_NV_ITEM *NvTable; IDS_NV_ITEM *NvPtr; IDS_CONTROL_STRUCT *IdsCtrlPtr; IDS_CALLOUT_STRUCT IdsCalloutData; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT16 MemTblSize; UINT8 HeapPersist; NvTblSize = 0; MemTblSize = 0; HeapPersist = HEAP_SYSTEM_MEM; //Heap status with HEAP_LOCAL_CACHE, will allocate heap with HEAP_LOCAL_CACHE //with HEAP_TEMP_MEM HEAP_SYSTEM_MEM HEAP_DO_NOT_EXIST_ANYMORE HEAP_S3_RESUME // with allocate with HEAP_SYSTEM_MEM if (StdHeader->HeapStatus == HEAP_LOCAL_CACHE) { MemTblSize = IDS_MAX_MEM_ITEMS; HeapPersist = IDS_HEAP_PERSIST_EARLY; } else if ((StdHeader->HeapStatus == HEAP_DO_NOT_EXIST_YET) || (StdHeader->HeapStatus == HEAP_DO_NOT_EXIST_ANYMORE)) { return AGESA_ERROR; } else { IDS_HEAP_ASSERTION_LATE; } IdsCalloutData.IdsNvPtr = IdsNvTable; IdsCalloutData.StdHeader = *StdHeader; IdsCalloutData.Reserved = FALSE; //init IDS_CALLOUT_STRUCT before calling out, give NVITEM default value for (i = AGESA_IDS_EXT_ID_START; i < IDS_NUM_NV_ITEM; i++) { IdsNvTable[i].IdsNvId = i; IdsNvTable[i].IdsNvValue = AGESA_IDS_DFT_VAL; } AGESA_TESTPOINT (TpIfBeforeGetIdsData, StdHeader); if (AgesaGetIdsData (IDS_CALLOUT_INIT, &IdsCalloutData) == AGESA_SUCCESS) { IDS_HDT_CONSOLE (IDS_TRACE , "Get IDS options from CBS Done\n"); NvTable = IdsCalloutData.IdsNvPtr; NvPtr = NvTable; while (NvPtr->IdsNvId != AGESA_IDS_NV_END) { IDS_HDT_CONSOLE (IDS_TRACE , "\tIDS_ID (%X) = %X\n", NvPtr->IdsNvId, NvPtr->IdsNvValue); NvTblSize ++; NvPtr ++; } NvTblSize ++; AllocHeapParams.RequestedBufferSize = sizeof (IDS_CONTROL_STRUCT); AllocHeapParams.RequestedBufferSize += NvTblSize * sizeof (IDS_NV_ITEM); AllocHeapParams.RequestedBufferSize += MemTblSize * sizeof (MEM_TABLE_ALIAS); AllocHeapParams.RequestedBufferSize += IDS_EXTENDED_HEAP_SIZE; AllocHeapParams.BufferHandle = IDS_CONTROL_HANDLE; AllocHeapParams.Persist = HeapPersist; // // Allocate data buffer in heap // if (HeapAllocateBuffer (&AllocHeapParams, (AMD_CONFIG_PARAMS *) StdHeader) == AGESA_SUCCESS) { // // Initialize IDS Date Buffer // IdsCtrlPtr = (IDS_CONTROL_STRUCT *) AllocHeapParams.BufferPtr; IdsCtrlPtr->IgnoreIdsDefault = (BOOLEAN) IdsCalloutData.Reserved; IdsCtrlPtr->IdsHeapMemSize = AllocHeapParams.RequestedBufferSize; IdsCtrlPtr->IdsNvTableOffset = sizeof (IDS_CONTROL_STRUCT); IdsCtrlPtr->IdsMemTableOffset = IdsCtrlPtr->IdsNvTableOffset + NvTblSize * sizeof (IDS_NV_ITEM); IdsCtrlPtr->IdsExtendOffset = IdsCtrlPtr->IdsMemTableOffset + MemTblSize * sizeof (MEM_TABLE_ALIAS); NvPtr = (IDS_NV_ITEM *) (AllocHeapParams.BufferPtr + IdsCtrlPtr->IdsNvTableOffset); for (i = 0; i < NvTblSize ; i++) { NvPtr->IdsNvId = NvTable->IdsNvId; NvPtr->IdsNvValue = NvTable->IdsNvValue; NvPtr ++; NvTable ++; } status = AGESA_SUCCESS; } else { status = AGESA_ERROR; } } else { if (!IsBsp (StdHeader, &IgnoreStatus)) { status = IDS_AP_GET_NV_FROM_CMOS (StdHeader); } else { IDS_HDT_CONSOLE (IDS_TRACE , "Get IDS options from CBS Fail\n"); status = AGESA_ERROR; } } AGESA_TESTPOINT (TpIfAfterGetIdsData, StdHeader); return status; }