5 * AMD CPU APIC related utility functions.
7 * Contains code that provides mechanism to invoke and control APIC communication.
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 44325 $ @e \$Date: 2010-12-22 03:29:53 -0700 (Wed, 22 Dec 2010) $
16 *****************************************************************************
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
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.
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.
43 * ***************************************************************************
47 /*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
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"
63 RDATA_GROUP (G1_PEICC)
65 #define FILECODE PROC_CPU_CPUAPICUTILITIES_FILECODE
67 /*----------------------------------------------------------------------------------------
68 * D E F I N I T I O N S A N D M A C R O S
69 *----------------------------------------------------------------------------------------
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
78 #define SEG_DESC_PRESENT 0x80
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
89 #define XFER_ELEMENT_SIZE sizeof (UINT32)
91 /*----------------------------------------------------------------------------------------
92 * T Y P E D E F S A N D S T R U C T U R E S
93 *----------------------------------------------------------------------------------------
96 typedef VOID F_CPU_AMD_NMI_HANDLER (
97 IN AMD_CONFIG_PARAMS *StdHeader
99 typedef F_CPU_AMD_NMI_HANDLER *PF_CPU_AMD_NMI_HANDLER;
101 /// Interrupt Descriptor Table entry
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
112 /// Structure needed to load the IDTR using the lidt instruction
114 // UINT16 Limit; ///< Interrupt Descriptor Table size
115 // UINT64 Base; ///< Interrupt Descriptor Table base address
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 *----------------------------------------------------------------------------------------
124 ApUtilSetupIdtForHlt (
125 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
126 IN AMD_CONFIG_PARAMS *StdHeader
135 IN AMD_CONFIG_PARAMS *StdHeader
143 IN AMD_CONFIG_PARAMS *StdHeader
150 IN AMD_CONFIG_PARAMS *StdHeader
155 ApUtilGetLocalApicBase (
156 OUT UINT64 *ApicBase,
157 IN AMD_CONFIG_PARAMS *StdHeader
162 ApUtilCalculateUniqueId (
165 IN AMD_CONFIG_PARAMS *StdHeader
170 ApUtilFireDirectedNmi (
173 IN AMD_CONFIG_PARAMS *StdHeader
178 ApUtilReceivePointer (
181 OUT VOID **ReturnPointer,
182 IN AMD_CONFIG_PARAMS *StdHeader
187 ApUtilTransmitPointer (
191 IN AMD_CONFIG_PARAMS *StdHeader
197 IN AMD_CONFIG_PARAMS *StdHeader
201 LocalApicInitialization (
202 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
203 IN AMD_CONFIG_PARAMS *StdHeader
207 LocalApicInitializationAtEarly (
208 IN CPU_SPECIFIC_SERVICES *FamilyServices,
209 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
210 IN AMD_CONFIG_PARAMS *StdHeader
213 /*----------------------------------------------------------------------------------------
214 * E X P O R T E D F U N C T I O N S
215 *----------------------------------------------------------------------------------------
219 ExecuteHltInstruction (
220 IN AMD_CONFIG_PARAMS *StdHeader
227 IN AMD_CONFIG_PARAMS *StdHeader
233 IN AMD_CONFIG_PARAMS *StdHeader
239 IN IDT_BASE_LIMIT *IdtInfo,
240 IN AMD_CONFIG_PARAMS *StdHeader
245 ExecuteFinalHltInstruction (
246 IN UINT32 SharedCore,
247 IN AP_MTRR_SETTINGS *ApMtrrSettingsList,
248 IN AMD_CONFIG_PARAMS *StdHeader
251 extern BUILD_OPT_CFG UserOptions;
253 /*---------------------------------------------------------------------------------------*/
255 * Initialize the Local APIC.
257 * This function determines and programs the appropriate APIC ID value
258 * for the executing core. This code must be run after HT initialization
261 * @param[in] CpuEarlyParamsPtr Service parameters.
262 * @param[in] StdHeader Config handle for library and services.
266 LocalApicInitialization (
267 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
268 IN AMD_CONFIG_PARAMS *StdHeader
272 UINT32 CurrentNodeNum;
275 UINT32 ProcessorCount;
276 UINT32 ProcessorApicIndex;
278 UINT32 StartLocalApicId;
279 UINT64 LocalApicBase;
283 CPUID_DATA CpuidData;
285 // Local variables default values
286 IoApicNum = CpuEarlyParamsPtr->PlatformConfig.NumberOfIoApics;
288 GetCurrentCore (&CurrentCore, StdHeader);
289 GetCurrentNodeNum (&CurrentNodeNum, StdHeader);
292 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
293 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
294 Mnc = 1 << (CoreIdBits & 0x000F);
296 // Get ProcessorCount in the system
297 ProcessorCount = GetNumberOfProcessors (StdHeader);
299 // Get the APIC Index of this processor.
300 ProcessorApicIndex = GetProcessorApicIndex (CurrentNodeNum, StdHeader);
302 TempVar_a = (Mnc * ProcessorCount) + IoApicNum;
303 ASSERT (TempVar_a < 255);
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;
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;
325 // Enable local apic id
326 LibAmdMsrRead (MSR_APIC_BAR, &MsrData, StdHeader);
327 MsrData |= APIC_ENABLE_BIT;
328 LibAmdMsrWrite (MSR_APIC_BAR, &MsrData, StdHeader);
330 // Get local apic base Address
331 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
333 Address = LocalApicBase + APIC_ID_REG;
334 LibAmdMemWrite (AccessWidth32, Address, &TempVar_a, StdHeader);
337 /*---------------------------------------------------------------------------------------*/
339 * Initialize the Local APIC at the AmdInitEarly entry point.
341 * This function acts as a wrapper for calling the LocalApicInitialization
342 * routine at AmdInitEarly.
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.
350 LocalApicInitializationAtEarly (
351 IN CPU_SPECIFIC_SERVICES *FamilyServices,
352 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
353 IN AMD_CONFIG_PARAMS *StdHeader
356 AGESA_TESTPOINT (TpProcCpuLocalApicInit, StdHeader);
357 LocalApicInitialization (EarlyParams, StdHeader);
361 /*---------------------------------------------------------------------------------------*/
363 * Main entry point for all APs in the system.
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.
372 * @param[in] StdHeader Handle to config for library and services.
373 * @param[in] CpuEarlyParams AMD_CPU_EARLY_PARAMS pointer.
378 IN AMD_CONFIG_PARAMS *StdHeader,
379 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
388 UINT32 CurrentSocket;
390 UINT32 *InputDataPtr;
393 AP_FUNCTION_PTR FuncAddress;
394 IDT_DESCRIPTOR IdtDesc;
395 AP_DATA_TRANSFER DataTransferInfo;
396 AGESA_STATUS IgnoredSts;
398 ASSERT (!IsBsp (StdHeader, &IgnoredSts));
400 // Initialize local variables
402 DataTransferInfo.DataTransferFlags = 0;
405 // Determine the executing core's socket and core numbers
406 IdentifyCore (StdHeader, &CurrentSocket, &Ignored, &CurrentCore, &IgnoredSts);
408 IDS_HDT_CONSOLE (CPU_TRACE, " Socket %d core %d begin AP tasking engine\n", CurrentSocket, CurrentCore);
410 // Determine the BSC's socket number
411 GetSocketModuleOfNode ((UINT32) 0x00000000, &BscSocket, &Ignored, StdHeader);
413 // Setup Interrupt Descriptor Table for sleep mode
414 ApUtilSetupIdtForHlt (&IdtDesc, StdHeader);
416 // Indicate to the BSC that we have reached the tasking engine
417 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
419 if (CurrentCore == 0) {
420 // Core 0s receive their tasks from the BSC
421 SourceSocket = (UINT8) BscSocket;
423 // All non-zero cores receive their tasks from the core 0 of their socket
424 SourceSocket = (UINT8) CurrentSocket;
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,
435 RemoteCmd = ApUtilReadRemoteControlByte (SourceSocket, 0, StdHeader);
436 if (RemoteCmd == CommandStart) {
437 ApFlags = ApUtilReadRemoteDataDword (SourceSocket, 0, StdHeader);
439 ApUtilReceivePointer (SourceSocket, 0, (VOID **) &FuncAddress, StdHeader);
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
451 InputDataPtr = (UINT32 *) DataTransferInfo.DataPtr;
453 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
456 FuncAddress.PfApTask (StdHeader);
458 case AP_TASK_HAS_INPUT:
459 FuncAddress.PfApTaskI (InputDataPtr, StdHeader);
461 case AP_PASS_EARLY_PARAMS:
462 FuncAddress.PfApTaskC (StdHeader, CpuEarlyParams);
464 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
465 FuncAddress.PfApTaskIC (InputDataPtr, StdHeader, CpuEarlyParams);
467 case AP_TASK_HAS_OUTPUT:
468 ReturnCode = FuncAddress.PfApTaskO (StdHeader);
470 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
471 ReturnCode = FuncAddress.PfApTaskIO (InputDataPtr, StdHeader);
473 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
474 ReturnCode = FuncAddress.PfApTaskOC (StdHeader, CpuEarlyParams);
476 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
477 ReturnCode = FuncAddress.PfApTaskIOC (InputDataPtr, StdHeader, CpuEarlyParams);
483 if (((ApFlags & AP_RETURN_PARAMS) != 0)) {
484 ApUtilTransmitBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader);
486 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
487 ApUtilWriteDataDword (ReturnCode, StdHeader);
489 if ((ApFlags & AP_END_AT_HLT) != 0) {
490 RemoteCmd = CORE_IDLE_HLT;
492 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
495 if (RemoteCmd == CORE_IDLE_HLT) {
496 SourceSocket = (UINT8) BscSocket;
497 ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
498 ExecuteHltInstruction (StdHeader);
499 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
505 /*---------------------------------------------------------------------------------------*/
507 * Reads the 'control byte' on the designated remote core.
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.
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
517 * @return The current value of the remote cores control byte
521 ApUtilReadRemoteControlByte (
524 IN AMD_CONFIG_PARAMS *StdHeader
530 ApicRegister = ApUtilRemoteRead (Socket, Core, APIC_CTRL_DWORD, StdHeader);
531 ControlByte = (UINT8) ((ApicRegister & APIC_CTRL_MASK) >> APIC_CTRL_SHIFT);
532 return (ControlByte);
536 /*---------------------------------------------------------------------------------------*/
538 * Writes the 'control byte' on the executing core.
540 * This function writes data to a local APIC offset used in inter-
541 * processor communication.
544 * @param[in] StdHeader
548 ApUtilWriteControlByte (
550 IN AMD_CONFIG_PARAMS *StdHeader
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);
561 /*---------------------------------------------------------------------------------------*/
563 * Reads the 'data dword' on the designated remote core.
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.
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
573 * @return The current value of the remote core's data dword
577 ApUtilReadRemoteDataDword (
580 IN AMD_CONFIG_PARAMS *StdHeader
583 return (ApUtilRemoteRead (Socket, Core, APIC_DATA_DWORD, StdHeader));
587 /*---------------------------------------------------------------------------------------*/
589 * Writes the 'data dword' on the executing core.
591 * This function writes data to a local APIC offset used in inter-
592 * processor communication.
594 * @param[in] Value Value to write
595 * @param[in] StdHeader Configuration parameters pointer
599 ApUtilWriteDataDword (
601 IN AMD_CONFIG_PARAMS *StdHeader
604 ApUtilLocalWrite (APIC_DATA_REG, Value, StdHeader);
608 /*---------------------------------------------------------------------------------------*/
610 * Runs the given task on the specified local core.
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.
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
621 * @return Return value of the task that the AP core ran,
622 * or zero if the task was VOID.
626 ApUtilRunCodeOnSocketCore (
630 IN AMD_CONFIG_PARAMS *StdHeader
638 AP_WAIT_FOR_STATUS WaitForStatus;
643 CoreId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
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;
653 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
654 ApFlags |= AP_TASK_HAS_OUTPUT;
657 if ((TaskPtr->ExeFlags & END_AT_HLT) != 0) {
658 ApFlags |= AP_END_AT_HLT;
661 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
662 ApFlags |= AP_PASS_EARLY_PARAMS;
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);
674 if (CurrentStatus != CORE_UNAVAILABLE) {
675 ApUtilWriteDataDword (ApFlags, StdHeader);
676 ApUtilWriteControlByte (CoreId, StdHeader);
678 if (CurrentStatus == CORE_IDLE_HLT) {
679 ApUtilFireDirectedNmi (Socket, Core, StdHeader);
682 ApUtilTransmitPointer (Socket, Core, (VOID **) &TaskPtr->FuncAddress, StdHeader);
684 if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
685 ApUtilTransmitBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader);
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.
699 ApUtilWaitForCoreStatus (Socket, Core, &WaitForStatus, StdHeader);
700 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
701 ReturnCode = ApUtilReadRemoteDataDword (Socket, Core, StdHeader);
711 /*---------------------------------------------------------------------------------------*/
713 * Waits for a remote core's control byte value to either be equal or
714 * not equal to any number of specified values.
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
725 * @param[in] WaitParamsPtr
726 * @param[in] StdHeader
728 * @return The current value of the remote core's control byte
732 ApUtilWaitForCoreStatus (
735 IN AP_WAIT_FOR_STATUS *WaitParamsPtr,
736 IN AMD_CONFIG_PARAMS *StdHeader
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.
751 for (j = 0; !IsEqual && j < WaitParamsPtr->NumberOfElements; ++j) {
752 if (CoreStatus == WaitParamsPtr->Status[j]) {
756 if ((((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) != 0) && IsEqual) ||
757 (((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) == 0) && !IsEqual)) {
765 /*---------------------------------------------------------------------------------------*/
767 * Runs the AP task on the executing core.
769 * @param[in] TaskPtr Function descriptor
770 * @param[in] StdHeader Configuration parameters pointer
771 * @param[in] ConfigParams Entry point CPU parameters pointer
773 * @return Return value of the task, or zero if the task
778 ApUtilTaskOnExecutingCore (
780 IN AMD_CONFIG_PARAMS *StdHeader,
781 IN VOID *ConfigParams
784 UINT32 InvocationOptions;
788 InvocationOptions = 0;
790 if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
791 InvocationOptions |= AP_TASK_HAS_INPUT;
793 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
794 InvocationOptions |= AP_TASK_HAS_OUTPUT;
796 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
797 InvocationOptions |= AP_PASS_EARLY_PARAMS;
800 switch (InvocationOptions) {
802 TaskPtr->FuncAddress.PfApTask (StdHeader);
804 case AP_TASK_HAS_INPUT:
805 TaskPtr->FuncAddress.PfApTaskI (TaskPtr->DataTransfer.DataPtr, StdHeader);
807 case AP_PASS_EARLY_PARAMS:
808 TaskPtr->FuncAddress.PfApTaskC (StdHeader, ConfigParams);
810 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
811 TaskPtr->FuncAddress.PfApTaskIC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
813 case AP_TASK_HAS_OUTPUT:
814 ReturnCode = TaskPtr->FuncAddress.PfApTaskO (StdHeader);
816 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
817 ReturnCode = TaskPtr->FuncAddress.PfApTaskIO (TaskPtr->DataTransfer.DataPtr, StdHeader);
819 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
820 ReturnCode = TaskPtr->FuncAddress.PfApTaskOC (StdHeader, ConfigParams);
822 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
823 ReturnCode = TaskPtr->FuncAddress.PfApTaskIOC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
832 /*---------------------------------------------------------------------------------------*/
834 * Sets up the AP's IDT with NMI (INT2) being the only valid descriptor
836 * This function prepares the executing AP core for recovering from a hlt
837 * instruction by initializing its IDTR.
839 * @param[in] NmiIdtDescPtr Pointer to a writable IDT entry to
841 * @param[in] StdHeader Configuration parameters pointer
846 ApUtilSetupIdtForHlt (
847 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
848 IN AMD_CONFIG_PARAMS *StdHeader
852 UINT64 HandlerOffset;
854 IDT_BASE_LIMIT IdtInfo;
856 LibAmdMsrRead (MSR_EXTENDED_FEATURE_EN, &EferRegister, StdHeader);
857 if ((EferRegister & 0x100) != 0) {
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);
877 /*---------------------------------------------------------------------------------------*/
879 * Calculate the APIC ID for a given core.
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!
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.
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.
897 GetLocalApicIdForCore (
898 IN UINT32 TargetSocket,
899 IN UINT32 TargetCore,
900 OUT UINT32 *LocalApicId,
901 IN AMD_CONFIG_PARAMS *StdHeader
908 UINT32 MaxCoresInProcessor;
910 UINT32 CurrentLocalApicId;
911 UINT64 LocalApicBase;
914 UINT32 ProcessorApicIndex;
915 BOOLEAN ReturnResult;
916 CPUID_DATA CpuidData;
920 // Get local apic base Address
921 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
922 Address = LocalApicBase + APIC_ID_REG;
924 LibAmdMemRead (AccessWidth32, Address, &TempVar_a, StdHeader);
927 CurrentLocalApicId = (TempVar_a >> APIC20_ApicId) & 0x000000FF;
929 GetCurrentNodeAndCore (&CurrentNode, &CurrentCore, StdHeader);
930 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
931 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
932 MaxCoresInProcessor = (1 << CoreIdBits);
934 // Get the APIC Index of this processor.
935 ProcessorApicIndex = GetProcessorApicIndex (CurrentNode, StdHeader);
937 TotalCores = (MaxCoresInProcessor * ProcessorApicIndex) + CurrentCore;
938 CurrentLocalApicId -= TotalCores;
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);
945 // Get the APIC Index of this processor.
946 ProcessorApicIndex = GetProcessorApicIndex (TargetNode, StdHeader);
948 CurrentLocalApicId += ((MaxCoresInProcessor * ProcessorApicIndex) + TargetCore);
949 *LocalApicId = CurrentLocalApicId;
952 /*---------------------------------------------------------------------------------------*/
954 * Securely passes a buffer to the designated remote core.
956 * This function uses a sequence of remote reads to transmit a data
957 * buffer, one UINT32 at a time.
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
963 * @param[in] StdHeader Configuration parameters pointer
967 ApUtilTransmitBuffer (
970 IN AP_DATA_TRANSFER *BufferInfo,
971 IN AMD_CONFIG_PARAMS *StdHeader
982 AP_WAIT_FOR_STATUS WaitForStatus;
983 AGESA_STATUS IgnoredSts;
985 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
986 ApUtilWriteDataDword ((UINT32) 0x00000000, StdHeader);
988 ApUtilWriteDataDword ((UINT32) BufferInfo->DataSizeInDwords, StdHeader);
990 TargetCore = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
992 ApUtilWriteControlByte (TargetCore, StdHeader);
994 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &IgnoredSts);
996 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
998 WaitForStatus.Status = &MyUniqueId;
999 WaitForStatus.NumberOfElements = 1;
1000 WaitForStatus.RetryCount = WAIT_INFINITELY;
1001 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1003 ApUtilWaitForCoreStatus (Socket, Core, &WaitForStatus, StdHeader);
1004 ApUtilWriteDataDword (BufferInfo->DataTransferFlags, StdHeader);
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);
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;
1026 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1030 /*---------------------------------------------------------------------------------------*/
1032 * Securely receives a buffer from the designated remote core.
1034 * This function uses a sequence of remote reads to receive a data
1035 * buffer, one UINT32 at a time.
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
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
1052 ApUtilReceiveBuffer (
1055 IN OUT AP_DATA_TRANSFER *BufferInfo,
1056 IN AMD_CONFIG_PARAMS *StdHeader
1060 UINT8 SourceUniqueId;
1061 UINT8 CurrentStatus;
1067 UINT32 TransactionSize;
1068 AGESA_STATUS ReturnStatus;
1069 ALLOCATE_HEAP_PARAMS HeapMalloc;
1070 AP_WAIT_FOR_STATUS WaitForStatus;
1072 ReturnStatus = AGESA_SUCCESS;
1073 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &ReturnStatus);
1075 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
1077 WaitForStatus.Status = &MyUniqueId;
1078 WaitForStatus.NumberOfElements = 1;
1079 WaitForStatus.RetryCount = WAIT_INFINITELY;
1080 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1082 ApUtilWaitForCoreStatus (Socket, Core, &WaitForStatus, StdHeader);
1083 TransactionSize = ApUtilReadRemoteDataDword (Socket, Core, StdHeader);
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);
1096 BufferInfo->DataSizeInDwords = 0;
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;
1112 ApUtilReceivePointer (Socket, Core, (VOID **) &BufferInfo->DataPtr, StdHeader);
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);
1126 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1128 BufferInfo->DataSizeInDwords = (UINT16) TransactionSize;
1129 ReturnStatus = AGESA_ERROR;
1131 return (ReturnStatus);
1136 RelinquishControlOfAllAPs (
1137 IN AMD_CONFIG_PARAMS *StdHeader
1145 UINT32 NumberOfSockets;
1147 AGESA_STATUS IgnoredSts;
1149 ASSERT (IsBsp (StdHeader, &IgnoredSts));
1151 TaskPtr.FuncAddress.PfApTask = PerformFinalHalt;
1152 TaskPtr.DataTransfer.DataSizeInDwords = 0;
1153 TaskPtr.ExeFlags = WAIT_FOR_CORE;
1155 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
1156 NumberOfSockets = GetPlatformNumberOfSockets ();
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);
1169 /*---------------------------------------------------------------------------------------
1170 * L O C A L F U N C T I O N S
1171 *---------------------------------------------------------------------------------------
1174 /*---------------------------------------------------------------------------------------*/
1176 * The last AGESA code that an AP performs
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.
1181 * @param[in] StdHeader Config handle for library and services
1187 IN AMD_CONFIG_PARAMS *StdHeader
1193 CPU_SPECIFIC_SERVICES *FamilyServices;
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;
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);
1205 // Aggregate the flags for the halt service.
1206 HaltFlags = PrimaryCore | (CacheEnDis << 1);
1208 ApUtilWriteControlByte (CORE_UNAVAILABLE, StdHeader);
1209 ExecuteFinalHltInstruction (HaltFlags, UserOptions.CfgApMtrrSettingsList, StdHeader);
1212 /*---------------------------------------------------------------------------------------*/
1214 * Reads the APIC register on the designated remote core.
1216 * This function uses the remote read inter-processor interrupt protocol
1217 * to read an APIC register from the remote core
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
1224 * @return The current value of the remote core's desired APIC register
1233 IN AMD_CONFIG_PARAMS *StdHeader
1236 UINT32 ApicRegister;
1237 UINT32 TargetApicId;
1241 ApUtilGetLocalApicBase (&ApicBase, StdHeader);
1242 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
1243 TargetApicId <<= LOCAL_APIC_ID;
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);
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);
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);
1264 /*---------------------------------------------------------------------------------------*/
1266 * Writes an APIC register on the executing core.
1268 * This function gets the base address of the executing core's local APIC,
1269 * and writes a UINT32 value to a specified offset.
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
1281 IN AMD_CONFIG_PARAMS *StdHeader
1286 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1287 ApicAddr += RegAddr;
1289 LibAmdMemWrite (AccessWidth32, ApicAddr, &Value, StdHeader);
1293 /*---------------------------------------------------------------------------------------*/
1295 * Reads an APIC register on the executing core.
1297 * This function gets the base address of the executing core's local APIC,
1298 * and reads a UINT32 value from a specified offset.
1300 * @param[in] RegAddr APIC register to read from
1301 * @param[in] StdHeader Configuration parameters pointer
1303 * @return The current value of the local APIC register
1310 IN AMD_CONFIG_PARAMS *StdHeader
1313 UINT32 ApicRegister;
1316 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1317 ApicAddr += RegAddr;
1318 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1320 return (ApicRegister);
1324 /*---------------------------------------------------------------------------------------*/
1326 * Returns the 64-bit base address of the executing core's local APIC.
1328 * This function reads the APICBASE MSR and isolates the programmed address.
1330 * @param[out] ApicBase Base address
1331 * @param[in] StdHeader Configuration parameters pointer
1336 ApUtilGetLocalApicBase (
1337 OUT UINT64 *ApicBase,
1338 IN AMD_CONFIG_PARAMS *StdHeader
1341 LibAmdMsrRead (MSR_APIC_BAR, ApicBase, StdHeader);
1342 *ApicBase &= LAPIC_BASE_ADDR_MASK;
1346 /*---------------------------------------------------------------------------------------*/
1348 * Determines the unique ID of the input Socket/Core.
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
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
1360 * @return The unique ID of the desired core
1365 ApUtilCalculateUniqueId (
1368 IN AMD_CONFIG_PARAMS *StdHeader
1373 UniqueId = ((Core << 3) | Socket);
1374 ASSERT ((UniqueId & 0x80) == 0);
1379 /*---------------------------------------------------------------------------------------*/
1381 * Wakes up a core from the halted state.
1383 * This function sends a directed NMI inter-processor interrupt to
1384 * the input Socket/Core.
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
1393 ApUtilFireDirectedNmi (
1396 IN AMD_CONFIG_PARAMS *StdHeader
1399 UINT32 TargetApicId;
1401 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
1402 TargetApicId <<= LOCAL_APIC_ID;
1404 ApUtilLocalWrite ((UINT32) APIC_CMD_HI_REG, TargetApicId, StdHeader);
1405 ApUtilLocalWrite ((UINT32) APIC_CMD_LO_REG, (UINT32) CMD_REG_TO_NMI, StdHeader);
1409 /*---------------------------------------------------------------------------------------*/
1411 * Securely receives a pointer from the designated remote core.
1413 * This function uses a sequence of remote reads to receive a pointer,
1414 * one UINT32 at a time.
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
1424 ApUtilReceivePointer (
1427 OUT VOID **ReturnPointer,
1428 IN AMD_CONFIG_PARAMS *StdHeader
1433 UINT32 *AddressScratchPtr;
1434 AP_WAIT_FOR_STATUS WaitForStatus;
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);
1453 /*---------------------------------------------------------------------------------------*/
1455 * Securely transmits a pointer to the designated remote core.
1457 * This function uses a sequence of remote reads to transmit a pointer,
1458 * one UINT32 at a time.
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
1468 ApUtilTransmitPointer (
1472 IN AMD_CONFIG_PARAMS *StdHeader
1477 UINT32 *AddressScratchPtr;
1478 AP_WAIT_FOR_STATUS WaitForStatus;
1480 WaitStatus = CORE_NEEDS_PTR;
1481 WaitForStatus.Status = &WaitStatus;
1482 WaitForStatus.NumberOfElements = 1;
1483 WaitForStatus.RetryCount = WAIT_INFINITELY;
1485 AddressScratchPtr = (UINT32 *) Pointer;
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);