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