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