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