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