/* $NoKeywords:$ */ /** * @file * * AMD CPU Family Translation functions. * * * @xrefitem bom "File Content Label" "Release Content" * @e project: AGESA * @e sub-project: CPU/Interface * @e \$Revision: 49967 $ @e \$Date: 2011-03-31 11:15:12 +0800 (Thu, 31 Mar 2011) $ * */ /* ****************************************************************************** * * 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 "CommonReturns.h" #include "GeneralServices.h" #include "cpuFamilyTranslation.h" #include "Filecode.h" CODE_GROUP (G1_PEICC) RDATA_GROUP (G1_PEICC) #define FILECODE PROC_CPU_CPUFAMILYTRANSLATION_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 *---------------------------------------------------------------------------------------- */ CONST CPU_SPECIFIC_SERVICES ROMDATA cpuNullServices = { 0, (PF_CPU_DISABLE_PSTATE) CommonReturnAgesaSuccess, (PF_CPU_TRANSITION_PSTATE) CommonReturnAgesaSuccess, (PF_CPU_GET_IDD_MAX) CommonReturnFalse, (PF_CPU_GET_TSC_RATE) CommonReturnAgesaSuccess, (PF_CPU_GET_NB_FREQ) CommonReturnAgesaSuccess, (PF_CPU_GET_MIN_MAX_NB_FREQ) CommonReturnAgesaSuccess, (PF_CPU_GET_NB_PSTATE_INFO) CommonReturnFalse, (PF_CPU_IS_NBCOF_INIT_NEEDED) CommonReturnAgesaSuccess, (PF_CPU_GET_NB_IDD_MAX) CommonReturnFalse, (PF_CPU_AP_INITIAL_LAUNCH) CommonReturnFalse, (PF_CPU_NUMBER_OF_PHYSICAL_CORES) CommonReturnZero8, (PF_CPU_AMD_GET_AP_MAILBOX_FROM_HARDWARE) CommonReturnAgesaSuccess, (PF_CPU_SET_AP_CORE_NUMBER) CommonVoid, (PF_CPU_GET_AP_CORE_NUMBER) CommonReturnZero32, (PF_CPU_TRANSFER_AP_CORE_NUMBER) CommonVoid, (PF_CORE_ID_POSITION_IN_INITIAL_APIC_ID) CommonReturnAgesaSuccess, (PF_CPU_SAVE_FEATURES) CommonReturnAgesaSuccess, (PF_CPU_WRITE_FEATURES) CommonReturnAgesaSuccess, (PF_CPU_SET_WARM_RESET_FLAG) CommonReturnAgesaSuccess, (PF_CPU_GET_WARM_RESET_FLAG) CommonReturnAgesaSuccess, GetEmptyArray, GetEmptyArray, GetEmptyArray, GetEmptyArray, GetEmptyArray, GetEmptyArray, GetEmptyArray, (PF_CPU_GET_PLATFORM_TYPE_SPECIFIC_INFO) CommonReturnAgesaSuccess, (PF_IS_NB_PSTATE_ENABLED) CommonReturnFalse, (PF_NEXT_LINK_HAS_HTFPY_FEATS) CommonReturnFalse, (PF_SET_HT_PHY_REGISTER) CommonVoid, (PF_GET_NEXT_HT_LINK_FEATURES) CommonVoid, NULL, NULL, NULL, NULL, InitCacheDisabled, (PF_GET_EARLY_INIT_TABLE) CommonVoid }; /*---------------------------------------------------------------------------------------- * 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 GetCpuServices ( IN CPU_FAMILY_SUPPORT_TABLE *FamilyTable, IN UINT64 *MatchData, OUT CONST VOID **CpuServices, IN AMD_CONFIG_PARAMS *StdHeader ); /*---------------------------------------------------------------------------------------- * E X P O R T E D F U N C T I O N S *---------------------------------------------------------------------------------------- */ extern CPU_FAMILY_SUPPORT_TABLE CpuSupportedFamiliesTable; extern CPU_FAMILY_ID_XLAT_TABLE CpuSupportedFamilyIdTable; /*---------------------------------------------------------------------------------------*/ /** * * Returns the logical ID of the desired processor. This will be obtained by * reading the CPUID and converting it into a "logical ID" which is not package * dependent. * * @param[in] Socket Socket * @param[out] LogicalId The Processor's Logical ID * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetLogicalIdOfSocket ( IN UINT32 Socket, OUT CPU_LOGICAL_ID *LogicalId, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT32 RawCpuid; PCI_ADDR PciAddress; AGESA_STATUS AssumedSuccess; RawCpuid = 0; if (GetPciAddress (StdHeader, (UINT8)Socket, 0, &PciAddress, &AssumedSuccess)) { PciAddress.Address.Function = FUNC_3; PciAddress.Address.Register = CPUID_FMR; LibAmdPciRead (AccessWidth32, PciAddress, &RawCpuid, StdHeader); GetLogicalIdFromCpuid (RawCpuid, LogicalId, StdHeader); } else { LogicalId->Family = 0; LogicalId->Revision = 0; // Logical ID was not found. IDS_ERROR_TRAP; } } /*---------------------------------------------------------------------------------------*/ /** * * Returns the logical ID of the executing core. This will be obtained by reading * the CPUID and converting it into a "logical ID" which is not package dependent. * * @param[out] LogicalId The Processor's Logical ID * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetLogicalIdOfCurrentCore ( OUT CPU_LOGICAL_ID *LogicalId, IN AMD_CONFIG_PARAMS *StdHeader ) { CPUID_DATA CpuidDataStruct; LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuidDataStruct, StdHeader); GetLogicalIdFromCpuid (CpuidDataStruct.EAX_Reg, LogicalId, StdHeader); } /*---------------------------------------------------------------------------------------*/ /** * * Returns the logical ID of a processor with the given CPUID value. This * will be obtained by converting it into a "logical ID" which is not package * dependent. * * @param[in] RawCpuid The unprocessed CPUID value to be translated * @param[out] LogicalId The Processor's Logical ID * @param[in] StdHeader Handle of Header for calling lib functions and services * */ VOID GetLogicalIdFromCpuid ( IN UINT32 RawCpuid, OUT CPU_LOGICAL_ID *LogicalId, IN AMD_CONFIG_PARAMS *StdHeader ) { UINT8 i; UINT8 k; UINT8 NumberOfFamiliesSupported; UINT8 NumberOfLogicalSubFamilies; UINT8 LogicalIdEntries; UINT32 j; UINT32 RawFamily; UINT32 CpuModelAndExtendedModel; UINT64 LogicalFamily; BOOLEAN IdNotFound; BOOLEAN FamilyNotFound; CONST PF_CPU_GET_SUBFAMILY_ID_ARRAY *SubFamilyIdPtr; CPU_LOGICAL_ID_XLAT *CpuLogicalIdAndRevPtr; CONST CPU_LOGICAL_ID_FAMILY_XLAT *ImageSupportedId; IdNotFound = TRUE; FamilyNotFound = TRUE; CpuLogicalIdAndRevPtr = NULL; ImageSupportedId = CpuSupportedFamilyIdTable.FamilyIdTable; NumberOfFamiliesSupported = CpuSupportedFamilyIdTable.Elements; RawFamily = ((RawCpuid & 0xF00) >> 8) + ((RawCpuid & 0xFF00000) >> 20); RawCpuid &= (UINT32) CPU_FMS_MASK; CpuModelAndExtendedModel = (UINT16) ((RawCpuid >> 8) | RawCpuid); LogicalId->Family = 0; LogicalId->Revision = 0; for (i = 0; i < NumberOfFamiliesSupported && FamilyNotFound; i++) { if (ImageSupportedId[i].Family == RawFamily) { FamilyNotFound = FALSE; LogicalId->Family = ImageSupportedId[i].UnknownRevision.Family; LogicalId->Revision = ImageSupportedId[i].UnknownRevision.Revision; NumberOfLogicalSubFamilies = ImageSupportedId[i].Elements; SubFamilyIdPtr = ImageSupportedId[i].SubFamilyIdTable; for (j = 0; j < NumberOfLogicalSubFamilies && IdNotFound; j++) { SubFamilyIdPtr[j] ((const CPU_LOGICAL_ID_XLAT **)&CpuLogicalIdAndRevPtr, &LogicalIdEntries, &LogicalFamily, StdHeader); ASSERT (CpuLogicalIdAndRevPtr != NULL); for (k = 0; k < LogicalIdEntries; k++) { if (CpuLogicalIdAndRevPtr[k].RawId == CpuModelAndExtendedModel) { IdNotFound = FALSE; LogicalId->Family = LogicalFamily; LogicalId->Revision = CpuLogicalIdAndRevPtr[k].LogicalId; break; } } } } } } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the desired processor's family specific services structure. * * @param[in] Socket The Processor in this Socket. * @param[out] FunctionTable The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetCpuServicesOfSocket ( IN UINT32 Socket, OUT CONST CPU_SPECIFIC_SERVICES **FunctionTable, IN AMD_CONFIG_PARAMS *StdHeader ) { GetFeatureServicesOfSocket (&CpuSupportedFamiliesTable, Socket, (const VOID **)FunctionTable, StdHeader); if (*FunctionTable == NULL) { *FunctionTable = &cpuNullServices; } } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the desired processor's family specific services structure. * * @param[in] FamilyTable The table to search in. * @param[in] Socket The Processor in this Socket. * @param[out] CpuServices The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetFeatureServicesOfSocket ( IN CPU_FAMILY_SUPPORT_TABLE *FamilyTable, IN UINT32 Socket, OUT CONST VOID **CpuServices, IN AMD_CONFIG_PARAMS *StdHeader ) { CPU_LOGICAL_ID CpuFamilyRevision; GetLogicalIdOfSocket (Socket, &CpuFamilyRevision, StdHeader); GetFeatureServicesFromLogicalId (FamilyTable, &CpuFamilyRevision, CpuServices, StdHeader); } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the executing core's family specific services structure. * * @param[out] FunctionTable The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetCpuServicesOfCurrentCore ( OUT CONST CPU_SPECIFIC_SERVICES **FunctionTable, IN AMD_CONFIG_PARAMS *StdHeader ) { GetFeatureServicesOfCurrentCore (&CpuSupportedFamiliesTable, (const VOID **)FunctionTable, StdHeader); if (*FunctionTable == NULL) { *FunctionTable = &cpuNullServices; } } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the family specific services structure for a processor * with the given logical ID. * * @param[in] FamilyTable The table to search in. * @param[out] CpuServices The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetFeatureServicesOfCurrentCore ( IN CPU_FAMILY_SUPPORT_TABLE *FamilyTable, OUT CONST VOID **CpuServices, IN AMD_CONFIG_PARAMS *StdHeader ) { CPU_LOGICAL_ID CpuFamilyRevision; GetLogicalIdOfCurrentCore (&CpuFamilyRevision, StdHeader); GetFeatureServicesFromLogicalId (FamilyTable, &CpuFamilyRevision, CpuServices, StdHeader); } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the family specific services structure for a processor * with the given logical ID. * * @param[in] LogicalId The Processor's logical ID. * @param[out] FunctionTable The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetCpuServicesFromLogicalId ( IN CPU_LOGICAL_ID *LogicalId, OUT CONST CPU_SPECIFIC_SERVICES **FunctionTable, IN AMD_CONFIG_PARAMS *StdHeader ) { GetFeatureServicesFromLogicalId (&CpuSupportedFamiliesTable, LogicalId, (const VOID **)FunctionTable, StdHeader); if (*FunctionTable == NULL) { *FunctionTable = &cpuNullServices; } } /*---------------------------------------------------------------------------------------*/ /** * * Retrieves a pointer to the family specific services structure for a processor * with the given logical ID. * * @param[in] FamilyTable The table to search in. * @param[in] LogicalId The Processor's logical ID. * @param[out] CpuServices The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetFeatureServicesFromLogicalId ( IN CPU_FAMILY_SUPPORT_TABLE *FamilyTable, IN CPU_LOGICAL_ID *LogicalId, OUT CONST VOID **CpuServices, IN AMD_CONFIG_PARAMS *StdHeader ) { GetCpuServices (FamilyTable, &LogicalId->Family, CpuServices, StdHeader); } /*---------------------------------------------------------------------------------------*/ /** * * Finds a family match in the given table, and returns the pointer to the * appropriate table. If no match is found in the table, NULL will be returned. * * @param[in] FamilyTable The table to search in. * @param[in] MatchData Family data that must match. * @param[out] CpuServices The Processor's Family Specific services. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID STATIC GetCpuServices ( IN CPU_FAMILY_SUPPORT_TABLE *FamilyTable, IN UINT64 *MatchData, OUT CONST VOID **CpuServices, IN AMD_CONFIG_PARAMS *StdHeader ) { BOOLEAN IsFamily; UINT8 i; UINT8 NumberOfFamiliesSupported; CONST CPU_SPECIFIC_SERVICES_XLAT *ImageSupportedFamiliesPtr; ImageSupportedFamiliesPtr = FamilyTable->FamilyTable; NumberOfFamiliesSupported = FamilyTable->Elements; IsFamily = FALSE; for (i = 0; i < NumberOfFamiliesSupported; i++) { if ((ImageSupportedFamiliesPtr[i].Family & *MatchData) != 0) { IsFamily = TRUE; break; } } if (IsFamily) { *CpuServices = ImageSupportedFamiliesPtr[i].TablePtr; } else { *CpuServices = NULL; } } /*---------------------------------------------------------------------------------------*/ /** * Used to stub out various family specific tables of information. * * @param[in] FamilySpecificServices The current Family Specific Services. * @param[in] Empty NULL, to indicate no data. * @param[out] NumberOfElements Zero, to indicate no data. * @param[in] StdHeader Handle of Header for calling lib functions and services. * */ VOID GetEmptyArray ( IN CPU_SPECIFIC_SERVICES *FamilySpecificServices, OUT CONST VOID **Empty, OUT UINT8 *NumberOfElements, IN AMD_CONFIG_PARAMS *StdHeader ) { *NumberOfElements = 0; *Empty = NULL; }