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