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