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