AMD Agesa macro expansion fix
[coreboot.git] / src / vendorcode / amd / agesa / f12 / Proc / CPU / cpuPostInit.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU POST API, and related functions.
6  *
7  * Contains code that initialized the CPU after memory init.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 49029 $   @e \$Date: 2011-03-16 09:55:06 +0800 (Wed, 16 Mar 2011) $
13  *
14  */
15 /*
16  ****************************************************************************
17  * AMD Generic Encapsulated Software Architecture
18  *
19  * Description: cpuPostInit.c - Cpu POST Initialization Functions.
20  *
21  ******************************************************************************
22  *
23  * Copyright (c) 2011, Advanced Micro Devices, Inc.
24  * All rights reserved.
25  * 
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.
36  * 
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  ******************************************************************************
48  */
49
50 /*----------------------------------------------------------------------------------------
51  *                             M O D U L E S    U S E D
52  *----------------------------------------------------------------------------------------
53  */
54
55 #include "AGESA.h"
56 #include "amdlib.h"
57 #include "Ids.h"
58 #include "Options.h"
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"
68 #include "Filecode.h"
69 CODE_GROUP (G1_PEICC)
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  *----------------------------------------------------------------------------------------
75  */
76
77 /*----------------------------------------------------------------------------------------
78  *                  T Y P E D E F S     A N D     S T R U C T U R E S
79  *----------------------------------------------------------------------------------------
80  */
81
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  *----------------------------------------------------------------------------------------
85  */
86 VOID
87 STATIC
88 SyncVariableMTRR (
89   IN       AMD_CONFIG_PARAMS  *StdHeader
90   );
91
92 AGESA_STATUS
93 GetPstateGatherDataAddressAtPost (
94      OUT   UINT64            **Ptr,
95   IN       AMD_CONFIG_PARAMS *StdHeader
96   );
97
98 VOID
99 SyncAllApMtrrToBsc (
100   IN       VOID *MtrrTable,
101   IN       AMD_CONFIG_PARAMS *StdHeader
102   );
103
104 /*----------------------------------------------------------------------------------------
105  *                          E X P O R T E D    F U N C T I O N S
106  *----------------------------------------------------------------------------------------
107  */
108 extern BUILD_OPT_CFG UserOptions;
109 extern CPU_FAMILY_SUPPORT_TABLE            PstateFamilyServiceTable;
110
111 extern
112 VOID
113 ExecuteWbinvdInstruction (
114   IN OUT   AMD_CONFIG_PARAMS *StdHeader
115   );
116
117 AGESA_STATUS
118 PstateCreateHeapInfo (
119   IN       PLATFORM_CONFIGURATION *PlatformConfig,
120   IN       AMD_CONFIG_PARAMS *StdHeader
121   );
122
123 /*---------------------------------------------------------------------------------------*/
124 /**
125  * Performs CPU related initialization at the POST entry point
126  *
127  * This function performs a large list of initialization items.  These items
128  * include:
129  *
130  *    -1      AP MTRR sync
131  *    -2      feature leveling
132  *    -3      P-state data gather
133  *    -4      P-state leveling
134  *    -5      AP cache breakdown & release
135  *
136  * @param[in]  StdHeader         Config handle for library and services
137  * @param[in]  PlatformConfig    Config handle for platform specific information
138  *
139  * @retval     AGESA_SUCCESS
140  *
141  */
142 AGESA_STATUS
143 AmdCpuPost (
144   IN       AMD_CONFIG_PARAMS *StdHeader,
145   IN       PLATFORM_CONFIGURATION *PlatformConfig
146   )
147 {
148   AGESA_STATUS AgesaStatus;
149   AGESA_STATUS CalledStatus;
150
151   AgesaStatus = AGESA_SUCCESS;
152   //
153   // Sync variable MTRR
154   //
155   AGESA_TESTPOINT (TpProcCpuApMtrrSync, StdHeader);
156   SyncVariableMTRR (StdHeader);
157
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;
163   }
164   //
165   // Feature Leveling
166   //
167   AGESA_TESTPOINT (TpProcCpuFeatureLeveling, StdHeader);
168   IDS_HDT_CONSOLE (CPU_TRACE, "  Perform feature leveling\n");
169   FeatureLeveling (StdHeader);
170   //
171   // P-state Gathered and set heap info
172   //
173   IDS_HDT_CONSOLE (CPU_TRACE, "  Create P-state info in the heap\n");
174   PstateCreateHeapInfo (PlatformConfig, StdHeader);
175
176   // Set TscFreqSel at the rate specified by the core P0 after core frequency leveling.
177   SetCoresTscFreqSel (StdHeader);
178
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;
185   }
186
187   // Relinquish control of all APs to IBV.
188   IDS_HDT_CONSOLE (CPU_TRACE, "  Relinquish control of APs\n");
189   RelinquishControlOfAllAPs (StdHeader);
190
191   return (AgesaStatus);
192 }
193
194 /*---------------------------------------------------------------------------------------
195  *                           L O C A L    F U N C T I O N S
196  *---------------------------------------------------------------------------------------
197  */
198
199 /*---------------------------------------------------------------------------------------*/
200 /**
201  * Determines the address in system DRAM that should be used for p-state data
202  * gather and leveling.
203  *
204  * @param[out] Ptr               Address to utilize
205  * @param[in]  StdHeader         Config handle for library and services
206  *
207  * @retval     AGESA_SUCCESS
208  *
209  */
210 AGESA_STATUS
211 GetPstateGatherDataAddressAtPost (
212      OUT   UINT64            **Ptr,
213   IN       AMD_CONFIG_PARAMS *StdHeader
214   )
215 {
216   UINT64 AddressValue;
217
218   AddressValue = P_STATE_DATA_GATHER_TEMP_ADDR;
219
220   *Ptr = (UINT64 *)(AddressValue);
221
222   return AGESA_SUCCESS;
223 }
224
225
226 /*---------------------------------------------------------------------------------------*/
227 /**
228  * AP task to sync memory subsystem MSRs with the BSC
229  *
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.
232  *
233  * @param[in]  MtrrTable         Memory related MSR table
234  * @param[in]  StdHeader         Config handle for library and services
235  *
236  */
237 VOID
238 SyncAllApMtrrToBsc (
239   IN       VOID *MtrrTable,
240   IN       AMD_CONFIG_PARAMS *StdHeader
241   )
242 {
243   UINT8   i;
244
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,
248                     StdHeader);
249   }
250 }
251
252
253 /*---------------------------------------------------------------------------------------*/
254 /**
255  * Creates p-state information on the heap
256  *
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.
261  *
262  * @param[in]  PlatformConfig    Pointer to runtime configuration options
263  * @param[in]  StdHeader         Config handle for library and services
264  *
265  * @retval     AGESA_SUCCESS     No error
266  * @retval     AGESA_ERROR       CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE
267  */
268 AGESA_STATUS
269 PstateCreateHeapInfo (
270   IN       PLATFORM_CONFIGURATION *PlatformConfig,
271   IN       AMD_CONFIG_PARAMS   *StdHeader
272   )
273 {
274   AGESA_STATUS            AgesaStatus;
275   S_CPU_AMD_PSTATE        *PStateBufferPtr;
276   ALLOCATE_HEAP_PARAMS    AllocHeapParams;
277   UINT8                   *PStateBufferPtrInHeap;
278
279   ASSERT (IsBsp (StdHeader, &AgesaStatus));
280
281   //
282   //Get proper address for gather data pool address
283   //Zero P-state gather data pool
284   //
285   GetPstateGatherDataAddressAtPost ((UINT64 **)&PStateBufferPtr, StdHeader);
286   LibAmdMemFill (PStateBufferPtr, 0, sizeof (S_CPU_AMD_PSTATE), StdHeader);
287
288   //
289   //Get all the CPUs P-States and fill the PStateBufferPtr for each core
290   //
291   AgesaStatus = PStateGatherData (PlatformConfig, PStateBufferPtr, StdHeader);
292   if (AgesaStatus != AGESA_SUCCESS) {
293     return AgesaStatus;
294   }
295
296   //
297   //Do Pstate Leveling for each core if needed.
298   //
299   AgesaStatus = PStateLeveling (PStateBufferPtr, StdHeader);
300
301   //
302   //Create Heap and store p-state data for ACPI table in CpuLate
303   //
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) {
309     //
310     // Zero Buffer
311     //
312     PStateBufferPtrInHeap = (UINT8 *) AllocHeapParams.BufferPtr;
313     LibAmdMemFill (PStateBufferPtrInHeap, 0, PStateBufferPtr->SizeOfBytes, StdHeader);
314     LibAmdMemCopy  (PStateBufferPtrInHeap, PStateBufferPtr, PStateBufferPtr->SizeOfBytes, StdHeader);
315
316   } else {
317     PutEventLog (AGESA_ERROR,
318                    CPU_ERROR_PSTATE_HEAP_NOT_AVAILABLE,
319                  0, 0, 0, 0, StdHeader);
320   }
321
322   return AgesaStatus;
323 }
324
325 VOID
326 SyncApMsrsToBsc (
327   IN OUT   BSC_AP_MSR_SYNC    *ApMsrSync,
328   IN       AMD_CONFIG_PARAMS  *StdHeader
329   )
330 {
331   AP_TASK                 TaskPtr;
332   UINT16                  i;
333   UINT32                  BscSocket;
334   UINT32                  Ignored;
335   UINT32                  BscCoreNum;
336   UINT32                  Core;
337   UINT32                  Socket;
338   UINT32                  NumberOfSockets;
339   UINT32                  NumberOfCores;
340   AGESA_STATUS            IgnoredSts;
341
342   ASSERT (IsBsp (StdHeader, &IgnoredSts));
343
344   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
345   NumberOfSockets = GetPlatformNumberOfSockets ();
346
347   //
348   //Sync all MTRR settings with BSP
349   //
350   for (i = 0; ApMsrSync[i].RegisterAddress != 0; i++) {
351     LibAmdMsrRead (ApMsrSync[i].RegisterAddress, &ApMsrSync[i].RegisterValue, StdHeader);
352   }
353
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;
359
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);
365         }
366       }
367     }
368   }
369 }
370
371 /*---------------------------------------------------------------------------------------*/
372 /**
373  * SyncVariableMTRR
374  *
375  * Sync variable MTRR
376  *
377  * @param[in]  StdHeader         Config handle for library and services
378  *
379  */
380 VOID
381 STATIC
382 SyncVariableMTRR (
383   IN       AMD_CONFIG_PARAMS  *StdHeader
384   )
385 {
386   BSC_AP_MSR_SYNC ApMsrSync[20];
387
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);
409 }
410
411 /*---------------------------------------------------------------------------------------*/
412 /**
413  * The function suppose to do any thing need to be done at the end of AmdInitPost.
414  *
415  * @param[in]  StdHeader         Config handle for library and services
416  *
417  * @retval     AGESA_SUCCESS
418  *
419  */
420 AGESA_STATUS
421 FinalizeAtPost (
422   IN       AMD_CONFIG_PARAMS *StdHeader
423   )
424 {
425   //
426   // Execute wbinvd to ensure heap data in cache write back to memory.
427   //
428   ExecuteWbinvdInstruction (StdHeader);
429
430   return AGESA_SUCCESS;
431 }
432 /*---------------------------------------------------------------------------------------*/
433 /**
434  * Set TSC Frequency Selection.
435  *
436  * This function set TSC Frequency Selection.
437  *
438  * @param[in]  StdHeader         Config handle for library and services
439  *
440  */
441 VOID
442 STATIC
443 SetTscFreqSel (
444   IN       AMD_CONFIG_PARAMS *StdHeader
445   )
446 {
447   PSTATE_CPU_FAMILY_SERVICES *FamilyServices;
448
449   FamilyServices = NULL;
450
451   GetFeatureServicesOfCurrentCore (&PstateFamilyServiceTable, (const VOID **)&FamilyServices, StdHeader);
452   if (FamilyServices != NULL) {
453     FamilyServices->CpuSetTscFreqSel (FamilyServices, StdHeader);
454   }
455
456 }
457
458 /*---------------------------------------------------------------------------------------*/
459 /**
460  * Set TSC Frequency Selection to all cores.
461  *
462  * This function set TscFreqSel to all cores in the system.
463  *
464  * @param[in]  StdHeader         Config handle for library and services
465  *
466  */
467 VOID
468 SetCoresTscFreqSel (
469   IN       AMD_CONFIG_PARAMS   *StdHeader
470   )
471 {
472   AP_TASK                 TaskPtr;
473   UINT32                  BscSocket;
474   UINT32                  Ignored;
475   UINT32                  BscCoreNum;
476   UINT32                  Core;
477   UINT32                  Socket;
478   UINT32                  NumberOfSockets;
479   UINT32                  NumberOfCores;
480   AGESA_STATUS            IgnoredSts;
481
482   ASSERT (IsBsp (StdHeader, &IgnoredSts));
483
484   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
485   NumberOfSockets = GetPlatformNumberOfSockets ();
486
487   SetTscFreqSel (StdHeader);
488
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;
494
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);
500         }
501       }
502     }
503   }
504 }