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 SupportBitMask
= (UINT8
*) PcdGetPtr (PcdCpuFeaturesSupport
);
70 return SupportBitMask
;
74 Worker function to get PcdCpuFeaturesUserConfiguration.
76 @return The pointer to CPU feature bits mask buffer.
79 GetConfigurationPcds (
84 UINT8
*SupportBitMask
;
86 BitMaskSize
= PcdGetSize (PcdCpuFeaturesUserConfiguration
);
87 SupportBitMask
= AllocateZeroPool (BitMaskSize
);
88 SupportBitMask
= (UINT8
*) PcdGetPtr (PcdCpuFeaturesUserConfiguration
);
90 return SupportBitMask
;
94 Collects CPU type and feature information.
96 @param[in, out] CpuInfo The pointer to CPU feature information
100 IN OUT REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
103 CPUID_VERSION_INFO_EAX Eax
;
104 CPUID_VERSION_INFO_ECX Ecx
;
105 CPUID_VERSION_INFO_EDX Edx
;
106 UINT32 DisplayedFamily
;
107 UINT32 DisplayedModel
;
109 AsmCpuid (CPUID_VERSION_INFO
, &Eax
.Uint32
, NULL
, &Ecx
.Uint32
, &Edx
.Uint32
);
111 DisplayedFamily
= Eax
.Bits
.FamilyId
;
112 if (Eax
.Bits
.FamilyId
== 0x0F) {
113 DisplayedFamily
|= (Eax
.Bits
.ExtendedFamilyId
<< 4);
116 DisplayedModel
= Eax
.Bits
.Model
;
117 if (Eax
.Bits
.FamilyId
== 0x06 || Eax
.Bits
.FamilyId
== 0x0f) {
118 DisplayedModel
|= (Eax
.Bits
.ExtendedModelId
<< 4);
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
;
130 Prepares for private data used for CPU features.
132 @param[in] NumberOfCpus Number of processor in system
135 CpuInitDataInitialize (
136 IN UINTN NumberOfCpus
140 UINTN ProcessorNumber
;
141 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer
;
142 CPU_FEATURES_ENTRY
*CpuFeature
;
143 CPU_FEATURES_INIT_ORDER
*InitOrder
;
144 CPU_FEATURES_DATA
*CpuFeaturesData
;
147 CpuFeaturesData
= GetCpuFeaturesData ();
148 CpuFeaturesData
->InitOrder
= AllocateZeroPool (sizeof (CPU_FEATURES_INIT_ORDER
) * NumberOfCpus
);
149 ASSERT (CpuFeaturesData
->InitOrder
!= NULL
);
150 CpuFeaturesData
->BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
153 // Collect CPU Features information
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
);
162 Entry
= Entry
->ForwardLink
;
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
);
172 &InitOrder
->CpuInfo
.ProcessorInfo
,
173 &ProcessorInfoBuffer
,
174 sizeof (EFI_PROCESSOR_INFORMATION
)
178 // Get support and configuration PCDs
180 CpuFeaturesData
->SupportPcds
= GetSupportPcds ();
181 CpuFeaturesData
->ConfigurationPcds
= GetConfigurationPcds ();
185 Worker function to do OR operation on CPU feature supported bits mask buffer.
187 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
188 @param[in] OrFeatureBitMask The feature bit mask to do OR operation
192 IN UINT8
*SupportedFeatureMask
,
193 IN UINT8
*OrFeatureBitMask
201 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
202 Data1
= SupportedFeatureMask
;
203 Data2
= OrFeatureBitMask
;
204 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
205 *(Data1
++) |= *(Data2
++);
210 Worker function to do AND operation on CPU feature supported bits mask buffer.
212 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
213 @param[in] AndFeatureBitMask The feature bit mask to do AND operation
217 IN UINT8
*SupportedFeatureMask
,
218 IN UINT8
*AndFeatureBitMask
226 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
227 Data1
= SupportedFeatureMask
;
228 Data2
= AndFeatureBitMask
;
229 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
230 *(Data1
++) &= *(Data2
++);
235 Worker function to check if the compared CPU feature set in the CPU feature
236 supported bits mask buffer.
238 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer
239 @param[in] ComparedFeatureBitMask The feature bit mask to be compared
241 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits
243 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits
248 IN UINT8
*SupportedFeatureMask
,
249 IN UINT8
*ComparedFeatureBitMask
257 BitMaskSize
= PcdGetSize (PcdCpuFeaturesSupport
);
259 Data1
= SupportedFeatureMask
;
260 Data2
= ComparedFeatureBitMask
;
261 for (Index
= 0; Index
< BitMaskSize
; Index
++) {
262 if (((*(Data1
++)) & (*(Data2
++))) != 0) {
270 Collects processor data for calling processor.
272 @param[in,out] Buffer The pointer to private data buffer.
276 CollectProcessorData (
280 UINTN ProcessorNumber
;
281 CPU_FEATURES_ENTRY
*CpuFeature
;
282 REGISTER_CPU_FEATURE_INFORMATION
*CpuInfo
;
284 CPU_FEATURES_DATA
*CpuFeaturesData
;
286 CpuFeaturesData
= GetCpuFeaturesData ();
287 ProcessorNumber
= GetProcessorIndex ();
288 CpuInfo
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
].CpuInfo
;
290 // collect processor information
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
) {
299 // If SupportFunc is NULL, then the feature is supported.
302 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
303 CpuFeature
->FeatureMask
305 } else if (CpuFeature
->SupportFunc (ProcessorNumber
, CpuInfo
, CpuFeature
->ConfigData
)) {
307 CpuFeaturesData
->InitOrder
[ProcessorNumber
].FeaturesSupportedMask
,
308 CpuFeature
->FeatureMask
312 Entry
= Entry
->ForwardLink
;
317 Dump the contents of a CPU register table.
319 @param[in] ProcessorNumber The index of the CPU to show the register table contents
321 @note This service could be called by BSP only.
324 DumpRegisterTableOnProcessor (
325 IN UINTN ProcessorNumber
328 CPU_FEATURES_DATA
*CpuFeaturesData
;
330 CPU_REGISTER_TABLE
*RegisterTable
;
331 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
332 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
333 UINT32 DebugPrintErrorLevel
;
335 DebugPrintErrorLevel
= (ProcessorNumber
== 0) ? DEBUG_INFO
: DEBUG_VERBOSE
;
336 CpuFeaturesData
= GetCpuFeaturesData ();
340 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
341 DEBUG ((DebugPrintErrorLevel
, "RegisterTable->TableLength = %d\n", RegisterTable
->TableLength
));
343 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
345 for (FeatureIndex
= 0; FeatureIndex
< RegisterTable
->TableLength
; FeatureIndex
++) {
346 RegisterTableEntry
= &RegisterTableEntryHead
[FeatureIndex
];
347 switch (RegisterTableEntry
->RegisterType
) {
350 DebugPrintErrorLevel
,
351 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
353 RegisterTableEntry
->Index
,
354 RegisterTableEntry
->ValidBitStart
,
355 RegisterTableEntry
->ValidBitLength
,
356 RegisterTableEntry
->Value
359 case ControlRegister
:
361 DebugPrintErrorLevel
,
362 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
364 RegisterTableEntry
->Index
,
365 RegisterTableEntry
->ValidBitStart
,
366 RegisterTableEntry
->ValidBitLength
,
367 RegisterTableEntry
->Value
372 DebugPrintErrorLevel
,
373 "Processor: %d: MMIO: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
375 RegisterTableEntry
->Index
,
376 RegisterTableEntry
->ValidBitStart
,
377 RegisterTableEntry
->ValidBitLength
,
378 RegisterTableEntry
->Value
383 DebugPrintErrorLevel
,
384 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",
386 RegisterTableEntry
->Index
,
387 RegisterTableEntry
->ValidBitStart
,
388 RegisterTableEntry
->ValidBitLength
,
389 RegisterTableEntry
->Value
399 Analysis register CPU features on each processor and save CPU setting in CPU register table.
401 @param[in] NumberOfCpus Number of processor in system
405 AnalysisProcessorFeatures (
406 IN UINTN NumberOfCpus
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
;
416 CPU_FEATURES_DATA
*CpuFeaturesData
;
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
];
424 // Calculate the last capability on all processors
426 SupportedMaskAnd (CpuFeaturesData
->CapabilityPcds
, CpuInitOrder
->FeaturesSupportedMask
);
429 // Calculate the last setting
432 CpuFeaturesData
->SettingPcds
= AllocateCopyPool (CpuFeaturesData
->BitMaskSize
, CpuFeaturesData
->CapabilityPcds
);
433 SupportedMaskAnd (CpuFeaturesData
->SettingPcds
, CpuFeaturesData
->ConfigurationPcds
);
436 // Save PCDs and display CPU PCDs
438 SetCapabilityPcd (CpuFeaturesData
->CapabilityPcds
);
439 SetSettingPcd (CpuFeaturesData
->SettingPcds
);
442 // Dump the last CPU feature list
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 ] "));
453 DEBUG ((DEBUG_INFO
, "[Disable ] "));
456 DEBUG ((DEBUG_INFO
, "[Unsupport] "));
458 DumpCpuFeature (CpuFeature
);
459 Entry
= Entry
->ForwardLink
;
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
);
471 for (ProcessorNumber
= 0; ProcessorNumber
< NumberOfCpus
; ProcessorNumber
++) {
472 CpuInitOrder
= &CpuFeaturesData
->InitOrder
[ProcessorNumber
];
473 Entry
= GetFirstNode (&CpuFeaturesData
->FeatureList
);
474 while (!IsNull (&CpuFeaturesData
->FeatureList
, Entry
)) {
476 // Insert each feature into processor's order list
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
);
483 Entry
= Entry
->ForwardLink
;
486 // Go through ordered feature list to initialize CPU features
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
);
495 Status
= CpuFeatureInOrder
->InitializeFunc (ProcessorNumber
, CpuInfo
, CpuFeatureInOrder
->ConfigData
, FALSE
);
497 ASSERT_EFI_ERROR (Status
);
498 Entry
= Entry
->ForwardLink
;
501 // Dump the RegisterTable
503 DumpRegisterTableOnProcessor (ProcessorNumber
);
508 Initialize the CPU registers from a register table.
510 @param[in] ProcessorNumber The index of the CPU executing this function.
512 @note This service could be called by BSP/APs.
515 ProgramProcessorRegister (
516 IN UINTN ProcessorNumber
519 CPU_FEATURES_DATA
*CpuFeaturesData
;
520 CPU_REGISTER_TABLE
*RegisterTable
;
521 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntry
;
524 CPU_REGISTER_TABLE_ENTRY
*RegisterTableEntryHead
;
526 CpuFeaturesData
= GetCpuFeaturesData ();
527 RegisterTable
= &CpuFeaturesData
->RegisterTable
[ProcessorNumber
];
530 // Traverse Register Table of this logical processor
532 RegisterTableEntryHead
= (CPU_REGISTER_TABLE_ENTRY
*) (UINTN
) RegisterTable
->RegisterTableEntry
;
534 for (Index
= 0; Index
< RegisterTable
->TableLength
; Index
++) {
536 RegisterTableEntry
= &RegisterTableEntryHead
[Index
];
539 // Check the type of specified register
541 switch (RegisterTableEntry
->RegisterType
) {
543 // The specified register is Control Register
545 case ControlRegister
:
546 switch (RegisterTableEntry
->Index
) {
548 Value
= AsmReadCr0 ();
549 Value
= (UINTN
) BitFieldWrite64 (
551 RegisterTableEntry
->ValidBitStart
,
552 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
553 RegisterTableEntry
->Value
558 Value
= AsmReadCr2 ();
559 Value
= (UINTN
) BitFieldWrite64 (
561 RegisterTableEntry
->ValidBitStart
,
562 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
563 RegisterTableEntry
->Value
568 Value
= AsmReadCr3 ();
569 Value
= (UINTN
) BitFieldWrite64 (
571 RegisterTableEntry
->ValidBitStart
,
572 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
573 RegisterTableEntry
->Value
578 Value
= AsmReadCr4 ();
579 Value
= (UINTN
) BitFieldWrite64 (
581 RegisterTableEntry
->ValidBitStart
,
582 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
583 RegisterTableEntry
->Value
589 // Do we need to support CR8?
597 // The specified register is Model Specific Register
601 // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode
603 AcquireSpinLock (&CpuFeaturesData
->MsrLock
);
604 if (RegisterTableEntry
->ValidBitLength
>= 64) {
606 // If length is not less than 64 bits, then directly write without reading
609 RegisterTableEntry
->Index
,
610 RegisterTableEntry
->Value
614 // Set the bit section according to bit start and length
616 AsmMsrBitFieldWrite64 (
617 RegisterTableEntry
->Index
,
618 RegisterTableEntry
->ValidBitStart
,
619 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
620 RegisterTableEntry
->Value
623 ReleaseSpinLock (&CpuFeaturesData
->MsrLock
);
626 // MemoryMapped operations
629 AcquireSpinLock (&CpuFeaturesData
->MemoryMappedLock
);
630 MmioBitFieldWrite32 (
631 RegisterTableEntry
->Index
,
632 RegisterTableEntry
->ValidBitStart
,
633 RegisterTableEntry
->ValidBitStart
+ RegisterTableEntry
->ValidBitLength
- 1,
634 (UINT32
)RegisterTableEntry
->Value
636 ReleaseSpinLock (&CpuFeaturesData
->MemoryMappedLock
);
639 // Enable or disable cache
643 // If value of the entry is 0, then disable cache. Otherwise, enable cache.
645 if (RegisterTableEntry
->Value
== 0) {
659 Programs registers for the calling processor.
661 @param[in,out] Buffer The pointer to private data buffer.
666 SetProcessorRegister (
670 UINTN ProcessorNumber
;
672 ProcessorNumber
= GetProcessorIndex ();
673 ProgramProcessorRegister (ProcessorNumber
);
677 Performs CPU features detection.
679 This service will invoke MP service to check CPU features'
680 capabilities on BSP/APs.
682 @note This service could be called by BSP only.
691 UINTN NumberOfEnabledProcessors
;
693 GetNumberOfProcessor (&NumberOfCpus
, &NumberOfEnabledProcessors
);
695 CpuInitDataInitialize (NumberOfCpus
);
698 // Wakeup all APs for data collection.
700 StartupAPsWorker (CollectProcessorData
);
703 // Collect data on BSP
705 CollectProcessorData (NULL
);
707 AnalysisProcessorFeatures (NumberOfCpus
);
711 Performs CPU features Initialization.
713 This service will invoke MP service to perform CPU features
714 initialization on BSP/APs per user configuration.
716 @note This service could be called by BSP only.
720 CpuFeaturesInitialize (
724 CPU_FEATURES_DATA
*CpuFeaturesData
;
727 CpuFeaturesData
= GetCpuFeaturesData ();
729 OldBspNumber
= GetProcessorIndex();
730 CpuFeaturesData
->BspNumber
= OldBspNumber
;
732 // Wakeup all APs for programming.
734 StartupAPsWorker (SetProcessorRegister
);
738 SetProcessorRegister (NULL
);
740 // Switch to new BSP if required
742 if (CpuFeaturesData
->BspNumber
!= OldBspNumber
) {
743 SwitchNewBsp (CpuFeaturesData
->BspNumber
);