| /* $NoKeywords:$ */ |
| /** |
| * @file |
| * |
| * AMD CPU Family Translation functions. |
| * |
| * |
| * @xrefitem bom "File Content Label" "Release Content" |
| * @e project: AGESA |
| * @e sub-project: CPU/Interface |
| * @e \$Revision: 37150 $ @e \$Date: 2010-08-31 23:53:37 +0800 (Tue, 31 Aug 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 "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_NB_PSTATE_INFO) CommonReturnFalse, |
| (PF_CPU_IS_NBCOF_INIT_NEEDED) CommonReturnAgesaSuccess, |
| (PF_CPU_AP_INITIAL_LAUNCH) CommonReturnFalse, |
| (PF_CPU_NUMBER_OF_BRANDSTRING_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; |
| } |