]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/CpuMpPei/PeiMpServices.c
UefiCpuPkg/CpuMpPei: Implementation of PeiGetProcessorInfo ()
[mirror_edk2.git] / UefiCpuPkg / CpuMpPei / PeiMpServices.c
CommitLineData
887810c8
JF
1/** @file
2 Implementation of Multiple Processor PPI services.
3
4 Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
9
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
12
13**/
14
15#include "PeiMpServices.h"
16
17
bf55f5b2
JF
18/**
19 Get CPU Package/Core/Thread location information.
20
21 @param InitialApicId CPU APIC ID
22 @param Location Pointer to CPU location information
23**/
24VOID
25ExtractProcessorLocation (
26 IN UINT32 InitialApicId,
27 OUT EFI_CPU_PHYSICAL_LOCATION *Location
28 )
29{
30 BOOLEAN TopologyLeafSupported;
31 UINTN ThreadBits;
32 UINTN CoreBits;
33 UINT32 RegEax;
34 UINT32 RegEbx;
35 UINT32 RegEcx;
36 UINT32 RegEdx;
37 UINT32 MaxCpuIdIndex;
38 UINT32 SubIndex;
39 UINTN LevelType;
40 UINT32 MaxLogicProcessorsPerPackage;
41 UINT32 MaxCoresPerPackage;
42
43 //
44 // Check if the processor is capable of supporting more than one logical processor.
45 //
46 AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &RegEdx);
47 if ((RegEdx & BIT28) == 0) {
48 Location->Thread = 0;
49 Location->Core = 0;
50 Location->Package = 0;
51 return;
52 }
53
54 ThreadBits = 0;
55 CoreBits = 0;
56
57 //
58 // Assume three-level mapping of APIC ID: Package:Core:SMT.
59 //
60
61 TopologyLeafSupported = FALSE;
62 //
63 // Get the max index of basic CPUID
64 //
65 AsmCpuid (CPUID_SIGNATURE, &MaxCpuIdIndex, NULL, NULL, NULL);
66
67 //
68 // If the extended topology enumeration leaf is available, it
69 // is the preferred mechanism for enumerating topology.
70 //
71 if (MaxCpuIdIndex >= CPUID_EXTENDED_TOPOLOGY) {
72 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, 0, &RegEax, &RegEbx, &RegEcx, NULL);
73 //
74 // If CPUID.(EAX=0BH, ECX=0H):EBX returns zero and maximum input value for
75 // basic CPUID information is greater than 0BH, then CPUID.0BH leaf is not
76 // supported on that processor.
77 //
78 if (RegEbx != 0) {
79 TopologyLeafSupported = TRUE;
80
81 //
82 // Sub-leaf index 0 (ECX= 0 as input) provides enumeration parameters to extract
83 // the SMT sub-field of x2APIC ID.
84 //
85 LevelType = (RegEcx >> 8) & 0xff;
86 ASSERT (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_SMT);
87 ThreadBits = RegEax & 0x1f;
88
89 //
90 // Software must not assume any "level type" encoding
91 // value to be related to any sub-leaf index, except sub-leaf 0.
92 //
93 SubIndex = 1;
94 do {
95 AsmCpuidEx (CPUID_EXTENDED_TOPOLOGY, SubIndex, &RegEax, NULL, &RegEcx, NULL);
96 LevelType = (RegEcx >> 8) & 0xff;
97 if (LevelType == CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_CORE) {
98 CoreBits = (RegEax & 0x1f) - ThreadBits;
99 break;
100 }
101 SubIndex++;
102 } while (LevelType != CPUID_EXTENDED_TOPOLOGY_LEVEL_TYPE_INVALID);
103 }
104 }
105
106 if (!TopologyLeafSupported) {
107 AsmCpuid (CPUID_VERSION_INFO, NULL, &RegEbx, NULL, NULL);
108 MaxLogicProcessorsPerPackage = (RegEbx >> 16) & 0xff;
109 if (MaxCpuIdIndex >= CPUID_CACHE_PARAMS) {
110 AsmCpuidEx (CPUID_CACHE_PARAMS, 0, &RegEax, NULL, NULL, NULL);
111 MaxCoresPerPackage = (RegEax >> 26) + 1;
112 } else {
113 //
114 // Must be a single-core processor.
115 //
116 MaxCoresPerPackage = 1;
117 }
118
119 ThreadBits = (UINTN) (HighBitSet32 (MaxLogicProcessorsPerPackage / MaxCoresPerPackage - 1) + 1);
120 CoreBits = (UINTN) (HighBitSet32 (MaxCoresPerPackage - 1) + 1);
121 }
122
123 Location->Thread = InitialApicId & ~((-1) << ThreadBits);
124 Location->Core = (InitialApicId >> ThreadBits) & ~((-1) << CoreBits);
125 Location->Package = (InitialApicId >> (ThreadBits + CoreBits));
126}
887810c8
JF
127
128/**
129 Find the current Processor number by APIC ID.
130
131 @param PeiCpuMpData Pointer to PEI CPU MP Data
132 @param ProcessorNumber Return the pocessor number found
133
134 @retval EFI_SUCCESS ProcessorNumber is found and returned.
135 @retval EFI_NOT_FOUND ProcessorNumber is not found.
136**/
137EFI_STATUS
138GetProcessorNumber (
139 IN PEI_CPU_MP_DATA *PeiCpuMpData,
140 OUT UINTN *ProcessorNumber
141 )
142{
143 UINTN TotalProcessorNumber;
144 UINTN Index;
145
146 TotalProcessorNumber = PeiCpuMpData->CpuCount;
147 for (Index = 0; Index < TotalProcessorNumber; Index ++) {
148 if (PeiCpuMpData->CpuData[Index].ApicId == GetInitialApicId ()) {
149 *ProcessorNumber = Index;
150 return EFI_SUCCESS;
151 }
152 }
153 return EFI_NOT_FOUND;
154}
155
a2cc8cae
JF
156/**
157 This service retrieves the number of logical processor in the platform
158 and the number of those logical processors that are enabled on this boot.
159 This service may only be called from the BSP.
160
161 This function is used to retrieve the following information:
162 - The number of logical processors that are present in the system.
163 - The number of enabled logical processors in the system at the instant
164 this call is made.
165
166 Because MP Service Ppi provides services to enable and disable processors
167 dynamically, the number of enabled logical processors may vary during the
168 course of a boot session.
169
170 If this service is called from an AP, then EFI_DEVICE_ERROR is returned.
171 If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then
172 EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors
173 is returned in NumberOfProcessors, the number of currently enabled processor
174 is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned.
175
176 @param[in] PeiServices An indirect pointer to the PEI Services Table
177 published by the PEI Foundation.
178 @param[in] This Pointer to this instance of the PPI.
179 @param[out] NumberOfProcessors Pointer to the total number of logical processors in
180 the system, including the BSP and disabled APs.
181 @param[out] NumberOfEnabledProcessors
182 Number of processors in the system that are enabled.
183
184 @retval EFI_SUCCESS The number of logical processors and enabled
185 logical processors was retrieved.
186 @retval EFI_DEVICE_ERROR The calling processor is an AP.
187 @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL.
188 NumberOfEnabledProcessors is NULL.
189**/
190EFI_STATUS
191EFIAPI
192PeiGetNumberOfProcessors (
193 IN CONST EFI_PEI_SERVICES **PeiServices,
194 IN EFI_PEI_MP_SERVICES_PPI *This,
195 OUT UINTN *NumberOfProcessors,
196 OUT UINTN *NumberOfEnabledProcessors
197 )
198{
199 PEI_CPU_MP_DATA *PeiCpuMpData;
200 UINTN CallerNumber;
201 UINTN ProcessorNumber;
202 UINTN EnabledProcessorNumber;
203 UINTN Index;
204
205 PeiCpuMpData = GetMpHobData ();
206 if (PeiCpuMpData == NULL) {
207 return EFI_NOT_FOUND;
208 }
209
210 if ((NumberOfProcessors == NULL) || (NumberOfEnabledProcessors == NULL)) {
211 return EFI_INVALID_PARAMETER;
212 }
213
214 //
215 // Check whether caller processor is BSP
216 //
217 PeiWhoAmI (PeiServices, This, &CallerNumber);
218 if (CallerNumber != PeiCpuMpData->BspNumber) {
219 return EFI_DEVICE_ERROR;
220 }
221
222 ProcessorNumber = PeiCpuMpData->CpuCount;
223 EnabledProcessorNumber = 0;
224 for (Index = 0; Index < ProcessorNumber; Index++) {
225 if (PeiCpuMpData->CpuData[Index].State != CpuStateDisabled) {
226 EnabledProcessorNumber ++;
227 }
228 }
229
230 *NumberOfProcessors = ProcessorNumber;
231 *NumberOfEnabledProcessors = EnabledProcessorNumber;
232
233 return EFI_SUCCESS;
234}
887810c8 235
bf55f5b2
JF
236/**
237 Gets detailed MP-related information on the requested processor at the
238 instant this call is made. This service may only be called from the BSP.
239
240 This service retrieves detailed MP-related information about any processor
241 on the platform. Note the following:
242 - The processor information may change during the course of a boot session.
243 - The information presented here is entirely MP related.
244
245 Information regarding the number of caches and their sizes, frequency of operation,
246 slot numbers is all considered platform-related information and is not provided
247 by this service.
248
249 @param[in] PeiServices An indirect pointer to the PEI Services Table
250 published by the PEI Foundation.
251 @param[in] This Pointer to this instance of the PPI.
252 @param[in] ProcessorNumber Pointer to the total number of logical processors in
253 the system, including the BSP and disabled APs.
254 @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled.
255
256 @retval EFI_SUCCESS Processor information was returned.
257 @retval EFI_DEVICE_ERROR The calling processor is an AP.
258 @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL.
259 @retval EFI_NOT_FOUND The processor with the handle specified by
260 ProcessorNumber does not exist in the platform.
261**/
262EFI_STATUS
263EFIAPI
264PeiGetProcessorInfo (
265 IN CONST EFI_PEI_SERVICES **PeiServices,
266 IN EFI_PEI_MP_SERVICES_PPI *This,
267 IN UINTN ProcessorNumber,
268 OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer
269 )
270{
271 PEI_CPU_MP_DATA *PeiCpuMpData;
272 UINTN CallerNumber;
273
274 PeiCpuMpData = GetMpHobData ();
275 if (PeiCpuMpData == NULL) {
276 return EFI_NOT_FOUND;
277 }
278
279 //
280 // Check whether caller processor is BSP
281 //
282 PeiWhoAmI (PeiServices, This, &CallerNumber);
283 if (CallerNumber != PeiCpuMpData->BspNumber) {
284 return EFI_DEVICE_ERROR;
285 }
286
287 if (ProcessorInfoBuffer == NULL) {
288 return EFI_INVALID_PARAMETER;
289 }
290
291 if (ProcessorNumber >= PeiCpuMpData->CpuCount) {
292 return EFI_NOT_FOUND;
293 }
294
295 ProcessorInfoBuffer->ProcessorId = (UINT64) PeiCpuMpData->CpuData[ProcessorNumber].ApicId;
296 ProcessorInfoBuffer->StatusFlag = 0;
297 if (PeiCpuMpData->CpuData[ProcessorNumber].ApicId == GetInitialApicId()) {
298 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_AS_BSP_BIT;
299 }
300 if (PeiCpuMpData->CpuData[ProcessorNumber].Health.Uint32 == 0) {
301 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_HEALTH_STATUS_BIT;
302 }
303 if (PeiCpuMpData->CpuData[ProcessorNumber].State == CpuStateDisabled) {
304 ProcessorInfoBuffer->StatusFlag &= ~PROCESSOR_ENABLED_BIT;
305 } else {
306 ProcessorInfoBuffer->StatusFlag |= PROCESSOR_ENABLED_BIT;
307 }
308
309 //
310 // Get processor location information
311 //
312 ExtractProcessorLocation (PeiCpuMpData->CpuData[ProcessorNumber].ApicId, &ProcessorInfoBuffer->Location);
313
314 return EFI_SUCCESS;
315}
316
887810c8
JF
317/**
318 This return the handle number for the calling processor. This service may be
319 called from the BSP and APs.
320
321 This service returns the processor handle number for the calling processor.
322 The returned value is in the range from 0 to the total number of logical
323 processors minus 1. The total number of logical processors can be retrieved
324 with EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). This service may be
325 called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER
326 is returned. Otherwise, the current processors handle number is returned in
327 ProcessorNumber, and EFI_SUCCESS is returned.
328
329 @param[in] PeiServices An indirect pointer to the PEI Services Table
330 published by the PEI Foundation.
331 @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance.
332 @param[out] ProcessorNumber The handle number of the AP. The range is from 0 to the
333 total number of logical processors minus 1. The total
334 number of logical processors can be retrieved by
335 EFI_PEI_MP_SERVICES_PPI.GetNumberOfProcessors().
336
337 @retval EFI_SUCCESS The current processor handle number was returned in
338 ProcessorNumber.
339 @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL.
340**/
341EFI_STATUS
342EFIAPI
343PeiWhoAmI (
344 IN CONST EFI_PEI_SERVICES **PeiServices,
345 IN EFI_PEI_MP_SERVICES_PPI *This,
346 OUT UINTN *ProcessorNumber
347 )
348{
349 PEI_CPU_MP_DATA *PeiCpuMpData;
350
351 PeiCpuMpData = GetMpHobData ();
352 if (PeiCpuMpData == NULL) {
353 return EFI_NOT_FOUND;
354 }
355
356 if (ProcessorNumber == NULL) {
357 return EFI_INVALID_PARAMETER;
358 }
359
360 return GetProcessorNumber (PeiCpuMpData, ProcessorNumber);
361}
362