5 * AMD CPU POST API, and related functions.
7 * Contains code that initialized the CPU after memory init.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 49029 $ @e \$Date: 2011-03-16 09:55:06 +0800 (Wed, 16 Mar 2011) $
16 ****************************************************************************
17 * AMD Generic Encapsulated Software Architecture
19 * Description: cpuPostInit.c - Cpu POST Initialization Functions.
21 ******************************************************************************
23 * Copyright (c) 2011, Advanced Micro Devices, Inc.
24 * All rights reserved.
26 * Redistribution and use in source and binary forms, with or without
27 * modification, are permitted provided that the following conditions are met:
28 * * Redistributions of source code must retain the above copyright
29 * notice, this list of conditions and the following disclaimer.
30 * * Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
34 * its contributors may be used to endorse or promote products derived
35 * from this software without specific prior written permission.
37 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
39 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
41 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
42 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
45 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
46 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47 ******************************************************************************
50 /*----------------------------------------------------------------------------------------
51 * M O D U L E S U S E D
52 *----------------------------------------------------------------------------------------
59 #include "cpuRegisters.h"
60 #include "cpuApicUtilities.h"
61 #include "heapManager.h"
62 #include "cpuServices.h"
63 #include "cpuFeatures.h"
64 #include "GeneralServices.h"
65 #include "cpuPostInit.h"
66 #include "cpuPstateTables.h"
67 #include "cpuFamilyTranslation.h"
70 RDATA_GROUP (G1_PEICC)
71 #define FILECODE PROC_CPU_CPUPOSTINIT_FILECODE
72 /*----------------------------------------------------------------------------------------
73 * D E F I N I T I O N S A N D M A C R O S
74 *----------------------------------------------------------------------------------------
77 /*----------------------------------------------------------------------------------------
78 * T Y P E D E F S A N D S T R U C T U R E S
79 *----------------------------------------------------------------------------------------
82 /*----------------------------------------------------------------------------------------
83 * 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
84 *----------------------------------------------------------------------------------------
89 IN AMD_CONFIG_PARAMS *StdHeader
93 GetPstateGatherDataAddressAtPost (
95 IN AMD_CONFIG_PARAMS *StdHeader
101 IN AMD_CONFIG_PARAMS *StdHeader
104 /*----------------------------------------------------------------------------------------
105 * E X P O R T E D F U N C T I O N S
106 *----------------------------------------------------------------------------------------
108 extern BUILD_OPT_CFG UserOptions;
109 extern CPU_FAMILY_SUPPORT_TABLE PstateFamilyServiceTable;
113 ExecuteWbinvdInstruction (
114 IN OUT AMD_CONFIG_PARAMS *StdHeader
118 PstateCreateHeapInfo (
119 IN PLATFORM_CONFIGURATION *PlatformConfig,
120 IN AMD_CONFIG_PARAMS *StdHeader
123 /*---------------------------------------------------------------------------------------*/
125 * Performs CPU related initialization at the POST entry point
127 * This function performs a large list of initialization items. These items
131 * -2 feature leveling
132 * -3 P-state data gather
133 * -4 P-state leveling
134 * -5 AP cache breakdown & release
136 * @param[in] StdHeader Config handle for library and services
137 * @param[in] PlatformConfig Config handle for platform specific information
139 * @retval AGESA_SUCCESS
144 IN AMD_CONFIG_PARAMS *StdHeader,
145 IN PLATFORM_CONFIGURATION *PlatformConfig
148 AGESA_STATUS AgesaStatus;
149 AGESA_STATUS CalledStatus;
151 AgesaStatus = AGESA_SUCCESS;
153 // Sync variable MTRR
155 AGESA_TESTPOINT (TpProcCpuApMtrrSync, StdHeader);
156 SyncVariableMTRR (StdHeader);
158 AGESA_TESTPOINT (TpProcCpuPostFeatureInit, StdHeader);
159 IDS_HDT_CONSOLE (CPU_TRACE, " Dispatch CPU features after AP MTRR sync\n");
160 CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_POST_MTRR_SYNC, PlatformConfig, StdHeader);
161 if (CalledStatus > AgesaStatus) {
162 AgesaStatus = CalledStatus;
167 AGESA_TESTPOINT (TpProcCpuFeatureLeveling, StdHeader);
168 IDS_HDT_CONSOLE (CPU_TRACE, " Perform feature leveling\n");
169 FeatureLeveling (StdHeader);
171 // P-state Gathered and set heap info
173 IDS_HDT_CONSOLE (CPU_TRACE, " Create P-state info in the heap\n");
174 PstateCreateHeapInfo (PlatformConfig, StdHeader);
176 // Set TscFreqSel at the rate specified by the core P0 after core frequency leveling.
177 SetCoresTscFreqSel (StdHeader);
179 // Dispatch CPU features before relinquishing control of APs
180 AGESA_TESTPOINT (TpProcCpuBeforeRelinquishAPsFeatureInit, StdHeader);
181 IDS_HDT_CONSOLE (CPU_TRACE, " Dispatch CPU features before Relinquishing control of APs\n");
182 CalledStatus = DispatchCpuFeatures (CPU_FEAT_BEFORE_RELINQUISH_AP, PlatformConfig, StdHeader);
183 if (CalledStatus > AgesaStatus) {
184 AgesaStatus = CalledStatus;
187 // Relinquish control of all APs to IBV.
188 IDS_HDT_CONSOLE (CPU_TRACE, " Relinquish control of APs\n");
189 RelinquishControlOfAllAPs (StdHeader);
191 return (AgesaStatus);
194 /*---------------------------------------------------------------------------------------
195 * L O C A L F U N C T I O N S
196 *---------------------------------------------------------------------------------------
199 /*---------------------------------------------------------------------------------------*/
201 * Determines the address in system DRAM that should be used for p-state data
202 * gather and leveling.
204 * @param[out] Ptr Address to utilize
205 * @param[in] StdHeader Config handle for library and services
207 * @retval AGESA_SUCCESS
211 GetPstateGatherDataAddressAtPost (
213 IN AMD_CONFIG_PARAMS *StdHeader
218 AddressValue = P_STATE_DATA_GATHER_TEMP_ADDR;
220 *Ptr = (UINT64 *)(AddressValue);
222 return AGESA_SUCCESS;
226 /*---------------------------------------------------------------------------------------*/
228 * AP task to sync memory subsystem MSRs with the BSC
230 * This function processes a list of MSRs and the BSC's current values for those
231 * MSRs. This will allow the APs to see system RAM.
233 * @param[in] MtrrTable Memory related MSR table
234 * @param[in] StdHeader Config handle for library and services
240 IN AMD_CONFIG_PARAMS *StdHeader
245 for (i = 0; ((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress != 0; i++) {
246 LibAmdMsrWrite (((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterAddress,
247 &((BSC_AP_MSR_SYNC *) MtrrTable)[i].RegisterValue,
253 /*---------------------------------------------------------------------------------------*/
255 * Creates p-state information on the heap
257 * This function gathers p-state information from all processors in the system,
258 * determines a level set of p-states, and places that information into the
259 * heap. This heap data will be used by GenerateSsdt to generate the
260 * final _PSS and XPSS objects.
262 * @param[in] PlatformConfig Pointer to runtime configuration options
263 * @param[in] StdHeader Config handle for library and services
265 * @retval AGESA_SUCCESS No error
266 * @retval AGESA_ERROR CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE
269 PstateCreateHeapInfo (
270 IN PLATFORM_CONFIGURATION *PlatformConfig,
271 IN AMD_CONFIG_PARAMS *StdHeader
274 AGESA_STATUS AgesaStatus;
275 S_CPU_AMD_PSTATE *PStateBufferPtr;
276 ALLOCATE_HEAP_PARAMS AllocHeapParams;
277 UINT8 *PStateBufferPtrInHeap;
279 ASSERT (IsBsp (StdHeader, &AgesaStatus));
282 //Get proper address for gather data pool address
283 //Zero P-state gather data pool
285 GetPstateGatherDataAddressAtPost ((UINT64 **)&PStateBufferPtr, StdHeader);
286 LibAmdMemFill (PStateBufferPtr, 0, sizeof (S_CPU_AMD_PSTATE), StdHeader);
289 //Get all the CPUs P-States and fill the PStateBufferPtr for each core
291 AgesaStatus = PStateGatherData (PlatformConfig, PStateBufferPtr, StdHeader);
292 if (AgesaStatus != AGESA_SUCCESS) {
297 //Do Pstate Leveling for each core if needed.
299 AgesaStatus = PStateLeveling (PStateBufferPtr, StdHeader);
302 //Create Heap and store p-state data for ACPI table in CpuLate
304 AllocHeapParams.RequestedBufferSize = PStateBufferPtr->SizeOfBytes;
305 AllocHeapParams.BufferHandle = AMD_PSTATE_DATA_BUFFER_HANDLE;
306 AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
307 AgesaStatus = HeapAllocateBuffer (&AllocHeapParams, StdHeader);
308 if (AgesaStatus == AGESA_SUCCESS) {
312 PStateBufferPtrInHeap = (UINT8 *) AllocHeapParams.BufferPtr;
313 LibAmdMemFill (PStateBufferPtrInHeap, 0, PStateBufferPtr->SizeOfBytes, StdHeader);
314 LibAmdMemCopy (PStateBufferPtrInHeap, PStateBufferPtr, PStateBufferPtr->SizeOfBytes, StdHeader);
317 PutEventLog (AGESA_ERROR,
318 CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE,
319 0, 0, 0, 0, StdHeader);
327 IN OUT BSC_AP_MSR_SYNC *ApMsrSync,
328 IN AMD_CONFIG_PARAMS *StdHeader
338 UINT32 NumberOfSockets;
339 UINT32 NumberOfCores;
340 AGESA_STATUS IgnoredSts;
342 ASSERT (IsBsp (StdHeader, &IgnoredSts));
344 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
345 NumberOfSockets = GetPlatformNumberOfSockets ();
348 //Sync all MTRR settings with BSP
350 for (i = 0; ApMsrSync[i].RegisterAddress != 0; i++) {
351 LibAmdMsrRead (ApMsrSync[i].RegisterAddress, &ApMsrSync[i].RegisterValue, StdHeader);
354 TaskPtr.FuncAddress.PfApTaskI = SyncAllApMtrrToBsc;
355 TaskPtr.DataTransfer.DataSizeInDwords = (UINT16) ((((sizeof (BSC_AP_MSR_SYNC)) * i) + 4) >> 2);
356 TaskPtr.ExeFlags = WAIT_FOR_CORE;
357 TaskPtr.DataTransfer.DataPtr = ApMsrSync;
358 TaskPtr.DataTransfer.DataTransferFlags = 0;
360 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
361 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
362 for (Core = 0; Core < NumberOfCores; Core++) {
363 if ((Socket != BscSocket) || (Core != BscCoreNum)) {
364 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
371 /*---------------------------------------------------------------------------------------*/
377 * @param[in] StdHeader Config handle for library and services
383 IN AMD_CONFIG_PARAMS *StdHeader
386 BSC_AP_MSR_SYNC ApMsrSync[20];
388 ApMsrSync[0].RegisterAddress = SYS_CFG;
389 ApMsrSync[1].RegisterAddress = TOP_MEM;
390 ApMsrSync[2].RegisterAddress = TOP_MEM2;
391 ApMsrSync[3].RegisterAddress = 0x200;
392 ApMsrSync[4].RegisterAddress = 0x201;
393 ApMsrSync[5].RegisterAddress = 0x202;
394 ApMsrSync[6].RegisterAddress = 0x203;
395 ApMsrSync[7].RegisterAddress = 0x204;
396 ApMsrSync[8].RegisterAddress = 0x205;
397 ApMsrSync[9].RegisterAddress = 0x206;
398 ApMsrSync[10].RegisterAddress = 0x207;
399 ApMsrSync[11].RegisterAddress = 0x208;
400 ApMsrSync[12].RegisterAddress = 0x209;
401 ApMsrSync[13].RegisterAddress = 0x20A;
402 ApMsrSync[14].RegisterAddress = 0x20B;
403 ApMsrSync[15].RegisterAddress = 0xC0010016;
404 ApMsrSync[16].RegisterAddress = 0xC0010017;
405 ApMsrSync[17].RegisterAddress = 0xC0010018;
406 ApMsrSync[18].RegisterAddress = 0xC0010019;
407 ApMsrSync[19].RegisterAddress = 0;
408 SyncApMsrsToBsc (ApMsrSync, StdHeader);
411 /*---------------------------------------------------------------------------------------*/
413 * The function suppose to do any thing need to be done at the end of AmdInitPost.
415 * @param[in] StdHeader Config handle for library and services
417 * @retval AGESA_SUCCESS
422 IN AMD_CONFIG_PARAMS *StdHeader
426 // Execute wbinvd to ensure heap data in cache write back to memory.
428 ExecuteWbinvdInstruction (StdHeader);
430 return AGESA_SUCCESS;
432 /*---------------------------------------------------------------------------------------*/
434 * Set TSC Frequency Selection.
436 * This function set TSC Frequency Selection.
438 * @param[in] StdHeader Config handle for library and services
444 IN AMD_CONFIG_PARAMS *StdHeader
447 PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
449 FamilyServices = NULL;
451 GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (const VOID **)&FamilyServices, StdHeader);
452 if (FamilyServices != NULL) {
453 FamilyServices->CpuSetTscFreqSel (FamilyServices, StdHeader);
458 /*---------------------------------------------------------------------------------------*/
460 * Set TSC Frequency Selection to all cores.
462 * This function set TscFreqSel to all cores in the system.
464 * @param[in] StdHeader Config handle for library and services
469 IN AMD_CONFIG_PARAMS *StdHeader
478 UINT32 NumberOfSockets;
479 UINT32 NumberOfCores;
480 AGESA_STATUS IgnoredSts;
482 ASSERT (IsBsp (StdHeader, &IgnoredSts));
484 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
485 NumberOfSockets = GetPlatformNumberOfSockets ();
487 SetTscFreqSel (StdHeader);
489 TaskPtr.FuncAddress.PfApTask = SetTscFreqSel;
490 TaskPtr.ExeFlags = WAIT_FOR_CORE;
491 TaskPtr.DataTransfer.DataTransferFlags = 0;
492 TaskPtr.DataTransfer.DataSizeInDwords = 0;
493 TaskPtr.DataTransfer.DataPtr = NULL;
495 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
496 if (GetActiveCoresInGivenSocket (Socket, &NumberOfCores, StdHeader)) {
497 for (Core = 0; Core < NumberOfCores; Core++) {
498 if ((Socket != BscSocket) || (Core != BscCoreNum)) {
499 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);