blob: e7267843c6e61c0a7de56d62fa1aa456b686475e [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * Implement External, AGESA Common, and CPU component General Services.
6 *
7 * Contains implementation of the interfaces: General Services API in AGESA.h,
8 * GeneralServices.h, and cpuServices.h.
9 *
10 * @xrefitem bom "File Content Label" "Release Content"
11 * @e project: AGESA
12 * @e sub-project: CPU
13 * @e \$Revision: 36208 $ @e \$Date: 2010-08-13 22:55:05 +0800 (Fri, 13 Aug 2010) $
14 *
15 */
16/*
17 *****************************************************************************
18 *
19 * Copyright (c) 2011, Advanced Micro Devices, Inc.
20 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100021 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000022 * Redistribution and use in source and binary forms, with or without
23 * modification, are permitted provided that the following conditions are met:
24 * * Redistributions of source code must retain the above copyright
25 * notice, this list of conditions and the following disclaimer.
26 * * Redistributions in binary form must reproduce the above copyright
27 * notice, this list of conditions and the following disclaimer in the
28 * documentation and/or other materials provided with the distribution.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100029 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
30 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000031 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100032 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000033 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
36 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
37 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
38 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
39 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
40 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
41 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
42 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100043 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000044 * ***************************************************************************
45 *
46 */
47
48/*----------------------------------------------------------------------------------------
49 * M O D U L E S U S E D
50 *----------------------------------------------------------------------------------------
51 */
52#include "AGESA.h"
53#include "amdlib.h"
54#include "Ids.h"
55#include "Options.h"
56#include "Topology.h"
57#include "cpuRegisters.h"
58#include "GeneralServices.h"
59#include "cpuFamilyTranslation.h"
60#include "cpuServices.h"
61#include "heapManager.h"
62#include "cpuApicUtilities.h"
63#include "Filecode.h"
64CODE_GROUP (G1_PEICC)
65RDATA_GROUP (G1_PEICC)
66
67#define FILECODE PROC_CPU_CPUGENERALSERVICES_FILECODE
68/*----------------------------------------------------------------------------------------
69 * D E F I N I T I O N S A N D M A C R O S
70 *----------------------------------------------------------------------------------------
71 */
72extern OPTIONS_CONFIG_TOPOLOGY TopologyConfiguration;
73extern BUILD_OPT_CFG UserOptions;
74
75/*----------------------------------------------------------------------------------------
76 * T Y P E D E F S A N D S T R U C T U R E S
77 *----------------------------------------------------------------------------------------
78 */
79
80/*----------------------------------------------------------------------------------------
81 * 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
82 *----------------------------------------------------------------------------------------
83 */
84
85/*----------------------------------------------------------------------------------------
86 * E X P O R T E D F U N C T I O N S - External General Services API
87 *----------------------------------------------------------------------------------------
88 */
89
90/**
91 * Get a specified Core's APIC ID.
92 *
93 * Invoke corresponding Cpu Service for external user.
94 *
95 * @param[in,out] AmdParamApic Our interface struct
96 *
97 * @return The most severe status of any called service.
98 */
99AGESA_STATUS
100AmdGetApicId (
101 IN OUT AMD_APIC_PARAMS *AmdParamApic
102 )
103{
104 AGESA_STATUS AgesaStatus;
105
106 AGESA_TESTPOINT (TpIfAmdGetApicIdEntry, &AmdParamApic->StdHeader);
107 AmdParamApic->StdHeader.HeapBasePtr = HeapGetBaseAddress (&AmdParamApic->StdHeader);
108
109 AmdParamApic->IsPresent = GetApicId (
110 &AmdParamApic->StdHeader,
111 AmdParamApic->Socket,
112 AmdParamApic->Core,
113 &AmdParamApic->ApicAddress,
114 &AgesaStatus
115 );
116
117 AGESA_TESTPOINT (TpIfAmdGetApicIdExit, &AmdParamApic->StdHeader);
118 return AgesaStatus;
119}
120
121/**
122 * Get Processor Module's PCI Config Space address.
123 *
124 * Invoke corresponding Cpu Service for external user.
125 *
126 * @param[in,out] AmdParamGetPci Our interface struct
127 *
128 * @return The most severe status of any called service.
129 */
130AGESA_STATUS
131AmdGetPciAddress (
132 IN OUT AMD_GET_PCI_PARAMS *AmdParamGetPci
133 )
134{
135 AGESA_STATUS AgesaStatus;
136
137 AGESA_TESTPOINT (TpIfAmdGetPciAddressEntry, &AmdParamGetPci->StdHeader);
138 AmdParamGetPci->StdHeader.HeapBasePtr = HeapGetBaseAddress (&AmdParamGetPci->StdHeader);
139
140 AmdParamGetPci->IsPresent = GetPciAddress (
141 &AmdParamGetPci->StdHeader,
142 AmdParamGetPci->Socket,
143 AmdParamGetPci->Module,
144 &AmdParamGetPci->PciAddress,
145 &AgesaStatus
146 );
147
148 AGESA_TESTPOINT (TpIfAmdGetPciAddressExit, &AmdParamGetPci->StdHeader);
149 return AgesaStatus;
150}
151
152/**
153 * "Who am I" for the current running core.
154 *
155 * Invoke corresponding Cpu Service for external user.
156 *
157 * @param[in,out] AmdParamIdentify Our interface struct
158 *
159 * @return The most severe status of any called service.
160 */
161AGESA_STATUS
162AmdIdentifyCore (
163 IN OUT AMD_IDENTIFY_PARAMS *AmdParamIdentify
164 )
165{
166 AGESA_STATUS AgesaStatus;
167 UINT32 Socket;
168 UINT32 Module;
169 UINT32 Core;
170
171 AGESA_TESTPOINT (TpIfAmdIdentifyCoreEntry, &AmdParamIdentify->StdHeader);
172 AmdParamIdentify->StdHeader.HeapBasePtr = HeapGetBaseAddress (&AmdParamIdentify->StdHeader);
173
174 IdentifyCore (
175 &AmdParamIdentify->StdHeader,
176 &Socket,
177 &Module,
178 &Core,
179 &AgesaStatus
180 );
181 AmdParamIdentify->Socket = (UINT8)Socket;
182 AmdParamIdentify->Module = (UINT8)Module;
183 AmdParamIdentify->Core = (UINT8)Core;
184
185 AGESA_TESTPOINT (TpIfAmdIdentifyCoreExit, &AmdParamIdentify->StdHeader);
186 return AgesaStatus;
187}
188
189/*----------------------------------------------------------------------------------------
190 * E X P O R T E D F U N C T I O N S - AGESA common General Services
191 *----------------------------------------------------------------------------------------
192 */
193
194/*---------------------------------------------------------------------------------------*/
195/**
196 * Get a specified Core's APIC ID.
197 *
198 * Code sync: This calculation MUST match the assignment
199 * calculation done in LocalApicInitializationAtEarly function.
200 *
201 * @param[in] StdHeader Header for library and services.
202 * @param[in] Socket The socket in which the Core's Processor is installed.
203 * @param[in] Core The Core id.
204 * @param[out] ApicAddress The Core's APIC ID.
205 * @param[out] AgesaStatus Aggregates AGESA_STATUS for external interface, Always Succeeds.
206 *
207 * @retval TRUE The core is present, APIC Id valid
208 * @retval FALSE The core is not present, APIC Id not valid.
209*/
210BOOLEAN
211GetApicId (
212 IN AMD_CONFIG_PARAMS *StdHeader,
213 IN UINT32 Socket,
214 IN UINT32 Core,
215 OUT UINT8 *ApicAddress,
216 OUT AGESA_STATUS *AgesaStatus
217 )
218{
219 BOOLEAN ReturnValue;
220 UINT32 CoreCount;
221 UINT32 ApicID;
222
223 ReturnValue = FALSE;
224 if (GetActiveCoresInGivenSocket (Socket, &CoreCount, StdHeader)) {
225 if (Core < CoreCount) {
226 ReturnValue = TRUE;
227 GetLocalApicIdForCore (Socket, Core, &ApicID, StdHeader);
228 *ApicAddress = (UINT8) ApicID;
229 }
230 }
231
232 // Always Succeeds.
233 *AgesaStatus = AGESA_SUCCESS;
234
235 return ReturnValue;
236}
237
238/*---------------------------------------------------------------------------------------*/
239/**
240 * Get Processor Module's PCI Config Space address.
241 *
242 * @param[in] StdHeader Header for library and services.
243 * @param[in] Socket The Core's Socket.
244 * @param[in] Module The Module in that Processor
245 * @param[out] PciAddress The Processor's PCI Config Space address (Function 0, Register 0)
246 * @param[out] AgesaStatus Aggregates AGESA_STATUS for external interface, Always Succeeds.
247 *
248 * @retval TRUE The core is present, PCI Address valid
249 * @retval FALSE The core is not present, PCI Address not valid.
250 */
251BOOLEAN
252GetPciAddress (
253 IN AMD_CONFIG_PARAMS *StdHeader,
254 IN UINT32 Socket,
255 IN UINT32 Module,
256 OUT PCI_ADDR *PciAddress,
257 OUT AGESA_STATUS *AgesaStatus
258 )
259{
260 UINT8 Node;
261 BOOLEAN Result;
262
263 ASSERT (Socket < MAX_SOCKETS);
264 ASSERT (Module < MAX_DIES);
265
266 Result = TRUE;
267 // Always Succeeds.
268 *AgesaStatus = AGESA_SUCCESS;
269
270 if (GetNodeId (Socket, Module, &Node, StdHeader)) {
271 // socket is populated
272 PciAddress->AddressValue = MAKE_SBDFO (0, 0, 24, 0, 0);
273 PciAddress->Address.Device = PciAddress->Address.Device + Node;
274 } else {
275 // socket is not populated
276 PciAddress->AddressValue = ILLEGAL_SBDFO;
277 Result = FALSE;
278 }
279 return Result;
280}
281
282/*---------------------------------------------------------------------------------------*/
283/**
284 * "Who am I" for the current running core.
285 *
286 * @param[in] StdHeader Header for library and services.
287 * @param[out] Socket The current Core's Socket
288 * @param[out] Module The current Core's Processor Module
289 * @param[out] Core The current Core's core id.
290 * @param[out] AgesaStatus Aggregates AGESA_STATUS for external interface, Always Succeeds.
291 *
292 */
293VOID
294IdentifyCore (
295 IN AMD_CONFIG_PARAMS *StdHeader,
296 OUT UINT32 *Socket,
297 OUT UINT32 *Module,
298 OUT UINT32 *Core,
299 OUT AGESA_STATUS *AgesaStatus
300 )
301{
302 AP_MAIL_INFO ApMailboxInfo;
303 UINT32 CurrentCore;
304
305 // Always Succeeds.
306 *AgesaStatus = AGESA_SUCCESS;
307
308 GetApMailbox (&ApMailboxInfo.Info, StdHeader);
309 ASSERT (ApMailboxInfo.Fields.Socket < MAX_SOCKETS);
310 ASSERT (ApMailboxInfo.Fields.Module < MAX_DIES);
311 *Socket = (UINT8)ApMailboxInfo.Fields.Socket;
312 *Module = (UINT8)ApMailboxInfo.Fields.Module;
313
314 // Get Core Id
315 GetCurrentCore (&CurrentCore, StdHeader);
316 *Core = (UINT8)CurrentCore;
317}
318
319
320/*----------------------------------------------------------------------------------------
321 * E X P O R T E D F U N C T I O N S - cpu component General Services
322 *----------------------------------------------------------------------------------------
323 */
324
325/*---------------------------------------------------------------------------------------*/
326/**
327 * Get the current Platform's number of Sockets, regardless of how many are populated.
328 *
329 * The Options component can provide how many sockets are available in system.
330 * This can be used to avoid testing presence of Processors in Sockets which don't exist.
331 * The result can be one socket to the maximum possible sockets of any supported processor family.
332 * You cannot assume that all sockets contain a processor or that the sockets have processors
333 * installed in any particular order. Do not convert this number to a number of nodes.
334 *
335 * @return The number of available sockets for the platform.
336 *
337 */
338UINT32
339GetPlatformNumberOfSockets ()
340{
341 return TopologyConfiguration.PlatformNumberOfSockets;
342}
343
344/*---------------------------------------------------------------------------------------*/
345/**
346 * Get the number of Modules to check presence in each Processor.
347 *
348 * The Options component can provide how many modules need to be check for presence in each
349 * processor, regardless whether all, or any, processor have that many modules present on this boot.
350 * The result can be one module to the maximum possible modules of any supported processor family.
351 * You cannot assume that Modules are in any particular order, especially with respect to node id.
352 *
353 * @return The maximum number of modules in each processor.
354 *
355 */
356UINT32
357GetPlatformNumberOfModules ()
358{
359 return TopologyConfiguration.PlatformNumberOfModules;
360}
361
362/*---------------------------------------------------------------------------------------*/
363/**
364 * Is a processor present in Socket?
365 *
366 * Check to see if any possible module of the processor is present. This provides
367 * support for a few cases where a PCI address isn't needed, but code still needs to
368 * iterate by Socket.
369 *
370 * @param[in] Socket The socket which is being tested
371 * @param[in] StdHeader Header for library and services.
372 *
373 * @retval TRUE The socket has a processor installed
374 * @retval FALSE The socket is empty (or the processor is dead).
375 *
376 */
377BOOLEAN
378IsProcessorPresent (
379 IN UINT32 Socket,
380 IN AMD_CONFIG_PARAMS *StdHeader
381 )
382{
383 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
384 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
385 BOOLEAN Result;
386 UINT32 Module;
387 AGESA_STATUS Status;
388
389 ASSERT (Socket < MAX_SOCKETS);
390 Result = FALSE;
391 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
392
393 // Get data block from heap
394 Status = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
395 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
396 ASSERT ((pSocketDieMap != NULL) && (Status == AGESA_SUCCESS));
397 for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
398 if ((*pSocketDieMap)[Socket][Module].Node != 0xFF) {
399 Result = TRUE;
400 break;
401 }
402 }
403 return Result;
404}
405
406/*---------------------------------------------------------------------------------------*/
407/**
408 * Provide the number of installed processors (not Nodes! and not Sockets!)
409 *
410 * Iterate over the Socket, Module to Node Map, counting the number of present nodes.
411 * Do not use this as a Node Count! Do not use this as the number of Sockets! (This
412 * is for APIC ID utilities.)
413 *
414 * @param[in] StdHeader Header for library and services.
415 *
416 * @return the number of processors installed
417 *
418 */
419UINT32
420GetNumberOfProcessors (
421 IN AMD_CONFIG_PARAMS *StdHeader
422 )
423{
424 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
425 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
426 UINT32 Result;
427 UINT32 Socket;
428 UINT32 Module;
429 AGESA_STATUS Status;
430
431 Result = 0;
432 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
433
434 // Get data block from heap
435 Status = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
436 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
437 ASSERT ((pSocketDieMap != NULL) && (Status == AGESA_SUCCESS));
438 for (Socket = 0; Socket < GetPlatformNumberOfSockets (); Socket++) {
439 for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
440 if ((*pSocketDieMap)[Socket][Module].Node != 0xFF) {
441 Result++;
442 break;
443 }
444 }
445 }
446 return Result;
447}
448
449/*---------------------------------------------------------------------------------------*/
450/**
451 * For a specific Node, get its Socket and Module ids.
452 *
453 * If asking for the current running Node, read the mailbox socket, module. Specific Node,
454 * locate the Node to Socket/Module Map in heap, and return the ids, if present.
455 *
456 * @param[in] Node What Socket and Module is this Node?
457 * @param[out] Socket The Socket containing that Node.
458 * @param[out] Module The Processor Module of that Node.
459 * @param[in] StdHeader Header for library and services.
460 *
461 * @retval TRUE Node is present, Socket, Module are valid.
462 * @retval FALSE Node is not present, why do you ask?
463 */
464BOOLEAN
465GetSocketModuleOfNode (
466 IN UINT32 Node,
467 OUT UINT32 *Socket,
468 OUT UINT32 *Module,
469 IN AMD_CONFIG_PARAMS *StdHeader
470 )
471{
472 NODE_TO_SOCKET_DIE_MAP pNodeMap;
473 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
474 BOOLEAN Result;
475 AGESA_STATUS Status;
476
477 Result = FALSE;
478
479 ASSERT (Node < MAX_NODES);
480
481 // Get Map from heap
482 SocketDieHeapDataBlock.BufferHandle = NODE_ID_MAP_HANDLE;
483 Status = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
484 pNodeMap = (NODE_TO_SOCKET_DIE_MAP)SocketDieHeapDataBlock.BufferPtr;
485 ASSERT ((pNodeMap != NULL) && (Status == AGESA_SUCCESS));
486 *Socket = (*pNodeMap)[Node].Socket;
487 *Module = (*pNodeMap)[Node].Die;
488 if ((*pNodeMap)[Node].Socket != 0xFF) {
489 Result = TRUE;
490 }
491 return Result;
492}
493
494/*---------------------------------------------------------------------------------------*/
495/**
496 * Get the current core's Processor APIC Index.
497 *
498 * The Processor APIC Index is the position of the current processor in the APIC id
499 * assignment. Processors are ordered in node id order. This is not the same, however,
500 * as the node id of the current socket and module or the current socket id.
501 *
502 * @param[in] Node The current desired core's node id (usually the current core).
503 * @param[in] StdHeader Header for library and services.
504 *
505 * @return Processor APIC Index
506 *
507 */
508UINT32
509GetProcessorApicIndex (
510 IN UINT32 Node,
511 IN AMD_CONFIG_PARAMS *StdHeader
512 )
513{
514 UINT32 ProcessorApicIndex;
515 UINT32 PreviousSocket;
516 UINT32 CurrentSocket;
517 UINT32 Ignored;
518 UINT32 i;
519
520 ASSERT (Node < MAX_NODES);
521
522 // Calculate total APIC devices up to Current Node, Core.
523 ProcessorApicIndex = 0;
524 PreviousSocket = 0xFF;
525 for (i = 0; i < (Node + 1); i++) {
526 GetSocketModuleOfNode (i, &CurrentSocket, &Ignored, StdHeader);
527 if (CurrentSocket != PreviousSocket) {
528 ProcessorApicIndex++;
529 PreviousSocket = CurrentSocket;
530 }
531 }
532 // Convert to Index (zero based) from count (one based).
533 ProcessorApicIndex--;
534 return ProcessorApicIndex;
535}
536
537/*---------------------------------------------------------------------------------------*/
538/**
539 * Returns current node number
540 *
541 * @param[out] Node This Core's Node id
542 * @param[in] StdHeader Header for library and services.
543 *
544 */
545VOID
546GetCurrentNodeNum (
547 OUT UINT32 *Node,
548 IN AMD_CONFIG_PARAMS *StdHeader
549 )
550{
551 AP_MAIL_INFO ApMailboxInfo;
552
553 // Get the Node Id from the Mailbox.
554 GetApMailbox (&ApMailboxInfo.Info, StdHeader);
555 ASSERT (ApMailboxInfo.Fields.Node < MAX_NODES);
556 *Node = ApMailboxInfo.Fields.Node;
557}
558
559/*---------------------------------------------------------------------------------------*/
560/**
561 * Writes to all nodes on the executing core's socket.
562 *
563 * @param[in] PciAddress The Function and Register to update
564 * @param[in] Mask The bitwise AND mask to apply to the current register value
565 * @param[in] Data The bitwise OR mask to apply to the current register value
566 * @param[in] StdHeader Header for library and services.
567 *
568 */
569VOID
570ModifyCurrentSocketPci (
571 IN PCI_ADDR *PciAddress,
572 IN UINT32 Mask,
573 IN UINT32 Data,
574 IN AMD_CONFIG_PARAMS *StdHeader
575 )
576{
577 UINT32 Socket;
578 UINT32 Module;
579 UINT32 Core;
efdesign9884cbce22011-08-04 12:09:17 -0600580 UINT32 PciReg;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000581 AGESA_STATUS AgesaStatus;
582 PCI_ADDR Reg;
583
584 IdentifyCore (StdHeader, &Socket, &Module, &Core, &AgesaStatus);
585
586 for (Module = 0; Module < (UINT8)GetPlatformNumberOfModules (); Module++) {
587 if (GetPciAddress (StdHeader, Socket, Module, &Reg, &AgesaStatus)) {
588 Reg.Address.Function = PciAddress->Address.Function;
589 Reg.Address.Register = PciAddress->Address.Register;
efdesign9884cbce22011-08-04 12:09:17 -0600590 LibAmdPciRead (AccessWidth32, Reg, &PciReg, StdHeader);
591 PciReg &= Mask;
592 PciReg |= Data;
593 LibAmdPciWrite (AccessWidth32, Reg, &PciReg, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000594 }
595 }
596}
597
598/*---------------------------------------------------------------------------------------*/
599/**
600 * Returns Total number of active cores in the current socket
601 *
602 * @param[out] CoreCount The cores in this processor.
603 * @param[in] StdHeader Header for library and services.
604 *
605 */
606VOID
607GetActiveCoresInCurrentSocket (
608 OUT UINT32 *CoreCount,
609 IN AMD_CONFIG_PARAMS *StdHeader
610 )
611{
612 CPUID_DATA CpuidDataStruct;
613 UINT32 TotalCoresCount;
614
615 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidDataStruct, StdHeader);
616 TotalCoresCount = (CpuidDataStruct.ECX_Reg & 0x000000FF) + 1;
617 *CoreCount = TotalCoresCount;
618}
619
620/*---------------------------------------------------------------------------------------*/
621/**
622 * Provides the Total number of active cores in the current core's node.
623 *
624 * @param[in] StdHeader Header for library and services.
625 *
626 * @return The current node core count
627 */
628UINTN
629GetActiveCoresInCurrentModule (
630 IN AMD_CONFIG_PARAMS *StdHeader
631 )
632{
633 UINT32 Socket;
634 UINT32 Module;
635 UINT32 Core;
636 UINT32 LowCore;
637 UINT32 HighCore;
638 UINT32 ProcessorCoreCount;
639 AGESA_STATUS AgesaStatus;
640
641 ProcessorCoreCount = 0;
642
643 IdentifyCore (StdHeader, &Socket, &Module, &Core, &AgesaStatus);
644 if (GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader)) {
645 ProcessorCoreCount = ((HighCore - LowCore) + 1);
646 }
647 return ProcessorCoreCount;
648}
649
650/**
651 * Provide the number of compute units on current module.
652 *
653 *
654 * @param[in] StdHeader Header for library and services.
655 *
656 * @return The current compute unit counts.
657 *
658 */
659UINTN
660GetNumberOfCompUnitsInCurrentModule (
661 IN AMD_CONFIG_PARAMS *StdHeader
662 )
663{
664 UINT32 Socket;
665 UINT32 Module;
666 UINT32 CurrentCore;
667 UINT32 ComputeUnitCount;
668 UINT32 Enabled;
669 AGESA_STATUS IgnoredSts;
670 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
671 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
672
673 ComputeUnitCount = 0;
674
675 ASSERT ((GetComputeUnitMapping (StdHeader) == AllCoresMapping) ||
676 (GetComputeUnitMapping (StdHeader) == EvenCoresMapping));
677
678 IdentifyCore (StdHeader, &Socket, &Module, &CurrentCore, &IgnoredSts);
679 // Get data block from heap
680 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
681 IgnoredSts = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
682 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
683 ASSERT ((pSocketDieMap != NULL) && (IgnoredSts == AGESA_SUCCESS));
684 // Current Core's socket, module must be present.
685 ASSERT ((*pSocketDieMap)[Socket][Module].Node != 0xFF);
686 // Process compute unit info
687 Enabled = (*pSocketDieMap)[Socket][Module].EnabledComputeUnits;
688
689 while (Enabled > 0) {
690 if ((Enabled & 0x1) != 0) {
691 ComputeUnitCount++;
692 }
693 Enabled >>= 1;
694 }
695
696 return ComputeUnitCount;
697}
698
699/*---------------------------------------------------------------------------------------*/
700/**
701 * Provides the Total number of active cores in the given socket.
702 *
703 * @param[in] Socket Get a core count for the processor in this socket.
704 * @param[out] CoreCount Its core count
705 * @param[in] StdHeader Header for library and services.
706 *
707 * @retval TRUE A processor is present in the Socket and the CoreCount is valid.
708 * @retval FALSE The Socket does not have a Processor
709 */
710BOOLEAN
711GetActiveCoresInGivenSocket (
712 IN UINT32 Socket,
713 OUT UINT32 *CoreCount,
714 IN AMD_CONFIG_PARAMS *StdHeader
715 )
716{
717 UINT32 Module;
718 UINT32 LowCore;
719 UINT32 HighCore;
720 UINT32 ProcessorCoreCount;
721 BOOLEAN Result;
722
723 Result = FALSE;
724 ProcessorCoreCount = 0;
725
726 for (Module = 0; Module < GetPlatformNumberOfModules (); Module++) {
727 if (GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader)) {
728 ProcessorCoreCount = ProcessorCoreCount + ((HighCore - LowCore) + 1);
729 Result = TRUE;
730 } else {
731 break;
732 }
733 }
734 *CoreCount = ProcessorCoreCount;
735 return Result;
736}
737
738/*---------------------------------------------------------------------------------------*/
739/**
740 * Provides the range of Cores in a Processor which are in a Module.
741 *
742 * Cores are named uniquely in a processor, 0 to TotalCores. Any module in the processor has
743 * a set of those cores, named from LowCore to HighCore.
744 *
745 * @param[in] Socket Get a core range for the processor in this socket.
746 * @param[in] Module Get a core range for this Module in the processor.
747 * @param[out] LowCore The lowest Processor Core in the Module.
748 * @param[out] HighCore The highest Processor Core in the Module.
749 * @param[in] StdHeader Header for library and services.
750 *
751 * @retval TRUE A processor is present in the Socket and the Core Range is valid.
752 * @retval FALSE The Socket does not have a Processor
753 */
754BOOLEAN
755GetGivenModuleCoreRange (
756 IN UINT32 Socket,
757 IN UINT32 Module,
758 OUT UINT32 *LowCore,
759 OUT UINT32 *HighCore,
760 IN AMD_CONFIG_PARAMS *StdHeader
761 )
762{
763 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
764 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
765 BOOLEAN Result;
766 AGESA_STATUS Status;
767
768 ASSERT (Socket < MAX_SOCKETS);
769 ASSERT (Module < MAX_DIES);
770 Result = FALSE;
771 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
772
773 // Get data block from heap
774 Status = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
775 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
776 ASSERT ((pSocketDieMap != NULL) && (Status == AGESA_SUCCESS));
777 *LowCore = (*pSocketDieMap)[Socket][Module].LowCore;
778 *HighCore = (*pSocketDieMap)[Socket][Module].HighCore;
779 if ((*pSocketDieMap)[Socket][Module].Node != 0xFF) {
780 Result = TRUE;
781 }
782 return Result;
783}
784
785/*---------------------------------------------------------------------------------------*/
786/**
787 * Returns the current running core number.
788 *
789 * @param[out] Core The core id.
790 * @param[in] StdHeader Header for library and services.
791 *
792 */
793VOID
794GetCurrentCore (
795 OUT UINT32 *Core,
796 IN AMD_CONFIG_PARAMS *StdHeader
797 )
798{
799 CPUID_DATA CpuidDataStruct;
800 UINT32 LocalApicId;
801 UINT32 ApicIdCoreIdSize;
802 CORE_ID_POSITION InitApicIdCpuIdLo;
803 CPU_SPECIFIC_SERVICES *FamilyServices;
804
efdesign9884cbce22011-08-04 12:09:17 -0600805 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000806 ASSERT (FamilyServices != NULL);
807
808 // Read CPUID ebx[31:24] to get initial APICID
809 LibAmdCpuidRead (AMD_CPUID_APICID_LPC_BID, &CpuidDataStruct, StdHeader);
810 LocalApicId = (CpuidDataStruct.EBX_Reg & 0xFF000000) >> 24;
811
812 // Find the core ID size.
813 LibAmdCpuidRead (AMD_CPUID_ASIZE_PCCOUNT, &CpuidDataStruct, StdHeader);
814 ApicIdCoreIdSize = (CpuidDataStruct.ECX_Reg & 0x0000F000) >> 12;
815
816 InitApicIdCpuIdLo = FamilyServices->CoreIdPositionInInitialApicId (FamilyServices, StdHeader);
817 ASSERT (InitApicIdCpuIdLo < CoreIdPositionMax);
818
819 // Now extract the core ID from the Apic ID by right justifying the id and masking off non-core Id bits.
820 *Core = ((LocalApicId >> ((1 - (UINT32)InitApicIdCpuIdLo) * (MAX_CORE_ID_SIZE - ApicIdCoreIdSize))) &
821 (MAX_CORE_ID_MASK >> (MAX_CORE_ID_SIZE - ApicIdCoreIdSize)));
822}
823
824/*---------------------------------------------------------------------------------------*/
825/**
826 * Returns current node, and core number.
827 *
828 * @param[out] Node The node id of the current core's node.
829 * @param[out] Core The core id if the current core.
830 * @param[in] StdHeader Config handle for library and services.
831 *
832 */
833VOID
834GetCurrentNodeAndCore (
835 OUT UINT32 *Node,
836 OUT UINT32 *Core,
837 IN AMD_CONFIG_PARAMS *StdHeader
838 )
839{
840 // Get Node Id
841 GetCurrentNodeNum (Node, StdHeader);
842
843 // Get Core Id
844 GetCurrentCore (Core, StdHeader);
845}
846
847/*---------------------------------------------------------------------------------------*/
848/**
849 * Is the current core a primary core of it's node?
850 *
851 * @param[in] StdHeader Config handle for library and services.
852 *
853 * @retval TRUE Is Primary Core
854 * @retval FALSE Is not Primary Core
855 *
856 */
857BOOLEAN
858IsCurrentCorePrimary (
859 IN AMD_CONFIG_PARAMS *StdHeader
860 )
861{
862 BOOLEAN Result;
863 UINT32 Core;
864 UINT32 Socket;
865 UINT32 Module;
866 UINT32 PrimaryCore;
867 UINT32 IgnoredCore;
868 AGESA_STATUS IgnoredSts;
869
870 Result = FALSE;
871
872 IdentifyCore (StdHeader, &Socket, &Module, &Core, &IgnoredSts);
873 GetGivenModuleCoreRange (Socket, Module, &PrimaryCore, &IgnoredCore, StdHeader);
874 if (Core == PrimaryCore) {
875 Result = TRUE;
876 }
877 return Result;
878}
879
880
881/*---------------------------------------------------------------------------------------*/
882/**
883 * Returns node id based on SocketId and ModuleId.
884 *
885 * @param[in] SocketId The socket to look up
886 * @param[in] ModuleId The module in that socket
887 * @param[out] NodeId Provide the corresponding Node Id.
888 * @param[in] StdHeader Handle of Header for calling lib functions and services.
889 *
890 * @retval TRUE The socket is populated
891 * @retval FALSE The socket is not populated
892 *
893 */
894BOOLEAN
895GetNodeId (
896 IN UINT32 SocketId,
897 IN UINT32 ModuleId,
898 OUT UINT8 *NodeId,
899 IN AMD_CONFIG_PARAMS *StdHeader
900 )
901{
902 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
903 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
904 BOOLEAN Result;
905 AGESA_STATUS Status;
906
907 Result = FALSE;
908 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
909
910 // Get data block from heap
911 Status = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
912 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
913 ASSERT ((pSocketDieMap != NULL) && (Status == AGESA_SUCCESS));
914 *NodeId = (*pSocketDieMap)[SocketId][ModuleId].Node;
915 if ((*pSocketDieMap)[SocketId][ModuleId].Node != 0xFF) {
916 Result = TRUE;
917 }
918 return Result;
919}
920
921/*---------------------------------------------------------------------------------------*/
922/**
923 * Get the cached AP Mailbox Info if available, or read the info from the hardware.
924 *
925 * Locate the known AP Mailbox Info Cache buffer in this core's local heap. If it
926 * doesn't exist, read the hardware to get the info.
927 * This routine gets the main AP mailbox, not the system degree.
928 *
929 * @param[out] ApMailboxInfo Provide the info in this AP core's mailbox
930 * @param[in] StdHeader Config handle for library and services.
931 *
932 */
933VOID
934GetApMailbox (
935 OUT UINT32 *ApMailboxInfo,
936 IN AMD_CONFIG_PARAMS *StdHeader
937 )
938{
939 AGESA_STATUS Ignored;
940 LOCATE_HEAP_PTR LocalApMailboxCache;
941 CPU_SPECIFIC_SERVICES *FamilyServices;
942 AP_MAILBOXES ApMailboxes;
943 BOOLEAN IamBsp;
944
945 IamBsp = IsBsp (StdHeader, &Ignored);
946 LocalApMailboxCache.BufferHandle = LOCAL_AP_MAIL_BOX_CACHE_HANDLE;
947 if (((StdHeader->HeapStatus == HEAP_LOCAL_CACHE) || IamBsp) &&
948 (HeapLocateBuffer (&LocalApMailboxCache, StdHeader) == AGESA_SUCCESS)) {
949 // If during HEAP_LOCAL_CACHE stage, we always try to get ApMailbox from heap
950 // If we're not in HEAP_LOCAL_CACHE stage, only BSP can get ApMailbox from heap
951 *ApMailboxInfo = ((AP_MAILBOXES *) LocalApMailboxCache.BufferPtr)->ApMailInfo.Info;
952 } else if (!IamBsp) {
953 // If this is an AP, the hardware register should be good.
efdesign9884cbce22011-08-04 12:09:17 -0600954 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000955 ASSERT (FamilyServices != NULL);
956 FamilyServices->GetApMailboxFromHardware (FamilyServices, &ApMailboxes, StdHeader);
957 *ApMailboxInfo = ApMailboxes.ApMailInfo.Info;
958 } else {
959 // This is the BSC. The hardware mailbox has not been set up yet.
960 ASSERT (FALSE);
961 }
962}
963
964/*---------------------------------------------------------------------------------------*/
965/**
966 * Cache the Ap Mailbox info in our local heap for later use.
967 *
968 * This enables us to use the info even after the mailbox register is initialized
969 * with operational values. Get all the AP mailboxes and keep them in one buffer.
970 *
971 * @param[in] StdHeader Config handle for library and services.
972 *
973 */
974VOID
975CacheApMailbox (
976 IN AMD_CONFIG_PARAMS *StdHeader
977 )
978{
979 ALLOCATE_HEAP_PARAMS AllocHeapParams;
980 AP_MAILBOXES ApMailboxes;
981 CPU_SPECIFIC_SERVICES *FamilyServices;
982
efdesign9884cbce22011-08-04 12:09:17 -0600983 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000984 ASSERT (FamilyServices != NULL);
985
986 // Get mailbox from hardware.
987 FamilyServices->GetApMailboxFromHardware (FamilyServices, &ApMailboxes, StdHeader);
988
989 // Allocate heap for the info
990 AllocHeapParams.RequestedBufferSize = sizeof (AP_MAILBOXES);
991 AllocHeapParams.BufferHandle = LOCAL_AP_MAIL_BOX_CACHE_HANDLE;
992 AllocHeapParams.Persist = HEAP_SYSTEM_MEM;
993 if (HeapAllocateBuffer (&AllocHeapParams, StdHeader) == AGESA_SUCCESS) {
994 *(AP_MAILBOXES *)AllocHeapParams.BufferPtr = ApMailboxes;
995 }
996}
997
998/*---------------------------------------------------------------------------------------*/
999/**
1000 * Compute the degree of the system.
1001 *
1002 * The degree of a system is the maximum degree of any node. The degree of a node is the
1003 * number of nodes to which it is directly connected (not considering width or redundant
1004 * links).
1005 *
1006 * @param[in] StdHeader Config handle for library and services.
1007 *
1008 */
1009UINTN
1010GetSystemDegree (
1011 IN AMD_CONFIG_PARAMS *StdHeader
1012 )
1013{
1014 AP_MAILBOXES *ApMailboxes;
1015 LOCATE_HEAP_PTR LocalApMailboxCache;
1016 AGESA_STATUS Status;
1017
1018 // Get data block from heap
1019 LocalApMailboxCache.BufferHandle = LOCAL_AP_MAIL_BOX_CACHE_HANDLE;
1020 Status = HeapLocateBuffer (&LocalApMailboxCache, StdHeader);
1021 // non-Success handled by ASSERT not NULL below.
1022 ApMailboxes = (AP_MAILBOXES *)LocalApMailboxCache.BufferPtr;
1023 ASSERT ((ApMailboxes != NULL) && (Status == AGESA_SUCCESS));
1024 return ApMailboxes->ApMailExtInfo.Fields.SystemDegree;
1025}
1026
1027/*---------------------------------------------------------------------------------------*/
1028/**
1029 * Spins until the number of microseconds specified have
1030 * expired regardless of CPU operational frequency.
1031 *
1032 * @param[in] Microseconds Wait time in microseconds
1033 * @param[in] StdHeader Header for library and services
1034 *
1035 */
1036VOID
1037WaitMicroseconds (
1038 IN UINT32 Microseconds,
1039 IN AMD_CONFIG_PARAMS *StdHeader
1040 )
1041{
1042 UINT32 TscRateInMhz;
1043 UINT64 NumberOfTicks;
1044 UINT64 InitialTsc;
1045 UINT64 CurrentTsc;
1046 CPU_SPECIFIC_SERVICES *FamilySpecificServices;
1047
1048 LibAmdMsrRead (TSC, &InitialTsc, StdHeader);
efdesign9884cbce22011-08-04 12:09:17 -06001049 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001050 FamilySpecificServices->GetTscRate (FamilySpecificServices, &TscRateInMhz, StdHeader);
1051 NumberOfTicks = Microseconds * TscRateInMhz;
1052 do {
1053 LibAmdMsrRead (TSC, &CurrentTsc, StdHeader);
1054 } while ((CurrentTsc - InitialTsc) < NumberOfTicks);
1055}
1056
1057/*---------------------------------------------------------------------------------------*/
1058/**
1059 * A boolean function determine executed CPU is BSP core.
1060 *
1061 * @param[in,out] StdHeader Header for library and services
1062 * @param[out] AgesaStatus Aggregates AGESA_STATUS for external interface, Always Succeeds.
1063 *
1064 */
1065BOOLEAN
1066IsBsp (
1067 IN OUT AMD_CONFIG_PARAMS *StdHeader,
1068 OUT AGESA_STATUS *AgesaStatus
1069 )
1070{
1071 UINT64 MsrData;
1072
1073 // Always Succeeds.
1074 *AgesaStatus = AGESA_SUCCESS;
1075
1076 // Read APIC_BASE register (0x1B), bit[8] returns 1 for BSP
1077 LibAmdMsrRead (MSR_APIC_BAR, &MsrData, StdHeader);
1078 if ((MsrData & BIT8) != 0 ) {
1079 return TRUE;
1080 } else {
1081 return FALSE;
1082 }
1083
1084}
1085
1086/*---------------------------------------------------------------------------------------*/
1087/**
1088 * Get the compute unit mapping algorithm.
1089 *
1090 * Look up the compute unit values for the current core's socket/module and find the matching
1091 * core pair map item. This will tell us how to determine the core's status.
1092 *
1093 * @param[in] StdHeader Header for library and services
1094 *
1095 * @retval AllCoresMapping Each core is in a compute unit of its own.
1096 * @retval EvenCoresMapping Even/Odd pairs of cores are in each compute unit.
1097 */
1098COMPUTE_UNIT_MAPPING
1099GetComputeUnitMapping (
1100 IN AMD_CONFIG_PARAMS *StdHeader
1101 )
1102{
1103 UINT32 CurrentCore;
1104 UINT32 Module;
1105 UINT32 Socket;
1106 UINT8 Enabled;
1107 UINT8 DualCore;
1108 AGESA_STATUS IgnoredSts;
1109 SOCKET_DIE_TO_NODE_MAP pSocketDieMap;
1110 LOCATE_HEAP_PTR SocketDieHeapDataBlock;
1111 CPU_SPECIFIC_SERVICES *FamilyServices;
1112 CORE_PAIR_MAP *CorePairMap;
1113 COMPUTE_UNIT_MAPPING Result;
1114
1115 // Invalid mapping, unless we find one.
1116 Result = MaxComputeUnitMapping;
1117
1118 IdentifyCore (StdHeader, &Socket, &Module, &CurrentCore, &IgnoredSts);
efdesign9884cbce22011-08-04 12:09:17 -06001119 GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001120 ASSERT (FamilyServices != NULL);
1121
1122 // Get data block from heap
1123 SocketDieHeapDataBlock.BufferHandle = SOCKET_DIE_MAP_HANDLE;
1124 IgnoredSts = HeapLocateBuffer (&SocketDieHeapDataBlock, StdHeader);
1125 pSocketDieMap = (SOCKET_DIE_TO_NODE_MAP)SocketDieHeapDataBlock.BufferPtr;
1126 ASSERT ((pSocketDieMap != NULL) && (IgnoredSts == AGESA_SUCCESS));
1127 // Current Core's socket, module must be present.
1128 ASSERT ((*pSocketDieMap)[Socket][Module].Node != 0xFF);
1129
1130 // Process compute unit info
1131 Enabled = (*pSocketDieMap)[Socket][Module].EnabledComputeUnits;
1132 DualCore = (*pSocketDieMap)[Socket][Module].DualCoreComputeUnits;
1133 CorePairMap = FamilyServices->CorePairMap;
1134 if ((Enabled != 0) && (CorePairMap != NULL)) {
1135 while (CorePairMap->Enabled != 0xFF) {
1136 if ((Enabled == CorePairMap->Enabled) && (DualCore == CorePairMap->DualCore)) {
1137 break;
1138 }
1139 CorePairMap++;
1140 }
1141 // The assert is for finding a processor configured in a way the core pair map doesn't support.
1142 ASSERT (CorePairMap->Enabled != 0xFF);
1143 Result = CorePairMap->Mapping;
1144 } else {
1145 // Families that don't have compute units act as though each core is in its own compute unit
1146 // and all cores are primary
1147 Result = AllCoresMapping;
1148 }
1149 return Result;
1150}
1151
1152/*---------------------------------------------------------------------------------------*/
1153/**
1154 * Is current core the primary core of its compute unit?
1155 *
1156 * Get the mapping algorithm and the current core number. Selecting First/Last ordering for
1157 * primary @b ASSUMES cores are launched in ascending core number order.
1158 *
1159 * @param[in] Selector Select whether first or last core has the primary core role.
1160 * @param[in] StdHeader Header for library and services
1161 *
1162 * @retval TRUE This is the primary core of a compute unit.
1163 * @retval FALSE This is the second shared core of a compute unit.
1164 *
1165 */
1166BOOLEAN
1167IsCorePairPrimary (
1168 IN COMPUTE_UNIT_PRIMARY_SELECTOR Selector,
1169 IN AMD_CONFIG_PARAMS *StdHeader
1170 )
1171{
1172 BOOLEAN Result;
1173 UINT32 CurrentCore;
1174 UINT32 Module;
1175 UINT32 Socket;
1176 AGESA_STATUS IgnoredSts;
1177
1178 IdentifyCore (StdHeader, &Socket, &Module, &CurrentCore, &IgnoredSts);
1179
1180 Result = FALSE;
1181 switch (GetComputeUnitMapping (StdHeader)) {
1182 case AllCoresMapping:
1183 // All cores are primaries
1184 Result = TRUE;
1185 break;
1186 case EvenCoresMapping:
1187 // Even core numbers are first to execute, odd cores are last to execute
1188 if (Selector == FirstCoreIsComputeUnitPrimary) {
1189 Result = (BOOLEAN) ((CurrentCore & 1) == 0);
1190 } else {
1191 Result = (BOOLEAN) ((CurrentCore & 1) != 0);
1192 }
1193 break;
1194 default:
1195 ASSERT (FALSE);
1196 }
1197 return Result;
1198}
1199
1200/*---------------------------------------------------------------------------------------*/
1201/**
1202 * Are the two specified cores shared in a compute unit?
1203 *
1204 * Look up the compute unit values for the current core's socket/module and find the matching
1205 * core pair map item. This will tell us how to determine the core's status.
1206 *
1207 * @param[in] Socket The processor in this socket is to be checked
1208 * @param[in] Module The processor in this module is to be checked
1209 * @param[in] CoreA One of the two cores to check
1210 * @param[in] CoreB The other core to be checked
1211 * @param[in] StdHeader Header for library and services
1212 *
1213 * @retval TRUE The cores are in the same compute unit.
1214 * @retval FALSE The cores are not in the same compute unit, or the processor does
1215 * not have compute units.
1216 *
1217 */
1218BOOLEAN
1219AreCoresPaired (
1220 IN UINT32 Socket,
1221 IN UINT32 Module,
1222 IN UINT32 CoreA,
1223 IN UINT32 CoreB,
1224 IN AMD_CONFIG_PARAMS *StdHeader
1225 )
1226{
1227 BOOLEAN Result;
1228
1229 Result = FALSE;
1230 switch (GetComputeUnitMapping (StdHeader)) {
1231 case AllCoresMapping:
1232 // No cores are sharing a compute unit
1233 Result = FALSE;
1234 break;
1235 case EvenCoresMapping:
1236 // Even core numbers are paired with odd core numbers, n with n + 1
1237 if ((CoreA & 1) == 0) {
1238 Result = (BOOLEAN) (CoreA == (CoreB - 1));
1239 } else {
1240 Result = (BOOLEAN) (CoreA == (CoreB + 1));
1241 }
1242 break;
1243 default:
1244 ASSERT (FALSE);
1245 }
1246 return Result;
1247}
1248
1249/*---------------------------------------------------------------------------------------*/
1250/**
1251 *
1252 * This routine programs the registers necessary to get the PCI MMIO mechanism
1253 * up and functioning.
1254 *
1255 * @param[in] StdHeader Pointer to structure containing the function call
1256 * whose parameter structure is to be created, the
1257 * allocation method, and a pointer to the newly
1258 * created structure.
1259 *
1260 */
1261VOID
1262InitializePciMmio (
1263 IN AMD_CONFIG_PARAMS *StdHeader
1264 )
1265{
1266 UINT8 EncodedSize;
efdesign9884cbce22011-08-04 12:09:17 -06001267 UINT64 MsrReg;
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001268
1269 // Make sure that Standard header is valid
1270 ASSERT (StdHeader != NULL);
1271
1272 if ((UserOptions.CfgPciMmioAddress != 0) && (UserOptions.CfgPciMmioSize != 0)) {
1273 EncodedSize = LibAmdBitScanForward (UserOptions.CfgPciMmioSize);
efdesign9884cbce22011-08-04 12:09:17 -06001274 MsrReg = ((UserOptions.CfgPciMmioAddress | BIT0) | (EncodedSize << 2));
1275 LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &MsrReg, StdHeader);
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001276 }
1277}