/* $NoKeywords:$ */ /** * @file * * AMD CPU POST API, and related functions. * * Contains code that initialized the CPU after memory init. * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: CPU * @e \$Revision: 35756 $ @e \$Date: 2010-07-30 08:37:21 +0800 (Fri, 30 Jul 2010) $ * */ /* ***************************************************************************** * * Copyright (c) 2011, Advanced Micro Devices, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of Advanced Micro Devices, Inc. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * *************************************************************************** * */ /*---------------------------------------------------------------------------------------- * M O D U L E S U S E D *---------------------------------------------------------------------------------------- */ #include "AGESA.h" #include "amdlib.h" #include "Ids.h" #include "Options.h" #include "cpuRegisters.h" #include "cpuApicUtilities.h" #include "heapManager.h" #include "cpuServices.h" #include "cpuFeatures.h" #include "GeneralServices.h" #include "cpuPostInit.h" #include "cpuPstateTables.h" #include "cpuFamilyTranslation.h" #include "Filecode.h" CODE_GROUP (G1_PEICC) RDATA_GROUP (G1_PEICC) #define FILECODE PROC_CPU_CPUPOSTINIT_FILECODE /*---------------------------------------------------------------------------------------- * D E F I N I T I O N S A N D M A C R O S *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * T Y P E D E F S A N D S T R U C T U R E S *---------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------- * P R O T O T Y P E S O F L O C A L F U N C T I O N S *---------------------------------------------------------------------------------------- */ VOID STATIC SyncVariableMTRR ( IN AMD_CONFIG_PARAMS *StdHeader ); AGESA_STATUS GetPstateGatherDataAddressAtPost ( OUT UINT64 **Ptr, IN AMD_CONFIG_PARAMS *StdHeader ); VOID SyncAllApMtrrToBsc ( IN VOID *MtrrTable, IN AMD_CONFIG_PARAMS *StdHeader ); /*---------------------------------------------------------------------------------------- * E X P O R T E D F U N C T I O N S *---------------------------------------------------------------------------------------- */ extern BUILD_OPT_CFG UserOptions; extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable; extern VOID ExecuteWbinvdInstruction ( IN OUT AMD_CONFIG_PARAMS *StdHeader ); AGESA_STATUS PstateCreateHeapInfo ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ); /*---------------------------------------------------------------------------------------*/ /** * Performs CPU related initialization at the POST entry point * * This function performs a large list of initialization items. These items * include: * * -1 AP MTRR sync * -2 feature leveling * -3 P-state data gather * -4 P-state leveling * -5 AP cache breakdown & release * * @param[in] StdHeader Config handle for library and services * @param[in] PlatformConfig Config handle for platform specific information * * @retval AGESA_SUCCESS * */ AGESA_STATUS AmdCpuPost ( IN AMD_CONFIG_PARAMS *StdHeader, IN PLATFORM_CONFIGURATION *PlatformConfig ) { AGESA_STATUS AgesaStatus; AGESA_STATUS CalledStatus; AgesaStatus = AGESA_SUCCESS; // // Sync variable MTRR // AGESA_TESTPOINT (TpProcCpuApMtrrSync, StdHeader); SyncVariableMTRR (StdHeader); AGESA_TESTPOINT (TpProcCpuPostFeatureInit, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " Dispatch CPU features after AP MTRR sync\n"); CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_POST_MTRR_SYNC, PlatformConfig, StdHeader); if (CalledStatus > AgesaStatus) { AgesaStatus = CalledStatus; } // // Feature Leveling // AGESA_TESTPOINT (TpProcCpuFeatureLeveling, StdHeader); IDS_HDT_CONSOLE (CPU_TRACE, " Perform feature leveling\n"); FeatureLeveling (StdHeader); // // P-state Gathered and set heap info // IDS_HDT_CONSOLE (CPU_TRACE, " Create P-state info in the heap\n"); PstateCreateHeapInfo (PlatformConfig, StdHeader); // Set TscFreqSel at the rate specified by the core P0 after core frequency leveling. SetCoresTscFreqSel (StdHeader); // Relinquish control of all APs to IBV. IDS_HDT_CONSOLE (CPU_TRACE, " Relinquish control of APs\n"); RelinquishControlOfAllAPs (StdHeader); return (AgesaStatus); } /*--------------------------------------------------------------------------------------- * L O C A L F U N C T I O N S *--------------------------------------------------------------------------------------- */ /*---------------------------------------------------------------------------------------*/ /** * Determines the address in system DRAM that should be used for p-state data * gather and leveling. * * @param[out] Ptr Address to utilize * @param[in] StdHeader Config handle for library and services * * @retval AGESA_SUCCESS * */ AGESA_STATUS GetPstateGatherDataAddressAtPost ( OUT UINT64 **Ptr, IN AMD_CONFIG_PARAMS *StdHeader ) { VOID *AddressValue; AddressValue = (VOID *)P_STATE_DATA_GATHER_TEMP_ADDR; *Ptr = AddressValue; return AGESA_SUCCESS; } /*---------------------------------------------------------------------------------------*/ /** * AP task to sync memory subsystem MSRs with the BSC * * This function processes a list of MSRs and the BSC's current values for those * MSRs. This will allow the APs to see system RAM. * * @param[in] MtrrTable Memory related MSR table * @param[in] StdHeader Config handle for library and services * */ VOID SyncAllApMtrrToBsc ( IN VOID *MtrrTable, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; for (i = 0; ((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress != 0; i++) { LibAmdMsrWrite (((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress, &((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterValue, StdHeader); } } /*---------------------------------------------------------------------------------------*/ /** * Creates p-state information on the heap * * This function gathers p-state information from all processors in the system, * determines a level set of p-states, and places that information into the * heap. This heap data will be used by GenerateSsdt to generate the * final _PSS and XPSS objects. * * @param[in] PlatformConfig Pointer to runtime configuration options * @param[in] StdHeader Config handle for library and services * * @retval AGESA_SUCCESS No error * @retval AGESA_ERROR CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE */ AGESA_STATUS PstateCreateHeapInfo ( IN PLATFORM_CONFIGURATION *PlatformConfig, IN AMD_CONFIG_PARAMS *StdHeader ) { AGESA_STATUS AgesaStatus; S_CPU_AMD_PSTATE *PStateBufferPtr; ALLOCATE_HEAP_PARAMS AllocHeapParams; UINT8 *PStateBufferPtrInHeap; ASSERT (IsBsp (StdHeader, &AgesaStatus)); // //Get proper address for gather data pool address //Zero P-state gather data pool // GetPstateGatherDataAddressAtPost ((UINT64 **)&PStateBufferPtr, StdHeader); LibAmdMemFill (PStateBufferPtr, 0, sizeof (S_CPU_AMD_PSTATE), StdHeader); // //Get all the CPUs P-States and fill the PStateBufferPtr for each core // AgesaStatus = PStateGatherData (PlatformConfig, PStateBufferPtr, StdHeader); if (AgesaStatus != AGESA_SUCCESS) { return AgesaStatus; } // //Do Pstate Leveling for each core if needed. // AgesaStatus = PStateLeveling (PStateBufferPtr, StdHeader); // //Create Heap and store p-state data for ACPI table in CpuLate // AllocHeapParams.RequestedBufferSize = PStateBufferPtr->SizeOfBytes; AllocHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE; AllocHeapParams.Persist = HEAP_SYSTEM_MEM; AgesaStatus = HeapAllocateBuffer (&AllocHeapParams, StdHeader); if (AgesaStatus == AGESA_SUCCESS) { // // Zero Buffer // PStateBufferPtrInHeap = (UINT8 *) AllocHeapParams.BufferPtr; LibAmdMemFill (PStateBufferPtrInHeap, 0, PStateBufferPtr->SizeOfBytes, StdHeader); LibAmdMemCopy (PStateBufferPtrInHeap, PStateBufferPtr, PStateBufferPtr->SizeOfBytes, StdHeader); } else { PutEventLog (AGESA_ERROR, CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE, 0, 0, 0, 0, StdHeader); } return AgesaStatus; } VOID SyncApMsrsToBsc ( IN OUT BSC_AP_MSR_SYNC *ApMsrSync, IN AMD_CONFIG_PARAMS *StdHeader ) { AP_TASK TaskPtr; UINT16 i; UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; UINT32 Core; UINT32 Socket; UINT32 NumberOfSockets; UINT32 NumberOfCores; AGESA_STATUS IgnoredSts; ASSERT (IsBsp (StdHeader, &IgnoredSts)); IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); // //Sync all MTRR settings with BSP // for (i = 0; ApMsrSync[i].RegisterAddress != 0; i++) { LibAmdMsrRead (ApMsrSync[i].RegisterAddress, &ApMsrSync[i].RegisterValue, StdHeader); } TaskPtr.FuncAddress.PfApTaskI = SyncAllApMtrrToBsc; TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((((sizeof (BSC_AP_MSR_SYNC)) * i) + 4) >> 2); TaskPtr.ExeFlags = WAIT_FOR_CORE; TaskPtr.DataTransfer.DataPtr = ApMsrSync; TaskPtr.DataTransfer.DataTransferFlags = 0; 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); } } } } } /*---------------------------------------------------------------------------------------*/ /** * SyncVariableMTRR * * Sync variable MTRR * * @param[in] StdHeader Config handle for library and services * */ VOID STATIC SyncVariableMTRR ( IN AMD_CONFIG_PARAMS *StdHeader ) { BSC_AP_MSR_SYNC ApMsrSync[20]; ApMsrSync[0].RegisterAddress = SYS_CFG; ApMsrSync[1].RegisterAddress = TOP_MEM; ApMsrSync[2].RegisterAddress = TOP_MEM2; ApMsrSync[3].RegisterAddress = 0x200; ApMsrSync[4].RegisterAddress = 0x201; ApMsrSync[5].RegisterAddress = 0x202; ApMsrSync[6].RegisterAddress = 0x203; ApMsrSync[7].RegisterAddress = 0x204; ApMsrSync[8].RegisterAddress = 0x205; ApMsrSync[9].RegisterAddress = 0x206; ApMsrSync[10].RegisterAddress = 0x207; ApMsrSync[11].RegisterAddress = 0x208; ApMsrSync[12].RegisterAddress = 0x209; ApMsrSync[13].RegisterAddress = 0x20A; ApMsrSync[14].RegisterAddress = 0x20B; ApMsrSync[15].RegisterAddress = 0xC0010016; ApMsrSync[16].RegisterAddress = 0xC0010017; ApMsrSync[17].RegisterAddress = 0xC0010018; ApMsrSync[18].RegisterAddress = 0xC0010019; ApMsrSync[19].RegisterAddress = 0; SyncApMsrsToBsc (ApMsrSync, StdHeader); } /*---------------------------------------------------------------------------------------*/ /** * The function suppose to do any thing need to be done at the end of AmdInitPost. * * @param[in] StdHeader Config handle for library and services * * @retval AGESA_SUCCESS * */ AGESA_STATUS FinalizeAtPost ( IN AMD_CONFIG_PARAMS *StdHeader ) { // // Execute wbinvd to ensure heap data in cache write back to memory. // ExecuteWbinvdInstruction (StdHeader); return AGESA_SUCCESS; } /*---------------------------------------------------------------------------------------*/ /** * Set TSC Frequency Selection. * * This function set TSC Frequency Selection. * * @param[in] StdHeader Config handle for library and services * */ VOID STATIC SetTscFreqSel ( IN AMD_CONFIG_PARAMS *StdHeader ) { PSTATE_CPU_FAMILY_SERVICES *FamilyServices; FamilyServices = NULL; GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (const VOID **)&FamilyServices, StdHeader); if (FamilyServices != NULL) { FamilyServices->CpuSetTscFreqSel (FamilyServices, StdHeader); } } /*---------------------------------------------------------------------------------------*/ /** * Set TSC Frequency Selection to all cores. * * This function set TscFreqSel to all cores in the system. * * @param[in] StdHeader Config handle for library and services * */ VOID SetCoresTscFreqSel ( IN AMD_CONFIG_PARAMS *StdHeader ) { AP_TASK TaskPtr; UINT32 BscSocket; UINT32 Ignored; UINT32 BscCoreNum; UINT32 Core; UINT32 Socket; UINT32 NumberOfSockets; UINT32 NumberOfCores; AGESA_STATUS IgnoredSts; ASSERT (IsBsp (StdHeader, &IgnoredSts)); IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts); NumberOfSockets = GetPlatformNumberOfSockets (); SetTscFreqSel (StdHeader); TaskPtr.FuncAddress.PfApTask = SetTscFreqSel; TaskPtr.ExeFlags = WAIT_FOR_CORE; TaskPtr.DataTransfer.DataTransferFlags = 0; TaskPtr.DataTransfer.DataSizeInDwords = 0; TaskPtr.DataTransfer.DataPtr = NULL; 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); } } } } }