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