AMD Agesa macro expansion fix
[coreboot.git] / src / vendorcode / amd / agesa / f12 / Proc / CPU / cpuEarlyInit.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU Reset API, and related functions.
6  *
7  * Contains code that initialized the CPU after early reset.
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:      AGESA
11  * @e sub-project:  CPU
12  * @e \$Revision: 49711 $   @e \$Date: 2011-03-28 20:19:38 +0800 (Mon, 28 Mar 2011) $
13  *
14  */
15 /*
16  ******************************************************************************
17  *
18  * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
21  * Redistribution and use in source and binary forms, with or without
22  * modification, are permitted provided that the following conditions are met:
23  *     * Redistributions of source code must retain the above copyright
24  *       notice, this list of conditions and the following disclaimer.
25  *     * Redistributions in binary form must reproduce the above copyright
26  *       notice, this list of conditions and the following disclaimer in the
27  *       documentation and/or other materials provided with the distribution.
28  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
29  *       its contributors may be used to endorse or promote products derived 
30  *       from this software without specific prior written permission.
31  * 
32  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35  * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42  ******************************************************************************
43  */
44
45 /*----------------------------------------------------------------------------------------
46  *                             M O D U L E S    U S E D
47  *----------------------------------------------------------------------------------------
48  */
49 #include "AGESA.h"
50 #include "amdlib.h"
51 #include "Ids.h"
52 #include "cpuRegisters.h"
53 #include "cpuServices.h"
54 #include "GeneralServices.h"
55 #include "Table.h"
56 #include "cpuApicUtilities.h"
57 #include "cpuEarlyInit.h"
58 #include "Topology.h"
59 #include "cpuFamilyTranslation.h"
60 #include "cpuFeatures.h"
61 #include "Filecode.h"
62 CODE_GROUP (G1_PEICC)
63 RDATA_GROUP (G1_PEICC)
64
65 #define FILECODE PROC_CPU_CPUEARLYINIT_FILECODE
66
67
68 /*----------------------------------------------------------------------------------------
69  *                   D E F I N I T I O N S    A N D    M A C R O S
70  *----------------------------------------------------------------------------------------
71  */
72 extern BUILD_OPT_CFG UserOptions;
73 /*----------------------------------------------------------------------------------------
74  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
75  *----------------------------------------------------------------------------------------
76  */
77
78 /*----------------------------------------------------------------------------------------
79  *           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
80  *----------------------------------------------------------------------------------------
81  */
82 VOID
83 AmdCpuEarlyInitializer (
84   IN       AMD_CONFIG_PARAMS      *StdHeader,
85   IN       PLATFORM_CONFIGURATION *PlatformConfig,
86   IN OUT   AMD_CPU_EARLY_PARAMS   *CpuEarlyParamsPtr
87   );
88
89 VOID
90 McaInitialization (
91   IN       AMD_CONFIG_PARAMS *StdHeader
92   );
93
94 VOID
95 STATIC
96 GetPerformEarlyFlag (
97   IN OUT   UINT32   *PerformEarlyFlag,
98   IN       AMD_CONFIG_PARAMS      *StdHeader
99   );
100
101 /*----------------------------------------------------------------------------------------
102  *                          E X P O R T E D    F U N C T I O N S
103  *----------------------------------------------------------------------------------------
104  */
105 VOID
106 McaInitializationAtEarly (
107   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
108   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
109   IN       AMD_CONFIG_PARAMS      *StdHeader
110   );
111
112 /*------------------------------------------------------------------------------------*/
113 /**
114  * Initializer routine that will be invoked by AmdCpuEarly to initialize the input
115  * structure for the Cpu Init @ Early routine.
116  *
117  * @param[in]       StdHeader         Opaque handle to standard config header
118  * @param[in]       PlatformConfig    Config handle for platform specific information
119  * @param[in,out]   CpuEarlyParamsPtr Service Interface structure to initialize.
120  *
121  * @retval          AGESA_SUCCESS     Always Succeeds
122  */
123 VOID
124 AmdCpuEarlyInitializer (
125   IN       AMD_CONFIG_PARAMS      *StdHeader,
126   IN       PLATFORM_CONFIGURATION *PlatformConfig,
127   IN OUT   AMD_CPU_EARLY_PARAMS   *CpuEarlyParamsPtr
128   )
129 {
130   ASSERT (CpuEarlyParamsPtr != NULL);
131
132   CpuEarlyParamsPtr->MemInitPState = (UINT8) UserOptions.CfgMemInitPstate;
133   CpuEarlyParamsPtr->PlatformConfig = *PlatformConfig;
134 }
135 /*---------------------------------------------------------------------------------------*/
136 /**
137  * Performs CPU related initialization at the early entry point
138  *
139  * This function performs a large list of initialization items.  These items
140  * include:
141  *
142  *    -1      local APIC initialization
143  *    -2      MSR table initialization
144  *    -3      PCI table initialization
145  *    -4      HT Phy PCI table initialization
146  *    -5      microcode patch loading
147  *    -6      namestring determination/programming
148  *    -7      AP initialization
149  *    -8      power management initialization
150  *    -9      core leveling
151  *
152  * This routine must be run by all cores in the system.  Please note that
153  * all APs that enter will never exit.
154  *
155  * @param[in]  StdHeader         Config handle for library and services
156  * @param[in]  PlatformConfig    Config handle for platform specific information
157  *
158  * @retval     AGESA_SUCCESS
159  *
160  */
161 AGESA_STATUS
162 AmdCpuEarly (
163   IN       AMD_CONFIG_PARAMS      *StdHeader,
164   IN       PLATFORM_CONFIGURATION *PlatformConfig
165   )
166 {
167   UINT8         WaitStatus;
168   UINT8         i;
169   UINT8         StartCore;
170   UINT8         EndCore;
171   UINT32        NodeNum;
172   UINT32        PrimaryCore;
173   UINT32        SocketNum;
174   UINT32        ModuleNum;
175   UINT32        HighCore;
176   UINT32        ApHeapIndex;
177   UINT32        CurrentPerformEarlyFlag;
178   UINT32        TargetApicId;
179   AP_WAIT_FOR_STATUS WaitForStatus;
180   AGESA_STATUS  Status;
181   AGESA_STATUS  CalledStatus;
182   CPU_SPECIFIC_SERVICES *FamilySpecificServices;
183   AMD_CPU_EARLY_PARAMS CpuEarlyParams;
184   S_PERFORM_EARLY_INIT_ON_CORE *EarlyTableOnCore;
185
186   Status = AGESA_SUCCESS;
187   CalledStatus = AGESA_SUCCESS;
188
189   AmdCpuEarlyInitializer (StdHeader, PlatformConfig, &CpuEarlyParams);
190
191   IDS_OPTION_HOOK (IDS_CPU_Early_Override, &CpuEarlyParams, StdHeader);
192
193   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
194   EarlyTableOnCore = NULL;
195   FamilySpecificServices->GetEarlyInitOnCoreTable (FamilySpecificServices, (const S_PERFORM_EARLY_INIT_ON_CORE **)&EarlyTableOnCore, &CpuEarlyParams, StdHeader);
196   if (EarlyTableOnCore != NULL) {
197     GetPerformEarlyFlag (&CurrentPerformEarlyFlag, StdHeader);
198     for (i = 0; EarlyTableOnCore[i].PerformEarlyInitOnCore != NULL; i++) {
199       if ((EarlyTableOnCore[i].PerformEarlyInitFlag & CurrentPerformEarlyFlag) != 0) {
200         IDS_HDT_CONSOLE (CPU_TRACE, "  Perform core init step %d\n", i);
201         EarlyTableOnCore[i].PerformEarlyInitOnCore (FamilySpecificServices, &CpuEarlyParams, StdHeader);
202       }
203     }
204   }
205
206   // B S P    C O D E    T O    I N I T I A L I Z E    A Ps
207   // -------------------------------------------------------
208   // -------------------------------------------------------
209   // IMPORTANT: Here we determine if we are BSP or AP
210   if (IsBsp (StdHeader, &CalledStatus)) {
211
212     // Even though the bsc does not need to send itself a heap index, this sequence performs other important initialization.
213     // Use '0' as a dummy heap index value.
214     GetSocketModuleOfNode (0, &SocketNum, &ModuleNum, StdHeader);
215     GetCpuServicesOfSocket (SocketNum, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
216     FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, 0, StdHeader);
217     FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, StdHeader);
218
219     // Clear BSP's Status Byte
220     ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
221
222     NodeNum = 0;
223     ApHeapIndex = 1;
224     while (NodeNum < MAX_NODES &&
225           GetSocketModuleOfNode (NodeNum, &SocketNum, &ModuleNum, StdHeader)) {
226       GetCpuServicesOfSocket (SocketNum, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
227       GetGivenModuleCoreRange (SocketNum, ModuleNum, &PrimaryCore, &HighCore, StdHeader);
228       if (NodeNum == 0) {
229         StartCore = (UINT8) PrimaryCore + 1;
230       } else {
231         StartCore = (UINT8) PrimaryCore;
232       }
233
234       EndCore = (UINT8) HighCore;
235       for (i = StartCore; i <= EndCore; i++) {
236         FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, ApHeapIndex, StdHeader);
237         IDS_HDT_CONSOLE (CPU_TRACE, "  Launch socket %d core %d\n", SocketNum, i);
238         if (FamilySpecificServices->LaunchApCore (FamilySpecificServices, SocketNum, ModuleNum, i, PrimaryCore, StdHeader)) {
239           IDS_HDT_CONSOLE (CPU_TRACE, "  Waiting for socket %d core %d\n", SocketNum, i);
240           GetLocalApicIdForCore (SocketNum, i, &TargetApicId, StdHeader);
241           WaitStatus = CORE_IDLE;
242           WaitForStatus.Status = &WaitStatus;
243           WaitForStatus.NumberOfElements = 1;
244           WaitForStatus.RetryCount = WAIT_INFINITELY;
245           WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
246           ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
247           ApHeapIndex++;
248         }
249       }
250       NodeNum++;
251     }
252
253     // B S P    P h a s e - 1   E N D
254
255     IDS_OPTION_HOOK (IDS_BEFORE_PM_INIT, &CpuEarlyParams, StdHeader);
256
257     AGESA_TESTPOINT (TpProcCpuBeforePMFeatureInit, StdHeader);
258     IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features before early power mgmt init\n");
259     CalledStatus = DispatchCpuFeatures (CPU_FEAT_BEFORE_PM_INIT, PlatformConfig, StdHeader);
260     if (CalledStatus > Status) {
261       Status = CalledStatus;
262     }
263
264     AGESA_TESTPOINT (TpProcCpuPowerMgmtInit, StdHeader);
265     CalledStatus = PmInitializationAtEarly (&CpuEarlyParams, StdHeader);
266     if (CalledStatus > Status) {
267       Status = CalledStatus;
268     }
269
270     AGESA_TESTPOINT (TpProcCpuEarlyFeatureInit, StdHeader);
271     IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features after early power mgmt init\n");
272     CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_PM_INIT, PlatformConfig, StdHeader);
273
274     IDS_OPTION_HOOK (IDS_BEFORE_AP_EARLY_HALT, &CpuEarlyParams, StdHeader);
275
276     // Sleep all APs
277     IDS_HDT_CONSOLE (CPU_TRACE, "  Halting all APs\n");
278     ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
279   } // if (amdIsBsp()) - END
280   else {
281     ApEntry (StdHeader, &CpuEarlyParams);
282   }
283
284   if (CalledStatus > Status) {
285     Status = CalledStatus;
286   }
287
288   return (Status);
289 }
290
291 /*---------------------------------------------------------------------------------------
292  *                           L O C A L    F U N C T I O N S
293  *---------------------------------------------------------------------------------------
294  */
295
296 /*---------------------------------------------------------------------------------------*/
297 /**
298  * Initialize Machine Check Architecture registers
299  *
300  * This function initializes the MCA MSRs.  On cold reset, these registers
301  * have an invalid data that must be cleared on all cores.
302  *
303  * @param[in]  StdHeader         Config handle for library and services
304  *
305  *---------------------------------------------------------------------------------------
306  */
307 VOID
308 McaInitialization (
309   IN       AMD_CONFIG_PARAMS *StdHeader
310   )
311 {
312   UINT16      TempVar16_a;
313   UINT32      MsrAddress;
314   UINT64      MsrData;
315   CPUID_DATA  CpuIdDataStruct;
316
317   if (!(IsWarmReset (StdHeader))) {
318     // Run CPUID to verify that the processor supports MCE and MCA
319     // i.e. edx[7], and edx[14]
320     // CPUID_MODEL = 1
321     LibAmdCpuidRead (1, &CpuIdDataStruct, StdHeader);
322     if ((CpuIdDataStruct.EDX_Reg & 0x4080) != 0) {
323       // Check to see if the MCG_CTL_P bit is set
324       // MCG = Global Machine Check Exception Reporting Control Register
325       LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader);
326       if ((MsrData & MCG_CTL_P) != 0) {
327         TempVar16_a = (UINT16) ((MsrData & 0x000000FF) << 2);
328         TempVar16_a += MSR_MC0_CTL;
329
330         // Initialize the data
331         MsrData = 0;
332         for (MsrAddress = MSR_MC0_CTL; MsrAddress < TempVar16_a; MsrAddress++) {
333           LibAmdMsrWrite (MsrAddress, &MsrData, StdHeader);
334         }
335       }
336     }
337   }
338 }
339
340
341 /*---------------------------------------------------------------------------------------*/
342 /**
343  * Initialize Machine Check Architecture registers
344  *
345  * This function acts as a wrapper for calling the McaInitialization
346  * routine at AmdInitEarly.
347  *
348  *  @param[in]   FamilyServices      The current Family Specific Services.
349  *  @param[in]   EarlyParams         Service parameters.
350  *  @param[in]   StdHeader           Config handle for library and services.
351  *
352  */
353 VOID
354 McaInitializationAtEarly (
355   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
356   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
357   IN       AMD_CONFIG_PARAMS      *StdHeader
358   )
359 {
360   McaInitialization (StdHeader);
361 }
362
363 /*---------------------------------------------------------------------------------------*/
364 /**
365  * Runs the given task on all cores (including self) on the socket of the executing
366  * core 0.
367  *
368  * This function is used to invoke all APs on the socket of the executing core 0 to
369  * run a specified AGESA procedure.
370  *
371  * @param[in]  TaskPtr      Function descriptor
372  * @param[in]  StdHeader    Config handle for library and services
373  * @param[in]  CpuEarlyParamsPtr Required input parameters for early CPU initialization
374  *
375  */
376 VOID
377 ApUtilRunCodeOnAllLocalCoresAtEarly (
378   IN       AP_TASK *TaskPtr,
379   IN       AMD_CONFIG_PARAMS *StdHeader,
380   IN       AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr
381   )
382 {
383   UINT32 Core;
384   UINT32 Socket;
385   UINT32 IgnoredModule;
386   UINT32 IgnoredCore;
387   UINT32 ActiveCores;
388   AGESA_STATUS IgnoredSts;
389
390   IdentifyCore (StdHeader, &Socket, &IgnoredModule, &IgnoredCore, &IgnoredSts);
391   GetActiveCoresInCurrentSocket (&ActiveCores, StdHeader);
392
393   for (Core = 1; Core < (UINT8) ActiveCores; ++Core) {
394     ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, TaskPtr, StdHeader);
395   }
396   ApUtilTaskOnExecutingCore (TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr);
397 }
398
399 /*---------------------------------------------------------------------------------------*/
400 /**
401  * Get current condition, such as warm/cold reset, to determine if related function
402  * need to be performed at early stage
403  *
404  *  @param[in, out]   PerformEarlyFlag      Perform early flag.
405  *  @param[in]        StdHeader             Config handle for library and services.
406  *
407  */
408 VOID
409 STATIC
410 GetPerformEarlyFlag (
411   IN OUT   UINT32   *PerformEarlyFlag,
412   IN       AMD_CONFIG_PARAMS      *StdHeader
413   )
414 {
415   *PerformEarlyFlag = 0;
416   if (IsWarmReset (StdHeader)) {
417     *PerformEarlyFlag |= PERFORM_EARLY_WARM_RESET;
418   } else {
419     *PerformEarlyFlag |= PERFORM_EARLY_COLD_BOOT;
420   }
421   return;
422 }