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