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: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
16 ******************************************************************************
18 * Copyright (C) 2012 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 ******************************************************************************
46 /*----------------------------------------------------------------------------------------
47 * M O D U L E S U S E D
48 *----------------------------------------------------------------------------------------
53 #include "cpuCacheInit.h"
54 #include "cpuRegisters.h"
55 #include "cpuApicUtilities.h"
56 #include "cpuFamilyTranslation.h"
57 #include "GeneralServices.h"
58 #include "cpuServices.h"
59 #include "heapManager.h"
64 #define FILECODE PROC_CPU_CPUAPICUTILITIES_FILECODE
66 /*----------------------------------------------------------------------------------------
67 * D E F I N I T I O N S A N D M A C R O S
68 *----------------------------------------------------------------------------------------
71 #define AP_TASK_HAS_INPUT 0x00000001
72 #define AP_TASK_HAS_OUTPUT 0x00000002
73 #define AP_RETURN_PARAMS 0x00000004
74 #define AP_END_AT_HLT 0x00000008
75 #define AP_PASS_EARLY_PARAMS 0x00000010
77 #define XFER_ELEMENT_SIZE sizeof (UINT32)
79 /*----------------------------------------------------------------------------------------
80 * T Y P E D E F S A N D S T R U C T U R E S
81 *----------------------------------------------------------------------------------------
84 typedef VOID F_CPU_AMD_NMI_HANDLER (
85 IN AMD_CONFIG_PARAMS *StdHeader
87 typedef F_CPU_AMD_NMI_HANDLER *PF_CPU_AMD_NMI_HANDLER;
89 /*----------------------------------------------------------------------------------------
90 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
91 *----------------------------------------------------------------------------------------
95 ApUtilSetupIdtForHlt (
96 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
97 IN AMD_CONFIG_PARAMS *StdHeader
103 IN UINT32 TargetApicId,
105 IN AMD_CONFIG_PARAMS *StdHeader
113 IN AMD_CONFIG_PARAMS *StdHeader
120 IN AMD_CONFIG_PARAMS *StdHeader
125 ApUtilGetLocalApicBase (
126 OUT UINT64 *ApicBase,
127 IN AMD_CONFIG_PARAMS *StdHeader
132 ApUtilCalculateUniqueId (
135 IN AMD_CONFIG_PARAMS *StdHeader
140 ApUtilFireDirectedNmi (
141 IN UINT32 TargetApicId,
142 IN AMD_CONFIG_PARAMS *StdHeader
147 ApUtilReceivePointer (
148 IN UINT32 TargetApicId,
149 OUT VOID **ReturnPointer,
150 IN AMD_CONFIG_PARAMS *StdHeader
155 ApUtilTransmitPointer (
156 IN UINT32 TargetApicId,
158 IN AMD_CONFIG_PARAMS *StdHeader
164 IN AMD_CONFIG_PARAMS *StdHeader
168 LocalApicInitialization (
169 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
170 IN AMD_CONFIG_PARAMS *StdHeader
174 LocalApicInitializationAtEarly (
175 IN CPU_SPECIFIC_SERVICES *FamilyServices,
176 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
177 IN AMD_CONFIG_PARAMS *StdHeader
179 /*----------------------------------------------------------------------------------------
180 * E X P O R T E D F U N C T I O N S
181 *----------------------------------------------------------------------------------------
185 ExecuteHltInstruction (
186 IN AMD_CONFIG_PARAMS *StdHeader
192 IN AMD_CONFIG_PARAMS *StdHeader
197 ExecuteFinalHltInstruction (
198 IN UINT32 SharedCore,
199 IN AP_MTRR_SETTINGS *ApMtrrSettingsList,
200 IN AMD_CONFIG_PARAMS *StdHeader
203 extern BUILD_OPT_CFG UserOptions;
205 /*---------------------------------------------------------------------------------------*/
207 * Initialize the Local APIC.
209 * This function determines and programs the appropriate APIC ID value
210 * for the executing core. This code must be run after HT initialization
213 * @param[in] CpuEarlyParamsPtr Service parameters.
214 * @param[in] StdHeader Config handle for library and services.
218 LocalApicInitialization (
219 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParamsPtr,
220 IN AMD_CONFIG_PARAMS *StdHeader
224 UINT32 CurrentNodeNum;
227 UINT32 ProcessorCount;
228 UINT32 ProcessorApicIndex;
230 UINT32 StartLocalApicId;
231 UINT64 LocalApicBase;
235 CPUID_DATA CpuidData;
237 // Local variables default values
238 IoApicNum = CpuEarlyParamsPtr->PlatformConfig.NumberOfIoApics;
240 GetCurrentCore (&CurrentCore, StdHeader);
241 GetCurrentNodeNum (&CurrentNodeNum, StdHeader);
244 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
245 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
246 Mnc = 1 << (CoreIdBits & 0x000F);
248 // Get ProcessorCount in the system
249 ProcessorCount = GetNumberOfProcessors (StdHeader);
251 // Get the APIC Index of this processor.
252 ProcessorApicIndex = GetProcessorApicIndex (CurrentNodeNum, StdHeader);
254 TempVar_a = (Mnc * ProcessorCount) + IoApicNum;
255 ASSERT (TempVar_a < 255);
257 // Apply apic enumeration rules
258 // For systems with >= 16 APICs, put the IO-APICs at 0..n and
259 // put the local-APICs at m..z
260 // For systems with < 16 APICs, put the Local-APICs at 0..n and
261 // put the IO-APICs at (n + 1)..z
262 // This is needed because many IO-APIC devices only have 4 bits
263 // for their APIC id and therefore must reside at 0..15
264 StartLocalApicId = 0;
265 if (TempVar_a >= 16) {
266 if (IoApicNum >= 1) {
267 StartLocalApicId = (IoApicNum - 1) / Mnc;
268 StartLocalApicId = (StartLocalApicId + 1) * Mnc;
273 TempVar_a = (ProcessorApicIndex * Mnc) + CurrentCore + StartLocalApicId;
274 IDS_HDT_CONSOLE (CPU_TRACE, " Node %d core %d APIC ID = 0x%x\n", CurrentNodeNum, CurrentCore, TempVar_a);
275 TempVar_a = TempVar_a << APIC20_ApicId;
277 // Enable local apic id
278 LibAmdMsrRead (MSR_APIC_BAR, &MsrData, StdHeader);
279 MsrData |= APIC_ENABLE_BIT;
280 LibAmdMsrWrite (MSR_APIC_BAR, &MsrData, StdHeader);
282 // Get local apic base Address
283 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
285 Address = LocalApicBase + APIC_ID_REG;
286 LibAmdMemWrite (AccessWidth32, Address, &TempVar_a, StdHeader);
289 /*---------------------------------------------------------------------------------------*/
291 * Initialize the Local APIC at the AmdInitEarly entry point.
293 * This function acts as a wrapper for calling the LocalApicInitialization
294 * routine at AmdInitEarly.
296 * @param[in] FamilyServices The current Family Specific Services.
297 * @param[in] EarlyParams Service parameters.
298 * @param[in] StdHeader Config handle for library and services.
302 LocalApicInitializationAtEarly (
303 IN CPU_SPECIFIC_SERVICES *FamilyServices,
304 IN AMD_CPU_EARLY_PARAMS *EarlyParams,
305 IN AMD_CONFIG_PARAMS *StdHeader
308 AGESA_TESTPOINT (TpProcCpuLocalApicInit, StdHeader);
309 LocalApicInitialization (EarlyParams, StdHeader);
313 /*---------------------------------------------------------------------------------------*/
315 * Main entry point for all APs in the system.
317 * This routine puts the AP cores in an infinite loop in which the cores
318 * will poll their masters, waiting to be told to perform a task. At early,
319 * all socket-relative core zeros will receive their tasks from the BSC.
320 * All others will receive their tasks from the core zero of their local
321 * processor. At the end of AmdInitEarly, all cores will switch to receiving
322 * their tasks from the BSC.
324 * @param[in] StdHeader Handle to config for library and services.
325 * @param[in] CpuEarlyParams AMD_CPU_EARLY_PARAMS pointer.
330 IN AMD_CONFIG_PARAMS *StdHeader,
331 IN AMD_CPU_EARLY_PARAMS *CpuEarlyParams
340 UINT32 CurrentSocket;
342 UINT32 *InputDataPtr;
346 AP_FUNCTION_PTR FuncAddress;
347 IDT_DESCRIPTOR IdtDesc[32];
348 AP_DATA_TRANSFER DataTransferInfo;
349 AGESA_STATUS IgnoredSts;
351 ASSERT (!IsBsp (StdHeader, &IgnoredSts));
353 // Initialize local variables
355 DataTransferInfo.DataTransferFlags = 0;
358 // Determine the executing core's socket and core numbers
359 IdentifyCore (StdHeader, &CurrentSocket, &Ignored, &CurrentCore, &IgnoredSts);
361 IDS_HDT_CONSOLE (CPU_TRACE, " Socket %d core %d begin AP tasking engine\n", CurrentSocket, CurrentCore);
363 // Determine the BSC's socket number
364 GetSocketModuleOfNode ((UINT32) 0x00000000, &BscSocket, &Ignored, StdHeader);
366 // Setup Interrupt Descriptor Table for sleep mode
367 ApUtilSetupIdtForHlt (&IdtDesc[2], StdHeader);
369 // Indicate to the BSC that we have reached the tasking engine
370 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
372 if (CurrentCore == 0) {
373 // Core 0s receive their tasks from the BSC
374 SourceSocket = (UINT8) BscSocket;
376 // All non-zero cores receive their tasks from the core 0 of their socket
377 SourceSocket = (UINT8) CurrentSocket;
380 GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
382 // Determine the unique value that the master will write when it has a task
383 // for this core to perform.
384 CommandStart = ApUtilCalculateUniqueId (
385 (UINT8)CurrentSocket,
390 RemoteCmd = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
391 if (RemoteCmd == CommandStart) {
392 ApFlags = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
394 ApUtilReceivePointer (TargetApicId, (VOID **) &FuncAddress, StdHeader);
396 FuncType = ApFlags & (UINT32) (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS);
397 if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
398 DataTransferInfo.DataSizeInDwords = 0;
399 DataTransferInfo.DataPtr = NULL;
400 DataTransferInfo.DataTransferFlags = 0;
401 if (ApUtilReceiveBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader) == AGESA_ERROR) {
402 // There is not enough space to put the input data on the heap. Undefined behavior is about
406 InputDataPtr = (UINT32 *) DataTransferInfo.DataPtr;
408 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
411 FuncAddress.PfApTask (StdHeader);
413 case AP_TASK_HAS_INPUT:
414 FuncAddress.PfApTaskI (InputDataPtr, StdHeader);
416 case AP_PASS_EARLY_PARAMS:
417 FuncAddress.PfApTaskC (StdHeader, CpuEarlyParams);
419 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
420 FuncAddress.PfApTaskIC (InputDataPtr, StdHeader, CpuEarlyParams);
422 case AP_TASK_HAS_OUTPUT:
423 ReturnCode = FuncAddress.PfApTaskO (StdHeader);
425 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
426 ReturnCode = FuncAddress.PfApTaskIO (InputDataPtr, StdHeader);
428 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
429 ReturnCode = FuncAddress.PfApTaskOC (StdHeader, CpuEarlyParams);
431 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
432 ReturnCode = FuncAddress.PfApTaskIOC (InputDataPtr, StdHeader, CpuEarlyParams);
438 if (((ApFlags & AP_RETURN_PARAMS) != 0)) {
439 ApUtilTransmitBuffer (SourceSocket, 0, &DataTransferInfo, StdHeader);
441 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
442 ApUtilWriteDataDword (ReturnCode, StdHeader);
444 if ((ApFlags & AP_END_AT_HLT) != 0) {
445 RemoteCmd = CORE_IDLE_HLT;
447 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
450 if (RemoteCmd == CORE_IDLE_HLT) {
451 SourceSocket = (UINT8) BscSocket;
452 GetLocalApicIdForCore (SourceSocket, 0, &TargetApicId, StdHeader);
453 ApUtilWriteControlByte (CORE_IDLE_HLT, StdHeader);
454 ExecuteHltInstruction (StdHeader);
455 ApUtilWriteControlByte (CORE_IDLE, StdHeader);
461 /*---------------------------------------------------------------------------------------*/
463 * Reads the 'control byte' on the designated remote core.
465 * This function will read the current contents of the control byte
466 * on the designated core using the APIC remote read inter-
467 * processor interrupt sequence.
469 * @param[in] TargetApicId Local APIC ID of the desired core
470 * @param[in] StdHeader Configuration parameters pointer
472 * @return The current value of the remote cores control byte
476 ApUtilReadRemoteControlByte (
477 IN UINT32 TargetApicId,
478 IN AMD_CONFIG_PARAMS *StdHeader
484 ApicRegister = ApUtilRemoteRead (TargetApicId, APIC_CTRL_DWORD, StdHeader);
485 ControlByte = (UINT8) ((ApicRegister & APIC_CTRL_MASK) >> APIC_CTRL_SHIFT);
486 return (ControlByte);
490 /*---------------------------------------------------------------------------------------*/
492 * Writes the 'control byte' on the executing core.
494 * This function writes data to a local APIC offset used in inter-
495 * processor communication.
498 * @param[in] StdHeader
502 ApUtilWriteControlByte (
504 IN AMD_CONFIG_PARAMS *StdHeader
509 ApicRegister = ApUtilLocalRead (APIC_CTRL_REG, StdHeader);
510 ApicRegister = ((ApicRegister & ~APIC_CTRL_MASK) | (UINT32) (Value << APIC_CTRL_SHIFT));
511 ApUtilLocalWrite (APIC_CTRL_REG, ApicRegister, StdHeader);
515 /*---------------------------------------------------------------------------------------*/
517 * Reads the 'data dword' on the designated remote core.
519 * This function will read the current contents of the data dword
520 * on the designated core using the APIC remote read inter-
521 * processor interrupt sequence.
523 * @param[in] TargetApicId Local APIC ID of the desired core
524 * @param[in] StdHeader Configuration parameters pointer
526 * @return The current value of the remote core's data dword
530 ApUtilReadRemoteDataDword (
531 IN UINT32 TargetApicId,
532 IN AMD_CONFIG_PARAMS *StdHeader
535 return (ApUtilRemoteRead (TargetApicId, APIC_DATA_DWORD, StdHeader));
539 /*---------------------------------------------------------------------------------------*/
541 * Writes the 'data dword' on the executing core.
543 * This function writes data to a local APIC offset used in inter-
544 * processor communication.
546 * @param[in] Value Value to write
547 * @param[in] StdHeader Configuration parameters pointer
551 ApUtilWriteDataDword (
553 IN AMD_CONFIG_PARAMS *StdHeader
556 ApUtilLocalWrite (APIC_DATA_REG, Value, StdHeader);
560 /*---------------------------------------------------------------------------------------*/
562 * Runs the given task on the specified local core.
564 * This function is used to invoke an AP to run a specified AGESA
565 * procedure. It can only be called by cores that have subordinate
566 * APs -- the BSC at POST, or any socket-relative core 0s at Early.
568 * @param[in] Socket Socket number of the target core
569 * @param[in] Core Core number of the target core
570 * @param[in] TaskPtr Function descriptor
571 * @param[in] StdHeader Configuration parameters pointer
573 * @return Return value of the task that the AP core ran,
574 * or zero if the task was VOID.
578 ApUtilRunCodeOnSocketCore (
582 IN AMD_CONFIG_PARAMS *StdHeader
591 AP_WAIT_FOR_STATUS WaitForStatus;
596 CoreId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
598 GetLocalApicIdForCore (Socket, Core, &TargetApicId, StdHeader);
600 if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
601 ApFlags |= AP_TASK_HAS_INPUT;
602 if (((TaskPtr->ExeFlags & RETURN_PARAMS) != 0) &&
603 ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
604 ApFlags |= AP_RETURN_PARAMS;
608 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
609 ApFlags |= AP_TASK_HAS_OUTPUT;
612 if ((TaskPtr->ExeFlags & END_AT_HLT) != 0) {
613 ApFlags |= AP_END_AT_HLT;
616 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
617 ApFlags |= AP_PASS_EARLY_PARAMS;
620 WaitStatus[0] = CORE_IDLE;
621 WaitStatus[1] = CORE_IDLE_HLT;
622 WaitStatus[2] = CORE_UNAVAILABLE;
623 WaitForStatus.Status = WaitStatus;
624 WaitForStatus.NumberOfElements = 3;
625 WaitForStatus.RetryCount = WAIT_INFINITELY;
626 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
627 CurrentStatus = ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
629 if (CurrentStatus != CORE_UNAVAILABLE) {
630 ApUtilWriteDataDword (ApFlags, StdHeader);
631 ApUtilWriteControlByte (CoreId, StdHeader);
633 if (CurrentStatus == CORE_IDLE_HLT) {
634 ApUtilFireDirectedNmi (TargetApicId, StdHeader);
637 ApUtilTransmitPointer (TargetApicId, (VOID **) &TaskPtr->FuncAddress, StdHeader);
639 if ((ApFlags & AP_TASK_HAS_INPUT) != 0) {
640 ApUtilTransmitBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader);
643 if ((TaskPtr->ExeFlags & WAIT_FOR_CORE) != 0) {
644 if (((ApFlags & AP_TASK_HAS_INPUT) != 0) &&
645 ((ApFlags & AP_RETURN_PARAMS) != 0) &&
646 ((TaskPtr->DataTransfer.DataTransferFlags & DATA_IN_MEMORY) == 0)) {
647 if (ApUtilReceiveBuffer (Socket, Core, &TaskPtr->DataTransfer, StdHeader) == AGESA_ERROR) {
648 // There is not enough space to put the return data. This should never occur. If it
649 // does, this would point to strange heap corruption.
654 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
655 if ((ApFlags & AP_TASK_HAS_OUTPUT) != 0) {
656 ReturnCode = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
666 /*---------------------------------------------------------------------------------------*/
668 * Waits for a remote core's control byte value to either be equal or
669 * not equal to any number of specified values.
671 * This function will loop doing remote read IPIs until the remote core's
672 * control byte becomes one of the values in the input array if the input
673 * flags are set for equality. Otherwise, the loop will continue until
674 * the control byte value is not equal to one of the elements in the
675 * array. The caller can also specify an iteration count for timeout
678 * @param[in] TargetApicId Local APIC ID of the desired core
679 * @param[in] WaitParamsPtr Wait parameter structure
680 * @param[in] StdHeader Configuration parameteres pointer
682 * @return The current value of the remote core's control byte
686 ApUtilWaitForCoreStatus (
687 IN UINT32 TargetApicId,
688 IN AP_WAIT_FOR_STATUS *WaitParamsPtr,
689 IN AMD_CONFIG_PARAMS *StdHeader
698 for (i = 0; (WaitParamsPtr->RetryCount == WAIT_INFINITELY) ||
699 (i < WaitParamsPtr->RetryCount); ++i) {
700 CoreStatus = ApUtilReadRemoteControlByte (TargetApicId, StdHeader);
701 // Determine whether or not the current remote status is equal
702 // to an element in the array.
704 for (j = 0; !IsEqual && j < WaitParamsPtr->NumberOfElements; ++j) {
705 if (CoreStatus == WaitParamsPtr->Status[j]) {
709 if ((((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) != 0) && IsEqual) ||
710 (((WaitParamsPtr->WaitForStatusFlags & WAIT_STATUS_EQUALITY) == 0) && !IsEqual)) {
718 /*---------------------------------------------------------------------------------------*/
720 * Runs the AP task on the executing core.
722 * @param[in] TaskPtr Function descriptor
723 * @param[in] StdHeader Configuration parameters pointer
724 * @param[in] ConfigParams Entry point CPU parameters pointer
726 * @return Return value of the task, or zero if the task
731 ApUtilTaskOnExecutingCore (
733 IN AMD_CONFIG_PARAMS *StdHeader,
734 IN VOID *ConfigParams
737 UINT32 InvocationOptions;
741 InvocationOptions = 0;
743 if (TaskPtr->DataTransfer.DataSizeInDwords != 0) {
744 InvocationOptions |= AP_TASK_HAS_INPUT;
746 if ((TaskPtr->ExeFlags & TASK_HAS_OUTPUT) != 0) {
747 InvocationOptions |= AP_TASK_HAS_OUTPUT;
749 if ((TaskPtr->ExeFlags & PASS_EARLY_PARAMS) != 0) {
750 InvocationOptions |= AP_PASS_EARLY_PARAMS;
753 switch (InvocationOptions) {
755 TaskPtr->FuncAddress.PfApTask (StdHeader);
757 case AP_TASK_HAS_INPUT:
758 TaskPtr->FuncAddress.PfApTaskI (TaskPtr->DataTransfer.DataPtr, StdHeader);
760 case AP_PASS_EARLY_PARAMS:
761 TaskPtr->FuncAddress.PfApTaskC (StdHeader, ConfigParams);
763 case (AP_TASK_HAS_INPUT | AP_PASS_EARLY_PARAMS):
764 TaskPtr->FuncAddress.PfApTaskIC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
766 case AP_TASK_HAS_OUTPUT:
767 ReturnCode = TaskPtr->FuncAddress.PfApTaskO (StdHeader);
769 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT):
770 ReturnCode = TaskPtr->FuncAddress.PfApTaskIO (TaskPtr->DataTransfer.DataPtr, StdHeader);
772 case (AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
773 ReturnCode = TaskPtr->FuncAddress.PfApTaskOC (StdHeader, ConfigParams);
775 case (AP_TASK_HAS_INPUT | AP_TASK_HAS_OUTPUT | AP_PASS_EARLY_PARAMS):
776 ReturnCode = TaskPtr->FuncAddress.PfApTaskIOC (TaskPtr->DataTransfer.DataPtr, StdHeader, ConfigParams);
785 /*---------------------------------------------------------------------------------------*/
787 * Sets up the AP's IDT with NMI (INT2) being the only valid descriptor
789 * This function prepares the executing AP core for recovering from a hlt
790 * instruction by initializing its IDTR.
792 * @param[in] NmiIdtDescPtr Pointer to a writable IDT entry to
794 * @param[in] StdHeader Configuration parameters pointer
799 ApUtilSetupIdtForHlt (
800 IN IDT_DESCRIPTOR *NmiIdtDescPtr,
801 IN AMD_CONFIG_PARAMS *StdHeader
805 UINT64 HandlerOffset;
807 IDT_BASE_LIMIT IdtInfo;
809 LibAmdMsrRead (MSR_EXTENDED_FEATURE_EN, &EferRegister, StdHeader);
810 if ((EferRegister & 0x100) != 0) {
816 HandlerOffset = (UINT64) NmiHandler;
817 NmiIdtDescPtr->OffsetLo = (UINT16) HandlerOffset & 0xFFFF;
818 NmiIdtDescPtr->OffsetHi = (UINT16) (HandlerOffset >> 16);
819 GetCsSelector (&NmiIdtDescPtr->Selector, StdHeader);
820 NmiIdtDescPtr->Flags = IDT_DESC_PRESENT | IDT_DESC_TYPE_INT32;
821 NmiIdtDescPtr->Rsvd = 0;
822 NmiIdtDescPtr->Offset64 = (UINT32) (HandlerOffset >> 32);
823 NmiIdtDescPtr->Rsvd64 = 0;
824 IdtInfo.Limit = (UINT16) ((DescSize * 3) - 1);
825 IdtInfo.Base = (UINT64) NmiIdtDescPtr - (DescSize * 2);
826 IDS_EXCEPTION_TRAP (IDS_IDT_UPDATE_EXCEPTION_VECTOR_FOR_AP, &IdtInfo, StdHeader);
827 SetIdtr (&IdtInfo , StdHeader);
831 /*---------------------------------------------------------------------------------------*/
833 * Calculate the APIC ID for a given core.
835 * Get the current node's apic id and deconstruct it to the base id of local apic id space.
836 * Then construct the target's apic id using that base.
837 * @b Assumes: The target Socket and Core exist!
839 * - Must run after HT initialization is complete.
840 * - Code sync: This calculation MUST match the assignment
841 * calculation done above in LocalApicInitializationAtEarly function.
842 * - Assumes family homogeneous population of all sockets.
844 * @param[in] TargetSocket The socket in which the Core's Processor is installed.
845 * @param[in] TargetCore The Core on that Processor
846 * @param[out] LocalApicId Its APIC Id
847 * @param[in] StdHeader Handle to header for library and services.
851 GetLocalApicIdForCore (
852 IN UINT32 TargetSocket,
853 IN UINT32 TargetCore,
854 OUT UINT32 *LocalApicId,
855 IN AMD_CONFIG_PARAMS *StdHeader
862 UINT32 MaxCoresInProcessor;
864 UINT32 CurrentLocalApicId;
865 UINT64 LocalApicBase;
868 UINT32 ProcessorApicIndex;
869 BOOLEAN ReturnResult;
870 CPUID_DATA CpuidData;
874 // Get local apic base Address
875 ApUtilGetLocalApicBase (&LocalApicBase, StdHeader);
876 Address = LocalApicBase + APIC_ID_REG;
878 LibAmdMemRead (AccessWidth32, Address, &TempVar_a, StdHeader);
881 CurrentLocalApicId = (TempVar_a >> APIC20_ApicId) & 0x000000FF;
883 GetCurrentNodeAndCore (&CurrentNode, &CurrentCore, StdHeader);
884 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidData, StdHeader);
885 CoreIdBits = (CpuidData.ECX_Reg & 0x0000F000) >> 12;
886 MaxCoresInProcessor = (1 << CoreIdBits);
888 // Get the APIC Index of this processor.
889 ProcessorApicIndex = GetProcessorApicIndex (CurrentNode, StdHeader);
891 TotalCores = (MaxCoresInProcessor * ProcessorApicIndex) + CurrentCore;
892 CurrentLocalApicId -= TotalCores;
894 // Use the Node Id of TargetSocket, Module 0. No socket transitions are missed or added,
895 // even if the TargetCore is not on Module 0 in that processor and that's all that matters now.
896 ReturnResult = GetNodeId (TargetSocket, 0, (UINT8 *)&TargetNode, StdHeader);
897 ASSERT (ReturnResult);
899 // Get the APIC Index of this processor.
900 ProcessorApicIndex = GetProcessorApicIndex (TargetNode, StdHeader);
902 CurrentLocalApicId += ((MaxCoresInProcessor * ProcessorApicIndex) + TargetCore);
903 *LocalApicId = CurrentLocalApicId;
906 /*---------------------------------------------------------------------------------------*/
908 * Securely passes a buffer to the designated remote core.
910 * This function uses a sequence of remote reads to transmit a data
911 * buffer, one UINT32 at a time.
913 * @param[in] Socket Socket number of the remote core
914 * @param[in] Core Core number of the remote core
915 * @param[in] BufferInfo Information about the buffer to pass, and
917 * @param[in] StdHeader Configuration parameters pointer
921 ApUtilTransmitBuffer (
924 IN AP_DATA_TRANSFER *BufferInfo,
925 IN AMD_CONFIG_PARAMS *StdHeader
937 AP_WAIT_FOR_STATUS WaitForStatus;
938 AGESA_STATUS IgnoredSts;
940 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
942 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
943 ApUtilWriteDataDword ((UINT32) 0x00000000, StdHeader);
945 ApUtilWriteDataDword ((UINT32) BufferInfo->DataSizeInDwords, StdHeader);
947 TargetCore = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
949 ApUtilWriteControlByte (TargetCore, StdHeader);
951 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &IgnoredSts);
953 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
955 WaitForStatus.Status = &MyUniqueId;
956 WaitForStatus.NumberOfElements = 1;
957 WaitForStatus.RetryCount = WAIT_INFINITELY;
958 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
960 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
961 ApUtilWriteDataDword (BufferInfo->DataTransferFlags, StdHeader);
963 ApUtilWriteControlByte (CORE_DATA_FLAGS_READY, StdHeader);
964 WaitForStatus.WaitForStatusFlags = 0;
965 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
966 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
967 ApUtilTransmitPointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
969 ApUtilWriteControlByte (CORE_STS_DATA_READY_1, StdHeader);
970 CurrentStatus = CORE_STS_DATA_READY_0;
971 WaitForStatus.Status = &CurrentStatus;
972 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
973 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
974 WaitForStatus.WaitForStatusFlags = 0;
975 CurrentPtr = (UINT32 *) BufferInfo->DataPtr;
976 for (i = 0; i < BufferInfo->DataSizeInDwords; ++i) {
977 ApUtilWriteDataDword (*CurrentPtr++, StdHeader);
978 ApUtilWriteControlByte (CurrentStatus, StdHeader);
979 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
980 CurrentStatus ^= 0x01;
983 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
987 /*---------------------------------------------------------------------------------------*/
989 * Securely receives a buffer from the designated remote core.
991 * This function uses a sequence of remote reads to receive a data
992 * buffer, one UINT32 at a time.
994 * @param[in] Socket Socket number of the remote core
995 * @param[in] Core Core number of the remote core
996 * @param[in] BufferInfo Information about where to place the buffer
997 * @param[in] StdHeader Configuration parameters pointer
999 * @retval AGESA_SUCCESS Transaction was successful
1000 * @retval AGESA_ALERT The non-NULL desired location to place
1001 * the buffer was not used as the buffer
1002 * resides in a shared memory space. The
1003 * input data pointer has changed.
1004 * @retval AGESA_ERROR There is not enough room to receive the
1009 ApUtilReceiveBuffer (
1012 IN OUT AP_DATA_TRANSFER *BufferInfo,
1013 IN AMD_CONFIG_PARAMS *StdHeader
1017 UINT8 SourceUniqueId;
1018 UINT8 CurrentStatus;
1024 UINT32 TransactionSize;
1025 UINT32 TargetApicId;
1026 AGESA_STATUS ReturnStatus;
1027 ALLOCATE_HEAP_PARAMS HeapMalloc;
1028 AP_WAIT_FOR_STATUS WaitForStatus;
1030 ReturnStatus = AGESA_SUCCESS;
1031 IdentifyCore (StdHeader, &MySocket, &Ignored, &MyCore, &ReturnStatus);
1033 MyUniqueId = ApUtilCalculateUniqueId ((UINT8)MySocket, (UINT8)MyCore, StdHeader);
1035 GetLocalApicIdForCore ((UINT32) Socket, (UINT32) Core, &TargetApicId, StdHeader);
1037 WaitForStatus.Status = &MyUniqueId;
1038 WaitForStatus.NumberOfElements = 1;
1039 WaitForStatus.RetryCount = WAIT_INFINITELY;
1040 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1042 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1043 TransactionSize = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1045 if (BufferInfo->DataPtr == NULL && TransactionSize != 0) {
1046 HeapMalloc.BufferHandle = AMD_CPU_AP_TASKING_HANDLE;
1047 HeapMalloc.Persist = HEAP_LOCAL_CACHE;
1048 // Deallocate the general purpose heap structure, if it exists. Ignore
1049 // the status in case it does not exist.
1050 HeapDeallocateBuffer (HeapMalloc.BufferHandle, StdHeader);
1051 HeapMalloc.RequestedBufferSize = (TransactionSize * XFER_ELEMENT_SIZE);
1052 if (HeapAllocateBuffer (&HeapMalloc, StdHeader) == AGESA_SUCCESS) {
1053 BufferInfo->DataPtr = (UINT32 *) HeapMalloc.BufferPtr;
1054 BufferInfo->DataSizeInDwords = (UINT16) (HeapMalloc.RequestedBufferSize / XFER_ELEMENT_SIZE);
1056 BufferInfo->DataSizeInDwords = 0;
1060 if (TransactionSize <= BufferInfo->DataSizeInDwords) {
1061 SourceUniqueId = ApUtilCalculateUniqueId (Socket, Core, StdHeader);
1062 ApUtilWriteControlByte (SourceUniqueId, StdHeader);
1063 CurrentStatus = CORE_DATA_FLAGS_READY;
1064 WaitForStatus.Status = &CurrentStatus;
1065 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1066 BufferInfo->DataTransferFlags = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1067 ApUtilWriteControlByte (CORE_DATA_FLAGS_ACKNOWLEDGE, StdHeader);
1068 if ((BufferInfo->DataTransferFlags & DATA_IN_MEMORY) != 0) {
1069 if (BufferInfo->DataPtr != NULL) {
1070 ReturnStatus = AGESA_ALERT;
1072 ApUtilReceivePointer (TargetApicId, (VOID **) &BufferInfo->DataPtr, StdHeader);
1074 CurrentStatus = CORE_STS_DATA_READY_1;
1075 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1076 CurrentStatus = CORE_STS_DATA_READY_0;
1077 ApUtilWriteControlByte (CurrentStatus, StdHeader);
1078 CurrentPtr = BufferInfo->DataPtr;
1079 for (i = 0; i < TransactionSize; ++i) {
1080 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1081 *CurrentPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1082 CurrentStatus ^= 0x01;
1083 ApUtilWriteControlByte (CurrentStatus, StdHeader);
1086 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1088 BufferInfo->DataSizeInDwords = (UINT16) TransactionSize;
1089 ReturnStatus = AGESA_ERROR;
1091 return (ReturnStatus);
1096 RelinquishControlOfAllAPs (
1097 IN AMD_CONFIG_PARAMS *StdHeader
1105 UINT32 NumberOfSockets;
1107 AGESA_STATUS IgnoredSts;
1109 ASSERT (IsBsp (StdHeader, &IgnoredSts));
1111 TaskPtr.FuncAddress.PfApTask = PerformFinalHalt;
1112 TaskPtr.DataTransfer.DataSizeInDwords = 0;
1113 TaskPtr.ExeFlags = WAIT_FOR_CORE;
1115 IdentifyCore (StdHeader, &BscSocket, &Ignored, &BscCoreNum, &IgnoredSts);
1116 NumberOfSockets = GetPlatformNumberOfSockets ();
1118 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
1119 if (GetActiveCoresInGivenSocket (Socket, &Core, StdHeader)) {
1120 while (Core-- > 0) {
1121 if ((Socket != BscSocket) || (Core != BscCoreNum)) {
1122 ApUtilRunCodeOnSocketCore ((UINT8) Socket, (UINT8) Core, &TaskPtr, StdHeader);
1129 /*---------------------------------------------------------------------------------------
1130 * L O C A L F U N C T I O N S
1131 *---------------------------------------------------------------------------------------
1134 /*---------------------------------------------------------------------------------------*/
1136 * The last AGESA code that an AP performs
1138 * This function, run only by APs, breaks down their cache subsystem, sets up
1139 * for memory to be present upon wake (from IBV Init/Startup IPIs), and halts.
1141 * @param[in] StdHeader Config handle for library and services
1147 IN AMD_CONFIG_PARAMS *StdHeader
1153 CPU_SPECIFIC_SERVICES *FamilyServices;
1155 GetCpuServicesOfCurrentCore ((CONST CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
1156 ASSERT (FamilyServices != NULL);
1157 // CacheEnDis is a family specific flag, that lets the code to decide whether to
1158 // keep the cache control bits set or cleared.
1159 CacheEnDis = FamilyServices->InitCacheDisabled;
1161 // Determine if the current core has the primary core role. The first core to execute
1162 // in each compute unit has the primary role.
1163 PrimaryCore = (UINT32) IsCorePairPrimary (FirstCoreIsComputeUnitPrimary, StdHeader);
1165 // Aggregate the flags for the halt service.
1166 HaltFlags = PrimaryCore | (CacheEnDis << 1);
1168 ApUtilWriteControlByte (CORE_UNAVAILABLE, StdHeader);
1169 ExecuteFinalHltInstruction (HaltFlags, UserOptions.CfgApMtrrSettingsList, StdHeader);
1172 /*---------------------------------------------------------------------------------------*/
1174 * Reads the APIC register on the designated remote core.
1176 * This function uses the remote read inter-processor interrupt protocol
1177 * to read an APIC register from the remote core
1179 * @param[in] TargetApicId Local APIC ID of the desired core
1180 * @param[in] RegAddr APIC register to read
1181 * @param[in] StdHeader Configuration parameters pointer
1183 * @return The current value of the remote core's desired APIC register
1189 IN UINT32 TargetApicId,
1191 IN AMD_CONFIG_PARAMS *StdHeader
1194 UINT32 ApicRegister;
1198 ApUtilGetLocalApicBase (&ApicBase, StdHeader);
1199 TargetApicId <<= LOCAL_APIC_ID;
1202 ApicAddr = ApicBase + APIC_CMD_HI_REG;
1203 LibAmdMemWrite (AccessWidth32, ApicAddr, &TargetApicId, StdHeader);
1204 ApicAddr = ApicBase + APIC_CMD_LO_REG;
1205 ApicRegister = CMD_REG_TO_READ | (UINT32) RegAddr;
1206 LibAmdMemWrite (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1208 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1209 } while ((ApicRegister & CMD_REG_DELIVERY_STATUS) != 0);
1210 while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) == CMD_REG_REMOTE_DELIVERY_PENDING) {
1211 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1213 } while ((ApicRegister & CMD_REG_REMOTE_RD_STS_MSK) != CMD_REG_REMOTE_DELIVERY_DONE);
1214 ApicAddr = ApicBase + APIC_REMOTE_READ_REG;
1215 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1216 return (ApicRegister);
1220 /*---------------------------------------------------------------------------------------*/
1222 * Writes an APIC register on the executing core.
1224 * This function gets the base address of the executing core's local APIC,
1225 * and writes a UINT32 value to a specified offset.
1227 * @param[in] RegAddr APIC register to write to
1228 * @param[in] Value Data to be written to the desired APIC register
1229 * @param[in] StdHeader Configuration parameters pointer
1237 IN AMD_CONFIG_PARAMS *StdHeader
1242 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1243 ApicAddr += RegAddr;
1245 LibAmdMemWrite (AccessWidth32, ApicAddr, &Value, StdHeader);
1249 /*---------------------------------------------------------------------------------------*/
1251 * Reads an APIC register on the executing core.
1253 * This function gets the base address of the executing core's local APIC,
1254 * and reads a UINT32 value from a specified offset.
1256 * @param[in] RegAddr APIC register to read from
1257 * @param[in] StdHeader Configuration parameters pointer
1259 * @return The current value of the local APIC register
1266 IN AMD_CONFIG_PARAMS *StdHeader
1269 UINT32 ApicRegister;
1272 ApUtilGetLocalApicBase (&ApicAddr, StdHeader);
1273 ApicAddr += RegAddr;
1274 LibAmdMemRead (AccessWidth32, ApicAddr, &ApicRegister, StdHeader);
1276 return (ApicRegister);
1280 /*---------------------------------------------------------------------------------------*/
1282 * Returns the 64-bit base address of the executing core's local APIC.
1284 * This function reads the APICBASE MSR and isolates the programmed address.
1286 * @param[out] ApicBase Base address
1287 * @param[in] StdHeader Configuration parameters pointer
1292 ApUtilGetLocalApicBase (
1293 OUT UINT64 *ApicBase,
1294 IN AMD_CONFIG_PARAMS *StdHeader
1297 LibAmdMsrRead (MSR_APIC_BAR, ApicBase, StdHeader);
1298 *ApicBase &= LAPIC_BASE_ADDR_MASK;
1302 /*---------------------------------------------------------------------------------------*/
1304 * Determines the unique ID of the input Socket/Core.
1306 * This routine converts a socket-core combination to to a number
1307 * that will be used to directly address a particular core. This
1308 * unique value must be less than 128 because we only have a byte
1309 * to use for status. APIC IDs are not guaranteed to be below
1312 * @param[in] Socket Socket number of the remote core
1313 * @param[in] Core Core number of the remote core
1314 * @param[in] StdHeader Configuration parameters pointer
1316 * @return The unique ID of the desired core
1321 ApUtilCalculateUniqueId (
1324 IN AMD_CONFIG_PARAMS *StdHeader
1329 UniqueId = ((Core << 3) | Socket);
1330 ASSERT ((UniqueId & 0x80) == 0);
1335 /*---------------------------------------------------------------------------------------*/
1337 * Wakes up a core from the halted state.
1339 * This function sends a directed NMI inter-processor interrupt to
1340 * the input Socket/Core.
1342 * @param[in] TargetApicId Local APIC ID of the desired core
1343 * @param[in] StdHeader Configuration parameters pointer
1348 ApUtilFireDirectedNmi (
1349 IN UINT32 TargetApicId,
1350 IN AMD_CONFIG_PARAMS *StdHeader
1353 TargetApicId <<= LOCAL_APIC_ID;
1355 ApUtilLocalWrite ((UINT32) APIC_CMD_HI_REG, TargetApicId, StdHeader);
1356 ApUtilLocalWrite ((UINT32) APIC_CMD_LO_REG, (UINT32) CMD_REG_TO_NMI, StdHeader);
1360 /*---------------------------------------------------------------------------------------*/
1362 * Securely receives a pointer from the designated remote core.
1364 * This function uses a sequence of remote reads to receive a pointer,
1365 * one UINT32 at a time.
1367 * @param[in] TargetApicId Local APIC ID of the desired core
1368 * @param[out] ReturnPointer Pointer passed from remote core
1369 * @param[in] StdHeader Configuration parameters pointer
1374 ApUtilReceivePointer (
1375 IN UINT32 TargetApicId,
1376 OUT VOID **ReturnPointer,
1377 IN AMD_CONFIG_PARAMS *StdHeader
1382 UINT32 *AddressScratchPtr;
1383 AP_WAIT_FOR_STATUS WaitForStatus;
1385 WaitStatus = CORE_STS_DATA_READY_0;
1386 WaitForStatus.Status = &WaitStatus;
1387 WaitForStatus.NumberOfElements = 1;
1388 WaitForStatus.RetryCount = WAIT_INFINITELY;
1389 AddressScratchPtr = (UINT32 *) ReturnPointer;
1390 for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); ++i) {
1391 ApUtilWriteControlByte (CORE_NEEDS_PTR, StdHeader);
1392 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1393 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1394 *AddressScratchPtr++ = ApUtilReadRemoteDataDword (TargetApicId, StdHeader);
1395 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);
1396 WaitForStatus.WaitForStatusFlags = 0;
1397 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1402 /*---------------------------------------------------------------------------------------*/
1404 * Securely transmits a pointer to the designated remote core.
1406 * This function uses a sequence of remote reads to transmit a pointer,
1407 * one UINT32 at a time.
1409 * @param[in] TargetApicId Local APIC ID of the desired core
1410 * @param[out] Pointer Pointer passed from remote core
1411 * @param[in] StdHeader Configuration parameters pointer
1416 ApUtilTransmitPointer (
1417 IN UINT32 TargetApicId,
1419 IN AMD_CONFIG_PARAMS *StdHeader
1424 UINT32 *AddressScratchPtr;
1425 AP_WAIT_FOR_STATUS WaitForStatus;
1427 WaitStatus = CORE_NEEDS_PTR;
1428 WaitForStatus.Status = &WaitStatus;
1429 WaitForStatus.NumberOfElements = 1;
1430 WaitForStatus.RetryCount = WAIT_INFINITELY;
1432 AddressScratchPtr = (UINT32 *) Pointer;
1434 for (i = 0; i < SIZE_IN_DWORDS (AddressScratchPtr); i++) {
1435 WaitForStatus.WaitForStatusFlags = WAIT_STATUS_EQUALITY;
1436 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1437 ApUtilWriteDataDword (*AddressScratchPtr++, StdHeader);
1438 ApUtilWriteControlByte (CORE_STS_DATA_READY_0, StdHeader);
1439 WaitForStatus.WaitForStatusFlags = 0;
1440 ApUtilWaitForCoreStatus (TargetApicId, &WaitForStatus, StdHeader);
1441 ApUtilWriteControlByte (CORE_ACTIVE, StdHeader);