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