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