Add constants for fast path resume copying
[coreboot.git] / src / vendorcode / amd / agesa / f14 / 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: 35636 $   @e \$Date: 2010-07-28 09:24:55 +0800 (Wed, 28 Jul 2010) $
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
47 /*----------------------------------------------------------------------------------------
48  *                             M O D U L E S    U S E D
49  *----------------------------------------------------------------------------------------
50  */
51 #include "AGESA.h"
52 #include "amdlib.h"
53 #include "Ids.h"
54 #include "cpuRegisters.h"
55 #include "cpuServices.h"
56 #include "GeneralServices.h"
57 #include "Table.h"
58 #include "cpuApicUtilities.h"
59 #include "cpuEarlyInit.h"
60 #include "Topology.h"
61 #include "cpuFamilyTranslation.h"
62 #include "cpuFeatures.h"
63 #include "Filecode.h"
64 CODE_GROUP (G1_PEICC)
65 RDATA_GROUP (G1_PEICC)
66
67 #define FILECODE PROC_CPU_CPUEARLYINIT_FILECODE
68
69
70 /*----------------------------------------------------------------------------------------
71  *                   D E F I N I T I O N S    A N D    M A C R O S
72  *----------------------------------------------------------------------------------------
73  */
74 extern BUILD_OPT_CFG UserOptions;
75 /*----------------------------------------------------------------------------------------
76  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
77  *----------------------------------------------------------------------------------------
78  */
79
80 /*----------------------------------------------------------------------------------------
81  *           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
82  *----------------------------------------------------------------------------------------
83  */
84 VOID
85 STATIC
86 GetPerformEarlyFlag (
87   IN OUT   UINT32   *PerformEarlyFlag,
88   IN       AMD_CONFIG_PARAMS      *StdHeader
89   );
90
91 VOID
92 McaInitialization (
93   IN       AMD_CONFIG_PARAMS *StdHeader
94   );
95
96 VOID
97 McaInitializationAtEarly (
98   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
99   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
100   IN       AMD_CONFIG_PARAMS      *StdHeader
101   );
102
103 /*----------------------------------------------------------------------------------------
104  *                          E X P O R T E D    F U N C T I O N S
105  *----------------------------------------------------------------------------------------
106  */
107 /*------------------------------------------------------------------------------------*/
108
109 VOID
110 AmdCpuEarlyInitializer (
111   IN       AMD_CONFIG_PARAMS      *StdHeader,
112   IN       PLATFORM_CONFIGURATION *PlatformConfig,
113   IN OUT   AMD_CPU_EARLY_PARAMS   *CpuEarlyParamsPtr
114   );
115
116 /**
117  * Initializer routine that will be invoked by AmdCpuEarly to initialize the input
118  * structure for the Cpu Init @ Early routine.
119  *
120  * @param[in]       StdHeader         Opaque handle to standard config header
121  * @param[in]       PlatformConfig    Config handle for platform specific information
122  * @param[in,out]   CpuEarlyParamsPtr Service Interface structure to initialize.
123  *
124  * @retval          AGESA_SUCCESS     Always Succeeds
125  */
126 VOID
127 AmdCpuEarlyInitializer (
128   IN       AMD_CONFIG_PARAMS      *StdHeader,
129   IN       PLATFORM_CONFIGURATION *PlatformConfig,
130   IN OUT   AMD_CPU_EARLY_PARAMS   *CpuEarlyParamsPtr
131   )
132 {
133   ASSERT (CpuEarlyParamsPtr != NULL);
134
135   CpuEarlyParamsPtr->MemInitPState = (UINT8) UserOptions.CfgMemInitPstate;
136   CpuEarlyParamsPtr->PlatformConfig = *PlatformConfig;
137 }
138 /*---------------------------------------------------------------------------------------*/
139 /**
140  * Performs CPU related initialization at the early entry point
141  *
142  * This function performs a large list of initialization items.  These items
143  * include:
144  *
145  *    -1      local APIC initialization
146  *    -2      MSR table initialization
147  *    -3      PCI table initialization
148  *    -4      HT Phy PCI table initialization
149  *    -5      microcode patch loading
150  *    -6      namestring determination/programming
151  *    -7      AP initialization
152  *    -8      power management initialization
153  *    -9      core leveling
154  *
155  * This routine must be run by all cores in the system.  Please note that
156  * all APs that enter will never exit.
157  *
158  * @param[in]  StdHeader         Config handle for library and services
159  * @param[in]  PlatformConfig    Config handle for platform specific information
160  *
161  * @retval     AGESA_SUCCESS
162  *
163  */
164 AGESA_STATUS
165 AmdCpuEarly (
166   IN       AMD_CONFIG_PARAMS      *StdHeader,
167   IN       PLATFORM_CONFIGURATION *PlatformConfig
168   )
169 {
170   UINT8         WaitStatus;
171   UINT8         i;
172   UINT8         StartCore;
173   UINT8         EndCore;
174   UINT32        NodeNum;
175   UINT32        PrimaryCore;
176   UINT32        SocketNum;
177   UINT32        ModuleNum;
178   UINT32        HighCore;
179   UINT32        ApHeapIndex;
180   UINT32        CurrentPerformEarlyFlag;
181   AP_WAIT_FOR_STATUS WaitForStatus;
182   AGESA_STATUS  Status;
183   AGESA_STATUS  CalledStatus;
184   CPU_SPECIFIC_SERVICES *FamilySpecificServices;
185   AMD_CPU_EARLY_PARAMS CpuEarlyParams;
186   S_PERFORM_EARLY_INIT_ON_CORE *EarlyTableOnCore;
187
188   Status = AGESA_SUCCESS;
189   CalledStatus = AGESA_SUCCESS;
190
191   AmdCpuEarlyInitializer (StdHeader, PlatformConfig, &CpuEarlyParams);
192
193   IDS_OPTION_HOOK (IDS_CPU_Early_Override, &CpuEarlyParams, StdHeader);
194
195   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
196   EarlyTableOnCore = NULL;
197   FamilySpecificServices->GetEarlyInitOnCoreTable (FamilySpecificServices, (const S_PERFORM_EARLY_INIT_ON_CORE **) &EarlyTableOnCore, &CpuEarlyParams, StdHeader);
198   if (EarlyTableOnCore != NULL) {
199     GetPerformEarlyFlag (&CurrentPerformEarlyFlag, StdHeader);
200     for (i = 0; EarlyTableOnCore[i].PerformEarlyInitOnCore != NULL; i++) {
201       if ((EarlyTableOnCore[i].PerformEarlyInitFlag & CurrentPerformEarlyFlag) != 0) {
202         IDS_HDT_CONSOLE (CPU_TRACE, "  Perform core init step %d\n", i);
203         EarlyTableOnCore[i].PerformEarlyInitOnCore (FamilySpecificServices, &CpuEarlyParams, StdHeader);
204       }
205     }
206   }
207
208   // B S P    C O D E    T O    I N I T I A L I Z E    A Ps
209   // -------------------------------------------------------
210   // -------------------------------------------------------
211   // IMPORTANT: Here we determine if we are BSP or AP
212   if (IsBsp (StdHeader, &CalledStatus)) {
213
214     // Even though the bsc does not need to send itself a heap index, this sequence performs other important initialization.
215     // Use '0' as a dummy heap index value.
216     GetSocketModuleOfNode (0, &SocketNum, &ModuleNum, StdHeader);
217     GetCpuServicesOfSocket (SocketNum, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
218     FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, 0, StdHeader);
219     FamilySpecificServices->TransferApCoreNumber (FamilySpecificServices, StdHeader);
220
221     // Clear BSP's Status Byte
222     ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
223
224     NodeNum = 0;
225     ApHeapIndex = 1;
226     while (NodeNum < MAX_NODES &&
227           GetSocketModuleOfNode (NodeNum, &SocketNum, &ModuleNum, StdHeader)) {
228       GetCpuServicesOfSocket (SocketNum, (const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
229       GetGivenModuleCoreRange (SocketNum, ModuleNum, &PrimaryCore, &HighCore, StdHeader);
230       if (NodeNum == 0) {
231         StartCore = (UINT8) PrimaryCore + 1;
232       } else {
233         StartCore = (UINT8) PrimaryCore;
234       }
235
236       EndCore = (UINT8) HighCore;
237       for (i = StartCore; i <= EndCore; i++) {
238         FamilySpecificServices->SetApCoreNumber (FamilySpecificServices, SocketNum, ModuleNum, ApHeapIndex, StdHeader);
239         IDS_HDT_CONSOLE (CPU_TRACE, "  Launch socket %d core %d\n", SocketNum, i);
240         if (FamilySpecificServices->LaunchApCore (FamilySpecificServices, SocketNum, ModuleNum, i, PrimaryCore, StdHeader)) {
241           IDS_HDT_CONSOLE (CPU_TRACE, "  Waiting for socket %d core %d\n", SocketNum, i);
242           WaitStatus = CORE_IDLE;
243           WaitForStatus.Status = &WaitStatus;
244           WaitForStatus.NumberOfElements = 1;
245           WaitForStatus.RetryCount = WAIT_INFINITELY;
246           WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
247           ApUtilWaitForCoreStatus ((UINT8) SocketNum,
248                                     i,
249                                     &WaitForStatus,
250                                     StdHeader
251                                   );
252           ApHeapIndex++;
253         }
254       }
255       NodeNum++;
256     }
257
258     // B S P    P h a s e - 1   E N D
259     AGESA_TESTPOINT (TpProcCpuBeforePMFeatureInit, StdHeader);
260     IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features before early power mgmt init\n");
261     CalledStatus = DispatchCpuFeatures (CPU_FEAT_BEFORE_PM_INIT, PlatformConfig, StdHeader);
262     if (CalledStatus > Status) {
263       Status = CalledStatus;
264     }
265
266     AGESA_TESTPOINT (TpProcCpuPowerMgmtInit, StdHeader);
267     CalledStatus = PmInitializationAtEarly (&CpuEarlyParams, StdHeader);
268     if (CalledStatus > Status) {
269       Status = CalledStatus;
270     }
271
272     AGESA_TESTPOINT (TpProcCpuEarlyFeatureInit, StdHeader);
273     IDS_HDT_CONSOLE (CPU_TRACE, "  Dispatch CPU features after early power mgmt init\n");
274     CalledStatus = DispatchCpuFeatures (CPU_FEAT_AFTER_PM_INIT, PlatformConfig, StdHeader);
275
276     IDS_OPTION_HOOK (IDS_BEFORE_AP_EARLY_HALT, &CpuEarlyParams, StdHeader);
277
278     // Sleep all APs
279     IDS_HDT_CONSOLE (CPU_TRACE, "  Halting all APs\n");
280     ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
281   } // if (amdIsBsp()) - END
282   else {
283     ApEntry (StdHeader, &CpuEarlyParams);
284   }
285
286   if (CalledStatus > Status) {
287     Status = CalledStatus;
288   }
289
290   return (Status);
291 }
292
293 /*---------------------------------------------------------------------------------------
294  *                           L O C A L    F U N C T I O N S
295  *---------------------------------------------------------------------------------------
296  */
297
298 /*---------------------------------------------------------------------------------------*/
299 /**
300  * Initialize Machine Check Architecture registers
301  *
302  * This function initializes the MCA MSRs.  On cold reset, these registers
303  * have an invalid data that must be cleared on all cores.
304  *
305  * @param[in]  StdHeader         Config handle for library and services
306  *
307  *---------------------------------------------------------------------------------------
308  */
309 VOID
310 McaInitialization (
311   IN       AMD_CONFIG_PARAMS *StdHeader
312   )
313 {
314   UINT16      TempVar16_a;
315   UINT32      MsrAddress;
316   UINT64      MsrData;
317   CPUID_DATA  CpuIdDataStruct;
318
319   if (!(IsWarmReset (StdHeader))) {
320     // Run CPUID to verify that the processor supports MCE and MCA
321     // i.e. edx[7], and edx[14]
322     // CPUID_MODEL = 1
323     LibAmdCpuidRead (1, &CpuIdDataStruct, StdHeader);
324     if ((CpuIdDataStruct.EDX_Reg & 0x4080) != 0) {
325       // Check to see if the MCG_CTL_P bit is set
326       // MCG = Global Machine Check Exception Reporting Control Register
327       LibAmdMsrRead (MSR_MCG_CAP, &MsrData, StdHeader);
328       if ((MsrData & MCG_CTL_P) != 0) {
329         TempVar16_a = (UINT16) ((MsrData & 0x000000FF) << 2);
330         TempVar16_a += MSR_MC0_CTL;
331
332         // Initialize the data
333         MsrData = 0;
334         for (MsrAddress = MSR_MC0_CTL; MsrAddress < TempVar16_a; MsrAddress++) {
335           LibAmdMsrWrite (MsrAddress, &MsrData, StdHeader);
336         }
337       }
338     }
339   }
340 }
341
342
343 /*---------------------------------------------------------------------------------------*/
344 /**
345  * Initialize Machine Check Architecture registers
346  *
347  * This function acts as a wrapper for calling the McaInitialization
348  * routine at AmdInitEarly.
349  *
350  *  @param[in]   FamilyServices      The current Family Specific Services.
351  *  @param[in]   EarlyParams         Service parameters.
352  *  @param[in]   StdHeader           Config handle for library and services.
353  *
354  */
355 VOID
356 McaInitializationAtEarly (
357   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
358   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
359   IN       AMD_CONFIG_PARAMS      *StdHeader
360   )
361 {
362   McaInitialization (StdHeader);
363 }
364
365 /*---------------------------------------------------------------------------------------*/
366 /**
367  * Runs the given task on all cores (including self) on the socket of the executing
368  * core 0.
369  *
370  * This function is used to invoke all APs on the socket of the executing core 0 to
371  * run a specified AGESA procedure.
372  *
373  * @param[in]  TaskPtr      Function descriptor
374  * @param[in]  StdHeader    Config handle for library and services
375  * @param[in]  CpuEarlyParamsPtr Required input parameters for early CPU initialization
376  *
377  */
378 VOID
379 ApUtilRunCodeOnAllLocalCoresAtEarly (
380   IN       AP_TASK *TaskPtr,
381   IN       AMD_CONFIG_PARAMS *StdHeader,
382   IN       AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr
383   )
384 {
385   UINT32 Core;
386   UINT32 Socket;
387   UINT32 IgnoredModule;
388   UINT32 IgnoredCore;
389   UINT32 ActiveCores;
390   AGESA_STATUS IgnoredSts;
391
392   IdentifyCore (StdHeader, &Socket, &IgnoredModule, &IgnoredCore, &IgnoredSts);
393   GetActiveCoresInCurrentSocket (&ActiveCores, StdHeader);
394
395   for (Core = 1; Core < (UINT8) ActiveCores; ++Core) {
396     ApUtilRunCodeOnSocketCore ((UINT8)Socket, (UINT8)Core, TaskPtr, StdHeader);
397   }
398   ApUtilTaskOnExecutingCore (TaskPtr, StdHeader, (VOID *) CpuEarlyParamsPtr);
399 }
400
401 /*---------------------------------------------------------------------------------------*/
402 /**
403  * Get current condition, such as warm/cold reset, to determine if related function
404  * need to be performed at early stage
405  *
406  *  @param[in, out]   PerformEarlyFlag      Perform early flag.
407  *  @param[in]        StdHeader             Config handle for library and services.
408  *
409  */
410 VOID
411 STATIC
412 GetPerformEarlyFlag (
413   IN OUT   UINT32   *PerformEarlyFlag,
414   IN       AMD_CONFIG_PARAMS      *StdHeader
415   )
416 {
417   *PerformEarlyFlag = 0;
418   if (IsWarmReset (StdHeader)) {
419     *PerformEarlyFlag |= PERFORM_EARLY_WARM_RESET;
420   } else {
421     *PerformEarlyFlag |= PERFORM_EARLY_COLD_BOOT;
422   }
423   return;
424 }