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