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