blob: 905fa01fef9d7f09cdabb95453b1ec2aa9da9204 [file] [log] [blame]
/**
* @file
*
* AMD CPU Reset API, and related functions.
*
* Contains code that initialized the CPU after early reset.
*
* @xrefitem bom "File Content Label" "Release Content"
* @e project: AGESA
* @e sub-project: CPU
* @e \$Revision: 44323 $ @e \$Date: 2010-12-22 01:24:58 -0700 (Wed, 22 Dec 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 "cpuRegisters.h"
#include "cpuServices.h"
#include "GeneralServices.h"
#include "Table.h"
#include "cpuApicUtilities.h"
#include "cpuEarlyInit.h"
#include "Topology.h"
#include "cpuFamilyTranslation.h"
#include "cpuFeatures.h"
#include "Filecode.h"
#define FILECODE PROC_CPU_CPUEARLYINIT_FILECODE
/*----------------------------------------------------------------------------------------
* D E F I N I T I O N S A N D M A C R O S
*----------------------------------------------------------------------------------------
*/
extern BUILD_OPT_CFG UserOptions;
/*----------------------------------------------------------------------------------------
* 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
*----------------------------------------------------------------------------------------
*/
/*----------------------------------------------------------------------------------------
* E X P O R T E D F U N C T I O N S
*----------------------------------------------------------------------------------------
*/
VOID
McaInitializationAtEarly (
IN CPU_SPECIFIC_SERVICES *FamilyServices,
IN AMD_CPU_EARLY_PARAMS *EarlyParams,
IN AMD_CONFIG_PARAMS *StdHeader
);
/*------------------------------------------------------------------------------------*/
/**
* Initializer routine that will be invoked by AmdCpuEarly to initialize the input
* structure for the Cpu Init @ Early routine.
*
* @param[in] StdHeader Opaque handle to standard config header
* @param[in] PlatformConfig Config handle for platform specific information
* @param[in,out] CpuEarlyParamsPtr Service Interface structure to initialize.
*
* @retval AGESA_SUCCESS Always Succeeds
*/
STATIC VOID
AmdCpuEarlyInitializer (
IN AMD_CONFIG_PARAMS *StdHeader,
IN PLATFORM_CONFIGURATION *PlatformConfig,
IN OUT AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr
)
{
ASSERT (CpuEarlyParamsPtr != NULL);
CpuEarlyParamsPtr->MemInitPState = (UINT8) UserOptions.CfgMemInitPstate;
CpuEarlyParamsPtr->PlatformConfig = *PlatformConfig;
}
/*---------------------------------------------------------------------------------------*/
/**
* 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 j;
UINT8 StartCore;
UINT8 EndCore;
UINT32 NodeNum;
UINT32 PrimaryCore;
UINT32 SocketNum;
UINT32 ModuleNum;
UINT32 HighCore;
UINT32 ApHeapIndex;
AP_WAIT_FOR_STATUS WaitForStatus;
AGESA_STATUS Status;
AGESA_STATUS CalledStatus;
CPU_SPECIFIC_SERVICES *FamilySpecificServices;
AMD_CPU_EARLY_PARAMS CpuEarlyParams;
PF_PERFORM_EARLY_INIT_ON_CORE *EarlyTableOnCore;
Status = AGESA_SUCCESS;
CalledStatus = AGESA_SUCCESS;
AmdCpuEarlyInitializer (StdHeader, PlatformConfig, &CpuEarlyParams);
ASSERT (CpuEarlyParams.PlatformConfig.VrmProperties.CurrentLimit >= CpuEarlyParams.PlatformConfig.VrmProperties.LowPowerThreshold);
IDS_OPTION_HOOK (IDS_CPU_Early_Override, &CpuEarlyParams, StdHeader);
GetCpuServicesOfCurrentCore (&FamilySpecificServices, StdHeader);
EarlyTableOnCore = NULL;
FamilySpecificServices->GetEarlyInitOnCoreTable (FamilySpecificServices, (CONST PF_PERFORM_EARLY_INIT_ON_CORE **)&EarlyTableOnCore, &CpuEarlyParams, StdHeader);
if (EarlyTableOnCore != NULL) {
for (i = 0; EarlyTableOnCore[i] != NULL; i++) {
EarlyTableOnCore[i] (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, &FamilySpecificServices, StdHeader);
FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, 0, StdHeader);
FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, StdHeader);
// Clear BSP's Status Byte
ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
NodeNum = 1;
ApHeapIndex = 1;
for (i = 0; i < 2; i++) {
while (NodeNum < MAX_NODES &&
GetSocketModuleOfNode (NodeNum, &SocketNum, &ModuleNum, StdHeader)) {
GetCpuServicesOfSocket (SocketNum, &FamilySpecificServices, StdHeader);
GetGivenModuleCoreRange (SocketNum, ModuleNum, &PrimaryCore, &HighCore, StdHeader);
if (i == 0) {
StartCore = (UINT8) PrimaryCore;
EndCore = (UINT8) PrimaryCore;
} else {
StartCore = (UINT8) PrimaryCore + 1;
EndCore = (UINT8) HighCore;
}
for (j = StartCore; j <= EndCore; j++) {
FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, ApHeapIndex, StdHeader);
if (FamilySpecificServices->LaunchApCore (FamilySpecificServices, SocketNum, ModuleNum, j, PrimaryCore, StdHeader)) {
WaitStatus = CORE_IDLE;
WaitForStatus.Status = &WaitStatus;
WaitForStatus.NumberOfElements = 1;
WaitForStatus.RetryCount = WAIT_INFINITELY;
WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
ApUtilWaitForCoreStatus (
(UINT8) SocketNum,
j,
&WaitForStatus,
StdHeader
);
ApHeapIndex++;
}
}
NodeNum++;
}
NodeNum = 0;
}
// B S P P h a s e - 1 E N D
AGESA_TESTPOINT (TpProcCpuPowerMgmtInit, StdHeader);
CalledStatus = PmInitializationAtEarly (&CpuEarlyParams, StdHeader);
if (CalledStatus > Status) {
Status = CalledStatus;
}
AGESA_TESTPOINT (TpProcCpuEarlyFeatureInit, StdHeader);
CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_PM_INIT, PlatformConfig, StdHeader);
// Sleep all APs
ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
} // if (amdIsBsp()) - END
else {
ApEntry (StdHeader, &CpuEarlyParams);
}
if (CalledStatus > Status) {
Status = CalledStatus;
}
return (Status);
}
/*---------------------------------------------------------------------------------------
* L O C A L F U N C T I O N S
*---------------------------------------------------------------------------------------
*/
/*---------------------------------------------------------------------------------------*/
/**
* Initialize Machine Check Architecture registers
*
* This function initializes the MCA MSRs. On cold reset, these registers
* have an invalid data that must be cleared on all cores.
*
* @param[in] StdHeader Config handle for library and services
*
*---------------------------------------------------------------------------------------
*/
STATIC VOID
McaInitialization (
IN AMD_CONFIG_PARAMS *StdHeader
)
{
UINT16 TempVar16_a;
UINT32 MsrAddress;
UINT64 MsrData;
CPUID_DATA CpuIdDataStruct;
if (!(IsWarmReset (StdHeader))) {
// Run CPUID to verify that the processor supports MCE and MCA
// i.e. edx[7], and edx[14]
// CPUID_MODEL = 1
LibAmdCpuidRead (1, &CpuIdDataStruct, StdHeader);
if ((CpuIdDataStruct.EDX_Reg & 0x4080) != 0) {
// Check to see if the MCG_CTL_P bit is set
// MCG = Global Machine Check Exception Reporting Control Register
LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader);
if ((MsrData & MCG_CTL_P) != 0) {
TempVar16_a = (UINT16) ((MsrData & 0x000000FF) << 2);
TempVar16_a += MSR_MC0_CTL;
// Initialize the data
MsrData = 0;
for (MsrAddress = MSR_MC0_CTL; MsrAddress < TempVar16_a; MsrAddress++) {
LibAmdMsrWrite (MsrAddress, &MsrData, StdHeader);
}
}
}
}
}
/*---------------------------------------------------------------------------------------*/
/**
* Initialize Machine Check Architecture registers
*
* This function acts as a wrapper for calling the McaInitialization
* routine 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
McaInitializationAtEarly (
IN CPU_SPECIFIC_SERVICES *FamilyServices,
IN AMD_CPU_EARLY_PARAMS *EarlyParams,
IN AMD_CONFIG_PARAMS *StdHeader
)
{
McaInitialization (StdHeader);
}
/*---------------------------------------------------------------------------------------*/
/**
* Runs the given task on all cores (including self) on the socket of the executing
* core 0.
*
* This function is used to invoke all APs on the socket of the executing core 0 to
* run a specified AGESA procedure.
*
* @param[in] TaskPtr Function descriptor
* @param[in] StdHeader Config handle for library and services
* @param[in] CpuEarlyParamsPtr Required input parameters for early CPU initialization
*
*/
VOID
ApUtilRunCodeOnAllLocalCoresAtEarly (
IN AP_TASK *TaskPtr,
IN AMD_CONFIG_PARAMS *StdHeader,
IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr
)
{
UINT32 Core;
UINT32 Socket;
UINT32 IgnoredModule;
UINT32 IgnoredCore;
UINT32 ActiveCores;
AGESA_STATUS IgnoredSts;
IdentifyCore (StdHeader, &Socket, &IgnoredModule, &IgnoredCore, &IgnoredSts);
GetActiveCoresInCurrentSocket (&ActiveCores, StdHeader);
for (Core = 1; Core < (UINT8) ActiveCores; ++Core) {
ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, TaskPtr, StdHeader);
}
ApUtilTaskOnExecutingCore (TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr);
}