5 * AMD CPU Pstate Data Gather Function.
7 * Contains code to collect all the Pstate related information from MSRs, and PCI registers.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
15 /*****************************************************************************
17 * Copyright (C) 2012 Advanced Micro Devices, Inc.
18 * All rights reserved.
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions are met:
22 * * Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * * Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
28 * its contributors may be used to endorse or promote products derived
29 * from this software without specific prior written permission.
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
33 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
34 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
35 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
37 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
38 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
40 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 ******************************************************************************
47 *----------------------------------------------------------------------------
50 *----------------------------------------------------------------------------
54 #include "OptionPstate.h"
55 #include "cpuRegisters.h"
56 #include "cpuServices.h"
57 #include "GeneralServices.h"
58 #include "cpuPostInit.h"
60 #include "cpuFamilyTranslation.h"
61 #include "cpuPstateTables.h"
62 #include "cpuApicUtilities.h"
63 #include "cpuFeatures.h"
68 #define FILECODE PROC_CPU_FEATURE_CPUPSTATEGATHER_FILECODE
70 /*----------------------------------------------------------------------------
71 * DEFINITIONS AND MACROS
73 *----------------------------------------------------------------------------
75 extern OPTION_PSTATE_POST_CONFIGURATION OptionPstatePostConfiguration; // global user config record
76 extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
78 /*----------------------------------------------------------------------------
79 * TYPEDEFS AND STRUCTURES
81 *----------------------------------------------------------------------------
84 /*----------------------------------------------------------------------------
85 * PROTOTYPES OF LOCAL FUNCTIONS
87 *----------------------------------------------------------------------------
91 IN AMD_CONFIG_PARAMS *StdHeader,
92 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
97 IN AMD_CONFIG_PARAMS *StdHeader,
98 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
102 /*----------------------------------------------------------------------------
105 *----------------------------------------------------------------------------
109 IN OUT VOID *PStateBuffer,
110 IN AMD_CONFIG_PARAMS *StdHeader
114 *---------------------------------------------------------------------------------------
119 * This function will gather PState information from the MSRs and fill up the
120 * pStateBuf. This buffer will be used by the PState Leveling, and PState Table
121 * generation code later.
124 * @param[in] *PlatformConfig
125 * @param[in, out] *PStateStrucPtr
126 * @param[in] *StdHeader
128 * @retval AGESA_STATUS
130 *---------------------------------------------------------------------------------------
134 IN PLATFORM_CONFIGURATION *PlatformConfig,
135 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr,
136 IN AMD_CONFIG_PARAMS *StdHeader
141 AGESA_STATUS AgesaStatus;
143 AGESA_TESTPOINT (TpProcCpuEntryPstateGather, StdHeader);
144 AgesaStatus = AGESA_SUCCESS;
146 // Gather data for ACPI Tables if ACPI P-States/C-States object generation is enabled.
147 if ((PlatformConfig->UserOptionPState) || (IsFeatureEnabled (IoCstate, PlatformConfig, StdHeader))) {
148 AgesaStatus = (*(OptionPstatePostConfiguration.PstateGather)) (StdHeader, PStateStrucPtr);
149 // Note: Split config struct into PEI/DXE halves. This one is PEI.
155 /**--------------------------------------------------------------------------------------
160 * This is the default routine for use when the PState option is NOT requested.
161 * The option install process will create and fill the transfer vector with
162 * the address of the proper routine (Main or Stub). The link optimizer will
163 * strip out of the .DLL the routine that is not used.
166 * @param[in] *StdHeader
167 * @param[in, out] *PStateStrucPtr
169 * @retval AGESA_STATUS
171 *---------------------------------------------------------------------------------------
175 IN AMD_CONFIG_PARAMS *StdHeader,
176 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
179 return AGESA_UNSUPPORTED;
182 /**--------------------------------------------------------------------------------------
187 * This is the common routine for BSP gathering the Pstate data.
190 * @param[in] *StdHeader
191 * @param[in, out] *PStateStrucPtr
193 * @retval AGESA_STATUS
195 *---------------------------------------------------------------------------------------
199 IN AMD_CONFIG_PARAMS *StdHeader,
200 IN OUT S_CPU_AMD_PSTATE *PStateStrucPtr
206 UINT32 PopulatedSockets;
207 UINT32 NumberOfSockets;
209 AGESA_STATUS IgnoredSts;
210 PSTATE_LEVELING *PStateBufferPtr;
211 PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
215 ASSERT (IsBsp (StdHeader, &IgnoredSts));
217 FamilyServices = NULL;
218 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
219 ASSERT (FamilyServices != NULL);
221 PopulatedSockets = 1;
222 PStateBufferPtr = PStateStrucPtr->PStateLevelingStruc;
224 NumberOfSockets = GetPlatformNumberOfSockets ();
225 IdentifyCore (StdHeader, &BscSocket, &Ignored, &Ignored, &IgnoredSts);
227 PStateStrucPtr->SizeOfBytes = sizeof (S_CPU_AMD_PSTATE);
230 FamilyServices->GetPstateMaxState (FamilyServices, &MaxState, &IgnoredByte, StdHeader);
232 TaskPtr.FuncAddress.PfApTaskI = PStateGather;
234 // Calculate max buffer size in dwords that need to pass to ap task.
236 TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((MaxState + 1) * (SIZE_IN_DWORDS (S_PSTATE_VALUES)));
237 TaskPtr.ExeFlags = WAIT_FOR_CORE;
238 TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
239 TaskPtr.DataTransfer.DataTransferFlags = DATA_IN_MEMORY;
242 //Get P-States and fill the PStateBufferPtr for BSP
244 ApUtilTaskOnExecutingCore (&TaskPtr, StdHeader, NULL);
247 //Calculate next node buffer address
249 PStateBufferPtr->SocketNumber = (UINT8) BscSocket;
250 PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
251 PStateStrucPtr->SizeOfBytes += (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES));
252 PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
253 CpuGetPStateLevelStructure (&PStateBufferPtr, PStateStrucPtr, 1, StdHeader);
255 //Get CPU P-States and fill the PStateBufferPtr for each node(BSC)
257 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
258 if (Socket != BscSocket) {
259 if (IsProcessorPresent (Socket, StdHeader)) {
261 LibAmdMemFill (PStateBufferPtr, 0, sizeof (PSTATE_LEVELING), StdHeader);
262 TaskPtr.DataTransfer.DataPtr = PStateBufferPtr;
263 ApUtilRunCodeOnSocketCore ((UINT8)Socket, 0, &TaskPtr, StdHeader);
264 PStateBufferPtr->SocketNumber = (UINT8) Socket;
266 //Calculate next node buffer address
268 PStateBufferPtr->PStateLevelingSizeOfBytes = (UINT16) (sizeof (PSTATE_LEVELING) + (UINT32) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
269 PStateStrucPtr->SizeOfBytes += PStateBufferPtr->PStateLevelingSizeOfBytes;
270 PStateBufferPtr = (PSTATE_LEVELING *) ((UINT8 *) PStateBufferPtr + (UINTN) sizeof (PSTATE_LEVELING) + (UINTN) (PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue * sizeof (S_PSTATE_VALUES)));
274 PStateStrucPtr->TotalSocketInSystem = PopulatedSockets;
276 return AGESA_SUCCESS;
278 /**--------------------------------------------------------------------------------------
283 * This is the common routine run on each BSC for gathering Pstate data.
286 * @param[in,out] *PStateBuffer
287 * @param[in] *StdHeader
291 *---------------------------------------------------------------------------------------
295 IN OUT VOID *PStateBuffer,
296 IN AMD_CONFIG_PARAMS *StdHeader
305 UINT32 TotalEnabledPStates;
309 PSTATE_LEVELING *PStateBufferPtr;
310 BOOLEAN PStateEnabled;
311 PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
313 AGESA_STATUS IgnoredSts;
316 PStateBufferPtr = (PSTATE_LEVELING *) PStateBuffer;
317 TotalEnabledPStates = 0;
318 FamilyServices = NULL;
319 PStateEnabled = FALSE;
321 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (CONST VOID **)&FamilyServices, StdHeader);
322 ASSERT (FamilyServices != NULL);
325 /// Sockets number: code looking at PStateBufferPtr->TotalCoresInNode
326 /// needs to know it is Processor (or socket) core count and NOT a Node Core count.
327 GetActiveCoresInCurrentSocket (&CoreNum, StdHeader);
328 PStateBufferPtr->TotalCoresInNode = (UINT8) CoreNum;
331 // Assume current CoreNum always zero.(BSC)
333 GetCurrentNodeAndCore (&NodeNum, &CoreNum, StdHeader);
335 PStateBufferPtr->CreateAcpiTables = 1;
338 // We need to know the max pstate state in this socket.
340 FamilyServices->GetPstateMaxState (FamilyServices, &TempVar_c, &BoostStates, StdHeader);
341 PStateBufferPtr->PStateCoreStruct[0].PStateMaxValue = (UINT8) TempVar_c;
342 PStateBufferPtr->PStateCoreStruct[0].NumberOfBoostedStates = BoostStates;
344 for (k = 0; k <= TempVar_c; k++) {
345 // Check if PState is enabled
346 FamilyServices->GetPstateRegisterInfo ( FamilyServices,
354 LibAmdMemFill (&(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k]), 0, sizeof (S_PSTATE_VALUES), StdHeader);
357 FamilyServices->GetPstateFrequency (
360 &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].CoreFreq),
363 FamilyServices->GetPstatePower (
366 &(PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].Power),
369 PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddValue = IddVal;
370 PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].IddDiv = IddDiv;
371 PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].SwPstateNumber = SwPstate;
373 PStateBufferPtr->PStateCoreStruct[0].PStateStruct[k].PStateEnable = 1;
374 TotalEnabledPStates++;
376 } // for (k = 0; k < MPPSTATE_MAXIMUM_STATES; k++)
378 // Don't create ACPI Tables if there is one or less than one PState is enabled
379 if (TotalEnabledPStates <= 1) {
380 PStateBufferPtr[0].CreateAcpiTables = 0;
383 //--------------------Check Again--------------------------------
385 IdentifyCore (StdHeader, &Socket, &NodeNum, &CoreNum, &IgnoredSts);
386 // Get the PCI address of internal die 0 as it is the only die programmed.
387 GetPciAddress (StdHeader, Socket, 0, &PciAddress, &IgnoredSts);
388 PciAddress.Address.Function = FUNC_3;
389 PciAddress.Address.Register = NORTH_BRIDGE_CAPABILITIES_REG;
391 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
392 PStateBufferPtr->PStateCoreStruct[0].HtcCapable =
393 (UINT8) ((TempVar_c & 0x00000400) >> 10); // Bit 10
396 PciAddress.Address.Register = HARDWARE_THERMAL_CTRL_REG;
397 LibAmdPciRead (AccessWidth32, PciAddress, &TempVar_c, StdHeader);
398 PStateBufferPtr->PStateCoreStruct[0].HtcPstateLimit =
399 (UINT8) ((TempVar_c & 0x70000000) >> 28); // Bits 30:28
401 // Get LocalApicId from CPUID Fn0000_0001_EBX
402 LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuId, StdHeader);
403 PStateBufferPtr->PStateCoreStruct[0].LocalApicId = (UINT8) ((CpuId.EBX_Reg & 0xFF000000) >> 24);
407 /*----------------------------------------------------------------------------
410 *----------------------------------------------------------------------------