]> git.proxmox.com Git - mirror_edk2.git/blob - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
UefiCpuPkg/RegisterCpuFeaturesLib: Fix the function header issues
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / CpuFeaturesInitialize.c
1 /** @file
2 CPU Features Initialize functions.
3
4 Copyright (c) 2017, 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 /**
18 Worker function to save PcdCpuFeaturesCapability.
19
20 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
21 **/
22 VOID
23 SetCapabilityPcd (
24 IN UINT8 *SupportedFeatureMask
25 )
26 {
27 EFI_STATUS Status;
28 UINTN BitMaskSize;
29
30 BitMaskSize = PcdGetSize (PcdCpuFeaturesCapability);
31 Status = PcdSetPtrS (PcdCpuFeaturesCapability, &BitMaskSize, SupportedFeatureMask);
32 ASSERT_EFI_ERROR (Status);
33 }
34
35 /**
36 Worker function to save PcdCpuFeaturesSetting.
37
38 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
39 **/
40 VOID
41 SetSettingPcd (
42 IN UINT8 *SupportedFeatureMask
43 )
44 {
45 EFI_STATUS Status;
46 UINTN BitMaskSize;
47
48 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);
49 Status = PcdSetPtrS (PcdCpuFeaturesSetting, &BitMaskSize, SupportedFeatureMask);
50 ASSERT_EFI_ERROR (Status);
51 }
52
53 /**
54 Worker function to get PcdCpuFeaturesSupport.
55
56 @return The pointer to CPU feature bits mask buffer.
57 **/
58 UINT8 *
59 GetSupportPcds (
60 VOID
61 )
62 {
63 UINTN BitMaskSize;
64 UINT8 *SupportBitMask;
65
66 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
67 SupportBitMask = AllocateZeroPool (BitMaskSize);
68 ASSERT (SupportBitMask != NULL);
69 SupportBitMask = (UINT8 *) PcdGetPtr (PcdCpuFeaturesSupport);
70
71 return SupportBitMask;
72 }
73
74 /**
75 Worker function to get PcdCpuFeaturesUserConfiguration.
76
77 @return The pointer to CPU feature bits mask buffer.
78 **/
79 UINT8 *
80 GetConfigurationPcds (
81 VOID
82 )
83 {
84 UINTN BitMaskSize;
85 UINT8 *SupportBitMask;
86
87 BitMaskSize = PcdGetSize (PcdCpuFeaturesUserConfiguration);
88 SupportBitMask = AllocateZeroPool (BitMaskSize);
89 ASSERT (SupportBitMask != NULL);
90 SupportBitMask = (UINT8 *) PcdGetPtr (PcdCpuFeaturesUserConfiguration);
91
92 return SupportBitMask;
93 }
94
95 /**
96 Collects CPU type and feature information.
97
98 @param[in, out] CpuInfo The pointer to CPU feature information
99 **/
100 VOID
101 FillProcessorInfo (
102 IN OUT REGISTER_CPU_FEATURE_INFORMATION *CpuInfo
103 )
104 {
105 CPUID_VERSION_INFO_EAX Eax;
106 CPUID_VERSION_INFO_ECX Ecx;
107 CPUID_VERSION_INFO_EDX Edx;
108 UINT32 DisplayedFamily;
109 UINT32 DisplayedModel;
110
111 AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, &Ecx.Uint32, &Edx.Uint32);
112
113 DisplayedFamily = Eax.Bits.FamilyId;
114 if (Eax.Bits.FamilyId == 0x0F) {
115 DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);
116 }
117
118 DisplayedModel = Eax.Bits.Model;
119 if (Eax.Bits.FamilyId == 0x06 || Eax.Bits.FamilyId == 0x0f) {
120 DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);
121 }
122
123 CpuInfo->DisplayFamily = DisplayedFamily;
124 CpuInfo->DisplayModel = DisplayedModel;
125 CpuInfo->SteppingId = Eax.Bits.SteppingId;
126 CpuInfo->ProcessorType = Eax.Bits.ProcessorType;
127 CpuInfo->CpuIdVersionInfoEcx.Uint32 = Ecx.Uint32;
128 CpuInfo->CpuIdVersionInfoEdx.Uint32 = Edx.Uint32;
129 }
130
131 /**
132 Prepares for private data used for CPU features.
133
134 @param[in] NumberOfCpus Number of processor in system
135 **/
136 VOID
137 CpuInitDataInitialize (
138 IN UINTN NumberOfCpus
139 )
140 {
141 EFI_STATUS Status;
142 UINTN ProcessorNumber;
143 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;
144 CPU_FEATURES_ENTRY *CpuFeature;
145 CPU_FEATURES_INIT_ORDER *InitOrder;
146 CPU_FEATURES_DATA *CpuFeaturesData;
147 LIST_ENTRY *Entry;
148
149 CpuFeaturesData = GetCpuFeaturesData ();
150 CpuFeaturesData->InitOrder = AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);
151 ASSERT (CpuFeaturesData->InitOrder != NULL);
152 CpuFeaturesData->BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
153
154 //
155 // Collect CPU Features information
156 //
157 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
158 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
159 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
160 ASSERT (CpuFeature->InitializeFunc != NULL);
161 if (CpuFeature->GetConfigDataFunc != NULL) {
162 CpuFeature->ConfigData = CpuFeature->GetConfigDataFunc (NumberOfCpus);
163 }
164 Entry = Entry->ForwardLink;
165 }
166
167 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
168 InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
169 InitOrder->FeaturesSupportedMask = AllocateZeroPool (CpuFeaturesData->BitMaskSize);
170 ASSERT (InitOrder->FeaturesSupportedMask != NULL);
171 InitializeListHead (&InitOrder->OrderList);
172 Status = GetProcessorInformation (ProcessorNumber, &ProcessorInfoBuffer);
173 ASSERT_EFI_ERROR (Status);
174 CopyMem (
175 &InitOrder->CpuInfo.ProcessorInfo,
176 &ProcessorInfoBuffer,
177 sizeof (EFI_PROCESSOR_INFORMATION)
178 );
179 }
180 //
181 // Get support and configuration PCDs
182 //
183 CpuFeaturesData->SupportPcds = GetSupportPcds ();
184 CpuFeaturesData->ConfigurationPcds = GetConfigurationPcds ();
185 }
186
187 /**
188 Worker function to do OR operation on CPU feature supported bits mask buffer.
189
190 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
191 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
192 **/
193 VOID
194 SupportedMaskOr (
195 IN UINT8 *SupportedFeatureMask,
196 IN UINT8 *OrFeatureBitMask
197 )
198 {
199 UINTN Index;
200 UINTN BitMaskSize;
201 UINT8 *Data1;
202 UINT8 *Data2;
203
204 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
205 Data1 = SupportedFeatureMask;
206 Data2 = OrFeatureBitMask;
207 for (Index = 0; Index < BitMaskSize; Index++) {
208 *(Data1++) |= *(Data2++);
209 }
210 }
211
212 /**
213 Worker function to do AND operation on CPU feature supported bits mask buffer.
214
215 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
216 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
217 **/
218 VOID
219 SupportedMaskAnd (
220 IN UINT8 *SupportedFeatureMask,
221 IN UINT8 *AndFeatureBitMask
222 )
223 {
224 UINTN Index;
225 UINTN BitMaskSize;
226 UINT8 *Data1;
227 UINT8 *Data2;
228
229 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
230 Data1 = SupportedFeatureMask;
231 Data2 = AndFeatureBitMask;
232 for (Index = 0; Index < BitMaskSize; Index++) {
233 *(Data1++) &= *(Data2++);
234 }
235 }
236
237 /**
238 Worker function to check if the compared CPU feature set in the CPU feature
239 supported bits mask buffer.
240
241 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
242 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
243
244 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
245 mask buffer.
246 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
247 mask buffer.
248 **/
249 BOOLEAN
250 IsBitMaskMatch (
251 IN UINT8 *SupportedFeatureMask,
252 IN UINT8 *ComparedFeatureBitMask
253 )
254 {
255 UINTN Index;
256 UINTN BitMaskSize;
257 UINT8 *Data1;
258 UINT8 *Data2;
259
260 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);
261
262 Data1 = SupportedFeatureMask;
263 Data2 = ComparedFeatureBitMask;
264 for (Index = 0; Index < BitMaskSize; Index++) {
265 if (((*(Data1++)) & (*(Data2++))) != 0) {
266 return TRUE;
267 }
268 }
269 return FALSE;
270 }
271
272 /**
273 Collects processor data for calling processor.
274
275 @param[in,out] Buffer The pointer to private data buffer.
276 **/
277 VOID
278 EFIAPI
279 CollectProcessorData (
280 IN OUT VOID *Buffer
281 )
282 {
283 UINTN ProcessorNumber;
284 CPU_FEATURES_ENTRY *CpuFeature;
285 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;
286 LIST_ENTRY *Entry;
287 CPU_FEATURES_DATA *CpuFeaturesData;
288
289 CpuFeaturesData = GetCpuFeaturesData ();
290 ProcessorNumber = GetProcessorIndex ();
291 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;
292 //
293 // collect processor information
294 //
295 FillProcessorInfo (CpuInfo);
296 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
297 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
298 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
299 if (IsBitMaskMatch (CpuFeaturesData->SupportPcds, CpuFeature->FeatureMask)) {
300 if (CpuFeature->SupportFunc == NULL) {
301 //
302 // If SupportFunc is NULL, then the feature is supported.
303 //
304 SupportedMaskOr (
305 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,
306 CpuFeature->FeatureMask
307 );
308 } else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {
309 SupportedMaskOr (
310 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,
311 CpuFeature->FeatureMask
312 );
313 }
314 }
315 Entry = Entry->ForwardLink;
316 }
317 }
318
319 /**
320 Dump the contents of a CPU register table.
321
322 @param[in] ProcessorNumber The index of the CPU to show the register table contents
323
324 @note This service could be called by BSP only.
325 **/
326 VOID
327 DumpRegisterTableOnProcessor (
328 IN UINTN ProcessorNumber
329 )
330 {
331 CPU_FEATURES_DATA *CpuFeaturesData;
332 UINTN FeatureIndex;
333 CPU_REGISTER_TABLE *RegisterTable;
334 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
335 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
336 UINT32 DebugPrintErrorLevel;
337
338 DebugPrintErrorLevel = (ProcessorNumber == 0) ? DEBUG_INFO : DEBUG_VERBOSE;
339 CpuFeaturesData = GetCpuFeaturesData ();
340 //
341 // Debug information
342 //
343 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
344 DEBUG ((DebugPrintErrorLevel, "RegisterTable->TableLength = %d\n", RegisterTable->TableLength));
345
346 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
347
348 for (FeatureIndex = 0; FeatureIndex < RegisterTable->TableLength; FeatureIndex++) {
349 RegisterTableEntry = &RegisterTableEntryHead[FeatureIndex];
350 switch (RegisterTableEntry->RegisterType) {
351 case Msr:
352 DEBUG ((
353 DebugPrintErrorLevel,
354 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
355 ProcessorNumber,
356 RegisterTableEntry->Index,
357 RegisterTableEntry->ValidBitStart,
358 RegisterTableEntry->ValidBitLength,
359 RegisterTableEntry->Value
360 ));
361 break;
362 case ControlRegister:
363 DEBUG ((
364 DebugPrintErrorLevel,
365 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
366 ProcessorNumber,
367 RegisterTableEntry->Index,
368 RegisterTableEntry->ValidBitStart,
369 RegisterTableEntry->ValidBitLength,
370 RegisterTableEntry->Value
371 ));
372 break;
373 case MemoryMapped:
374 DEBUG ((
375 DebugPrintErrorLevel,
376 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
377 ProcessorNumber,
378 RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),
379 RegisterTableEntry->ValidBitStart,
380 RegisterTableEntry->ValidBitLength,
381 RegisterTableEntry->Value
382 ));
383 break;
384 case CacheControl:
385 DEBUG ((
386 DebugPrintErrorLevel,
387 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
388 ProcessorNumber,
389 RegisterTableEntry->Index,
390 RegisterTableEntry->ValidBitStart,
391 RegisterTableEntry->ValidBitLength,
392 RegisterTableEntry->Value
393 ));
394 break;
395 default:
396 break;
397 }
398 }
399 }
400
401 /**
402 Analysis register CPU features on each processor and save CPU setting in CPU register table.
403
404 @param[in] NumberOfCpus Number of processor in system
405
406 **/
407 VOID
408 AnalysisProcessorFeatures (
409 IN UINTN NumberOfCpus
410 )
411 {
412 EFI_STATUS Status;
413 UINTN ProcessorNumber;
414 CPU_FEATURES_ENTRY *CpuFeature;
415 CPU_FEATURES_ENTRY *CpuFeatureInOrder;
416 CPU_FEATURES_INIT_ORDER *CpuInitOrder;
417 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;
418 LIST_ENTRY *Entry;
419 CPU_FEATURES_DATA *CpuFeaturesData;
420
421 CpuFeaturesData = GetCpuFeaturesData ();
422 CpuFeaturesData->CapabilityPcds = AllocatePool (CpuFeaturesData->BitMaskSize);
423 ASSERT (CpuFeaturesData->CapabilityPcds != NULL);
424 SetMem (CpuFeaturesData->CapabilityPcds, CpuFeaturesData->BitMaskSize, 0xFF);
425 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
426 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
427 //
428 // Calculate the last capability on all processors
429 //
430 SupportedMaskAnd (CpuFeaturesData->CapabilityPcds, CpuInitOrder->FeaturesSupportedMask);
431 }
432 //
433 // Calculate the last setting
434 //
435
436 CpuFeaturesData->SettingPcds = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcds);
437 ASSERT (CpuFeaturesData->SettingPcds != NULL);
438 SupportedMaskAnd (CpuFeaturesData->SettingPcds, CpuFeaturesData->ConfigurationPcds);
439
440 //
441 // Save PCDs and display CPU PCDs
442 //
443 SetCapabilityPcd (CpuFeaturesData->CapabilityPcds);
444 SetSettingPcd (CpuFeaturesData->SettingPcds);
445
446 //
447 // Dump the last CPU feature list
448 //
449 DEBUG_CODE (
450 DEBUG ((DEBUG_INFO, "Last CPU features list...\n"));
451 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
452 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
453 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
454 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {
455 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcds)) {
456 DEBUG ((DEBUG_INFO, "[Enable ] "));
457 } else {
458 DEBUG ((DEBUG_INFO, "[Disable ] "));
459 }
460 } else {
461 DEBUG ((DEBUG_INFO, "[Unsupport] "));
462 }
463 DumpCpuFeature (CpuFeature);
464 Entry = Entry->ForwardLink;
465 }
466 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSupport:\n"));
467 DumpCpuFeatureMask (CpuFeaturesData->SupportPcds);
468 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesUserConfiguration:\n"));
469 DumpCpuFeatureMask (CpuFeaturesData->ConfigurationPcds);
470 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));
471 DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcds);
472 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSetting:\n"));
473 DumpCpuFeatureMask (CpuFeaturesData->SettingPcds);
474 );
475
476 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {
477 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];
478 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);
479 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {
480 //
481 // Insert each feature into processor's order list
482 //
483 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
484 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {
485 CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);
486 ASSERT (CpuFeatureInOrder != NULL);
487 InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);
488 }
489 Entry = Entry->ForwardLink;
490 }
491 //
492 // Go through ordered feature list to initialize CPU features
493 //
494 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;
495 Entry = GetFirstNode (&CpuInitOrder->OrderList);
496 while (!IsNull (&CpuInitOrder->OrderList, Entry)) {
497 CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);
498 if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcds)) {
499 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);
500 } else {
501 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);
502 }
503 ASSERT_EFI_ERROR (Status);
504 Entry = Entry->ForwardLink;
505 }
506 //
507 // Dump the RegisterTable
508 //
509 DumpRegisterTableOnProcessor (ProcessorNumber);
510 }
511 }
512
513 /**
514 Initialize the CPU registers from a register table.
515
516 @param[in] ProcessorNumber The index of the CPU executing this function.
517
518 @note This service could be called by BSP/APs.
519 **/
520 VOID
521 ProgramProcessorRegister (
522 IN UINTN ProcessorNumber
523 )
524 {
525 CPU_FEATURES_DATA *CpuFeaturesData;
526 CPU_REGISTER_TABLE *RegisterTable;
527 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;
528 UINTN Index;
529 UINTN Value;
530 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;
531
532 CpuFeaturesData = GetCpuFeaturesData ();
533 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];
534
535 //
536 // Traverse Register Table of this logical processor
537 //
538 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;
539
540 for (Index = 0; Index < RegisterTable->TableLength; Index++) {
541
542 RegisterTableEntry = &RegisterTableEntryHead[Index];
543
544 //
545 // Check the type of specified register
546 //
547 switch (RegisterTableEntry->RegisterType) {
548 //
549 // The specified register is Control Register
550 //
551 case ControlRegister:
552 switch (RegisterTableEntry->Index) {
553 case 0:
554 Value = AsmReadCr0 ();
555 Value = (UINTN) BitFieldWrite64 (
556 Value,
557 RegisterTableEntry->ValidBitStart,
558 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
559 RegisterTableEntry->Value
560 );
561 AsmWriteCr0 (Value);
562 break;
563 case 2:
564 Value = AsmReadCr2 ();
565 Value = (UINTN) BitFieldWrite64 (
566 Value,
567 RegisterTableEntry->ValidBitStart,
568 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
569 RegisterTableEntry->Value
570 );
571 AsmWriteCr2 (Value);
572 break;
573 case 3:
574 Value = AsmReadCr3 ();
575 Value = (UINTN) BitFieldWrite64 (
576 Value,
577 RegisterTableEntry->ValidBitStart,
578 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
579 RegisterTableEntry->Value
580 );
581 AsmWriteCr3 (Value);
582 break;
583 case 4:
584 Value = AsmReadCr4 ();
585 Value = (UINTN) BitFieldWrite64 (
586 Value,
587 RegisterTableEntry->ValidBitStart,
588 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
589 RegisterTableEntry->Value
590 );
591 AsmWriteCr4 (Value);
592 break;
593 case 8:
594 //
595 // Do we need to support CR8?
596 //
597 break;
598 default:
599 break;
600 }
601 break;
602 //
603 // The specified register is Model Specific Register
604 //
605 case Msr:
606 //
607 // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
608 //
609 AcquireSpinLock (&CpuFeaturesData->MsrLock);
610 if (RegisterTableEntry->ValidBitLength >= 64) {
611 //
612 // If length is not less than 64 bits, then directly write without reading
613 //
614 AsmWriteMsr64 (
615 RegisterTableEntry->Index,
616 RegisterTableEntry->Value
617 );
618 } else {
619 //
620 // Set the bit section according to bit start and length
621 //
622 AsmMsrBitFieldWrite64 (
623 RegisterTableEntry->Index,
624 RegisterTableEntry->ValidBitStart,
625 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
626 RegisterTableEntry->Value
627 );
628 }
629 ReleaseSpinLock (&CpuFeaturesData->MsrLock);
630 break;
631 //
632 // MemoryMapped operations
633 //
634 case MemoryMapped:
635 AcquireSpinLock (&CpuFeaturesData->MemoryMappedLock);
636 MmioBitFieldWrite32 (
637 (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),
638 RegisterTableEntry->ValidBitStart,
639 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,
640 (UINT32)RegisterTableEntry->Value
641 );
642 ReleaseSpinLock (&CpuFeaturesData->MemoryMappedLock);
643 break;
644 //
645 // Enable or disable cache
646 //
647 case CacheControl:
648 //
649 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
650 //
651 if (RegisterTableEntry->Value == 0) {
652 AsmDisableCache ();
653 } else {
654 AsmEnableCache ();
655 }
656 break;
657
658 default:
659 break;
660 }
661 }
662 }
663
664 /**
665 Programs registers for the calling processor.
666
667 @param[in,out] Buffer The pointer to private data buffer.
668
669 **/
670 VOID
671 EFIAPI
672 SetProcessorRegister (
673 IN OUT VOID *Buffer
674 )
675 {
676 UINTN ProcessorNumber;
677
678 ProcessorNumber = GetProcessorIndex ();
679 ProgramProcessorRegister (ProcessorNumber);
680 }
681
682 /**
683 Performs CPU features detection.
684
685 This service will invoke MP service to check CPU features'
686 capabilities on BSP/APs.
687
688 @note This service could be called by BSP only.
689 **/
690 VOID
691 EFIAPI
692 CpuFeaturesDetect (
693 VOID
694 )
695 {
696 UINTN NumberOfCpus;
697 UINTN NumberOfEnabledProcessors;
698
699 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);
700
701 CpuInitDataInitialize (NumberOfCpus);
702
703 //
704 // Wakeup all APs for data collection.
705 //
706 StartupAPsWorker (CollectProcessorData);
707
708 //
709 // Collect data on BSP
710 //
711 CollectProcessorData (NULL);
712
713 AnalysisProcessorFeatures (NumberOfCpus);
714 }
715
716 /**
717 Performs CPU features Initialization.
718
719 This service will invoke MP service to perform CPU features
720 initialization on BSP/APs per user configuration.
721
722 @note This service could be called by BSP only.
723 **/
724 VOID
725 EFIAPI
726 CpuFeaturesInitialize (
727 VOID
728 )
729 {
730 CPU_FEATURES_DATA *CpuFeaturesData;
731 UINTN OldBspNumber;
732
733 CpuFeaturesData = GetCpuFeaturesData ();
734
735 OldBspNumber = GetProcessorIndex();
736 CpuFeaturesData->BspNumber = OldBspNumber;
737 //
738 // Wakeup all APs for programming.
739 //
740 StartupAPsWorker (SetProcessorRegister);
741 //
742 // Programming BSP
743 //
744 SetProcessorRegister (NULL);
745 //
746 // Switch to new BSP if required
747 //
748 if (CpuFeaturesData->BspNumber != OldBspNumber) {
749 SwitchNewBsp (CpuFeaturesData->BspNumber);
750 }
751 }