5 * AMD CPU Core Leveling Function.
7 * Contains code to Level the number of core in a multi-socket system
9 * @xrefitem bom "File Content Label" "Release Content"
12 * @e \$Revision: 56279 $ @e \$Date: 2011-07-11 13:11:28 -0600 (Mon, 11 Jul 2011) $
16 ******************************************************************************
18 * Copyright (C) 2012 Advanced Micro Devices, Inc.
19 * All rights reserved.
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
28 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
30 * from this software without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43 ******************************************************************************
44 *----------------------------------------------------------------------------
49 *----------------------------------------------------------------------------
52 *----------------------------------------------------------------------------
57 #include "cpuRegisters.h"
58 #include "GeneralServices.h"
59 #include "cpuServices.h"
60 #include "cpuFamilyTranslation.h"
61 #include "cpuFeatures.h"
62 #include "cpuEarlyInit.h"
66 #define FILECODE PROC_CPU_FEATURE_CPUCORELEVELING_FILECODE
67 /*----------------------------------------------------------------------------
68 * DEFINITIONS AND MACROS
70 *----------------------------------------------------------------------------
74 /*----------------------------------------------------------------------------
75 * TYPEDEFS AND STRUCTURES
77 *----------------------------------------------------------------------------
80 /*----------------------------------------------------------------------------------------
81 * E X P O R T E D F U N C T I O N S
82 *----------------------------------------------------------------------------------------
84 extern CPU_FAMILY_SUPPORT_TABLE CoreLevelingFamilyServiceTable;
86 /*----------------------------------------------------------------------------
87 * PROTOTYPES OF LOCAL FUNCTIONS
89 *----------------------------------------------------------------------------
94 IN PLATFORM_CONFIGURATION *PlatformConfig,
95 IN AMD_CONFIG_PARAMS *StdHeader
98 /*----------------------------------------------------------------------------------------
99 * P U B L I C F U N C T I O N S
100 *----------------------------------------------------------------------------------------
103 /*---------------------------------------------------------------------------------------*/
105 * Should core leveling be enabled
107 * @param[in] PlatformConfig Contains the runtime modifiable feature input data.
108 * @param[in] StdHeader Config Handle for library, services.
110 * @retval TRUE core leveling is supported.
111 * @retval FALSE core leveling cannot be enabled.
116 IsCoreLevelingEnabled (
117 IN PLATFORM_CONFIGURATION *PlatformConfig,
118 IN AMD_CONFIG_PARAMS *StdHeader
121 CORE_LEVELING_TYPE CoreLevelMode;
123 CoreLevelMode = (CORE_LEVELING_TYPE) PlatformConfig->CoreLevelingMode;
124 if (CoreLevelMode != CORE_LEVEL_NONE) {
131 /*---------------------------------------------------------------------------------------*/
133 * Performs core leveling for the system.
135 * This function implements the AMD_CPU_EARLY_PARAMS.CoreLevelingMode parameter.
136 * The possible modes are:
137 * -0 CORE_LEVEL_LOWEST Level to lowest common denominator
138 * -1 CORE_LEVEL_TWO Level to 2 cores
139 * -2 CORE_LEVEL_POWER_OF_TWO Level to 1,2,4 or 8
140 * -3 CORE_LEVEL_NONE Do no leveling
141 * -4 CORE_LEVEL_COMPUTE_UNIT Level cores to one core per compute unit
143 * @param[in] EntryPoint Timepoint designator.
144 * @param[in] PlatformConfig Contains the leveling mode parameter
145 * @param[in] StdHeader Config handle for library and services
147 * @return The most severe status of any family specific service.
151 CoreLevelingAtEarly (
152 IN UINT64 EntryPoint,
153 IN PLATFORM_CONFIGURATION *PlatformConfig,
154 IN AMD_CONFIG_PARAMS *StdHeader
157 UINT32 CoreNumPerComputeUnit;
158 UINT32 MinNumOfComputeUnit;
159 UINT32 EnabledComputeUnit;
162 UINT32 NumberOfSockets;
163 UINT32 NumberOfModules;
164 UINT32 MinCoreCountOnNode;
165 UINT32 MaxCoreCountOnNode;
169 UINT32 RequestedCores;
170 UINT32 TotalEnabledCoresOnNode;
172 AP_MAIL_INFO ApMailboxInfo;
173 CORE_LEVELING_TYPE CoreLevelMode;
174 CPU_CORE_LEVELING_FAMILY_SERVICES *FamilySpecificServices;
175 WARM_RESET_REQUEST Request;
177 IDS_HDT_CONSOLE (CPU_TRACE, "CoreLevelingAtEarly\n CoreLevelMode: %d\n", PlatformConfig->CoreLevelingMode);
179 MaxCoreCountOnNode = 0;
180 MinCoreCountOnNode = 0xFFFFFFFF;
182 CoreNumPerComputeUnit = 1;
183 MinNumOfComputeUnit = 0xFF;
185 ASSERT (PlatformConfig->CoreLevelingMode < CoreLevelModeMax);
187 // Get OEM IO core level mode
188 CoreLevelMode = (CORE_LEVELING_TYPE) PlatformConfig->CoreLevelingMode;
191 NumberOfSockets = GetPlatformNumberOfSockets ();
192 GetApMailbox (&ApMailboxInfo.Info, StdHeader);
193 NumberOfModules = ApMailboxInfo.Fields.ModuleType + 1;
195 // Collect cpu core info
196 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
197 if (IsProcessorPresent (Socket, StdHeader)) {
198 for (Module = 0; Module < NumberOfModules; Module++) {
199 if (GetGivenModuleCoreRange (Socket, Module, &LowCore, &HighCore, StdHeader)) {
200 // Get the highest and lowest core count in all nodes
201 TotalEnabledCoresOnNode = HighCore - LowCore + 1;
202 if (TotalEnabledCoresOnNode < MinCoreCountOnNode) {
203 MinCoreCountOnNode = TotalEnabledCoresOnNode;
205 if (TotalEnabledCoresOnNode > MaxCoreCountOnNode) {
206 MaxCoreCountOnNode = TotalEnabledCoresOnNode;
208 EnabledComputeUnit = TotalEnabledCoresOnNode;
209 switch (GetComputeUnitMapping (StdHeader)) {
210 case AllCoresMapping:
211 // All cores are in their own compute unit.
213 case EvenCoresMapping:
214 // Cores are paired in compute units.
215 CoreNumPerComputeUnit = 2;
216 EnabledComputeUnit = (TotalEnabledCoresOnNode / 2);
221 // Get minimum of compute unit. This will either be the minimum number of cores (AllCoresMapping),
222 // or less (EvenCoresMapping).
223 if (EnabledComputeUnit < MinNumOfComputeUnit) {
224 MinNumOfComputeUnit = EnabledComputeUnit;
226 IDS_HDT_CONSOLE (CPU_TRACE, " Socket %d Module %d MaxCoreCountOnNode %d MinCoreCountOnNode %d TotalEnabledCoresOnNode %d EnabledComputeUnit %d MinNumOfComputeUnit %d\n", \
227 Socket, Module, MaxCoreCountOnNode, MinCoreCountOnNode, TotalEnabledCoresOnNode, EnabledComputeUnit, MinNumOfComputeUnit);
234 switch (CoreLevelMode) {
235 case CORE_LEVEL_LOWEST:
236 if (MinCoreCountOnNode == MaxCoreCountOnNode) {
237 return (AGESA_SUCCESS);
239 LeveledCores = (MinCoreCountOnNode / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
242 LeveledCores = 2 / NumberOfModules;
243 if (LeveledCores != 0) {
244 LeveledCores = (LeveledCores <= MinCoreCountOnNode) ? LeveledCores : MinCoreCountOnNode;
246 return (AGESA_WARNING);
248 if ((LeveledCores * NumberOfModules) != 2) {
251 CPU_WARNING_ADJUSTED_LEVELING_MODE,
252 2, (LeveledCores * NumberOfModules), 0, 0, StdHeader
256 case CORE_LEVEL_POWER_OF_TWO:
257 // Level to power of 2 (1, 2, 4, 8...)
259 while (MinCoreCountOnNode >= (LeveledCores * 2)) {
260 LeveledCores = LeveledCores * 2;
263 case CORE_LEVEL_COMPUTE_UNIT:
264 // Level cores to one core per compute unit, with additional reduction to level
265 // all processors to match the processor with the minimum number of cores.
266 if (CoreNumPerComputeUnit == 1) {
267 // If there is one core per compute unit, this is the same as CORE_LEVEL_LOWEST.
268 if (MinCoreCountOnNode == MaxCoreCountOnNode) {
269 return (AGESA_SUCCESS);
271 LeveledCores = MinCoreCountOnNode;
273 // If there are more than one core per compute unit, level to the number of compute units.
274 LeveledCores = MinNumOfComputeUnit;
279 if (NumberOfModules > 1) {
282 CPU_WARNING_ADJUSTED_LEVELING_MODE,
283 1, NumberOfModules, 0, 0, StdHeader
287 case CORE_LEVEL_THREE:
288 case CORE_LEVEL_FOUR:
289 case CORE_LEVEL_FIVE:
291 case CORE_LEVEL_SEVEN:
292 case CORE_LEVEL_EIGHT:
293 case CORE_LEVEL_NINE:
295 case CORE_LEVEL_ELEVEN:
296 case CORE_LEVEL_TWELVE:
297 case CORE_LEVEL_THIRTEEN:
298 case CORE_LEVEL_FOURTEEN:
299 case CORE_LEVEL_FIFTEEN:
300 // MCM processors can not have an odd number of cores. For an odd CORE_LEVEL_N, MCM processors will be
301 // leveled as though CORE_LEVEL_N+1 was chosen.
302 // Processors with compute units disable all cores in an entire compute unit at a time, or on an MCM processor,
303 // two compute units at a time. For example, on an SCM processor with two cores per compute unit, the effective
304 // explicit levels are CORE_LEVEL_ONE, CORE_LEVEL_TWO, CORE_LEVEL_FOUR, CORE_LEVEL_SIX, and
305 // CORE_LEVEL_EIGHT. The same example for an MCM processor with two cores per compute unit has effective
306 // explicit levels of CORE_LEVEL_TWO, CORE_LEVEL_FOUR, CORE_LEVEL_EIGHT, and CORE_LEVEL_TWELVE.
307 RequestedCores = CoreLevelMode - CORE_LEVEL_THREE + 3;
308 LeveledCores = (RequestedCores + NumberOfModules - 1) / NumberOfModules;
309 LeveledCores = (LeveledCores / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
310 LeveledCores = (LeveledCores <= MinCoreCountOnNode) ? LeveledCores : MinCoreCountOnNode;
311 if (LeveledCores != 1) {
312 LeveledCores = (LeveledCores / CoreNumPerComputeUnit) * CoreNumPerComputeUnit;
314 if ((LeveledCores * NumberOfModules * CoreNumPerComputeUnit) != RequestedCores) {
317 CPU_WARNING_ADJUSTED_LEVELING_MODE,
318 RequestedCores, (LeveledCores * NumberOfModules * CoreNumPerComputeUnit), 0, 0, StdHeader
326 // Set down core register
327 for (Socket = 0; Socket < NumberOfSockets; Socket++) {
328 if (IsProcessorPresent (Socket, StdHeader)) {
329 GetFeatureServicesOfSocket (&CoreLevelingFamilyServiceTable, Socket, (CONST VOID **)&FamilySpecificServices, StdHeader);
330 if (FamilySpecificServices != NULL) {
331 for (Module = 0; Module < NumberOfModules; Module++) {
332 IDS_HDT_CONSOLE (CPU_TRACE, " SetDownCoreRegister: Socket %d Module %d LeveledCores %d CoreLevelMode %d\n", Socket, Module, LeveledCores, CoreLevelMode);
333 RegUpdated = FamilySpecificServices->SetDownCoreRegister (FamilySpecificServices, &Socket, &Module, &LeveledCores, CoreLevelMode, StdHeader);
334 // If the down core register is updated, trigger a warm reset.
336 GetWarmResetFlag (StdHeader, &Request);
337 Request.RequestBit = TRUE;
338 Request.StateBits = Request.PostStage - 1;
339 IDS_HDT_CONSOLE (CPU_TRACE, " Request a warm reset.\n");
340 SetWarmResetFlag (StdHeader, &Request);
347 return (AGESA_SUCCESS);
351 CONST CPU_FEATURE_DESCRIPTOR ROMDATA CpuFeatureCoreLeveling =
354 (CPU_FEAT_AFTER_PM_INIT),
355 IsCoreLevelingEnabled,
359 /*----------------------------------------------------------------------------------------
360 * L O C A L F U N C T I O N S
361 *----------------------------------------------------------------------------------------