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: 44393 $ @e \$Date: 2010-12-24 07:38:46 +0800 (Fri, 24 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.
42 ******************************************************************************
45 /*----------------------------------------------------------------------------------------
46 * M O D U L E S U S E D
47 *----------------------------------------------------------------------------------------
52 #include "cpuCacheInit.h"
53 #include "cpuRegisters.h"
54 #include "cpuApicUtilities.h"
55 #include "cpuFamilyTranslation.h"
56 #include "GeneralServices.h"
57 #include "cpuServices.h"
58 #include "heapManager.h"
61 RDATA_GROUP (G1_PEICC)
63 #define FILECODE PROC_CPU_CPUAPICUTILITIES_FILECODE
65 /*----------------------------------------------------------------------------------------
66 * D E F I N I T I O N S A N D M A C R O S
67 *----------------------------------------------------------------------------------------
70 #define AP_TASK_HAS_INPUT 0x00000001
71 #define AP_TASK_HAS_OUTPUT 0x00000002
72 #define AP_RETURN_PARAMS 0x00000004
73 #define AP_END_AT_HLT 0x00000008
74 #define AP_PASS_EARLY_PARAMS 0x00000010
76 #define XFER_ELEMENT_SIZE sizeof (UINT32)
78 /*----------------------------------------------------------------------------------------
79 * T Y P E D E F S A N D S T R U C T U R E S
80 *----------------------------------------------------------------------------------------
83 typedef VOID F_CPU_AMD_NMI_HANDLER (
84 IN AMD_CONFIG_PARAMS *StdHeader
86 typedef F_CPU_AMD_NMI_HANDLER *PF_CPU_AMD_NMI_HANDLER;
88 /*----------------------------------------------------------------------------------------
89 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
90 *----------------------------------------------------------------------------------------
94 ApUtilSetupIdtForHlt (
95 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
96 IN AMD_CONFIG_PARAMS *StdHeader
102 IN UINT32 TargetApicId,
104 IN AMD_CONFIG_PARAMS *StdHeader
112 IN AMD_CONFIG_PARAMS *StdHeader
119 IN AMD_CONFIG_PARAMS *StdHeader
124 ApUtilGetLocalApicBase (
125 OUT UINT64 *ApicBase,
126 IN AMD_CONFIG_PARAMS *StdHeader
131 ApUtilCalculateUniqueId (
134 IN AMD_CONFIG_PARAMS *StdHeader
139 ApUtilFireDirectedNmi (
140 IN UINT32 TargetApicId,
141 IN AMD_CONFIG_PARAMS *StdHeader
146 ApUtilReceivePointer (
147 IN UINT32 TargetApicId,
148 OUT VOID **ReturnPointer,
149 IN AMD_CONFIG_PARAMS *StdHeader
154 ApUtilTransmitPointer (
155 IN UINT32 TargetApicId,
157 IN AMD_CONFIG_PARAMS *StdHeader
163 IN AMD_CONFIG_PARAMS *StdHeader
167 LocalApicInitializationAtEarly (
168 IN CPU_SPECIFIC_SERVICES *FamilyServices,
169 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
170 IN AMD_CONFIG_PARAMS *StdHeader
173 /*----------------------------------------------------------------------------------------
174 * E X P O R T E D F U N C T I O N S
175 *----------------------------------------------------------------------------------------
179 ExecuteHltInstruction (
180 IN AMD_CONFIG_PARAMS *StdHeader
186 IN AMD_CONFIG_PARAMS *StdHeader
191 ExecuteFinalHltInstruction (
192 IN UINT32 SharedCore,
193 IN AP_MTRR_SETTINGS *ApMtrrSettingsList,
194 IN AMD_CONFIG_PARAMS *StdHeader
197 extern BUILD_OPT_CFG UserOptions;
199 /*---------------------------------------------------------------------------------------*/
201 * Initialize the Local APIC.
203 * This function determines and programs the appropriate APIC ID value
204 * for the executing core. This code must be run after HT initialization
207 * @param[in] CpuEarlyParamsPtr Service parameters.
208 * @param[in] StdHeader Config handle for library and services.
212 LocalApicInitialization (
213 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
214 IN AMD_CONFIG_PARAMS *StdHeader
218 UINT32 CurrentNodeNum;
221 UINT32 ProcessorCount;
222 UINT32 ProcessorApicIndex;
224 UINT32 StartLocalApicId;
225 UINT64 LocalApicBase;
229 CPUID_DATA CpuidData;
231 // Local variables default values
232 IoApicNum = CpuEarlyParamsPtr->PlatformConfig.NumberOfIoApics;
234 GetCurrentCore (&CurrentCore, StdHeader);
235 GetCurrentNodeNum (&CurrentNodeNum, StdHeader);
238 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
239 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
240 Mnc = 1 << (CoreIdBits & 0x000F);
242 // Get ProcessorCount in the system
243 ProcessorCount = GetNumberOfProcessors (StdHeader);
245 // Get the APIC Index of this processor.
246 ProcessorApicIndex = GetProcessorApicIndex (CurrentNodeNum, StdHeader);
248 TempVar_a = (Mnc * ProcessorCount) + IoApicNum;
249 ASSERT (TempVar_a < 255);
251 // Apply apic enumeration rules
252 // For systems with >= 16 APICs, put the IO-APICs at 0..n and
253 // put the local-APICs at m..z
254 // For systems with < 16 APICs, put the Local-APICs at 0..n and
255 // put the IO-APICs at (n + 1)..z
256 // This is needed because many IO-APIC devices only have 4 bits
257 // for their APIC id and therefore must reside at 0..15
258 StartLocalApicId = 0;
259 if (TempVar_a >= 16) {
260 if (IoApicNum >= 1) {
261 StartLocalApicId = (IoApicNum - 1) / Mnc;
262 StartLocalApicId = (StartLocalApicId + 1) * Mnc;
267 TempVar_a = (ProcessorApicIndex * Mnc) + CurrentCore + StartLocalApicId;
268 IDS_HDT_CONSOLE (CPU_TRACE, " Node %d core %d APIC ID = 0x%x\n", CurrentNodeNum, CurrentCore, TempVar_a);
269 TempVar_a = TempVar_a << APIC20_ApicId;
271 // Enable local apic id
272 LibAmdMsrRead (MSR_APIC_BAR, &MsrData, StdHeader);
273 MsrData |= APIC_ENABLE_BIT;
274 LibAmdMsrWrite (MSR_APIC_BAR, &MsrData, StdHeader);
276 // Get local apic base Address
277 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
279 Address = LocalApicBase + APIC_ID_REG;
280 LibAmdMemWrite (AccessWidth32, Address, &TempVar_a, StdHeader);
283 /*---------------------------------------------------------------------------------------*/
285 * Initialize the Local APIC at the AmdInitEarly entry point.
287 * This function acts as a wrapper for calling the LocalApicInitialization
288 * routine at AmdInitEarly.
290 * @param[in] FamilyServices The current Family Specific Services.
291 * @param[in] EarlyParams Service parameters.
292 * @param[in] StdHeader Config handle for library and services.
296 LocalApicInitializationAtEarly (
297 IN CPU_SPECIFIC_SERVICES *FamilyServices,
298 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
299 IN AMD_CONFIG_PARAMS *StdHeader
302 AGESA_TESTPOINT (TpProcCpuLocalApicInit, StdHeader);
303 LocalApicInitialization (EarlyParams, StdHeader);
307 /*---------------------------------------------------------------------------------------*/
309 * Main entry point for all APs in the system.
311 * This routine puts the AP cores in an infinite loop in which the cores
312 * will poll their masters, waiting to be told to perform a task. At early,
313 * all socket-relative core zeros will receive their tasks from the BSC.
314 * All others will receive their tasks from the core zero of their local
315 * processor. At the end of AmdInitEarly, all cores will switch to receiving
316 * their tasks from the BSC.
318 * @param[in] StdHeader Handle to config for library and services.
319 * @param[in] CpuEarlyParams AMD_CPU_EARLY_PARAMS pointer.
324 IN AMD_CONFIG_PARAMS *StdHeader,
325 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
334 UINT32 CurrentSocket;
336 UINT32 *InputDataPtr;
340 AP_FUNCTION_PTR FuncAddress;
341 IDT_DESCRIPTOR IdtDesc[32];
342 AP_DATA_TRANSFER DataTransferInfo;
343 AGESA_STATUS IgnoredSts;
345 ASSERT (!IsBsp (StdHeader, &IgnoredSts));
347 // Initialize local variables
349 DataTransferInfo.DataTransferFlags = 0;
352 // Determine the executing core's socket and core numbers
353 IdentifyCore (StdHeader, &CurrentSocket, &Ignored, &CurrentCore, &IgnoredSts);
355 IDS_HDT_CONSOLE (CPU_TRACE, " Socket %d core %d begin AP tasking engine\n", CurrentSocket, CurrentCore);
357 // Determine the BSC's socket number
358 GetSocketModuleOfNode ((UINT32) 0x00000000, &BscSocket, &Ignored, StdHeader);
360 // Setup Interrupt Descriptor Table for sleep mode
361 ApUtilSetupIdtForHlt (&IdtDesc[2], StdHeader);
363 // Indicate to the BSC that we have reached the tasking engine
364 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
366 if (CurrentCore == 0) {
367 // Core 0s receive their tasks from the BSC
368 SourceSocket = (UINT8) BscSocket;
370 // All non-zero cores receive their tasks from the core 0 of their socket
371 SourceSocket = (UINT8) CurrentSocket;
374 GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
376 // Determine the unique value that the master will write when it has a task
377 // for this core to perform.
378 CommandStart = ApUtilCalculateUniqueId (
379 (UINT8)CurrentSocket,
384 RemoteCmd = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
385 if (RemoteCmd == CommandStart) {
386 ApFlags = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
388 ApUtilReceivePointer (TargetApicId, (VOID **) &FuncAddress, StdHeader);
390 FuncType = ApFlags & (UINT32) (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS);
391 if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
392 DataTransferInfo.DataSizeInDwords = 0;
393 DataTransferInfo.DataPtr = NULL;
394 DataTransferInfo.DataTransferFlags = 0;
395 if (ApUtilReceiveBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader) == AGESA_ERROR) {
396 // There is not enough space to put the input data on the heap. Undefined behavior is about
400 InputDataPtr = (UINT32 *) DataTransferInfo.DataPtr;
402 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
405 FuncAddress.PfApTask (StdHeader);
407 case AP_TASK_HAS_INPUT:
408 FuncAddress.PfApTaskI (InputDataPtr, StdHeader);
410 case AP_PASS_EARLY_PARAMS:
411 FuncAddress.PfApTaskC (StdHeader, CpuEarlyParams);
413 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
414 FuncAddress.PfApTaskIC (InputDataPtr, StdHeader, CpuEarlyParams);
416 case AP_TASK_HAS_OUTPUT:
417 ReturnCode = FuncAddress.PfApTaskO (StdHeader);
419 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
420 ReturnCode = FuncAddress.PfApTaskIO (InputDataPtr, StdHeader);
422 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
423 ReturnCode = FuncAddress.PfApTaskOC (StdHeader, CpuEarlyParams);
425 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
426 ReturnCode = FuncAddress.PfApTaskIOC (InputDataPtr, StdHeader, CpuEarlyParams);
432 if (((ApFlags & AP_RETURN_PARAMS) != 0)) {
433 ApUtilTransmitBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader);
435 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
436 ApUtilWriteDataDword (ReturnCode, StdHeader);
438 if ((ApFlags & AP_END_AT_HLT) != 0) {
439 RemoteCmd = CORE_IDLE_HLT;
441 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
444 if (RemoteCmd == CORE_IDLE_HLT) {
445 SourceSocket = (UINT8) BscSocket;
446 GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
447 ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
448 ExecuteHltInstruction (StdHeader);
449 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
455 /*---------------------------------------------------------------------------------------*/
457 * Reads the 'control byte' on the designated remote core.
459 * This function will read the current contents of the control byte
460 * on the designated core using the APIC remote read inter-
461 * processor interrupt sequence.
463 * @param[in] TargetApicId Local APIC ID of the desired core
464 * @param[in] StdHeader Configuration parameters pointer
466 * @return The current value of the remote cores control byte
470 ApUtilReadRemoteControlByte (
471 IN UINT32 TargetApicId,
472 IN AMD_CONFIG_PARAMS *StdHeader
478 ApicRegister = ApUtilRemoteRead (TargetApicId, APIC_CTRL_DWORD, StdHeader);
479 ControlByte = (UINT8) ((ApicRegister & APIC_CTRL_MASK) >> APIC_CTRL_SHIFT);
480 return (ControlByte);
484 /*---------------------------------------------------------------------------------------*/
486 * Writes the 'control byte' on the executing core.
488 * This function writes data to a local APIC offset used in inter-
489 * processor communication.
492 * @param[in] StdHeader
496 ApUtilWriteControlByte (
498 IN AMD_CONFIG_PARAMS *StdHeader
503 ApicRegister = ApUtilLocalRead (APIC_CTRL_REG, StdHeader);
504 ApicRegister = ((ApicRegister & ~APIC_CTRL_MASK) | (UINT32) (Value << APIC_CTRL_SHIFT));
505 ApUtilLocalWrite (APIC_CTRL_REG, ApicRegister, StdHeader);
509 /*---------------------------------------------------------------------------------------*/
511 * Reads the 'data dword' on the designated remote core.
513 * This function will read the current contents of the data dword
514 * on the designated core using the APIC remote read inter-
515 * processor interrupt sequence.
517 * @param[in] TargetApicId Local APIC ID of the desired core
518 * @param[in] StdHeader Configuration parameters pointer
520 * @return The current value of the remote core's data dword
524 ApUtilReadRemoteDataDword (
525 IN UINT32 TargetApicId,
526 IN AMD_CONFIG_PARAMS *StdHeader
529 return (ApUtilRemoteRead (TargetApicId, APIC_DATA_DWORD, StdHeader));
533 /*---------------------------------------------------------------------------------------*/
535 * Writes the 'data dword' on the executing core.
537 * This function writes data to a local APIC offset used in inter-
538 * processor communication.
540 * @param[in] Value Value to write
541 * @param[in] StdHeader Configuration parameters pointer
545 ApUtilWriteDataDword (
547 IN AMD_CONFIG_PARAMS *StdHeader
550 ApUtilLocalWrite (APIC_DATA_REG, Value, StdHeader);
554 /*---------------------------------------------------------------------------------------*/
556 * Runs the given task on the specified local core.
558 * This function is used to invoke an AP to run a specified AGESA
559 * procedure. It can only be called by cores that have subordinate
560 * APs -- the BSC at POST, or any socket-relative core 0s at Early.
562 * @param[in] Socket Socket number of the target core
563 * @param[in] Core Core number of the target core
564 * @param[in] TaskPtr Function descriptor
565 * @param[in] StdHeader Configuration parameters pointer
567 * @return Return value of the task that the AP core ran,
568 * or zero if the task was VOID.
572 ApUtilRunCodeOnSocketCore (
576 IN AMD_CONFIG_PARAMS *StdHeader
585 AP_WAIT_FOR_STATUS WaitForStatus;
590 CoreId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
592 GetLocalApicIdForCore (Socket, Core, &TargetApicId, StdHeader);
594 if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
595 ApFlags |= AP_TASK_HAS_INPUT;
596 if (((TaskPtr->ExeFlags & RETURN_PARAMS) != 0) &&
597 ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
598 ApFlags |= AP_RETURN_PARAMS;
602 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
603 ApFlags |= AP_TASK_HAS_OUTPUT;
606 if ((TaskPtr->ExeFlags & END_AT_HLT) != 0) {
607 ApFlags |= AP_END_AT_HLT;
610 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
611 ApFlags |= AP_PASS_EARLY_PARAMS;
614 WaitStatus[0] = CORE_IDLE;
615 WaitStatus[1] = CORE_IDLE_HLT;
616 WaitStatus[2] = CORE_UNAVAILABLE;
617 WaitForStatus.Status = WaitStatus;
618 WaitForStatus.NumberOfElements = 3;
619 WaitForStatus.RetryCount = WAIT_INFINITELY;
620 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
621 CurrentStatus = ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
623 if (CurrentStatus != CORE_UNAVAILABLE) {
624 ApUtilWriteDataDword (ApFlags, StdHeader);
625 ApUtilWriteControlByte (CoreId, StdHeader);
627 if (CurrentStatus == CORE_IDLE_HLT) {
628 ApUtilFireDirectedNmi (TargetApicId, StdHeader);
631 ApUtilTransmitPointer (TargetApicId, (VOID **) &TaskPtr->FuncAddress, StdHeader);
633 if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
634 ApUtilTransmitBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader);
637 if ((TaskPtr->ExeFlags & WAIT_FOR_CORE) != 0) {
638 if (((ApFlags & AP_TASK_HAS_INPUT) != 0) &&
639 ((ApFlags & AP_RETURN_PARAMS) != 0) &&
640 ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
641 if (ApUtilReceiveBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader) == AGESA_ERROR) {
642 // There is not enough space to put the return data. This should never occur. If it
643 // does, this would point to strange heap corruption.
648 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
649 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
650 ReturnCode = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
660 /*---------------------------------------------------------------------------------------*/
662 * Waits for a remote core's control byte value to either be equal or
663 * not equal to any number of specified values.
665 * This function will loop doing remote read IPIs until the remote core's
666 * control byte becomes one of the values in the input array if the input
667 * flags are set for equality. Otherwise, the loop will continue until
668 * the control byte value is not equal to one of the elements in the
669 * array. The caller can also specify an iteration count for timeout
672 * @param[in] TargetApicId Local APIC ID of the desired core
673 * @param[in] WaitParamsPtr Wait parameter structure
674 * @param[in] StdHeader Configuration parameteres pointer
676 * @return The current value of the remote core's control byte
680 ApUtilWaitForCoreStatus (
681 IN UINT32 TargetApicId,
682 IN AP_WAIT_FOR_STATUS *WaitParamsPtr,
683 IN AMD_CONFIG_PARAMS *StdHeader
692 for (i = 0; (WaitParamsPtr->RetryCount == WAIT_INFINITELY) ||
693 (i < WaitParamsPtr->RetryCount); ++i) {
694 CoreStatus = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
695 // Determine whether or not the current remote status is equal
696 // to an element in the array.
698 for (j = 0; !IsEqual && j < WaitParamsPtr->NumberOfElements; ++j) {
699 if (CoreStatus == WaitParamsPtr->Status[j]) {
703 if ((((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) != 0) && IsEqual) ||
704 (((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) == 0) && !IsEqual)) {
712 /*---------------------------------------------------------------------------------------*/
714 * Runs the AP task on the executing core.
716 * @param[in] TaskPtr Function descriptor
717 * @param[in] StdHeader Configuration parameters pointer
718 * @param[in] ConfigParams Entry point CPU parameters pointer
720 * @return Return value of the task, or zero if the task
725 ApUtilTaskOnExecutingCore (
727 IN AMD_CONFIG_PARAMS *StdHeader,
728 IN VOID *ConfigParams
731 UINT32 InvocationOptions;
735 InvocationOptions = 0;
737 if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
738 InvocationOptions |= AP_TASK_HAS_INPUT;
740 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
741 InvocationOptions |= AP_TASK_HAS_OUTPUT;
743 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
744 InvocationOptions |= AP_PASS_EARLY_PARAMS;
747 switch (InvocationOptions) {
749 TaskPtr->FuncAddress.PfApTask (StdHeader);
751 case AP_TASK_HAS_INPUT:
752 TaskPtr->FuncAddress.PfApTaskI (TaskPtr->DataTransfer.DataPtr, StdHeader);
754 case AP_PASS_EARLY_PARAMS:
755 TaskPtr->FuncAddress.PfApTaskC (StdHeader, ConfigParams);
757 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
758 TaskPtr->FuncAddress.PfApTaskIC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
760 case AP_TASK_HAS_OUTPUT:
761 ReturnCode = TaskPtr->FuncAddress.PfApTaskO (StdHeader);
763 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
764 ReturnCode = TaskPtr->FuncAddress.PfApTaskIO (TaskPtr->DataTransfer.DataPtr, StdHeader);
766 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
767 ReturnCode = TaskPtr->FuncAddress.PfApTaskOC (StdHeader, ConfigParams);
769 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
770 ReturnCode = TaskPtr->FuncAddress.PfApTaskIOC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
779 /*---------------------------------------------------------------------------------------*/
781 * Sets up the AP's IDT with NMI (INT2) being the only valid descriptor
783 * This function prepares the executing AP core for recovering from a hlt
784 * instruction by initializing its IDTR.
786 * @param[in] NmiIdtDescPtr Pointer to a writable IDT entry to
788 * @param[in] StdHeader Configuration parameters pointer
793 ApUtilSetupIdtForHlt (
794 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
795 IN AMD_CONFIG_PARAMS *StdHeader
799 UINT64 HandlerOffset;
801 IDT_BASE_LIMIT IdtInfo;
803 LibAmdMsrRead (MSR_EXTENDED_FEATURE_EN, &EferRegister, StdHeader);
804 if ((EferRegister & 0x100) != 0) {
810 HandlerOffset = (UINT64) NmiHandler;
811 NmiIdtDescPtr->OffsetLo = (UINT16) HandlerOffset & 0xFFFF;
812 NmiIdtDescPtr->OffsetHi = (UINT16) (HandlerOffset >> 16);
813 GetCsSelector (&NmiIdtDescPtr->Selector, StdHeader);
814 NmiIdtDescPtr->Flags = IDT_DESC_PRESENT | IDT_DESC_TYPE_INT32;
815 NmiIdtDescPtr->Rsvd = 0;
816 NmiIdtDescPtr->Offset64 = (UINT32) (HandlerOffset >> 32);
817 NmiIdtDescPtr->Rsvd64 = 0;
818 IdtInfo.Limit = (UINT16) ((DescSize * 3) - 1);
819 IdtInfo.Base = (UINT64) NmiIdtDescPtr - (DescSize * 2);
820 // IDS_EXCEPTION_TRAP (IDS_IDT_UPDATE_EXCEPTION_VECTOR_FOR_AP, &IdtInfo, StdHeader);
821 SetIdtr (&IdtInfo , StdHeader);
825 /*---------------------------------------------------------------------------------------*/
827 * Calculate the APIC ID for a given core.
829 * Get the current node's apic id and deconstruct it to the base id of local apic id space.
830 * Then construct the target's apic id using that base.
831 * @b Assumes: The target Socket and Core exist!
833 * - Must run after HT initialization is complete.
834 * - Code sync: This calculation MUST match the assignment
835 * calculation done above in LocalApicInitializationAtEarly function.
836 * - Assumes family homogeneous population of all sockets.
838 * @param[in] TargetSocket The socket in which the Core's Processor is installed.
839 * @param[in] TargetCore The Core on that Processor
840 * @param[out] LocalApicId Its APIC Id
841 * @param[in] StdHeader Handle to header for library and services.
845 GetLocalApicIdForCore (
846 IN UINT32 TargetSocket,
847 IN UINT32 TargetCore,
848 OUT UINT32 *LocalApicId,
849 IN AMD_CONFIG_PARAMS *StdHeader
856 UINT32 MaxCoresInProcessor;
858 UINT32 CurrentLocalApicId;
859 UINT64 LocalApicBase;
862 UINT32 ProcessorApicIndex;
863 BOOLEAN ReturnResult;
864 CPUID_DATA CpuidData;
868 // Get local apic base Address
869 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
870 Address = LocalApicBase + APIC_ID_REG;
872 LibAmdMemRead (AccessWidth32, Address, &TempVar_a, StdHeader);
875 CurrentLocalApicId = (TempVar_a >> APIC20_ApicId) & 0x000000FF;
877 GetCurrentNodeAndCore (&CurrentNode, &CurrentCore, StdHeader);
878 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
879 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
880 MaxCoresInProcessor = (1 << CoreIdBits);
882 // Get the APIC Index of this processor.
883 ProcessorApicIndex = GetProcessorApicIndex (CurrentNode, StdHeader);
885 TotalCores = (MaxCoresInProcessor * ProcessorApicIndex) + CurrentCore;
886 CurrentLocalApicId -= TotalCores;
888 // Use the Node Id of TargetSocket, Module 0. No socket transitions are missed or added,
889 // even if the TargetCore is not on Module 0 in that processor and that's all that matters now.
890 ReturnResult = GetNodeId (TargetSocket, 0, (UINT8 *)&TargetNode, StdHeader);
891 ASSERT (ReturnResult);
893 // Get the APIC Index of this processor.
894 ProcessorApicIndex = GetProcessorApicIndex (TargetNode, StdHeader);
896 CurrentLocalApicId += ((MaxCoresInProcessor * ProcessorApicIndex) + TargetCore);
897 *LocalApicId = CurrentLocalApicId;
900 /*---------------------------------------------------------------------------------------*/
902 * Securely passes a buffer to the designated remote core.
904 * This function uses a sequence of remote reads to transmit a data
905 * buffer, one UINT32 at a time.
907 * @param[in] Socket Socket number of the remote core
908 * @param[in] Core Core number of the remote core
909 * @param[in] BufferInfo Information about the buffer to pass, and
911 * @param[in] StdHeader Configuration parameters pointer
915 ApUtilTransmitBuffer (
918 IN AP_DATA_TRANSFER *BufferInfo,
919 IN AMD_CONFIG_PARAMS *StdHeader
931 AP_WAIT_FOR_STATUS WaitForStatus;
932 AGESA_STATUS IgnoredSts;
934 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
936 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
937 ApUtilWriteDataDword ((UINT32) 0x00000000, StdHeader);
939 ApUtilWriteDataDword ((UINT32) BufferInfo->DataSizeInDwords, StdHeader);
941 TargetCore = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
943 ApUtilWriteControlByte (TargetCore, StdHeader);
945 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &IgnoredSts);
947 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
949 WaitForStatus.Status = &MyUniqueId;
950 WaitForStatus.NumberOfElements = 1;
951 WaitForStatus.RetryCount = WAIT_INFINITELY;
952 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
954 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
955 ApUtilWriteDataDword (BufferInfo->DataTransferFlags, StdHeader);
957 ApUtilWriteControlByte (CORE_DATA_FLAGS_READY, StdHeader);
958 WaitForStatus.WaitForStatusFlags = 0;
959 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
960 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
961 ApUtilTransmitPointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
963 ApUtilWriteControlByte (CORE_STS_DATA_READY_1, StdHeader);
964 CurrentStatus = CORE_STS_DATA_READY_0;
965 WaitForStatus.Status = &CurrentStatus;
966 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
967 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
968 WaitForStatus.WaitForStatusFlags = 0;
969 CurrentPtr = (UINT32 *) BufferInfo->DataPtr;
970 for (i = 0; i < BufferInfo->DataSizeInDwords; ++i) {
971 ApUtilWriteDataDword (*CurrentPtr++, StdHeader);
972 ApUtilWriteControlByte (CurrentStatus, StdHeader);
973 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
974 CurrentStatus ^= 0x01;
977 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
981 /*---------------------------------------------------------------------------------------*/
983 * Securely receives a buffer from the designated remote core.
985 * This function uses a sequence of remote reads to receive a data
986 * buffer, one UINT32 at a time.
988 * @param[in] Socket Socket number of the remote core
989 * @param[in] Core Core number of the remote core
990 * @param[in] BufferInfo Information about where to place the buffer
991 * @param[in] StdHeader Configuration parameters pointer
993 * @retval AGESA_SUCCESS Transaction was successful
994 * @retval AGESA_ALERT The non-NULL desired location to place
995 * the buffer was not used as the buffer
996 * resides in a shared memory space. The
997 * input data pointer has changed.
998 * @retval AGESA_ERROR There is not enough room to receive the
1003 ApUtilReceiveBuffer (
1006 IN OUT AP_DATA_TRANSFER *BufferInfo,
1007 IN AMD_CONFIG_PARAMS *StdHeader
1011 UINT8 SourceUniqueId;
1012 UINT8 CurrentStatus;
1018 UINT32 TransactionSize;
1019 UINT32 TargetApicId;
1020 AGESA_STATUS ReturnStatus;
1021 ALLOCATE_HEAP_PARAMS HeapMalloc;
1022 AP_WAIT_FOR_STATUS WaitForStatus;
1024 ReturnStatus = AGESA_SUCCESS;
1025 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &ReturnStatus);
1027 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
1029 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
1031 WaitForStatus.Status = &MyUniqueId;
1032 WaitForStatus.NumberOfElements = 1;
1033 WaitForStatus.RetryCount = WAIT_INFINITELY;
1034 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1036 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1037 TransactionSize = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1039 if (BufferInfo->DataPtr == NULL && TransactionSize != 0) {
1040 HeapMalloc.BufferHandle = AMD_CPU_AP_TASKING_HANDLE;
1041 HeapMalloc.Persist = HEAP_LOCAL_CACHE;
1042 // Deallocate the general purpose heap structure, if it exists. Ignore
1043 // the status in case it does not exist.
1044 HeapDeallocateBuffer (HeapMalloc.BufferHandle, StdHeader);
1045 HeapMalloc.RequestedBufferSize = (TransactionSize * XFER_ELEMENT_SIZE);
1046 if (HeapAllocateBuffer (&HeapMalloc, StdHeader) == AGESA_SUCCESS) {
1047 BufferInfo->DataPtr = (UINT32 *) HeapMalloc.BufferPtr;
1048 BufferInfo->DataSizeInDwords = (UINT16) (HeapMalloc.RequestedBufferSize / XFER_ELEMENT_SIZE);
1050 BufferInfo->DataSizeInDwords = 0;
1054 if (TransactionSize <= BufferInfo->DataSizeInDwords) {
1055 SourceUniqueId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
1056 ApUtilWriteControlByte (SourceUniqueId, StdHeader);
1057 CurrentStatus = CORE_DATA_FLAGS_READY;
1058 WaitForStatus.Status = &CurrentStatus;
1059 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1060 BufferInfo->DataTransferFlags = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1061 ApUtilWriteControlByte (CORE_DATA_FLAGS_ACKNOWLEDGE, StdHeader);
1062 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
1063 if (BufferInfo->DataPtr != NULL) {
1064 ReturnStatus = AGESA_ALERT;
1066 ApUtilReceivePointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
1068 CurrentStatus = CORE_STS_DATA_READY_1;
1069 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1070 CurrentStatus = CORE_STS_DATA_READY_0;
1071 ApUtilWriteControlByte (CurrentStatus, StdHeader);
1072 CurrentPtr = BufferInfo->DataPtr;
1073 for (i = 0; i < TransactionSize; ++i) {
1074 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1075 *CurrentPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1076 CurrentStatus ^= 0x01;
1077 ApUtilWriteControlByte (CurrentStatus, StdHeader);
1080 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1082 BufferInfo->DataSizeInDwords = (UINT16) TransactionSize;
1083 ReturnStatus = AGESA_ERROR;
1085 return (ReturnStatus);
1090 RelinquishControlOfAllAPs (
1091 IN AMD_CONFIG_PARAMS *StdHeader
1099 UINT32 NumberOfSockets;
1101 AGESA_STATUS IgnoredSts;
1103 ASSERT (IsBsp (StdHeader, &IgnoredSts));
1105 TaskPtr.FuncAddress.PfApTask = PerformFinalHalt;
1106 TaskPtr.DataTransfer.DataSizeInDwords = 0;
1107 TaskPtr.ExeFlags = WAIT_FOR_CORE;
1109 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
1110 NumberOfSockets = GetPlatformNumberOfSockets ();
1112 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
1113 if (GetActiveCoresInGivenSocket (Socket, &Core, StdHeader)) {
1114 while (Core-- > 0) {
1115 if ((Socket != BscSocket) || (Core != BscCoreNum)) {
1116 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
1123 /*---------------------------------------------------------------------------------------
1124 * L O C A L F U N C T I O N S
1125 *---------------------------------------------------------------------------------------
1128 /*---------------------------------------------------------------------------------------*/
1130 * The last AGESA code that an AP performs
1132 * This function, run only by APs, breaks down their cache subsystem, sets up
1133 * for memory to be present upon wake (from IBV Init/Startup IPIs), and halts.
1135 * @param[in] StdHeader Config handle for library and services
1141 IN AMD_CONFIG_PARAMS *StdHeader
1147 CPU_SPECIFIC_SERVICES *FamilyServices;
1149 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
1150 ASSERT (FamilyServices != NULL);
1151 // CacheEnDis is a family specific flag, that lets the code to decide whether to
1152 // keep the cache control bits set or cleared.
1153 CacheEnDis = FamilyServices->InitCacheDisabled;
1155 // Determine if the current core has the primary core role. The first core to execute
1156 // in each compute unit has the primary role.
1157 PrimaryCore = (UINT32) IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader);
1159 // Aggregate the flags for the halt service.
1160 HaltFlags = PrimaryCore | (CacheEnDis << 1);
1162 ApUtilWriteControlByte (CORE_UNAVAILABLE, StdHeader);
1163 ExecuteFinalHltInstruction (HaltFlags, UserOptions.CfgApMtrrSettingsList, StdHeader);
1166 /*---------------------------------------------------------------------------------------*/
1168 * Reads the APIC register on the designated remote core.
1170 * This function uses the remote read inter-processor interrupt protocol
1171 * to read an APIC register from the remote core
1173 * @param[in] TargetApicId Local APIC ID of the desired core
1174 * @param[in] RegAddr APIC register to read
1175 * @param[in] StdHeader Configuration parameters pointer
1177 * @return The current value of the remote core's desired APIC register
1183 IN UINT32 TargetApicId,
1185 IN AMD_CONFIG_PARAMS *StdHeader
1188 UINT32 ApicRegister;
1192 ApUtilGetLocalApicBase (&ApicBase, StdHeader);
1193 TargetApicId <<= LOCAL_APIC_ID;
1196 ApicAddr = ApicBase + APIC_CMD_HI_REG;
1197 LibAmdMemWrite (AccessWidth32, ApicAddr, &TargetApicId, StdHeader);
1198 ApicAddr = ApicBase + APIC_CMD_LO_REG;
1199 ApicRegister = CMD_REG_TO_READ | (UINT32) RegAddr;
1200 LibAmdMemWrite (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1202 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1203 } while ((ApicRegister & CMD_REG_DELIVERY_STATUS) != 0);
1204 while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) == CMD_REG_REMOTE_DELIVERY_PENDING) {
1205 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1207 } while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) != CMD_REG_REMOTE_DELIVERY_DONE);
1208 ApicAddr = ApicBase + APIC_REMOTE_READ_REG;
1209 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1210 return (ApicRegister);
1214 /*---------------------------------------------------------------------------------------*/
1216 * Writes an APIC register on the executing core.
1218 * This function gets the base address of the executing core's local APIC,
1219 * and writes a UINT32 value to a specified offset.
1221 * @param[in] RegAddr APIC register to write to
1222 * @param[in] Value Data to be written to the desired APIC register
1223 * @param[in] StdHeader Configuration parameters pointer
1231 IN AMD_CONFIG_PARAMS *StdHeader
1236 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1237 ApicAddr += RegAddr;
1239 LibAmdMemWrite (AccessWidth32, ApicAddr, &Value, StdHeader);
1243 /*---------------------------------------------------------------------------------------*/
1245 * Reads an APIC register on the executing core.
1247 * This function gets the base address of the executing core's local APIC,
1248 * and reads a UINT32 value from a specified offset.
1250 * @param[in] RegAddr APIC register to read from
1251 * @param[in] StdHeader Configuration parameters pointer
1253 * @return The current value of the local APIC register
1260 IN AMD_CONFIG_PARAMS *StdHeader
1263 UINT32 ApicRegister;
1266 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1267 ApicAddr += RegAddr;
1268 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1270 return (ApicRegister);
1274 /*---------------------------------------------------------------------------------------*/
1276 * Returns the 64-bit base address of the executing core's local APIC.
1278 * This function reads the APICBASE MSR and isolates the programmed address.
1280 * @param[out] ApicBase Base address
1281 * @param[in] StdHeader Configuration parameters pointer
1286 ApUtilGetLocalApicBase (
1287 OUT UINT64 *ApicBase,
1288 IN AMD_CONFIG_PARAMS *StdHeader
1291 LibAmdMsrRead (MSR_APIC_BAR, ApicBase, StdHeader);
1292 *ApicBase &= (UINT64) LAPIC_BASE_ADDR_MASK;
1296 /*---------------------------------------------------------------------------------------*/
1298 * Determines the unique ID of the input Socket/Core.
1300 * This routine converts a socket-core combination to to a number
1301 * that will be used to directly address a particular core. This
1302 * unique value must be less than 128 because we only have a byte
1303 * to use for status. APIC IDs are not guaranteed to be below
1306 * @param[in] Socket Socket number of the remote core
1307 * @param[in] Core Core number of the remote core
1308 * @param[in] StdHeader Configuration parameters pointer
1310 * @return The unique ID of the desired core
1315 ApUtilCalculateUniqueId (
1318 IN AMD_CONFIG_PARAMS *StdHeader
1323 UniqueId = ((Core << 3) | Socket);
1324 ASSERT ((UniqueId & 0x80) == 0);
1329 /*---------------------------------------------------------------------------------------*/
1331 * Wakes up a core from the halted state.
1333 * This function sends a directed NMI inter-processor interrupt to
1334 * the input Socket/Core.
1336 * @param[in] TargetApicId Local APIC ID of the desired core
1337 * @param[in] StdHeader Configuration parameters pointer
1342 ApUtilFireDirectedNmi (
1343 IN UINT32 TargetApicId,
1344 IN AMD_CONFIG_PARAMS *StdHeader
1347 TargetApicId <<= LOCAL_APIC_ID;
1349 ApUtilLocalWrite ((UINT32) APIC_CMD_HI_REG, TargetApicId, StdHeader);
1350 ApUtilLocalWrite ((UINT32) APIC_CMD_LO_REG, (UINT32) CMD_REG_TO_NMI, StdHeader);
1354 /*---------------------------------------------------------------------------------------*/
1356 * Securely receives a pointer from the designated remote core.
1358 * This function uses a sequence of remote reads to receive a pointer,
1359 * one UINT32 at a time.
1361 * @param[in] TargetApicId Local APIC ID of the desired core
1362 * @param[out] ReturnPointer Pointer passed from remote core
1363 * @param[in] StdHeader Configuration parameters pointer
1368 ApUtilReceivePointer (
1369 IN UINT32 TargetApicId,
1370 OUT VOID **ReturnPointer,
1371 IN AMD_CONFIG_PARAMS *StdHeader
1376 UINT32 *AddressScratchPtr;
1377 AP_WAIT_FOR_STATUS WaitForStatus;
1379 WaitStatus = CORE_STS_DATA_READY_0;
1380 WaitForStatus.Status = &WaitStatus;
1381 WaitForStatus.NumberOfElements = 1;
1382 WaitForStatus.RetryCount = WAIT_INFINITELY;
1383 AddressScratchPtr = (UINT32 *) ReturnPointer;
1384 for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); ++i) {
1385 ApUtilWriteControlByte (CORE_NEEDS_PTR, StdHeader);
1386 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1387 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1388 *AddressScratchPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1389 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1390 WaitForStatus.WaitForStatusFlags = 0;
1391 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1396 /*---------------------------------------------------------------------------------------*/
1398 * Securely transmits a pointer to the designated remote core.
1400 * This function uses a sequence of remote reads to transmit a pointer,
1401 * one UINT32 at a time.
1403 * @param[in] TargetApicId Local APIC ID of the desired core
1404 * @param[out] Pointer Pointer passed from remote core
1405 * @param[in] StdHeader Configuration parameters pointer
1410 ApUtilTransmitPointer (
1411 IN UINT32 TargetApicId,
1413 IN AMD_CONFIG_PARAMS *StdHeader
1418 UINT32 *AddressScratchPtr;
1419 AP_WAIT_FOR_STATUS WaitForStatus;
1421 WaitStatus = CORE_NEEDS_PTR;
1422 WaitForStatus.Status = &WaitStatus;
1423 WaitForStatus.NumberOfElements = 1;
1424 WaitForStatus.RetryCount = WAIT_INFINITELY;
1426 AddressScratchPtr = (UINT32 *) Pointer;
1428 for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); i++) {
1429 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1430 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1431 ApUtilWriteDataDword (*AddressScratchPtr++, StdHeader);
1432 ApUtilWriteControlByte (CORE_STS_DATA_READY_0, StdHeader);
1433 WaitForStatus.WaitForStatusFlags = 0;
1434 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1435 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);