S3 code whitespaces changes.
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / CPU / cpuGeneralServices.c
1 /* $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.
21  * 
22  * 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.
29  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
30  *       its contributors may be used to endorse or promote products derived 
31  *       from this software without specific prior written permission.
32  * 
33  * 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.
43  * 
44  * ***************************************************************************
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"
64 CODE_GROUP (G1_PEICC)
65 RDATA_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  */
72 extern OPTIONS_CONFIG_TOPOLOGY TopologyConfiguration;
73 extern 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  */
99 AGESA_STATUS
100 AmdGetApicId (
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  */
130 AGESA_STATUS
131 AmdGetPciAddress (
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  */
161 AGESA_STATUS
162 AmdIdentifyCore (
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 */
210 BOOLEAN
211 GetApicId (
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  */
251 BOOLEAN
252 GetPciAddress (
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  */
293 VOID
294 IdentifyCore (
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  */
338 UINT32
339 GetPlatformNumberOfSockets ()
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  */
356 UINT32
357 GetPlatformNumberOfModules ()
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  */
377 BOOLEAN
378 IsProcessorPresent (
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  */
419 UINT32
420 GetNumberOfProcessors (
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  */
464 BOOLEAN
465 GetSocketModuleOfNode (
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  */
508 UINT32
509 GetProcessorApicIndex (
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  */
545 VOID
546 GetCurrentNodeNum (
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  */
569 VOID
570 ModifyCurrentSocketPci (
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;
580   UINT32 PciReg;
581   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;
590       LibAmdPciRead (AccessWidth32, Reg, &PciReg, StdHeader);
591       PciReg &= Mask;
592       PciReg |= Data;
593       LibAmdPciWrite (AccessWidth32, Reg, &PciReg, StdHeader);
594     }
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  */
606 VOID
607 GetActiveCoresInCurrentSocket (
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  */
628 UINTN
629 GetActiveCoresInCurrentModule (
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  */
659 UINTN
660 GetNumberOfCompUnitsInCurrentModule (
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  */
710 BOOLEAN
711 GetActiveCoresInGivenSocket (
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  */
754 BOOLEAN
755 GetGivenModuleCoreRange (
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  */
793 VOID
794 GetCurrentCore (
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
805   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
806   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  */
833 VOID
834 GetCurrentNodeAndCore (
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  */
857 BOOLEAN
858 IsCurrentCorePrimary (
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  */
894 BOOLEAN
895 GetNodeId (
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  */
933 VOID
934 GetApMailbox (
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.
954     GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
955     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  */
974 VOID
975 CacheApMailbox (
976   IN       AMD_CONFIG_PARAMS    *StdHeader
977   )
978 {
979   ALLOCATE_HEAP_PARAMS AllocHeapParams;
980   AP_MAILBOXES ApMailboxes;
981   CPU_SPECIFIC_SERVICES *FamilyServices;
982
983   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
984   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  */
1009 UINTN
1010 GetSystemDegree (
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  */
1036 VOID
1037 WaitMicroseconds (
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);
1049   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilySpecificServices, StdHeader);
1050   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  */
1065 BOOLEAN
1066 IsBsp (
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  */
1098 COMPUTE_UNIT_MAPPING
1099 GetComputeUnitMapping (
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);
1119   GetCpuServicesOfCurrentCore ((const CPU_SPECIFIC_SERVICES **)&FamilyServices, StdHeader);
1120   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  */
1166 BOOLEAN
1167 IsCorePairPrimary (
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  */
1218 BOOLEAN
1219 AreCoresPaired (
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  */
1261 VOID
1262 InitializePciMmio (
1263   IN       AMD_CONFIG_PARAMS *StdHeader
1264   )
1265 {
1266   UINT8        EncodedSize;
1267   UINT64       MsrReg;
1268
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);
1274     MsrReg = ((UserOptions.CfgPciMmioAddress | BIT0) | (EncodedSize << 2));
1275     LibAmdMsrWrite (MSR_MMIO_Cfg_Base, &MsrReg, StdHeader);
1276   }
1277 }