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