AGESA F15: AMD family15 AGESA code
[coreboot.git] / src / vendorcode / amd / agesa / f15 / Proc / CPU / cpuApicUtilities.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * AMD CPU APIC related utility functions.
6  *
7  * Contains code that provides mechanism to invoke and control APIC communication.
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 "cpuCacheInit.h"
54 #include "cpuRegisters.h"
55 #include "cpuApicUtilities.h"
56 #include "cpuFamilyTranslation.h"
57 #include "GeneralServices.h"
58 #include "cpuServices.h"
59 #include "heapManager.h"
60 #include "Filecode.h"
61 CODE_GROUP (G1_PEICC)
62 RDATA_GROUP (G2_PEI)
63
64 #define FILECODE PROC_CPU_CPUAPICUTILITIES_FILECODE
65
66 /*----------------------------------------------------------------------------------------
67  *                   D E F I N I T I O N S    A N D    M A C R O S
68  *----------------------------------------------------------------------------------------
69  */
70 /* ApFlags bits */
71 #define AP_TASK_HAS_INPUT    0x00000001
72 #define AP_TASK_HAS_OUTPUT   0x00000002
73 #define AP_RETURN_PARAMS     0x00000004
74 #define AP_END_AT_HLT        0x00000008
75 #define AP_PASS_EARLY_PARAMS 0x00000010
76
77 #define XFER_ELEMENT_SIZE    sizeof (UINT32)
78
79 /*----------------------------------------------------------------------------------------
80  *                  T Y P E D E F S     A N D     S T R U C T U R E S
81  *----------------------------------------------------------------------------------------
82  */
83
84 typedef VOID F_CPU_AMD_NMI_HANDLER (
85   IN       AMD_CONFIG_PARAMS *StdHeader
86   );
87 typedef F_CPU_AMD_NMI_HANDLER *PF_CPU_AMD_NMI_HANDLER;
88
89 /*----------------------------------------------------------------------------------------
90  *           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
91  *----------------------------------------------------------------------------------------
92  */
93 VOID
94 STATIC
95 ApUtilSetupIdtForHlt (
96   IN       IDT_DESCRIPTOR *NmiIdtDescPtr,
97   IN       AMD_CONFIG_PARAMS *StdHeader
98   );
99
100 UINT32
101 STATIC
102 ApUtilRemoteRead (
103   IN       UINT32 TargetApicId,
104   IN       UINT8  RegAddr,
105   IN       AMD_CONFIG_PARAMS *StdHeader
106   );
107
108 VOID
109 STATIC
110 ApUtilLocalWrite (
111   IN       UINT32 RegAddr,
112   IN       UINT32 Value,
113   IN       AMD_CONFIG_PARAMS *StdHeader
114   );
115
116 UINT32
117 STATIC
118 ApUtilLocalRead (
119   IN       UINT32 RegAddr,
120   IN       AMD_CONFIG_PARAMS *StdHeader
121   );
122
123 VOID
124 STATIC
125 ApUtilGetLocalApicBase (
126      OUT   UINT64 *ApicBase,
127   IN       AMD_CONFIG_PARAMS *StdHeader
128   );
129
130 UINT8
131 STATIC
132 ApUtilCalculateUniqueId (
133   IN      UINT8 Socket,
134   IN      UINT8 Core,
135   IN      AMD_CONFIG_PARAMS *StdHeader
136   );
137
138 VOID
139 STATIC
140 ApUtilFireDirectedNmi (
141   IN      UINT32 TargetApicId,
142   IN      AMD_CONFIG_PARAMS *StdHeader
143   );
144
145 VOID
146 STATIC
147 ApUtilReceivePointer (
148   IN       UINT32 TargetApicId,
149      OUT   VOID  **ReturnPointer,
150   IN       AMD_CONFIG_PARAMS *StdHeader
151   );
152
153 VOID
154 STATIC
155 ApUtilTransmitPointer (
156   IN       UINT32 TargetApicId,
157   IN       VOID  **Pointer,
158   IN       AMD_CONFIG_PARAMS *StdHeader
159   );
160
161 VOID
162 STATIC
163 PerformFinalHalt (
164   IN       AMD_CONFIG_PARAMS *StdHeader
165   );
166
167 VOID
168 LocalApicInitialization (
169   IN       AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
170   IN       AMD_CONFIG_PARAMS    *StdHeader
171   );
172
173 VOID
174 LocalApicInitializationAtEarly (
175   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
176   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
177   IN       AMD_CONFIG_PARAMS      *StdHeader
178   );
179 /*----------------------------------------------------------------------------------------
180  *                          E X P O R T E D    F U N C T I O N S
181  *----------------------------------------------------------------------------------------
182  */
183 extern
184 VOID
185 ExecuteHltInstruction (
186   IN       AMD_CONFIG_PARAMS *StdHeader
187   );
188
189 extern
190 VOID
191 NmiHandler (
192   IN       AMD_CONFIG_PARAMS *StdHeader
193   );
194
195 extern
196 VOID
197 ExecuteFinalHltInstruction (
198   IN       UINT32 SharedCore,
199   IN       AP_MTRR_SETTINGS  *ApMtrrSettingsList,
200   IN       AMD_CONFIG_PARAMS *StdHeader
201   );
202
203 extern BUILD_OPT_CFG UserOptions;
204
205 /*---------------------------------------------------------------------------------------*/
206 /**
207  * Initialize the Local APIC.
208  *
209  * This function determines and programs the appropriate APIC ID value
210  * for the executing core.  This code must be run after HT initialization
211  * is complete.
212  *
213  *  @param[in]     CpuEarlyParamsPtr  Service parameters.
214  *  @param[in]     StdHeader          Config handle for library and services.
215  *
216  */
217 VOID
218 LocalApicInitialization (
219   IN       AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
220   IN       AMD_CONFIG_PARAMS    *StdHeader
221   )
222 {
223   UINT32    CurrentCore;
224   UINT32    CurrentNodeNum;
225   UINT32    CoreIdBits;
226   UINT32    Mnc;
227   UINT32    ProcessorCount;
228   UINT32    ProcessorApicIndex;
229   UINT32    IoApicNum;
230   UINT32    StartLocalApicId;
231   UINT64    LocalApicBase;
232   UINT32    TempVar_a;
233   UINT64    MsrData;
234   UINT64    Address;
235   CPUID_DATA  CpuidData;
236
237   // Local variables default values
238   IoApicNum = CpuEarlyParamsPtr->PlatformConfig.NumberOfIoApics;
239
240   GetCurrentCore (&CurrentCore, StdHeader);
241   GetCurrentNodeNum (&CurrentNodeNum, StdHeader);
242
243   // Get Mnc
244   LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
245   CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
246   Mnc = 1 << (CoreIdBits & 0x000F);
247
248   // Get ProcessorCount in the system
249   ProcessorCount = GetNumberOfProcessors (StdHeader);
250
251   // Get the APIC Index of this processor.
252   ProcessorApicIndex = GetProcessorApicIndex (CurrentNodeNum, StdHeader);
253
254   TempVar_a = (Mnc * ProcessorCount) + IoApicNum;
255   ASSERT (TempVar_a < 255);
256
257   // Apply apic enumeration rules
258   // For systems with >= 16 APICs, put the IO-APICs at 0..n and
259   // put the local-APICs at m..z
260   // For systems with < 16 APICs, put the Local-APICs at 0..n and
261   // put the IO-APICs at (n + 1)..z
262   // This is needed because many IO-APIC devices only have 4 bits
263   // for their APIC id and therefore must reside at 0..15
264   StartLocalApicId = 0;
265   if (TempVar_a >= 16) {
266     if (IoApicNum >= 1) {
267       StartLocalApicId = (IoApicNum - 1) / Mnc;
268       StartLocalApicId = (StartLocalApicId + 1) * Mnc;
269     }
270   }
271
272   // Set local apic id
273   TempVar_a = (ProcessorApicIndex * Mnc) + CurrentCore + StartLocalApicId;
274   IDS_HDT_CONSOLE (CPU_TRACE, "  Node %d core %d APIC ID = 0x%x\n", CurrentNodeNum, CurrentCore, TempVar_a);
275   TempVar_a = TempVar_a << APIC20_ApicId;
276
277   // Enable local apic id
278   LibAmdMsrRead (MSR_APIC_BAR, &MsrData, StdHeader);
279   MsrData |= APIC_ENABLE_BIT;
280   LibAmdMsrWrite (MSR_APIC_BAR, &MsrData, StdHeader);
281
282   // Get local apic base Address
283   ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
284
285   Address = LocalApicBase + APIC_ID_REG;
286   LibAmdMemWrite (AccessWidth32, Address, &TempVar_a, StdHeader);
287 }
288
289 /*---------------------------------------------------------------------------------------*/
290 /**
291  * Initialize the Local APIC at the AmdInitEarly entry point.
292  *
293  * This function acts as a wrapper for calling the LocalApicInitialization
294  * routine at AmdInitEarly.
295  *
296  *  @param[in]   FamilyServices      The current Family Specific Services.
297  *  @param[in]   EarlyParams         Service parameters.
298  *  @param[in]   StdHeader           Config handle for library and services.
299  *
300  */
301 VOID
302 LocalApicInitializationAtEarly (
303   IN       CPU_SPECIFIC_SERVICES  *FamilyServices,
304   IN       AMD_CPU_EARLY_PARAMS   *EarlyParams,
305   IN       AMD_CONFIG_PARAMS      *StdHeader
306   )
307 {
308   AGESA_TESTPOINT (TpProcCpuLocalApicInit, StdHeader);
309   LocalApicInitialization (EarlyParams, StdHeader);
310 }
311
312
313 /*---------------------------------------------------------------------------------------*/
314 /**
315  * Main entry point for all APs in the system.
316  *
317  * This routine puts the AP cores in an infinite loop in which the cores
318  * will poll their masters, waiting to be told to perform a task.  At early,
319  * all socket-relative core zeros will receive their tasks from the BSC.
320  * All others will receive their tasks from the core zero of their local
321  * processor.  At the end of AmdInitEarly, all cores will switch to receiving
322  * their tasks from the BSC.
323  *
324  * @param[in]     StdHeader       Handle to config for library and services.
325  * @param[in]     CpuEarlyParams  AMD_CPU_EARLY_PARAMS pointer.
326  *
327  */
328 VOID
329 ApEntry (
330   IN       AMD_CONFIG_PARAMS *StdHeader,
331   IN       AMD_CPU_EARLY_PARAMS *CpuEarlyParams
332   )
333 {
334   UINT8   RemoteCmd;
335   UINT8   SourceSocket;
336   UINT8   CommandStart;
337   UINT32  ApFlags;
338   UINT32  FuncType;
339   UINT32  ReturnCode;
340   UINT32  CurrentSocket;
341   UINT32  CurrentCore;
342   UINT32  *InputDataPtr;
343   UINT32  BscSocket;
344   UINT32  Ignored;
345   UINT32  TargetApicId;
346   AP_FUNCTION_PTR FuncAddress;
347   IDT_DESCRIPTOR IdtDesc[32];
348   AP_DATA_TRANSFER DataTransferInfo;
349   AGESA_STATUS IgnoredSts;
350
351   ASSERT (!IsBsp (StdHeader, &IgnoredSts));
352
353   // Initialize local variables
354   ReturnCode = 0;
355   DataTransferInfo.DataTransferFlags = 0;
356   InputDataPtr = NULL;
357
358   // Determine the executing core's socket and core numbers
359   IdentifyCore (StdHeader, &CurrentSocket, &Ignored, &CurrentCore, &IgnoredSts);
360
361   IDS_HDT_CONSOLE (CPU_TRACE, "  Socket %d core %d begin AP tasking engine\n", CurrentSocket, CurrentCore);
362
363   // Determine the BSC's socket number
364   GetSocketModuleOfNode ((UINT32) 0x00000000, &BscSocket, &Ignored, StdHeader);
365
366   // Setup Interrupt Descriptor Table for sleep mode
367   ApUtilSetupIdtForHlt (&IdtDesc[2], StdHeader);
368
369   // Indicate to the BSC that we have reached the tasking engine
370   ApUtilWriteControlByte (CORE_IDLE, StdHeader);
371
372   if (CurrentCore == 0) {
373     // Core 0s receive their tasks from the BSC
374     SourceSocket = (UINT8) BscSocket;
375   } else {
376     // All non-zero cores receive their tasks from the core 0 of their socket
377     SourceSocket = (UINT8) CurrentSocket;
378   }
379
380   GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
381
382   // Determine the unique value that the master will write when it has a task
383   // for this core to perform.
384   CommandStart = ApUtilCalculateUniqueId (
385                    (UINT8)CurrentSocket,
386                    (UINT8)CurrentCore,
387                    StdHeader
388                    );
389   for (;;) {
390     RemoteCmd = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
391     if (RemoteCmd == CommandStart) {
392       ApFlags = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
393
394       ApUtilReceivePointer (TargetApicId, (VOID **) &FuncAddress, StdHeader);
395
396       FuncType = ApFlags & (UINT32) (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS);
397       if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
398         DataTransferInfo.DataSizeInDwords = 0;
399         DataTransferInfo.DataPtr = NULL;
400         DataTransferInfo.DataTransferFlags = 0;
401         if (ApUtilReceiveBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader) == AGESA_ERROR) {
402           // There is not enough space to put the input data on the heap.  Undefined behavior is about
403           // to result.
404           IDS_ERROR_TRAP;
405         }
406         InputDataPtr = (UINT32 *) DataTransferInfo.DataPtr;
407       }
408       ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
409       switch (FuncType) {
410       case 0:
411         FuncAddress.PfApTask (StdHeader);
412         break;
413       case AP_TASK_HAS_INPUT:
414         FuncAddress.PfApTaskI (InputDataPtr, StdHeader);
415         break;
416       case AP_PASS_EARLY_PARAMS:
417         FuncAddress.PfApTaskC (StdHeader, CpuEarlyParams);
418         break;
419       case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
420         FuncAddress.PfApTaskIC (InputDataPtr, StdHeader, CpuEarlyParams);
421         break;
422       case AP_TASK_HAS_OUTPUT:
423         ReturnCode = FuncAddress.PfApTaskO (StdHeader);
424         break;
425       case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
426         ReturnCode = FuncAddress.PfApTaskIO (InputDataPtr, StdHeader);
427         break;
428       case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
429         ReturnCode = FuncAddress.PfApTaskOC (StdHeader, CpuEarlyParams);
430         break;
431       case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
432         ReturnCode = FuncAddress.PfApTaskIOC (InputDataPtr, StdHeader, CpuEarlyParams);
433         break;
434       default:
435         ReturnCode = 0;
436         break;
437       }
438       if (((ApFlags & AP_RETURN_PARAMS) != 0)) {
439         ApUtilTransmitBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader);
440       }
441       if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
442         ApUtilWriteDataDword (ReturnCode, StdHeader);
443       }
444       if ((ApFlags & AP_END_AT_HLT) != 0) {
445         RemoteCmd = CORE_IDLE_HLT;
446       } else {
447         ApUtilWriteControlByte (CORE_IDLE, StdHeader);
448       }
449     }
450     if (RemoteCmd == CORE_IDLE_HLT) {
451       SourceSocket = (UINT8) BscSocket;
452       GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
453       ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
454       ExecuteHltInstruction (StdHeader);
455       ApUtilWriteControlByte (CORE_IDLE, StdHeader);
456     }
457   }
458 }
459
460
461 /*---------------------------------------------------------------------------------------*/
462 /**
463  * Reads the 'control byte' on the designated remote core.
464  *
465  * This function will read the current contents of the control byte
466  * on the designated core using the APIC remote read inter-
467  * processor interrupt sequence.
468  *
469  * @param[in]      TargetApicId  Local APIC ID of the desired core
470  * @param[in]      StdHeader     Configuration parameters pointer
471  *
472  * @return         The current value of the remote cores control byte
473  *
474  */
475 UINT8
476 ApUtilReadRemoteControlByte (
477   IN       UINT32 TargetApicId,
478   IN       AMD_CONFIG_PARAMS *StdHeader
479   )
480 {
481   UINT8  ControlByte;
482   UINT32 ApicRegister;
483
484   ApicRegister = ApUtilRemoteRead (TargetApicId, APIC_CTRL_DWORD, StdHeader);
485   ControlByte = (UINT8) ((ApicRegister & APIC_CTRL_MASK) >> APIC_CTRL_SHIFT);
486   return (ControlByte);
487 }
488
489
490 /*---------------------------------------------------------------------------------------*/
491 /**
492  * Writes the 'control byte' on the executing core.
493  *
494  * This function writes data to a local APIC offset used in inter-
495  * processor communication.
496  *
497  * @param[in]       Value
498  * @param[in]       StdHeader
499  *
500  */
501 VOID
502 ApUtilWriteControlByte (
503   IN       UINT8 Value,
504   IN       AMD_CONFIG_PARAMS *StdHeader
505   )
506 {
507   UINT32 ApicRegister;
508
509   ApicRegister = ApUtilLocalRead (APIC_CTRL_REG, StdHeader);
510   ApicRegister = ((ApicRegister & ~APIC_CTRL_MASK) | (UINT32) (Value << APIC_CTRL_SHIFT));
511   ApUtilLocalWrite (APIC_CTRL_REG, ApicRegister, StdHeader);
512 }
513
514
515 /*---------------------------------------------------------------------------------------*/
516 /**
517  * Reads the 'data dword' on the designated remote core.
518  *
519  * This function will read the current contents of the data dword
520  * on the designated core using the APIC remote read inter-
521  * processor interrupt sequence.
522  *
523  * @param[in]      TargetApicId  Local APIC ID of the desired core
524  * @param[in]      StdHeader     Configuration parameters pointer
525  *
526  * @return         The current value of the remote core's data dword
527  *
528  */
529 UINT32
530 ApUtilReadRemoteDataDword (
531   IN       UINT32 TargetApicId,
532   IN       AMD_CONFIG_PARAMS *StdHeader
533   )
534 {
535   return (ApUtilRemoteRead (TargetApicId, APIC_DATA_DWORD, StdHeader));
536 }
537
538
539 /*---------------------------------------------------------------------------------------*/
540 /**
541  * Writes the 'data dword' on the executing core.
542  *
543  * This function writes data to a local APIC offset used in inter-
544  * processor communication.
545  *
546  * @param[in]      Value        Value to write
547  * @param[in]      StdHeader    Configuration parameters pointer
548  *
549  */
550 VOID
551 ApUtilWriteDataDword (
552   IN       UINT32 Value,
553   IN       AMD_CONFIG_PARAMS *StdHeader
554   )
555 {
556   ApUtilLocalWrite (APIC_DATA_REG, Value, StdHeader);
557 }
558
559
560 /*---------------------------------------------------------------------------------------*/
561 /**
562  * Runs the given task on the specified local core.
563  *
564  * This function is used to invoke an AP to run a specified AGESA
565  * procedure.  It can only be called by cores that have subordinate
566  * APs -- the BSC at POST, or any socket-relative core 0s at Early.
567  *
568  * @param[in]      Socket       Socket number of the target core
569  * @param[in]      Core         Core number of the target core
570  * @param[in]      TaskPtr      Function descriptor
571  * @param[in]      StdHeader    Configuration parameters pointer
572  *
573  * @return         Return value of the task that the AP core ran,
574  *                 or zero if the task was VOID.
575  *
576  */
577 UINT32
578 ApUtilRunCodeOnSocketCore (
579   IN       UINT8   Socket,
580   IN       UINT8   Core,
581   IN       AP_TASK *TaskPtr,
582   IN       AMD_CONFIG_PARAMS *StdHeader
583   )
584 {
585   UINT8  CoreId;
586   UINT8  CurrentStatus;
587   UINT8  WaitStatus[3];
588   UINT32 ApFlags;
589   UINT32 ReturnCode;
590   UINT32 TargetApicId;
591   AP_WAIT_FOR_STATUS WaitForStatus;
592
593   ApFlags = 0;
594   ReturnCode = 0;
595
596   CoreId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
597
598   GetLocalApicIdForCore (Socket, Core, &TargetApicId, StdHeader);
599
600   if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
601     ApFlags |= AP_TASK_HAS_INPUT;
602     if (((TaskPtr->ExeFlags & RETURN_PARAMS) != 0) &&
603         ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
604       ApFlags |= AP_RETURN_PARAMS;
605     }
606   }
607
608   if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
609     ApFlags |= AP_TASK_HAS_OUTPUT;
610   }
611
612   if ((TaskPtr->ExeFlags & END_AT_HLT) != 0) {
613     ApFlags |= AP_END_AT_HLT;
614   }
615
616   if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
617     ApFlags |= AP_PASS_EARLY_PARAMS;
618   }
619
620   WaitStatus[0] = CORE_IDLE;
621   WaitStatus[1] = CORE_IDLE_HLT;
622   WaitStatus[2] = CORE_UNAVAILABLE;
623   WaitForStatus.Status = WaitStatus;
624   WaitForStatus.NumberOfElements = 3;
625   WaitForStatus.RetryCount = WAIT_INFINITELY;
626   WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
627   CurrentStatus = ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
628
629   if (CurrentStatus != CORE_UNAVAILABLE) {
630     ApUtilWriteDataDword (ApFlags, StdHeader);
631     ApUtilWriteControlByte (CoreId, StdHeader);
632
633     if (CurrentStatus == CORE_IDLE_HLT) {
634       ApUtilFireDirectedNmi (TargetApicId, StdHeader);
635     }
636
637     ApUtilTransmitPointer (TargetApicId, (VOID **) &TaskPtr->FuncAddress, StdHeader);
638
639     if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
640       ApUtilTransmitBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader);
641     }
642
643     if ((TaskPtr->ExeFlags & WAIT_FOR_CORE) != 0) {
644       if (((ApFlags & AP_TASK_HAS_INPUT) != 0) &&
645           ((ApFlags & AP_RETURN_PARAMS) != 0) &&
646           ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
647         if (ApUtilReceiveBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader) == AGESA_ERROR) {
648           // There is not enough space to put the return data.  This should never occur.  If it
649           // does, this would point to strange heap corruption.
650           IDS_ERROR_TRAP;
651         }
652       }
653
654       ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
655       if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
656         ReturnCode = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
657       }
658     }
659   } else {
660     ReturnCode = 0;
661   }
662   return (ReturnCode);
663 }
664
665
666 /*---------------------------------------------------------------------------------------*/
667 /**
668  * Waits for a remote core's control byte value to either be equal or
669  * not equal to any number of specified values.
670  *
671  * This function will loop doing remote read IPIs until the remote core's
672  * control byte becomes one of the values in the input array if the input
673  * flags are set for equality.  Otherwise, the loop will continue until
674  * the control byte value is not equal to one of the elements in the
675  * array.  The caller can also specify an iteration count for timeout
676  * purposes.
677  *
678  * @param[in]      TargetApicId   Local APIC ID of the desired core
679  * @param[in]      WaitParamsPtr  Wait parameter structure
680  * @param[in]      StdHeader      Configuration parameteres pointer
681  *
682  * @return         The current value of the remote core's control byte
683  *
684  */
685 UINT8
686 ApUtilWaitForCoreStatus (
687   IN       UINT32 TargetApicId,
688   IN       AP_WAIT_FOR_STATUS *WaitParamsPtr,
689   IN       AMD_CONFIG_PARAMS  *StdHeader
690   )
691 {
692   BOOLEAN  IsEqual;
693   UINT8 CoreStatus;
694   UINT8 i;
695   UINT8 j;
696
697   CoreStatus = 0;
698   for (i = 0; (WaitParamsPtr->RetryCount == WAIT_INFINITELY) ||
699               (i < WaitParamsPtr->RetryCount); ++i) {
700     CoreStatus = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
701     // Determine whether or not the current remote status is equal
702     // to an element in the array.
703     IsEqual = FALSE;
704     for (j = 0; !IsEqual && j < WaitParamsPtr->NumberOfElements; ++j) {
705       if (CoreStatus == WaitParamsPtr->Status[j]) {
706         IsEqual = TRUE;
707       }
708     }
709     if ((((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) != 0) && IsEqual) ||
710         (((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) == 0) && !IsEqual)) {
711       break;
712     }
713   }
714   return (CoreStatus);
715 }
716
717
718 /*---------------------------------------------------------------------------------------*/
719 /**
720  * Runs the AP task on the executing core.
721  *
722  * @param[in]      TaskPtr      Function descriptor
723  * @param[in]      StdHeader    Configuration parameters pointer
724  * @param[in]      ConfigParams Entry point CPU parameters pointer
725  *
726  * @return         Return value of the task, or zero if the task
727  *                 was VOID.
728  *
729  */
730 UINT32
731 ApUtilTaskOnExecutingCore (
732   IN       AP_TASK *TaskPtr,
733   IN       AMD_CONFIG_PARAMS *StdHeader,
734   IN       VOID *ConfigParams
735   )
736 {
737   UINT32   InvocationOptions;
738   UINT32   ReturnCode;
739
740   ReturnCode = 0;
741   InvocationOptions = 0;
742
743   if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
744     InvocationOptions |= AP_TASK_HAS_INPUT;
745   }
746   if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
747     InvocationOptions |= AP_TASK_HAS_OUTPUT;
748   }
749   if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
750     InvocationOptions |= AP_PASS_EARLY_PARAMS;
751   }
752
753   switch (InvocationOptions) {
754   case 0:
755     TaskPtr->FuncAddress.PfApTask (StdHeader);
756     break;
757   case AP_TASK_HAS_INPUT:
758     TaskPtr->FuncAddress.PfApTaskI (TaskPtr->DataTransfer.DataPtr, StdHeader);
759     break;
760   case AP_PASS_EARLY_PARAMS:
761     TaskPtr->FuncAddress.PfApTaskC (StdHeader, ConfigParams);
762     break;
763   case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
764     TaskPtr->FuncAddress.PfApTaskIC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
765     break;
766   case AP_TASK_HAS_OUTPUT:
767     ReturnCode = TaskPtr->FuncAddress.PfApTaskO (StdHeader);
768     break;
769   case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
770     ReturnCode = TaskPtr->FuncAddress.PfApTaskIO (TaskPtr->DataTransfer.DataPtr, StdHeader);
771     break;
772   case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
773     ReturnCode = TaskPtr->FuncAddress.PfApTaskOC (StdHeader, ConfigParams);
774     break;
775   case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
776     ReturnCode = TaskPtr->FuncAddress.PfApTaskIOC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
777     break;
778   default:
779     ReturnCode = 0;
780     break;
781   }
782   return (ReturnCode);
783 }
784
785 /*---------------------------------------------------------------------------------------*/
786 /**
787  * Sets up the AP's IDT with NMI (INT2) being the only valid descriptor
788  *
789  * This function prepares the executing AP core for recovering from a hlt
790  * instruction by initializing its IDTR.
791  *
792  * @param[in]        NmiIdtDescPtr Pointer to a writable IDT entry to
793  *                                 be used for NMIs
794  * @param[in]        StdHeader     Configuration parameters pointer
795  *
796  */
797 VOID
798 STATIC
799 ApUtilSetupIdtForHlt (
800   IN       IDT_DESCRIPTOR *NmiIdtDescPtr,
801   IN       AMD_CONFIG_PARAMS *StdHeader
802   )
803 {
804   UINT8   DescSize;
805   UINT64  HandlerOffset;
806   UINT64  EferRegister;
807   IDT_BASE_LIMIT IdtInfo;
808
809   LibAmdMsrRead (MSR_EXTENDED_FEATURE_EN, &EferRegister, StdHeader);
810   if ((EferRegister & 0x100) != 0) {
811     DescSize = 16;
812   } else {
813     DescSize = 8;
814   }
815
816   HandlerOffset = (UINT64) NmiHandler;
817   NmiIdtDescPtr->OffsetLo = (UINT16) HandlerOffset & 0xFFFF;
818   NmiIdtDescPtr->OffsetHi = (UINT16) (HandlerOffset >> 16);
819   GetCsSelector (&NmiIdtDescPtr->Selector, StdHeader);
820   NmiIdtDescPtr->Flags = IDT_DESC_PRESENT | IDT_DESC_TYPE_INT32;
821   NmiIdtDescPtr->Rsvd = 0;
822   NmiIdtDescPtr->Offset64 = (UINT32) (HandlerOffset >> 32);
823   NmiIdtDescPtr->Rsvd64 = 0;
824   IdtInfo.Limit = (UINT16) ((DescSize * 3) - 1);
825   IdtInfo.Base = (UINT64) NmiIdtDescPtr - (DescSize * 2);
826   IDS_EXCEPTION_TRAP (IDS_IDT_UPDATE_EXCEPTION_VECTOR_FOR_AP, &IdtInfo, StdHeader);
827   SetIdtr (&IdtInfo , StdHeader);
828 }
829
830
831 /*---------------------------------------------------------------------------------------*/
832 /**
833  * Calculate the APIC ID for a given core.
834  *
835  * Get the current node's apic id and deconstruct it to the base id of local apic id space.
836  * Then construct the target's apic id using that base.
837  * @b Assumes: The target Socket and Core exist!
838  * Other Notes:
839  *  - Must run after HT initialization is complete.
840  *  - Code sync: This calculation MUST match the assignment
841  *    calculation done above in LocalApicInitializationAtEarly function.
842  *  - Assumes family homogeneous population of all sockets.
843  *
844  *  @param[in]      TargetSocket   The socket in which the Core's Processor is installed.
845  *  @param[in]      TargetCore     The Core on that Processor
846  *  @param[out]     LocalApicId    Its APIC Id
847  *  @param[in]      StdHeader      Handle to header for library and services.
848  *
849  */
850 VOID
851 GetLocalApicIdForCore (
852   IN       UINT32            TargetSocket,
853   IN       UINT32            TargetCore,
854      OUT   UINT32            *LocalApicId,
855   IN       AMD_CONFIG_PARAMS *StdHeader
856   )
857 {
858   UINT32  CoreIdBits;
859   UINT32  CurrentNode;
860   UINT32  CurrentCore;
861   UINT32  TargetNode;
862   UINT32  MaxCoresInProcessor;
863   UINT32  TotalCores;
864   UINT32  CurrentLocalApicId;
865   UINT64  LocalApicBase;
866   UINT32  TempVar_a;
867   UINT64  Address;
868   UINT32  ProcessorApicIndex;
869   BOOLEAN ReturnResult;
870   CPUID_DATA  CpuidData;
871
872   TargetNode = 0;
873
874   // Get local apic base Address
875   ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
876   Address = LocalApicBase + APIC_ID_REG;
877
878   LibAmdMemRead (AccessWidth32, Address, &TempVar_a, StdHeader);
879
880   // ApicId [7:0]
881   CurrentLocalApicId = (TempVar_a >> APIC20_ApicId) & 0x000000FF;
882
883   GetCurrentNodeAndCore (&CurrentNode, &CurrentCore, StdHeader);
884   LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
885   CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
886   MaxCoresInProcessor = (1 << CoreIdBits);
887
888   // Get the APIC Index of this processor.
889   ProcessorApicIndex = GetProcessorApicIndex (CurrentNode, StdHeader);
890
891   TotalCores = (MaxCoresInProcessor * ProcessorApicIndex) + CurrentCore;
892   CurrentLocalApicId -= TotalCores;
893
894   // Use the Node Id of TargetSocket, Module 0.  No socket transitions are missed or added,
895   // even if the TargetCore is not on Module 0 in that processor and that's all that matters now.
896   ReturnResult = GetNodeId (TargetSocket, 0, (UINT8 *)&TargetNode, StdHeader);
897   ASSERT (ReturnResult);
898
899   // Get the APIC Index of this processor.
900   ProcessorApicIndex = GetProcessorApicIndex (TargetNode, StdHeader);
901
902   CurrentLocalApicId += ((MaxCoresInProcessor * ProcessorApicIndex) + TargetCore);
903   *LocalApicId = CurrentLocalApicId;
904 }
905
906 /*---------------------------------------------------------------------------------------*/
907 /**
908  * Securely passes a buffer to the designated remote core.
909  *
910  * This function uses a sequence of remote reads to transmit a data
911  * buffer, one UINT32 at a time.
912  *
913  * @param[in]      Socket       Socket number of the remote core
914  * @param[in]      Core         Core number of the remote core
915  * @param[in]      BufferInfo   Information about the buffer to pass, and
916  *                              how to pass it
917  * @param[in]      StdHeader    Configuration parameters pointer
918  *
919  */
920 VOID
921 ApUtilTransmitBuffer (
922   IN       UINT8   Socket,
923   IN       UINT8   Core,
924   IN       AP_DATA_TRANSFER  *BufferInfo,
925   IN       AMD_CONFIG_PARAMS *StdHeader
926   )
927 {
928   UINT8  TargetCore;
929   UINT8  MyUniqueId;
930   UINT8  CurrentStatus;
931   UINT32 *CurrentPtr;
932   UINT32 i;
933   UINT32 MyCore;
934   UINT32 MySocket;
935   UINT32 Ignored;
936   UINT32 TargetApicId;
937   AP_WAIT_FOR_STATUS WaitForStatus;
938   AGESA_STATUS IgnoredSts;
939
940   GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
941
942   if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
943     ApUtilWriteDataDword ((UINT32) 0x00000000, StdHeader);
944   } else {
945     ApUtilWriteDataDword ((UINT32) BufferInfo->DataSizeInDwords, StdHeader);
946   }
947   TargetCore = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
948
949   ApUtilWriteControlByte (TargetCore, StdHeader);
950
951   IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &IgnoredSts);
952
953   MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
954
955   WaitForStatus.Status = &MyUniqueId;
956   WaitForStatus.NumberOfElements = 1;
957   WaitForStatus.RetryCount = WAIT_INFINITELY;
958   WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
959
960   ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
961   ApUtilWriteDataDword (BufferInfo->DataTransferFlags, StdHeader);
962
963   ApUtilWriteControlByte (CORE_DATA_FLAGS_READY, StdHeader);
964   WaitForStatus.WaitForStatusFlags = 0;
965   ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
966   if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
967     ApUtilTransmitPointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
968   } else {
969     ApUtilWriteControlByte (CORE_STS_DATA_READY_1, StdHeader);
970     CurrentStatus = CORE_STS_DATA_READY_0;
971     WaitForStatus.Status = &CurrentStatus;
972     WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
973     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
974     WaitForStatus.WaitForStatusFlags = 0;
975     CurrentPtr = (UINT32 *) BufferInfo->DataPtr;
976     for (i = 0; i < BufferInfo->DataSizeInDwords; ++i) {
977       ApUtilWriteDataDword (*CurrentPtr++, StdHeader);
978       ApUtilWriteControlByte (CurrentStatus, StdHeader);
979       ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
980       CurrentStatus ^= 0x01;
981     }
982   }
983   ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
984 }
985
986
987 /*---------------------------------------------------------------------------------------*/
988 /**
989  * Securely receives a buffer from the designated remote core.
990  *
991  * This function uses a sequence of remote reads to receive a data
992  * buffer, one UINT32 at a time.
993  *
994  * @param[in]      Socket       Socket number of the remote core
995  * @param[in]      Core         Core number of the remote core
996  * @param[in]      BufferInfo   Information about where to place the buffer
997  * @param[in]      StdHeader    Configuration parameters pointer
998  *
999  * @retval         AGESA_SUCCESS Transaction was successful
1000  * @retval         AGESA_ALERT   The non-NULL desired location to place
1001  *                               the buffer was not used as the buffer
1002  *                               resides in a shared memory space.  The
1003  *                               input data pointer has changed.
1004  * @retval         AGESA_ERROR   There is not enough room to receive the
1005  *                               buffer.
1006  *
1007  */
1008 AGESA_STATUS
1009 ApUtilReceiveBuffer (
1010   IN       UINT8   Socket,
1011   IN       UINT8   Core,
1012   IN OUT   AP_DATA_TRANSFER  *BufferInfo,
1013   IN       AMD_CONFIG_PARAMS *StdHeader
1014   )
1015 {
1016   UINT8    MyUniqueId;
1017   UINT8    SourceUniqueId;
1018   UINT8    CurrentStatus;
1019   UINT32   i;
1020   UINT32   MySocket;
1021   UINT32   MyCore;
1022   UINT32   Ignored;
1023   UINT32   *CurrentPtr;
1024   UINT32   TransactionSize;
1025   UINT32   TargetApicId;
1026   AGESA_STATUS ReturnStatus;
1027   ALLOCATE_HEAP_PARAMS HeapMalloc;
1028   AP_WAIT_FOR_STATUS WaitForStatus;
1029
1030   ReturnStatus = AGESA_SUCCESS;
1031   IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &ReturnStatus);
1032
1033   MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
1034
1035   GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
1036
1037   WaitForStatus.Status = &MyUniqueId;
1038   WaitForStatus.NumberOfElements = 1;
1039   WaitForStatus.RetryCount = WAIT_INFINITELY;
1040   WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1041
1042   ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1043   TransactionSize = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1044
1045   if (BufferInfo->DataPtr == NULL && TransactionSize != 0) {
1046     HeapMalloc.BufferHandle = AMD_CPU_AP_TASKING_HANDLE;
1047     HeapMalloc.Persist = HEAP_LOCAL_CACHE;
1048     // Deallocate the general purpose heap structure, if it exists.  Ignore
1049     // the status in case it does not exist.
1050     HeapDeallocateBuffer (HeapMalloc.BufferHandle, StdHeader);
1051     HeapMalloc.RequestedBufferSize = (TransactionSize * XFER_ELEMENT_SIZE);
1052     if (HeapAllocateBuffer (&HeapMalloc, StdHeader) == AGESA_SUCCESS) {
1053       BufferInfo->DataPtr = (UINT32 *) HeapMalloc.BufferPtr;
1054       BufferInfo->DataSizeInDwords = (UINT16) (HeapMalloc.RequestedBufferSize / XFER_ELEMENT_SIZE);
1055     } else {
1056       BufferInfo->DataSizeInDwords = 0;
1057     }
1058   }
1059
1060   if (TransactionSize <= BufferInfo->DataSizeInDwords) {
1061     SourceUniqueId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
1062     ApUtilWriteControlByte (SourceUniqueId, StdHeader);
1063     CurrentStatus = CORE_DATA_FLAGS_READY;
1064     WaitForStatus.Status = &CurrentStatus;
1065     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1066     BufferInfo->DataTransferFlags =  ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1067     ApUtilWriteControlByte (CORE_DATA_FLAGS_ACKNOWLEDGE, StdHeader);
1068     if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
1069       if (BufferInfo->DataPtr != NULL) {
1070         ReturnStatus = AGESA_ALERT;
1071       }
1072       ApUtilReceivePointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
1073     } else {
1074       CurrentStatus = CORE_STS_DATA_READY_1;
1075       ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1076       CurrentStatus = CORE_STS_DATA_READY_0;
1077       ApUtilWriteControlByte (CurrentStatus, StdHeader);
1078       CurrentPtr = BufferInfo->DataPtr;
1079       for (i = 0; i < TransactionSize; ++i) {
1080         ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1081         *CurrentPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1082         CurrentStatus ^= 0x01;
1083         ApUtilWriteControlByte (CurrentStatus, StdHeader);
1084       }
1085     }
1086     ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1087   } else {
1088     BufferInfo->DataSizeInDwords = (UINT16) TransactionSize;
1089     ReturnStatus = AGESA_ERROR;
1090   }
1091   return (ReturnStatus);
1092 }
1093
1094
1095 VOID
1096 RelinquishControlOfAllAPs (
1097   IN       AMD_CONFIG_PARAMS   *StdHeader
1098   )
1099 {
1100   UINT32        BscSocket;
1101   UINT32        Ignored;
1102   UINT32        BscCoreNum;
1103   UINT32        Core;
1104   UINT32        Socket;
1105   UINT32        NumberOfSockets;
1106   AP_TASK       TaskPtr;
1107   AGESA_STATUS  IgnoredSts;
1108
1109   ASSERT (IsBsp (StdHeader, &IgnoredSts));
1110
1111   TaskPtr.FuncAddress.PfApTask = PerformFinalHalt;
1112   TaskPtr.DataTransfer.DataSizeInDwords = 0;
1113   TaskPtr.ExeFlags = WAIT_FOR_CORE;
1114
1115   IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
1116   NumberOfSockets = GetPlatformNumberOfSockets ();
1117
1118   for (Socket = 0; Socket < NumberOfSockets; Socket++) {
1119     if (GetActiveCoresInGivenSocket (Socket, &Core, StdHeader)) {
1120       while (Core-- > 0) {
1121         if ((Socket != BscSocket) || (Core != BscCoreNum)) {
1122           ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
1123         }
1124       }
1125     }
1126   }
1127 }
1128
1129 /*---------------------------------------------------------------------------------------
1130  *                           L O C A L    F U N C T I O N S
1131  *---------------------------------------------------------------------------------------
1132  */
1133
1134 /*---------------------------------------------------------------------------------------*/
1135 /**
1136  * The last AGESA code that an AP performs
1137  *
1138  * This function, run only by APs, breaks down their cache subsystem, sets up
1139  * for memory to be present upon wake (from IBV Init/Startup IPIs), and halts.
1140  *
1141  * @param[in]  StdHeader         Config handle for library and services
1142  *
1143  */
1144 VOID
1145 STATIC
1146 PerformFinalHalt (
1147   IN       AMD_CONFIG_PARAMS *StdHeader
1148   )
1149 {
1150   UINT32 PrimaryCore;
1151   UINT32 HaltFlags;
1152   UINT32 CacheEnDis;
1153   CPU_SPECIFIC_SERVICES *FamilyServices;
1154
1155   GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
1156   ASSERT (FamilyServices != NULL);
1157   // CacheEnDis is a family specific flag, that lets the code to decide whether to
1158   // keep the cache control bits set or cleared.
1159   CacheEnDis = FamilyServices->InitCacheDisabled;
1160
1161   // Determine if the current core has the primary core role.  The first core to execute
1162   // in each compute unit has the primary role.
1163   PrimaryCore = (UINT32) IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader);
1164
1165   // Aggregate the flags for the halt service.
1166   HaltFlags = PrimaryCore | (CacheEnDis << 1);
1167
1168   ApUtilWriteControlByte (CORE_UNAVAILABLE, StdHeader);
1169   ExecuteFinalHltInstruction (HaltFlags, UserOptions.CfgApMtrrSettingsList, StdHeader);
1170 }
1171
1172 /*---------------------------------------------------------------------------------------*/
1173 /**
1174  * Reads the APIC register on the designated remote core.
1175  *
1176  * This function uses the remote read inter-processor interrupt protocol
1177  * to read an APIC register from the remote core
1178  *
1179  * @param[in]        TargetApicId  Local APIC ID of the desired core
1180  * @param[in]        RegAddr       APIC register to read
1181  * @param[in]        StdHeader     Configuration parameters pointer
1182  *
1183  * @return           The current value of the remote core's desired APIC register
1184  *
1185  */
1186 UINT32
1187 STATIC
1188 ApUtilRemoteRead (
1189   IN       UINT32            TargetApicId,
1190   IN       UINT8             RegAddr,
1191   IN       AMD_CONFIG_PARAMS *StdHeader
1192   )
1193 {
1194   UINT32 ApicRegister;
1195   UINT64 ApicBase;
1196   UINT64 ApicAddr;
1197
1198   ApUtilGetLocalApicBase (&ApicBase, StdHeader);
1199   TargetApicId <<= LOCAL_APIC_ID;
1200
1201   do {
1202     ApicAddr = ApicBase + APIC_CMD_HI_REG;
1203     LibAmdMemWrite (AccessWidth32, ApicAddr, &TargetApicId, StdHeader);
1204     ApicAddr = ApicBase + APIC_CMD_LO_REG;
1205     ApicRegister = CMD_REG_TO_READ | (UINT32) RegAddr;
1206     LibAmdMemWrite (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1207     do {
1208       LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1209     } while ((ApicRegister & CMD_REG_DELIVERY_STATUS) != 0);
1210     while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) == CMD_REG_REMOTE_DELIVERY_PENDING) {
1211       LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1212     }
1213   } while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) != CMD_REG_REMOTE_DELIVERY_DONE);
1214   ApicAddr = ApicBase + APIC_REMOTE_READ_REG;
1215   LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1216   return (ApicRegister);
1217 }
1218
1219
1220 /*---------------------------------------------------------------------------------------*/
1221 /**
1222  * Writes an APIC register on the executing core.
1223  *
1224  * This function gets the base address of the executing core's local APIC,
1225  * and writes a UINT32 value to a specified offset.
1226  *
1227  * @param[in]      RegAddr      APIC register to write to
1228  * @param[in]      Value        Data to be written to the desired APIC register
1229  * @param[in]      StdHeader    Configuration parameters pointer
1230  *
1231  */
1232 VOID
1233 STATIC
1234 ApUtilLocalWrite (
1235   IN       UINT32 RegAddr,
1236   IN       UINT32 Value,
1237   IN       AMD_CONFIG_PARAMS *StdHeader
1238   )
1239 {
1240   UINT64 ApicAddr;
1241
1242   ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1243   ApicAddr += RegAddr;
1244
1245   LibAmdMemWrite (AccessWidth32, ApicAddr, &Value, StdHeader);
1246 }
1247
1248
1249 /*---------------------------------------------------------------------------------------*/
1250 /**
1251  * Reads an APIC register on the executing core.
1252  *
1253  * This function gets the base address of the executing core's local APIC,
1254  * and reads a UINT32 value from a specified offset.
1255  *
1256  * @param[in]      RegAddr      APIC register to read from
1257  * @param[in]      StdHeader    Configuration parameters pointer
1258  *
1259  * @return         The current value of the local APIC register
1260  *
1261  */
1262 UINT32
1263 STATIC
1264 ApUtilLocalRead (
1265   IN       UINT32  RegAddr,
1266   IN       AMD_CONFIG_PARAMS *StdHeader
1267   )
1268 {
1269   UINT32 ApicRegister;
1270   UINT64 ApicAddr;
1271
1272   ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1273   ApicAddr += RegAddr;
1274   LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1275
1276   return (ApicRegister);
1277 }
1278
1279
1280 /*---------------------------------------------------------------------------------------*/
1281 /**
1282  * Returns the 64-bit base address of the executing core's local APIC.
1283  *
1284  * This function reads the APICBASE MSR and isolates the programmed address.
1285  *
1286  * @param[out]     ApicBase     Base address
1287  * @param[in]      StdHeader    Configuration parameters pointer
1288  *
1289  */
1290 VOID
1291 STATIC
1292 ApUtilGetLocalApicBase (
1293      OUT   UINT64 *ApicBase,
1294   IN       AMD_CONFIG_PARAMS *StdHeader
1295   )
1296 {
1297   LibAmdMsrRead (MSR_APIC_BAR, ApicBase, StdHeader);
1298   *ApicBase &= LAPIC_BASE_ADDR_MASK;
1299 }
1300
1301
1302 /*---------------------------------------------------------------------------------------*/
1303 /**
1304  * Determines the unique ID of the input Socket/Core.
1305  *
1306  * This routine converts a socket-core combination to to a number
1307  * that will be used to directly address a particular core.  This
1308  * unique value must be less than 128 because we only have a byte
1309  * to use for status.  APIC IDs are not guaranteed to be below
1310  * 128.
1311  *
1312  * @param[in]      Socket       Socket number of the remote core
1313  * @param[in]      Core         Core number of the remote core
1314  * @param[in]      StdHeader    Configuration parameters pointer
1315  *
1316  * @return         The unique ID of the desired core
1317  *
1318  */
1319 UINT8
1320 STATIC
1321 ApUtilCalculateUniqueId (
1322   IN       UINT8 Socket,
1323   IN       UINT8 Core,
1324   IN       AMD_CONFIG_PARAMS *StdHeader
1325   )
1326 {
1327   UINT8 UniqueId;
1328
1329   UniqueId = ((Core << 3) | Socket);
1330   ASSERT ((UniqueId & 0x80) == 0);
1331   return (UniqueId);
1332 }
1333
1334
1335 /*---------------------------------------------------------------------------------------*/
1336 /**
1337  * Wakes up a core from the halted state.
1338  *
1339  * This function sends a directed NMI inter-processor interrupt to
1340  * the input Socket/Core.
1341  *
1342  * @param[in]      TargetApicId    Local APIC ID of the desired core
1343  * @param[in]      StdHeader       Configuration parameters pointer
1344  *
1345  */
1346 VOID
1347 STATIC
1348 ApUtilFireDirectedNmi (
1349   IN       UINT32 TargetApicId,
1350   IN       AMD_CONFIG_PARAMS *StdHeader
1351   )
1352 {
1353   TargetApicId <<= LOCAL_APIC_ID;
1354
1355   ApUtilLocalWrite ((UINT32) APIC_CMD_HI_REG, TargetApicId, StdHeader);
1356   ApUtilLocalWrite ((UINT32) APIC_CMD_LO_REG, (UINT32) CMD_REG_TO_NMI, StdHeader);
1357 }
1358
1359
1360 /*---------------------------------------------------------------------------------------*/
1361 /**
1362  * Securely receives a pointer from the designated remote core.
1363  *
1364  * This function uses a sequence of remote reads to receive a pointer,
1365  * one UINT32 at a time.
1366  *
1367  * @param[in]      TargetApicId  Local APIC ID of the desired core
1368  * @param[out]     ReturnPointer Pointer passed from remote core
1369  * @param[in]      StdHeader     Configuration parameters pointer
1370  *
1371  */
1372 VOID
1373 STATIC
1374 ApUtilReceivePointer (
1375   IN       UINT32 TargetApicId,
1376      OUT   VOID  **ReturnPointer,
1377   IN       AMD_CONFIG_PARAMS *StdHeader
1378   )
1379 {
1380   UINT8   i;
1381   UINT8   WaitStatus;
1382   UINT32  *AddressScratchPtr;
1383   AP_WAIT_FOR_STATUS WaitForStatus;
1384
1385   WaitStatus = CORE_STS_DATA_READY_0;
1386   WaitForStatus.Status = &WaitStatus;
1387   WaitForStatus.NumberOfElements = 1;
1388   WaitForStatus.RetryCount = WAIT_INFINITELY;
1389   AddressScratchPtr = (UINT32 *) ReturnPointer;
1390   for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); ++i) {
1391     ApUtilWriteControlByte (CORE_NEEDS_PTR, StdHeader);
1392     WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1393     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1394     *AddressScratchPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1395     ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1396     WaitForStatus.WaitForStatusFlags = 0;
1397     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1398   }
1399 }
1400
1401
1402 /*---------------------------------------------------------------------------------------*/
1403 /**
1404  * Securely transmits a pointer to the designated remote core.
1405  *
1406  * This function uses a sequence of remote reads to transmit a pointer,
1407  * one UINT32 at a time.
1408  *
1409  * @param[in]      TargetApicId  Local APIC ID of the desired core
1410  * @param[out]     Pointer       Pointer passed from remote core
1411  * @param[in]      StdHeader     Configuration parameters pointer
1412  *
1413  */
1414 VOID
1415 STATIC
1416 ApUtilTransmitPointer (
1417   IN       UINT32 TargetApicId,
1418   IN       VOID  **Pointer,
1419   IN       AMD_CONFIG_PARAMS *StdHeader
1420   )
1421 {
1422   UINT8   i;
1423   UINT8   WaitStatus;
1424   UINT32  *AddressScratchPtr;
1425   AP_WAIT_FOR_STATUS WaitForStatus;
1426
1427   WaitStatus = CORE_NEEDS_PTR;
1428   WaitForStatus.Status = &WaitStatus;
1429   WaitForStatus.NumberOfElements = 1;
1430   WaitForStatus.RetryCount = WAIT_INFINITELY;
1431
1432   AddressScratchPtr = (UINT32 *) Pointer;
1433
1434   for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); i++) {
1435     WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1436     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1437     ApUtilWriteDataDword (*AddressScratchPtr++, StdHeader);
1438     ApUtilWriteControlByte (CORE_STS_DATA_READY_0, StdHeader);
1439     WaitForStatus.WaitForStatusFlags = 0;
1440     ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1441     ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1442   }
1443 }