2 CPU Features Initialize functions.
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
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.
15 #include "RegisterCpuFeatures.h"
18 Worker function to save PcdCpuFeaturesCapability.
20 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
24 IN UINT8
*SupportedFeatureMask
30 BitMaskSize
= PcdGetSize (PcdCpuFeaturesCapability
);
31 Status
= PcdSetPtrS (PcdCpuFeaturesCapability
, &BitMaskSize
, SupportedFeatureMask
);
32 ASSERT_EFI_ERROR (Status
);
36 Worker function to save PcdCpuFeaturesSetting.
38 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
42 IN UINT8
*SupportedFeatureMask
48 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSetting
);
49 Status
= PcdSetPtrS (PcdCpuFeaturesSetting
, &BitMaskSize
, SupportedFeatureMask
);
50 ASSERT_EFI_ERROR (Status
);
54 Worker function to get PcdCpuFeaturesSupport.
56 @return The pointer to CPU feature bits mask buffer.
64 UINT8
*SupportBitMask
;
66 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
67 SupportBitMask
= AllocateZeroPool (BitMaskSize
);
68 ASSERT (SupportBitMask
!= NULL
);
69 SupportBitMask
= (UINT8
*) PcdGetPtr (PcdCpuFeaturesSupport
);
71 return SupportBitMask
;
75 Worker function to get PcdCpuFeaturesUserConfiguration.
77 @return The pointer to CPU feature bits mask buffer.
80 GetConfigurationPcds (
85 UINT8
*SupportBitMask
;
87 BitMaskSize
= PcdGetSize (PcdCpuFeaturesUserConfiguration
);
88 SupportBitMask
= AllocateZeroPool (BitMaskSize
);
89 ASSERT (SupportBitMask
!= NULL
);
90 SupportBitMask
= (UINT8
*) PcdGetPtr (PcdCpuFeaturesUserConfiguration
);
92 return SupportBitMask
;
96 Collects CPU type and feature information.
98 @param[in, out] CpuInfo The pointer to CPU feature information
102 IN OUT REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
105 CPUID_VERSION_INFO_EAX Eax
;
106 CPUID_VERSION_INFO_ECX Ecx
;
107 CPUID_VERSION_INFO_EDX Edx
;
108 UINT32 DisplayedFamily
;
109 UINT32 DisplayedModel
;
111 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, &Ecx
.Uint32
, &Edx
.Uint32
);
113 DisplayedFamily
= Eax
.Bits
.FamilyId
;
114 if (Eax
.Bits
.FamilyId
== 0x0F) {
115 DisplayedFamily
|= (Eax
.Bits
.ExtendedFamilyId
<< 4);
118 DisplayedModel
= Eax
.Bits
.Model
;
119 if (Eax
.Bits
.FamilyId
== 0x06 || Eax
.Bits
.FamilyId
== 0x0f) {
120 DisplayedModel
|= (Eax
.Bits
.ExtendedModelId
<< 4);
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
;
132 Prepares for private data used for CPU features.
134 @param[in] NumberOfCpus Number of processor in system
137 CpuInitDataInitialize (
138 IN UINTN NumberOfCpus
142 UINTN ProcessorNumber
;
143 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
144 CPU_FEATURES_ENTRY
*CpuFeature
;
145 CPU_FEATURES_INIT_ORDER
*InitOrder
;
146 CPU_FEATURES_DATA
*CpuFeaturesData
;
149 CpuFeaturesData
= GetCpuFeaturesData ();
150 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
151 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
152 CpuFeaturesData
->BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
155 // Collect CPU Features information
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
);
164 Entry
= Entry
->ForwardLink
;
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
);
175 &InitOrder
->CpuInfo
.ProcessorInfo
,
176 &ProcessorInfoBuffer
,
177 sizeof (EFI_PROCESSOR_INFORMATION
)
181 // Get support and configuration PCDs
183 CpuFeaturesData
->SupportPcds
= GetSupportPcds ();
184 CpuFeaturesData
->ConfigurationPcds
= GetConfigurationPcds ();
188 Worker function to do OR operation on CPU feature supported bits mask buffer.
190 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
191 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
195 IN UINT8
*SupportedFeatureMask
,
196 IN UINT8
*OrFeatureBitMask
204 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
205 Data1
= SupportedFeatureMask
;
206 Data2
= OrFeatureBitMask
;
207 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
208 *(Data1
++) |= *(Data2
++);
213 Worker function to do AND operation on CPU feature supported bits mask buffer.
215 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
216 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
220 IN UINT8
*SupportedFeatureMask
,
221 IN UINT8
*AndFeatureBitMask
229 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
230 Data1
= SupportedFeatureMask
;
231 Data2
= AndFeatureBitMask
;
232 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
233 *(Data1
++) &= *(Data2
++);
238 Worker function to check if the compared CPU feature set in the CPU feature
239 supported bits mask buffer.
241 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
242 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
244 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
246 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
251 IN UINT8
*SupportedFeatureMask
,
252 IN UINT8
*ComparedFeatureBitMask
260 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
262 Data1
= SupportedFeatureMask
;
263 Data2
= ComparedFeatureBitMask
;
264 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
265 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
273 Collects processor data for calling processor.
275 @param[in,out] Buffer The pointer to private data buffer.
279 CollectProcessorData (
283 UINTN ProcessorNumber
;
284 CPU_FEATURES_ENTRY
*CpuFeature
;
285 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
287 CPU_FEATURES_DATA
*CpuFeaturesData
;
289 CpuFeaturesData
= GetCpuFeaturesData ();
290 ProcessorNumber
= GetProcessorIndex ();
291 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
293 // collect processor information
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
) {
302 // If SupportFunc is NULL, then the feature is supported.
305 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
306 CpuFeature
->FeatureMask
308 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
310 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
311 CpuFeature
->FeatureMask
315 Entry
= Entry
->ForwardLink
;
320 Dump the contents of a CPU register table.
322 @param[in] ProcessorNumber The index of the CPU to show the register table contents
324 @note This service could be called by BSP only.
327 DumpRegisterTableOnProcessor (
328 IN UINTN ProcessorNumber
331 CPU_FEATURES_DATA
*CpuFeaturesData
;
333 CPU_REGISTER_TABLE
*RegisterTable
;
334 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
335 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
336 UINT32 DebugPrintErrorLevel
;
338 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
339 CpuFeaturesData
= GetCpuFeaturesData ();
343 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
344 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
346 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
348 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
349 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
350 switch (RegisterTableEntry
->RegisterType
) {
353 DebugPrintErrorLevel
,
354 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
356 RegisterTableEntry
->Index
,
357 RegisterTableEntry
->ValidBitStart
,
358 RegisterTableEntry
->ValidBitLength
,
359 RegisterTableEntry
->Value
362 case ControlRegister
:
364 DebugPrintErrorLevel
,
365 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
367 RegisterTableEntry
->Index
,
368 RegisterTableEntry
->ValidBitStart
,
369 RegisterTableEntry
->ValidBitLength
,
370 RegisterTableEntry
->Value
375 DebugPrintErrorLevel
,
376 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
378 RegisterTableEntry
->Index
| LShiftU64 (RegisterTableEntry
->HighIndex
, 32),
379 RegisterTableEntry
->ValidBitStart
,
380 RegisterTableEntry
->ValidBitLength
,
381 RegisterTableEntry
->Value
386 DebugPrintErrorLevel
,
387 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
389 RegisterTableEntry
->Index
,
390 RegisterTableEntry
->ValidBitStart
,
391 RegisterTableEntry
->ValidBitLength
,
392 RegisterTableEntry
->Value
402 Analysis register CPU features on each processor and save CPU setting in CPU register table.
404 @param[in] NumberOfCpus Number of processor in system
408 AnalysisProcessorFeatures (
409 IN UINTN NumberOfCpus
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
;
419 CPU_FEATURES_DATA
*CpuFeaturesData
;
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
];
428 // Calculate the last capability on all processors
430 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcds
, CpuInitOrder
->FeaturesSupportedMask
);
433 // Calculate the last setting
436 CpuFeaturesData
->SettingPcds
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcds
);
437 ASSERT (CpuFeaturesData
->SettingPcds
!= NULL
);
438 SupportedMaskAnd (CpuFeaturesData
->SettingPcds
, CpuFeaturesData
->ConfigurationPcds
);
441 // Save PCDs and display CPU PCDs
443 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcds
);
444 SetSettingPcd (CpuFeaturesData
->SettingPcds
);
447 // Dump the last CPU feature list
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 ] "));
458 DEBUG ((DEBUG_INFO
, "[Disable ] "));
461 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
463 DumpCpuFeature (CpuFeature
);
464 Entry
= Entry
->ForwardLink
;
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
);
476 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
477 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
478 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
479 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
481 // Insert each feature into processor's order list
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
);
489 Entry
= Entry
->ForwardLink
;
492 // Go through ordered feature list to initialize CPU features
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
);
501 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
503 ASSERT_EFI_ERROR (Status
);
504 Entry
= Entry
->ForwardLink
;
507 // Dump the RegisterTable
509 DumpRegisterTableOnProcessor (ProcessorNumber
);
514 Initialize the CPU registers from a register table.
516 @param[in] ProcessorNumber The index of the CPU executing this function.
518 @note This service could be called by BSP/APs.
521 ProgramProcessorRegister (
522 IN UINTN ProcessorNumber
525 CPU_FEATURES_DATA
*CpuFeaturesData
;
526 CPU_REGISTER_TABLE
*RegisterTable
;
527 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
530 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
532 CpuFeaturesData
= GetCpuFeaturesData ();
533 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
536 // Traverse Register Table of this logical processor
538 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
540 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
542 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
545 // Check the type of specified register
547 switch (RegisterTableEntry
->RegisterType
) {
549 // The specified register is Control Register
551 case ControlRegister
:
552 switch (RegisterTableEntry
->Index
) {
554 Value
= AsmReadCr0 ();
555 Value
= (UINTN
) BitFieldWrite64 (
557 RegisterTableEntry
->ValidBitStart
,
558 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
559 RegisterTableEntry
->Value
564 Value
= AsmReadCr2 ();
565 Value
= (UINTN
) BitFieldWrite64 (
567 RegisterTableEntry
->ValidBitStart
,
568 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
569 RegisterTableEntry
->Value
574 Value
= AsmReadCr3 ();
575 Value
= (UINTN
) BitFieldWrite64 (
577 RegisterTableEntry
->ValidBitStart
,
578 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
579 RegisterTableEntry
->Value
584 Value
= AsmReadCr4 ();
585 Value
= (UINTN
) BitFieldWrite64 (
587 RegisterTableEntry
->ValidBitStart
,
588 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
589 RegisterTableEntry
->Value
595 // Do we need to support CR8?
603 // The specified register is Model Specific Register
607 // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
609 AcquireSpinLock (&CpuFeaturesData
->MsrLock
);
610 if (RegisterTableEntry
->ValidBitLength
>= 64) {
612 // If length is not less than 64 bits, then directly write without reading
615 RegisterTableEntry
->Index
,
616 RegisterTableEntry
->Value
620 // Set the bit section according to bit start and length
622 AsmMsrBitFieldWrite64 (
623 RegisterTableEntry
->Index
,
624 RegisterTableEntry
->ValidBitStart
,
625 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
626 RegisterTableEntry
->Value
629 ReleaseSpinLock (&CpuFeaturesData
->MsrLock
);
632 // MemoryMapped operations
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
642 ReleaseSpinLock (&CpuFeaturesData
->MemoryMappedLock
);
645 // Enable or disable cache
649 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
651 if (RegisterTableEntry
->Value
== 0) {
665 Programs registers for the calling processor.
667 @param[in,out] Buffer The pointer to private data buffer.
672 SetProcessorRegister (
676 UINTN ProcessorNumber
;
678 ProcessorNumber
= GetProcessorIndex ();
679 ProgramProcessorRegister (ProcessorNumber
);
683 Performs CPU features detection.
685 This service will invoke MP service to check CPU features'
686 capabilities on BSP/APs.
688 @note This service could be called by BSP only.
697 UINTN NumberOfEnabledProcessors
;
699 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
701 CpuInitDataInitialize (NumberOfCpus
);
704 // Wakeup all APs for data collection.
706 StartupAPsWorker (CollectProcessorData
);
709 // Collect data on BSP
711 CollectProcessorData (NULL
);
713 AnalysisProcessorFeatures (NumberOfCpus
);
717 Performs CPU features Initialization.
719 This service will invoke MP service to perform CPU features
720 initialization on BSP/APs per user configuration.
722 @note This service could be called by BSP only.
726 CpuFeaturesInitialize (
730 CPU_FEATURES_DATA
*CpuFeaturesData
;
733 CpuFeaturesData
= GetCpuFeaturesData ();
735 OldBspNumber
= GetProcessorIndex();
736 CpuFeaturesData
->BspNumber
= OldBspNumber
;
738 // Wakeup all APs for programming.
740 StartupAPsWorker (SetProcessorRegister
);
744 SetProcessorRegister (NULL
);
746 // Switch to new BSP if required
748 if (CpuFeaturesData
->BspNumber
!= OldBspNumber
) {
749 SwitchNewBsp (CpuFeaturesData
->BspNumber
);