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