]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
UefiCpuPkg/RegisterCpuFeaturesLib: Fix build failure.
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / CpuFeaturesInitialize.c
CommitLineData
80c4b236
JF
1/** @file\r
2 CPU Features Initialize functions.\r
3\r
7367cc6c 4 Copyright (c) 2017 - 2018, Intel Corporation. All rights reserved.<BR>\r
80c4b236
JF
5 This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13**/\r
14\r
15#include "RegisterCpuFeatures.h"\r
16\r
b3c71b47
ED
17CHAR16 *mDependTypeStr[] = {L"None", L"Thread", L"Core", L"Package", L"Invalid" };\r
18CHAR16 *mRegisterTypeStr[] = {L"MSR", L"CR", L"MMIO", L"CACHE", L"SEMAP", L"INVALID" };\r
19\r
80c4b236
JF
20/**\r
21 Worker function to save PcdCpuFeaturesCapability.\r
22\r
23 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
24**/\r
25VOID\r
26SetCapabilityPcd (\r
27 IN UINT8 *SupportedFeatureMask\r
28 )\r
29{\r
30 EFI_STATUS Status;\r
31 UINTN BitMaskSize;\r
32\r
33 BitMaskSize = PcdGetSize (PcdCpuFeaturesCapability);\r
34 Status = PcdSetPtrS (PcdCpuFeaturesCapability, &BitMaskSize, SupportedFeatureMask);\r
35 ASSERT_EFI_ERROR (Status);\r
36}\r
37\r
38/**\r
39 Worker function to save PcdCpuFeaturesSetting.\r
40\r
41 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
42**/\r
43VOID\r
44SetSettingPcd (\r
45 IN UINT8 *SupportedFeatureMask\r
46 )\r
47{\r
48 EFI_STATUS Status;\r
49 UINTN BitMaskSize;\r
50\r
51 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
52 Status = PcdSetPtrS (PcdCpuFeaturesSetting, &BitMaskSize, SupportedFeatureMask);\r
53 ASSERT_EFI_ERROR (Status);\r
54}\r
55\r
56/**\r
57 Worker function to get PcdCpuFeaturesSupport.\r
58\r
59 @return The pointer to CPU feature bits mask buffer.\r
60**/\r
61UINT8 *\r
7d3a7c22 62GetSupportPcd (\r
80c4b236
JF
63 VOID\r
64 )\r
65{\r
80c4b236
JF
66 UINT8 *SupportBitMask;\r
67\r
6619cf3b 68 SupportBitMask = AllocateCopyPool (\r
7367cc6c 69 PcdGetSize (PcdCpuFeaturesSupport),\r
6619cf3b
ED
70 PcdGetPtr (PcdCpuFeaturesSupport)\r
71 );\r
80c4b236 72 ASSERT (SupportBitMask != NULL);\r
80c4b236
JF
73\r
74 return SupportBitMask;\r
75}\r
76\r
77/**\r
78 Worker function to get PcdCpuFeaturesUserConfiguration.\r
79\r
80 @return The pointer to CPU feature bits mask buffer.\r
81**/\r
82UINT8 *\r
7d3a7c22 83GetConfigurationPcd (\r
80c4b236
JF
84 VOID\r
85 )\r
86{\r
80c4b236
JF
87 UINT8 *SupportBitMask;\r
88\r
6619cf3b 89 SupportBitMask = AllocateCopyPool (\r
7367cc6c 90 PcdGetSize (PcdCpuFeaturesUserConfiguration),\r
6619cf3b
ED
91 PcdGetPtr (PcdCpuFeaturesUserConfiguration)\r
92 );\r
80c4b236 93 ASSERT (SupportBitMask != NULL);\r
80c4b236
JF
94\r
95 return SupportBitMask;\r
96}\r
97\r
98/**\r
99 Collects CPU type and feature information.\r
100\r
101 @param[in, out] CpuInfo The pointer to CPU feature information\r
102**/\r
103VOID\r
104FillProcessorInfo (\r
105 IN OUT REGISTER_CPU_FEATURE_INFORMATION *CpuInfo\r
106 )\r
107{\r
108 CPUID_VERSION_INFO_EAX Eax;\r
109 CPUID_VERSION_INFO_ECX Ecx;\r
110 CPUID_VERSION_INFO_EDX Edx;\r
111 UINT32 DisplayedFamily;\r
112 UINT32 DisplayedModel;\r
113\r
114 AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, &Ecx.Uint32, &Edx.Uint32);\r
115\r
116 DisplayedFamily = Eax.Bits.FamilyId;\r
117 if (Eax.Bits.FamilyId == 0x0F) {\r
118 DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);\r
119 }\r
120\r
121 DisplayedModel = Eax.Bits.Model;\r
122 if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {\r
123 DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);\r
124 }\r
125\r
126 CpuInfo->DisplayFamily = DisplayedFamily;\r
127 CpuInfo->DisplayModel = DisplayedModel;\r
128 CpuInfo->SteppingId = Eax.Bits.SteppingId;\r
129 CpuInfo->ProcessorType = Eax.Bits.ProcessorType;\r
130 CpuInfo->CpuIdVersionInfoEcx.Uint32 = Ecx.Uint32;\r
131 CpuInfo->CpuIdVersionInfoEdx.Uint32 = Edx.Uint32;\r
132}\r
133\r
134/**\r
135 Prepares for private data used for CPU features.\r
136\r
137 @param[in] NumberOfCpus Number of processor in system\r
138**/\r
139VOID\r
140CpuInitDataInitialize (\r
141 IN UINTN NumberOfCpus\r
142 )\r
143{\r
144 EFI_STATUS Status;\r
145 UINTN ProcessorNumber;\r
146 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
147 CPU_FEATURES_ENTRY *CpuFeature;\r
148 CPU_FEATURES_INIT_ORDER *InitOrder;\r
149 CPU_FEATURES_DATA *CpuFeaturesData;\r
150 LIST_ENTRY *Entry;\r
b3c71b47
ED
151 UINT32 Core;\r
152 UINT32 Package;\r
153 UINT32 Thread;\r
154 EFI_CPU_PHYSICAL_LOCATION *Location;\r
155 BOOLEAN *CoresVisited;\r
156 UINTN Index;\r
157 ACPI_CPU_DATA *AcpiCpuData;\r
158 CPU_STATUS_INFORMATION *CpuStatus;\r
159 UINT32 *ValidCoreCountPerPackage;\r
160\r
161 Core = 0;\r
162 Package = 0;\r
163 Thread = 0;\r
80c4b236
JF
164\r
165 CpuFeaturesData = GetCpuFeaturesData ();\r
166 CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
167 ASSERT (CpuFeaturesData->InitOrder != NULL);\r
80c4b236
JF
168\r
169 //\r
170 // Collect CPU Features information\r
171 //\r
172 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
173 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
174 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
175 ASSERT (CpuFeature->InitializeFunc != NULL);\r
176 if (CpuFeature->GetConfigDataFunc != NULL) {\r
177 CpuFeature->ConfigData = CpuFeature->GetConfigDataFunc (NumberOfCpus);\r
178 }\r
179 Entry = Entry->ForwardLink;\r
180 }\r
181\r
b3c71b47
ED
182 CpuFeaturesData->NumberOfCpus = (UINT32) NumberOfCpus;\r
183\r
184 AcpiCpuData = GetAcpiCpuData ();\r
185 ASSERT (AcpiCpuData != NULL);\r
186 CpuFeaturesData->AcpiCpuData= AcpiCpuData;\r
187\r
188 CpuStatus = &AcpiCpuData->CpuStatus;\r
189 Location = AllocateZeroPool (sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus);\r
190 ASSERT (Location != NULL);\r
191 AcpiCpuData->ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\r
192\r
80c4b236
JF
193 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
194 InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
195 InitOrder->FeaturesSupportedMask = AllocateZeroPool (CpuFeaturesData->BitMaskSize);\r
196 ASSERT (InitOrder->FeaturesSupportedMask != NULL);\r
197 InitializeListHead (&InitOrder->OrderList);\r
198 Status = GetProcessorInformation (ProcessorNumber, &ProcessorInfoBuffer);\r
199 ASSERT_EFI_ERROR (Status);\r
200 CopyMem (\r
201 &InitOrder->CpuInfo.ProcessorInfo,\r
202 &ProcessorInfoBuffer,\r
203 sizeof (EFI_PROCESSOR_INFORMATION)\r
204 );\r
b3c71b47
ED
205 CopyMem (\r
206 &Location[ProcessorNumber],\r
207 &ProcessorInfoBuffer.Location,\r
208 sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
209 );\r
210\r
211 //\r
212 // Collect CPU package count info.\r
213 //\r
214 if (Package < ProcessorInfoBuffer.Location.Package) {\r
215 Package = ProcessorInfoBuffer.Location.Package;\r
216 }\r
217 //\r
218 // Collect CPU max core count info.\r
219 //\r
220 if (Core < ProcessorInfoBuffer.Location.Core) {\r
221 Core = ProcessorInfoBuffer.Location.Core;\r
222 }\r
223 //\r
224 // Collect CPU max thread count info.\r
225 //\r
226 if (Thread < ProcessorInfoBuffer.Location.Thread) {\r
227 Thread = ProcessorInfoBuffer.Location.Thread;\r
228 }\r
80c4b236 229 }\r
b3c71b47
ED
230 CpuStatus->PackageCount = Package + 1;\r
231 CpuStatus->MaxCoreCount = Core + 1;\r
232 CpuStatus->MaxThreadCount = Thread + 1;\r
233 DEBUG ((DEBUG_INFO, "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",\r
234 CpuStatus->PackageCount,\r
235 CpuStatus->MaxCoreCount,\r
236 CpuStatus->MaxThreadCount));\r
237\r
238 //\r
239 // Collect valid core count in each package because not all cores are valid.\r
240 //\r
241 ValidCoreCountPerPackage= AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount);\r
242 ASSERT (ValidCoreCountPerPackage != 0);\r
243 CpuStatus->ValidCoreCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ValidCoreCountPerPackage;\r
244 CoresVisited = AllocatePool (sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
245 ASSERT (CoresVisited != NULL);\r
246\r
247 for (Index = 0; Index < CpuStatus->PackageCount; Index ++ ) {\r
248 ZeroMem (CoresVisited, sizeof (BOOLEAN) * CpuStatus->MaxCoreCount);\r
249 //\r
250 // Collect valid cores in Current package.\r
251 //\r
252 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
253 Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
254 if (Location->Package == Index && !CoresVisited[Location->Core] ) {\r
255 //\r
256 // The ValidCores position for Location->Core is valid.\r
257 // The possible values in ValidCores[Index] are 0 or 1.\r
258 // FALSE means no valid threads in this Core.\r
259 // TRUE means have valid threads in this core, no matter the thead count is 1 or more.\r
260 //\r
261 CoresVisited[Location->Core] = TRUE;\r
262 ValidCoreCountPerPackage[Index]++;\r
263 }\r
264 }\r
265 }\r
266 FreePool (CoresVisited);\r
267\r
268 for (Index = 0; Index <= Package; Index++) {\r
269 DEBUG ((DEBUG_INFO, "Package: %d, Valid Core : %d\n", Index, ValidCoreCountPerPackage[Index]));\r
270 }\r
271\r
272 CpuFeaturesData->CpuFlags.SemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
273 ASSERT (CpuFeaturesData->CpuFlags.SemaphoreCount != NULL);\r
274\r
80c4b236
JF
275 //\r
276 // Get support and configuration PCDs\r
277 //\r
7d3a7c22
SB
278 CpuFeaturesData->SupportPcd = GetSupportPcd ();\r
279 CpuFeaturesData->ConfigurationPcd = GetConfigurationPcd ();\r
80c4b236
JF
280}\r
281\r
282/**\r
283 Worker function to do OR operation on CPU feature supported bits mask buffer.\r
284\r
285 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
286 @param[in] OrFeatureBitMask The feature bit mask to do OR operation\r
287**/\r
288VOID\r
289SupportedMaskOr (\r
290 IN UINT8 *SupportedFeatureMask,\r
291 IN UINT8 *OrFeatureBitMask\r
292 )\r
293{\r
294 UINTN Index;\r
295 UINTN BitMaskSize;\r
296 UINT8 *Data1;\r
297 UINT8 *Data2;\r
298\r
299 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
300 Data1 = SupportedFeatureMask;\r
301 Data2 = OrFeatureBitMask;\r
302 for (Index = 0; Index < BitMaskSize; Index++) {\r
303 *(Data1++) |= *(Data2++);\r
304 }\r
305}\r
306\r
307/**\r
308 Worker function to do AND operation on CPU feature supported bits mask buffer.\r
309\r
310 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
311 @param[in] AndFeatureBitMask The feature bit mask to do AND operation\r
312**/\r
313VOID\r
314SupportedMaskAnd (\r
315 IN UINT8 *SupportedFeatureMask,\r
316 IN UINT8 *AndFeatureBitMask\r
317 )\r
318{\r
319 UINTN Index;\r
320 UINTN BitMaskSize;\r
321 UINT8 *Data1;\r
322 UINT8 *Data2;\r
323\r
324 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
325 Data1 = SupportedFeatureMask;\r
326 Data2 = AndFeatureBitMask;\r
327 for (Index = 0; Index < BitMaskSize; Index++) {\r
328 *(Data1++) &= *(Data2++);\r
329 }\r
330}\r
331\r
05973f9e
ED
332/**\r
333 Worker function to clean bit operation on CPU feature supported bits mask buffer.\r
334\r
335 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
336 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation\r
337**/\r
338VOID\r
339SupportedMaskCleanBit (\r
340 IN UINT8 *SupportedFeatureMask,\r
341 IN UINT8 *AndFeatureBitMask\r
342 )\r
343{\r
344 UINTN Index;\r
345 UINTN BitMaskSize;\r
346 UINT8 *Data1;\r
347 UINT8 *Data2;\r
348\r
349 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
350 Data1 = SupportedFeatureMask;\r
351 Data2 = AndFeatureBitMask;\r
352 for (Index = 0; Index < BitMaskSize; Index++) {\r
353 *(Data1++) &= ~(*(Data2++));\r
354 }\r
355}\r
356\r
80c4b236
JF
357/**\r
358 Worker function to check if the compared CPU feature set in the CPU feature\r
359 supported bits mask buffer.\r
360\r
361 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
362 @param[in] ComparedFeatureBitMask The feature bit mask to be compared\r
363\r
364 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits\r
365 mask buffer.\r
366 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits\r
367 mask buffer.\r
368**/\r
369BOOLEAN\r
370IsBitMaskMatch (\r
371 IN UINT8 *SupportedFeatureMask,\r
372 IN UINT8 *ComparedFeatureBitMask\r
373 )\r
374{\r
375 UINTN Index;\r
376 UINTN BitMaskSize;\r
377 UINT8 *Data1;\r
378 UINT8 *Data2;\r
379\r
380 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
381\r
382 Data1 = SupportedFeatureMask;\r
383 Data2 = ComparedFeatureBitMask;\r
384 for (Index = 0; Index < BitMaskSize; Index++) {\r
385 if (((*(Data1++)) & (*(Data2++))) != 0) {\r
386 return TRUE;\r
387 }\r
388 }\r
389 return FALSE;\r
390}\r
391\r
392/**\r
393 Collects processor data for calling processor.\r
394\r
395 @param[in,out] Buffer The pointer to private data buffer.\r
396**/\r
397VOID\r
398EFIAPI\r
399CollectProcessorData (\r
400 IN OUT VOID *Buffer\r
401 )\r
402{\r
403 UINTN ProcessorNumber;\r
404 CPU_FEATURES_ENTRY *CpuFeature;\r
405 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
406 LIST_ENTRY *Entry;\r
407 CPU_FEATURES_DATA *CpuFeaturesData;\r
408\r
b3c71b47 409 CpuFeaturesData = (CPU_FEATURES_DATA *)Buffer;\r
80c4b236
JF
410 ProcessorNumber = GetProcessorIndex ();\r
411 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
412 //\r
413 // collect processor information\r
414 //\r
415 FillProcessorInfo (CpuInfo);\r
416 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
417 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
418 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
7d3a7c22 419 if (IsBitMaskMatch (CpuFeaturesData->SupportPcd, CpuFeature->FeatureMask)) {\r
80c4b236
JF
420 if (CpuFeature->SupportFunc == NULL) {\r
421 //\r
422 // If SupportFunc is NULL, then the feature is supported.\r
423 //\r
424 SupportedMaskOr (\r
425 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
426 CpuFeature->FeatureMask\r
427 );\r
428 } else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {\r
429 SupportedMaskOr (\r
430 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
431 CpuFeature->FeatureMask\r
432 );\r
433 }\r
434 }\r
435 Entry = Entry->ForwardLink;\r
436 }\r
437}\r
438\r
439/**\r
440 Dump the contents of a CPU register table.\r
441\r
442 @param[in] ProcessorNumber The index of the CPU to show the register table contents\r
443\r
444 @note This service could be called by BSP only.\r
445**/\r
446VOID\r
447DumpRegisterTableOnProcessor (\r
448 IN UINTN ProcessorNumber\r
449 )\r
450{\r
451 CPU_FEATURES_DATA *CpuFeaturesData;\r
452 UINTN FeatureIndex;\r
453 CPU_REGISTER_TABLE *RegisterTable;\r
454 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
455 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
456 UINT32 DebugPrintErrorLevel;\r
457\r
458 DebugPrintErrorLevel = (ProcessorNumber == 0) ? DEBUG_INFO : DEBUG_VERBOSE;\r
459 CpuFeaturesData = GetCpuFeaturesData ();\r
460 //\r
461 // Debug information\r
462 //\r
463 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
464 DEBUG ((DebugPrintErrorLevel, "RegisterTable->TableLength = %d\n", RegisterTable->TableLength));\r
465\r
466 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
467\r
468 for (FeatureIndex = 0; FeatureIndex < RegisterTable->TableLength; FeatureIndex++) {\r
469 RegisterTableEntry = &RegisterTableEntryHead[FeatureIndex];\r
470 switch (RegisterTableEntry->RegisterType) {\r
471 case Msr:\r
472 DEBUG ((\r
473 DebugPrintErrorLevel,\r
474 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
475 ProcessorNumber,\r
476 RegisterTableEntry->Index,\r
477 RegisterTableEntry->ValidBitStart,\r
478 RegisterTableEntry->ValidBitLength,\r
479 RegisterTableEntry->Value\r
480 ));\r
481 break;\r
482 case ControlRegister:\r
483 DEBUG ((\r
484 DebugPrintErrorLevel,\r
485 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
486 ProcessorNumber,\r
487 RegisterTableEntry->Index,\r
488 RegisterTableEntry->ValidBitStart,\r
489 RegisterTableEntry->ValidBitLength,\r
490 RegisterTableEntry->Value\r
491 ));\r
492 break;\r
493 case MemoryMapped:\r
494 DEBUG ((\r
495 DebugPrintErrorLevel,\r
496 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
497 ProcessorNumber,\r
498 RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),\r
499 RegisterTableEntry->ValidBitStart,\r
500 RegisterTableEntry->ValidBitLength,\r
501 RegisterTableEntry->Value\r
502 ));\r
503 break;\r
504 case CacheControl:\r
505 DEBUG ((\r
506 DebugPrintErrorLevel,\r
507 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
508 ProcessorNumber,\r
509 RegisterTableEntry->Index,\r
510 RegisterTableEntry->ValidBitStart,\r
511 RegisterTableEntry->ValidBitLength,\r
512 RegisterTableEntry->Value\r
513 ));\r
514 break;\r
b3c71b47
ED
515 case Semaphore:\r
516 DEBUG ((\r
517 DebugPrintErrorLevel,\r
518 "Processor: %d: Semaphore: Scope Value: %s\r\n",\r
519 ProcessorNumber,\r
beabfd58 520 mDependTypeStr[MIN ((UINT32)RegisterTableEntry->Value, InvalidDepType)]\r
b3c71b47
ED
521 ));\r
522 break;\r
523\r
80c4b236
JF
524 default:\r
525 break;\r
526 }\r
527 }\r
528}\r
529\r
530/**\r
531 Analysis register CPU features on each processor and save CPU setting in CPU register table.\r
532\r
533 @param[in] NumberOfCpus Number of processor in system\r
534\r
535**/\r
536VOID\r
537AnalysisProcessorFeatures (\r
538 IN UINTN NumberOfCpus\r
539 )\r
540{\r
541 EFI_STATUS Status;\r
542 UINTN ProcessorNumber;\r
543 CPU_FEATURES_ENTRY *CpuFeature;\r
544 CPU_FEATURES_ENTRY *CpuFeatureInOrder;\r
545 CPU_FEATURES_INIT_ORDER *CpuInitOrder;\r
546 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
547 LIST_ENTRY *Entry;\r
548 CPU_FEATURES_DATA *CpuFeaturesData;\r
b3c71b47
ED
549 LIST_ENTRY *NextEntry;\r
550 CPU_FEATURES_ENTRY *NextCpuFeatureInOrder;\r
551 BOOLEAN Success;\r
552 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep;\r
553 CPU_FEATURE_DEPENDENCE_TYPE AfterDep;\r
80c4b236
JF
554\r
555 CpuFeaturesData = GetCpuFeaturesData ();\r
7d3a7c22
SB
556 CpuFeaturesData->CapabilityPcd = AllocatePool (CpuFeaturesData->BitMaskSize);\r
557 ASSERT (CpuFeaturesData->CapabilityPcd != NULL);\r
558 SetMem (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize, 0xFF);\r
80c4b236
JF
559 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
560 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
561 //\r
562 // Calculate the last capability on all processors\r
563 //\r
7d3a7c22 564 SupportedMaskAnd (CpuFeaturesData->CapabilityPcd, CpuInitOrder->FeaturesSupportedMask);\r
80c4b236
JF
565 }\r
566 //\r
567 // Calculate the last setting\r
568 //\r
569\r
7d3a7c22
SB
570 CpuFeaturesData->SettingPcd = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcd);\r
571 ASSERT (CpuFeaturesData->SettingPcd != NULL);\r
572 SupportedMaskAnd (CpuFeaturesData->SettingPcd, CpuFeaturesData->ConfigurationPcd);\r
80c4b236
JF
573\r
574 //\r
575 // Save PCDs and display CPU PCDs\r
576 //\r
7d3a7c22
SB
577 SetCapabilityPcd (CpuFeaturesData->CapabilityPcd);\r
578 SetSettingPcd (CpuFeaturesData->SettingPcd);\r
80c4b236
JF
579\r
580 //\r
581 // Dump the last CPU feature list\r
582 //\r
583 DEBUG_CODE (\r
584 DEBUG ((DEBUG_INFO, "Last CPU features list...\n"));\r
585 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
586 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
587 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
7d3a7c22
SB
588 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd)) {\r
589 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcd)) {\r
80c4b236
JF
590 DEBUG ((DEBUG_INFO, "[Enable ] "));\r
591 } else {\r
592 DEBUG ((DEBUG_INFO, "[Disable ] "));\r
593 }\r
594 } else {\r
595 DEBUG ((DEBUG_INFO, "[Unsupport] "));\r
596 }\r
597 DumpCpuFeature (CpuFeature);\r
598 Entry = Entry->ForwardLink;\r
599 }\r
600 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSupport:\n"));\r
7d3a7c22 601 DumpCpuFeatureMask (CpuFeaturesData->SupportPcd);\r
80c4b236 602 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesUserConfiguration:\n"));\r
7d3a7c22 603 DumpCpuFeatureMask (CpuFeaturesData->ConfigurationPcd);\r
80c4b236 604 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));\r
7d3a7c22 605 DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcd);\r
80c4b236 606 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSetting:\n"));\r
7d3a7c22 607 DumpCpuFeatureMask (CpuFeaturesData->SettingPcd);\r
80c4b236
JF
608 );\r
609\r
610 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
611 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
612 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
613 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
614 //\r
615 // Insert each feature into processor's order list\r
616 //\r
617 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
7d3a7c22 618 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd)) {\r
80c4b236
JF
619 CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);\r
620 ASSERT (CpuFeatureInOrder != NULL);\r
621 InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);\r
622 }\r
623 Entry = Entry->ForwardLink;\r
624 }\r
625 //\r
626 // Go through ordered feature list to initialize CPU features\r
627 //\r
628 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
629 Entry = GetFirstNode (&CpuInitOrder->OrderList);\r
b3c71b47 630 NextEntry = Entry->ForwardLink;\r
80c4b236
JF
631 while (!IsNull (&CpuInitOrder->OrderList, Entry)) {\r
632 CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
b3c71b47
ED
633 if (!IsNull (&CpuInitOrder->OrderList, NextEntry)) {\r
634 NextCpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);\r
635 } else {\r
636 NextCpuFeatureInOrder = NULL;\r
637 }\r
638 Success = FALSE;\r
7d3a7c22 639 if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcd)) {\r
80c4b236 640 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);\r
05973f9e
ED
641 if (EFI_ERROR (Status)) {\r
642 //\r
643 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.\r
644 //\r
7d3a7c22 645 SupportedMaskCleanBit (CpuFeaturesData->SettingPcd, CpuFeatureInOrder->FeatureMask);\r
05973f9e 646 if (CpuFeatureInOrder->FeatureName != NULL) {\r
2bda6247 647 DEBUG ((DEBUG_WARN, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder->FeatureName));\r
05973f9e 648 } else {\r
2bda6247 649 DEBUG ((DEBUG_WARN, "Warning :: Failed to enable Feature: Mask = "));\r
05973f9e
ED
650 DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask);\r
651 }\r
b3c71b47
ED
652 } else {\r
653 Success = TRUE;\r
05973f9e 654 }\r
80c4b236
JF
655 } else {\r
656 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);\r
852b3935
ED
657 if (EFI_ERROR (Status)) {\r
658 if (CpuFeatureInOrder->FeatureName != NULL) {\r
2bda6247 659 DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder->FeatureName));\r
852b3935 660 } else {\r
2bda6247 661 DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Mask = "));\r
852b3935
ED
662 DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask);\r
663 }\r
b3c71b47
ED
664 } else {\r
665 Success = TRUE;\r
852b3935 666 }\r
80c4b236 667 }\r
b3c71b47
ED
668\r
669 if (Success) {\r
670 //\r
671 // If feature has dependence with the next feature (ONLY care core/package dependency).\r
672 // and feature initialize succeed, add sync semaphere here.\r
673 //\r
b3c71b47 674 if (NextCpuFeatureInOrder != NULL) {\r
1475b83f
ED
675 BeforeDep = DetectFeatureScope (CpuFeatureInOrder, TRUE, NextCpuFeatureInOrder->FeatureMask);\r
676 AfterDep = DetectFeatureScope (NextCpuFeatureInOrder, FALSE, CpuFeatureInOrder->FeatureMask);\r
b3c71b47 677 } else {\r
1475b83f 678 BeforeDep = DetectFeatureScope (CpuFeatureInOrder, TRUE, NULL);\r
b3c71b47
ED
679 AfterDep = NoneDepType;\r
680 }\r
681 //\r
682 // Assume only one of the depend is valid.\r
683 //\r
684 ASSERT (!(BeforeDep > ThreadDepType && AfterDep > ThreadDepType));\r
685 if (BeforeDep > ThreadDepType) {\r
686 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, BeforeDep);\r
687 }\r
688 if (AfterDep > ThreadDepType) {\r
689 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, AfterDep);\r
690 }\r
691 }\r
692\r
693 Entry = Entry->ForwardLink;\r
694 NextEntry = Entry->ForwardLink;\r
80c4b236 695 }\r
05973f9e
ED
696\r
697 //\r
698 // Dump PcdCpuFeaturesSetting again because this value maybe updated\r
699 // again during initialize the features.\r
700 //\r
701 DEBUG ((DEBUG_INFO, "Dump final value for PcdCpuFeaturesSetting:\n"));\r
7d3a7c22 702 DumpCpuFeatureMask (CpuFeaturesData->SettingPcd);\r
05973f9e 703\r
80c4b236
JF
704 //\r
705 // Dump the RegisterTable\r
706 //\r
707 DumpRegisterTableOnProcessor (ProcessorNumber);\r
708 }\r
709}\r
710\r
b3c71b47
ED
711/**\r
712 Increment semaphore by 1.\r
713\r
714 @param Sem IN: 32-bit unsigned integer\r
715\r
716**/\r
717VOID\r
718LibReleaseSemaphore (\r
719 IN OUT volatile UINT32 *Sem\r
720 )\r
721{\r
722 InterlockedIncrement (Sem);\r
723}\r
724\r
725/**\r
726 Decrement the semaphore by 1 if it is not zero.\r
727\r
728 Performs an atomic decrement operation for semaphore.\r
729 The compare exchange operation must be performed using\r
730 MP safe mechanisms.\r
731\r
732 @param Sem IN: 32-bit unsigned integer\r
733\r
734**/\r
735VOID\r
736LibWaitForSemaphore (\r
737 IN OUT volatile UINT32 *Sem\r
738 )\r
739{\r
740 UINT32 Value;\r
741\r
742 do {\r
743 Value = *Sem;\r
744 } while (Value == 0 ||\r
745 InterlockedCompareExchange32 (\r
746 Sem,\r
747 Value,\r
748 Value - 1\r
749 ) != Value);\r
750}\r
751\r
80c4b236
JF
752/**\r
753 Initialize the CPU registers from a register table.\r
754\r
b3c71b47
ED
755 @param[in] RegisterTable The register table for this AP.\r
756 @param[in] ApLocation AP location info for this ap.\r
757 @param[in] CpuStatus CPU status info for this CPU.\r
758 @param[in] CpuFlags Flags data structure used when program the register.\r
80c4b236
JF
759\r
760 @note This service could be called by BSP/APs.\r
761**/\r
762VOID\r
763ProgramProcessorRegister (\r
b3c71b47
ED
764 IN CPU_REGISTER_TABLE *RegisterTable,\r
765 IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,\r
766 IN CPU_STATUS_INFORMATION *CpuStatus,\r
767 IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags\r
80c4b236
JF
768 )\r
769{\r
80c4b236
JF
770 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
771 UINTN Index;\r
772 UINTN Value;\r
773 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
b3c71b47
ED
774 volatile UINT32 *SemaphorePtr;\r
775 UINT32 FirstThread;\r
776 UINT32 PackageThreadsCount;\r
777 UINT32 CurrentThread;\r
778 UINTN ProcessorIndex;\r
779 UINTN ThreadIndex;\r
780 UINTN ValidThreadCount;\r
781 UINT32 *ValidCoreCountPerPackage;\r
80c4b236
JF
782\r
783 //\r
784 // Traverse Register Table of this logical processor\r
785 //\r
786 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
787\r
788 for (Index = 0; Index < RegisterTable->TableLength; Index++) {\r
789\r
790 RegisterTableEntry = &RegisterTableEntryHead[Index];\r
791\r
b3c71b47
ED
792 DEBUG_CODE_BEGIN ();\r
793 AcquireSpinLock (&CpuFlags->ConsoleLogLock);\r
794 ThreadIndex = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount +\r
795 ApLocation->Core * CpuStatus->MaxThreadCount +\r
796 ApLocation->Thread;\r
797 DEBUG ((\r
798 DEBUG_INFO,\r
799 "Processor = %lu, Entry Index %lu, Type = %s!\n",\r
800 (UINT64)ThreadIndex,\r
801 (UINT64)Index,\r
802 mRegisterTypeStr[MIN ((REGISTER_TYPE)RegisterTableEntry->RegisterType, InvalidReg)]\r
803 ));\r
804 ReleaseSpinLock (&CpuFlags->ConsoleLogLock);\r
805 DEBUG_CODE_END ();\r
806\r
80c4b236
JF
807 //\r
808 // Check the type of specified register\r
809 //\r
810 switch (RegisterTableEntry->RegisterType) {\r
811 //\r
812 // The specified register is Control Register\r
813 //\r
814 case ControlRegister:\r
815 switch (RegisterTableEntry->Index) {\r
816 case 0:\r
817 Value = AsmReadCr0 ();\r
818 Value = (UINTN) BitFieldWrite64 (\r
819 Value,\r
820 RegisterTableEntry->ValidBitStart,\r
821 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
822 RegisterTableEntry->Value\r
823 );\r
824 AsmWriteCr0 (Value);\r
825 break;\r
826 case 2:\r
827 Value = AsmReadCr2 ();\r
828 Value = (UINTN) BitFieldWrite64 (\r
829 Value,\r
830 RegisterTableEntry->ValidBitStart,\r
831 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
832 RegisterTableEntry->Value\r
833 );\r
834 AsmWriteCr2 (Value);\r
835 break;\r
836 case 3:\r
837 Value = AsmReadCr3 ();\r
838 Value = (UINTN) BitFieldWrite64 (\r
839 Value,\r
840 RegisterTableEntry->ValidBitStart,\r
841 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
842 RegisterTableEntry->Value\r
843 );\r
844 AsmWriteCr3 (Value);\r
845 break;\r
846 case 4:\r
847 Value = AsmReadCr4 ();\r
848 Value = (UINTN) BitFieldWrite64 (\r
849 Value,\r
850 RegisterTableEntry->ValidBitStart,\r
851 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
852 RegisterTableEntry->Value\r
853 );\r
854 AsmWriteCr4 (Value);\r
855 break;\r
856 case 8:\r
857 //\r
858 // Do we need to support CR8?\r
859 //\r
860 break;\r
861 default:\r
862 break;\r
863 }\r
864 break;\r
865 //\r
866 // The specified register is Model Specific Register\r
867 //\r
868 case Msr:\r
80c4b236
JF
869 if (RegisterTableEntry->ValidBitLength >= 64) {\r
870 //\r
871 // If length is not less than 64 bits, then directly write without reading\r
872 //\r
873 AsmWriteMsr64 (\r
874 RegisterTableEntry->Index,\r
875 RegisterTableEntry->Value\r
876 );\r
877 } else {\r
878 //\r
879 // Set the bit section according to bit start and length\r
880 //\r
881 AsmMsrBitFieldWrite64 (\r
882 RegisterTableEntry->Index,\r
883 RegisterTableEntry->ValidBitStart,\r
884 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
885 RegisterTableEntry->Value\r
886 );\r
887 }\r
80c4b236
JF
888 break;\r
889 //\r
890 // MemoryMapped operations\r
891 //\r
892 case MemoryMapped:\r
b3c71b47 893 AcquireSpinLock (&CpuFlags->MemoryMappedLock);\r
80c4b236
JF
894 MmioBitFieldWrite32 (\r
895 (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),\r
896 RegisterTableEntry->ValidBitStart,\r
897 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
898 (UINT32)RegisterTableEntry->Value\r
899 );\r
b3c71b47 900 ReleaseSpinLock (&CpuFlags->MemoryMappedLock);\r
80c4b236
JF
901 break;\r
902 //\r
903 // Enable or disable cache\r
904 //\r
905 case CacheControl:\r
906 //\r
907 // If value of the entry is 0, then disable cache. Otherwise, enable cache.\r
908 //\r
909 if (RegisterTableEntry->Value == 0) {\r
910 AsmDisableCache ();\r
911 } else {\r
912 AsmEnableCache ();\r
913 }\r
914 break;\r
915\r
b3c71b47
ED
916 case Semaphore:\r
917 // Semaphore works logic like below:\r
918 //\r
919 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);\r
920 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);\r
921 //\r
922 // All threads (T0...Tn) waits in P() line and continues running\r
923 // together.\r
924 //\r
925 //\r
926 // T0 T1 ... Tn\r
927 //\r
928 // V(0...n) V(0...n) ... V(0...n)\r
929 // n * P(0) n * P(1) ... n * P(n)\r
930 //\r
931 SemaphorePtr = CpuFlags->SemaphoreCount;\r
932 switch (RegisterTableEntry->Value) {\r
933 case CoreDepType:\r
934 //\r
935 // Get Offset info for the first thread in the core which current thread belongs to.\r
936 //\r
937 FirstThread = (ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core) * CpuStatus->MaxThreadCount;\r
938 CurrentThread = FirstThread + ApLocation->Thread;\r
939 //\r
940 // First Notify all threads in current Core that this thread has ready.\r
941 //\r
942 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
943 LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
944 }\r
945 //\r
946 // Second, check whether all valid threads in current core have ready.\r
947 //\r
948 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex ++) {\r
949 LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
950 }\r
951 break;\r
952\r
953 case PackageDepType:\r
954 ValidCoreCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ValidCoreCountPerPackage;\r
955 //\r
956 // Get Offset info for the first thread in the package which current thread belongs to.\r
957 //\r
958 FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;\r
959 //\r
960 // Get the possible threads count for current package.\r
961 //\r
962 PackageThreadsCount = CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount;\r
963 CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;\r
964 //\r
965 // Get the valid thread count for current package.\r
966 //\r
967 ValidThreadCount = CpuStatus->MaxThreadCount * ValidCoreCountPerPackage[ApLocation->Package];\r
968\r
969 //\r
970 // Different packages may have different valid cores in them. If driver maintail clearly\r
971 // cores number in different packages, the logic will be much complicated.\r
972 // Here driver just simply records the max core number in all packages and use it as expect\r
973 // core number for all packages.\r
974 // In below two steps logic, first current thread will Release semaphore for each thread\r
975 // in current package. Maybe some threads are not valid in this package, but driver don't\r
976 // care. Second, driver will let current thread wait semaphore for all valid threads in\r
977 // current package. Because only the valid threads will do release semaphore for this\r
978 // thread, driver here only need to wait the valid thread count.\r
979 //\r
980\r
981 //\r
982 // First Notify ALL THREADS in current package that this thread has ready.\r
983 //\r
984 for (ProcessorIndex = 0; ProcessorIndex < PackageThreadsCount ; ProcessorIndex ++) {\r
985 LibReleaseSemaphore ((UINT32 *) &SemaphorePtr[FirstThread + ProcessorIndex]);\r
986 }\r
987 //\r
988 // Second, check whether VALID THREADS (not all threads) in current package have ready.\r
989 //\r
990 for (ProcessorIndex = 0; ProcessorIndex < ValidThreadCount; ProcessorIndex ++) {\r
991 LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
992 }\r
993 break;\r
994\r
995 default:\r
996 break;\r
997 }\r
998 break;\r
999\r
80c4b236
JF
1000 default:\r
1001 break;\r
1002 }\r
1003 }\r
1004}\r
1005\r
1006/**\r
1007 Programs registers for the calling processor.\r
1008\r
1009 @param[in,out] Buffer The pointer to private data buffer.\r
1010\r
1011**/\r
1012VOID\r
1013EFIAPI\r
1014SetProcessorRegister (\r
1015 IN OUT VOID *Buffer\r
1016 )\r
1017{\r
b3c71b47
ED
1018 CPU_FEATURES_DATA *CpuFeaturesData;\r
1019 CPU_REGISTER_TABLE *RegisterTable;\r
1020 CPU_REGISTER_TABLE *RegisterTables;\r
1021 UINT32 InitApicId;\r
1022 UINTN ProcIndex;\r
1023 UINTN Index;\r
1024 ACPI_CPU_DATA *AcpiCpuData;\r
80c4b236 1025\r
b3c71b47
ED
1026 CpuFeaturesData = (CPU_FEATURES_DATA *) Buffer;\r
1027 AcpiCpuData = CpuFeaturesData->AcpiCpuData;\r
1028\r
1029 RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->RegisterTable;\r
1030\r
1031 InitApicId = GetInitialApicId ();\r
1032 RegisterTable = NULL;\r
692e318d 1033 ProcIndex = (UINTN)-1;\r
b3c71b47
ED
1034 for (Index = 0; Index < AcpiCpuData->NumberOfCpus; Index++) {\r
1035 if (RegisterTables[Index].InitialApicId == InitApicId) {\r
1036 RegisterTable = &RegisterTables[Index];\r
1037 ProcIndex = Index;\r
1038 break;\r
1039 }\r
1040 }\r
1041 ASSERT (RegisterTable != NULL);\r
1042\r
1043 ProgramProcessorRegister (\r
1044 RegisterTable,\r
1045 (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->ApLocation + ProcIndex,\r
1046 &AcpiCpuData->CpuStatus,\r
1047 &CpuFeaturesData->CpuFlags\r
1048 );\r
80c4b236
JF
1049}\r
1050\r
1051/**\r
1052 Performs CPU features detection.\r
1053\r
1054 This service will invoke MP service to check CPU features'\r
1055 capabilities on BSP/APs.\r
1056\r
1057 @note This service could be called by BSP only.\r
1058**/\r
1059VOID\r
1060EFIAPI\r
1061CpuFeaturesDetect (\r
1062 VOID\r
1063 )\r
1064{\r
1065 UINTN NumberOfCpus;\r
1066 UINTN NumberOfEnabledProcessors;\r
b3c71b47
ED
1067 CPU_FEATURES_DATA *CpuFeaturesData;\r
1068\r
1069 CpuFeaturesData = GetCpuFeaturesData();\r
80c4b236
JF
1070\r
1071 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
1072\r
1073 CpuInitDataInitialize (NumberOfCpus);\r
1074\r
1075 //\r
1076 // Wakeup all APs for data collection.\r
1077 //\r
b3c71b47 1078 StartupAPsWorker (CollectProcessorData, NULL);\r
80c4b236
JF
1079\r
1080 //\r
1081 // Collect data on BSP\r
1082 //\r
b3c71b47 1083 CollectProcessorData (CpuFeaturesData);\r
80c4b236
JF
1084\r
1085 AnalysisProcessorFeatures (NumberOfCpus);\r
1086}\r
1087\r