]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
OvmfPkg/QemuFwCfgLib: Suppress GCC49 IA32 build failure
[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
152 CpuFeaturesData->BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
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
237/**\r
238 Worker function to check if the compared CPU feature set in the CPU feature\r
239 supported bits mask buffer.\r
240\r
241 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
242 @param[in] ComparedFeatureBitMask The feature bit mask to be compared\r
243\r
244 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits\r
245 mask buffer.\r
246 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits\r
247 mask buffer.\r
248**/\r
249BOOLEAN\r
250IsBitMaskMatch (\r
251 IN UINT8 *SupportedFeatureMask,\r
252 IN UINT8 *ComparedFeatureBitMask\r
253 )\r
254{\r
255 UINTN Index;\r
256 UINTN BitMaskSize;\r
257 UINT8 *Data1;\r
258 UINT8 *Data2;\r
259\r
260 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
261\r
262 Data1 = SupportedFeatureMask;\r
263 Data2 = ComparedFeatureBitMask;\r
264 for (Index = 0; Index < BitMaskSize; Index++) {\r
265 if (((*(Data1++)) & (*(Data2++))) != 0) {\r
266 return TRUE;\r
267 }\r
268 }\r
269 return FALSE;\r
270}\r
271\r
272/**\r
273 Collects processor data for calling processor.\r
274\r
275 @param[in,out] Buffer The pointer to private data buffer.\r
276**/\r
277VOID\r
278EFIAPI\r
279CollectProcessorData (\r
280 IN OUT VOID *Buffer\r
281 )\r
282{\r
283 UINTN ProcessorNumber;\r
284 CPU_FEATURES_ENTRY *CpuFeature;\r
285 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
286 LIST_ENTRY *Entry;\r
287 CPU_FEATURES_DATA *CpuFeaturesData;\r
288\r
289 CpuFeaturesData = GetCpuFeaturesData ();\r
290 ProcessorNumber = GetProcessorIndex ();\r
291 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
292 //\r
293 // collect processor information\r
294 //\r
295 FillProcessorInfo (CpuInfo);\r
296 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
297 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
298 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
299 if (IsBitMaskMatch (CpuFeaturesData->SupportPcds, CpuFeature->FeatureMask)) {\r
300 if (CpuFeature->SupportFunc == NULL) {\r
301 //\r
302 // If SupportFunc is NULL, then the feature is supported.\r
303 //\r
304 SupportedMaskOr (\r
305 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
306 CpuFeature->FeatureMask\r
307 );\r
308 } else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {\r
309 SupportedMaskOr (\r
310 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
311 CpuFeature->FeatureMask\r
312 );\r
313 }\r
314 }\r
315 Entry = Entry->ForwardLink;\r
316 }\r
317}\r
318\r
319/**\r
320 Dump the contents of a CPU register table.\r
321\r
322 @param[in] ProcessorNumber The index of the CPU to show the register table contents\r
323\r
324 @note This service could be called by BSP only.\r
325**/\r
326VOID\r
327DumpRegisterTableOnProcessor (\r
328 IN UINTN ProcessorNumber\r
329 )\r
330{\r
331 CPU_FEATURES_DATA *CpuFeaturesData;\r
332 UINTN FeatureIndex;\r
333 CPU_REGISTER_TABLE *RegisterTable;\r
334 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
335 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
336 UINT32 DebugPrintErrorLevel;\r
337\r
338 DebugPrintErrorLevel = (ProcessorNumber == 0) ? DEBUG_INFO : DEBUG_VERBOSE;\r
339 CpuFeaturesData = GetCpuFeaturesData ();\r
340 //\r
341 // Debug information\r
342 //\r
343 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
344 DEBUG ((DebugPrintErrorLevel, "RegisterTable->TableLength = %d\n", RegisterTable->TableLength));\r
345\r
346 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
347\r
348 for (FeatureIndex = 0; FeatureIndex < RegisterTable->TableLength; FeatureIndex++) {\r
349 RegisterTableEntry = &RegisterTableEntryHead[FeatureIndex];\r
350 switch (RegisterTableEntry->RegisterType) {\r
351 case Msr:\r
352 DEBUG ((\r
353 DebugPrintErrorLevel,\r
354 "Processor: %d: MSR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
355 ProcessorNumber,\r
356 RegisterTableEntry->Index,\r
357 RegisterTableEntry->ValidBitStart,\r
358 RegisterTableEntry->ValidBitLength,\r
359 RegisterTableEntry->Value\r
360 ));\r
361 break;\r
362 case ControlRegister:\r
363 DEBUG ((\r
364 DebugPrintErrorLevel,\r
365 "Processor: %d: CR: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
366 ProcessorNumber,\r
367 RegisterTableEntry->Index,\r
368 RegisterTableEntry->ValidBitStart,\r
369 RegisterTableEntry->ValidBitLength,\r
370 RegisterTableEntry->Value\r
371 ));\r
372 break;\r
373 case MemoryMapped:\r
374 DEBUG ((\r
375 DebugPrintErrorLevel,\r
376 "Processor: %d: MMIO: %lx, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
377 ProcessorNumber,\r
378 RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),\r
379 RegisterTableEntry->ValidBitStart,\r
380 RegisterTableEntry->ValidBitLength,\r
381 RegisterTableEntry->Value\r
382 ));\r
383 break;\r
384 case CacheControl:\r
385 DEBUG ((\r
386 DebugPrintErrorLevel,\r
387 "Processor: %d: CACHE: %x, Bit Start: %d, Bit Length: %d, Value: %lx\r\n",\r
388 ProcessorNumber,\r
389 RegisterTableEntry->Index,\r
390 RegisterTableEntry->ValidBitStart,\r
391 RegisterTableEntry->ValidBitLength,\r
392 RegisterTableEntry->Value\r
393 ));\r
394 break;\r
395 default:\r
396 break;\r
397 }\r
398 }\r
399}\r
400\r
401/**\r
402 Analysis register CPU features on each processor and save CPU setting in CPU register table.\r
403\r
404 @param[in] NumberOfCpus Number of processor in system\r
405\r
406**/\r
407VOID\r
408AnalysisProcessorFeatures (\r
409 IN UINTN NumberOfCpus\r
410 )\r
411{\r
412 EFI_STATUS Status;\r
413 UINTN ProcessorNumber;\r
414 CPU_FEATURES_ENTRY *CpuFeature;\r
415 CPU_FEATURES_ENTRY *CpuFeatureInOrder;\r
416 CPU_FEATURES_INIT_ORDER *CpuInitOrder;\r
417 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
418 LIST_ENTRY *Entry;\r
419 CPU_FEATURES_DATA *CpuFeaturesData;\r
420\r
421 CpuFeaturesData = GetCpuFeaturesData ();\r
422 CpuFeaturesData->CapabilityPcds = AllocatePool (CpuFeaturesData->BitMaskSize);\r
423 ASSERT (CpuFeaturesData->CapabilityPcds != NULL);\r
424 SetMem (CpuFeaturesData->CapabilityPcds, CpuFeaturesData->BitMaskSize, 0xFF);\r
425 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
426 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
427 //\r
428 // Calculate the last capability on all processors\r
429 //\r
430 SupportedMaskAnd (CpuFeaturesData->CapabilityPcds, CpuInitOrder->FeaturesSupportedMask);\r
431 }\r
432 //\r
433 // Calculate the last setting\r
434 //\r
435\r
436 CpuFeaturesData->SettingPcds = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcds);\r
437 ASSERT (CpuFeaturesData->SettingPcds != NULL);\r
438 SupportedMaskAnd (CpuFeaturesData->SettingPcds, CpuFeaturesData->ConfigurationPcds);\r
439\r
440 //\r
441 // Save PCDs and display CPU PCDs\r
442 //\r
443 SetCapabilityPcd (CpuFeaturesData->CapabilityPcds);\r
444 SetSettingPcd (CpuFeaturesData->SettingPcds);\r
445\r
446 //\r
447 // Dump the last CPU feature list\r
448 //\r
449 DEBUG_CODE (\r
450 DEBUG ((DEBUG_INFO, "Last CPU features list...\n"));\r
451 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
452 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
453 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
454 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {\r
455 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcds)) {\r
456 DEBUG ((DEBUG_INFO, "[Enable ] "));\r
457 } else {\r
458 DEBUG ((DEBUG_INFO, "[Disable ] "));\r
459 }\r
460 } else {\r
461 DEBUG ((DEBUG_INFO, "[Unsupport] "));\r
462 }\r
463 DumpCpuFeature (CpuFeature);\r
464 Entry = Entry->ForwardLink;\r
465 }\r
466 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSupport:\n"));\r
467 DumpCpuFeatureMask (CpuFeaturesData->SupportPcds);\r
468 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesUserConfiguration:\n"));\r
469 DumpCpuFeatureMask (CpuFeaturesData->ConfigurationPcds);\r
470 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));\r
471 DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcds);\r
472 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesSetting:\n"));\r
473 DumpCpuFeatureMask (CpuFeaturesData->SettingPcds);\r
474 );\r
475\r
476 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
477 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
478 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
479 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
480 //\r
481 // Insert each feature into processor's order list\r
482 //\r
483 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
484 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcds)) {\r
485 CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);\r
486 ASSERT (CpuFeatureInOrder != NULL);\r
487 InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);\r
488 }\r
489 Entry = Entry->ForwardLink;\r
490 }\r
491 //\r
492 // Go through ordered feature list to initialize CPU features\r
493 //\r
494 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
495 Entry = GetFirstNode (&CpuInitOrder->OrderList);\r
496 while (!IsNull (&CpuInitOrder->OrderList, Entry)) {\r
497 CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
498 if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcds)) {\r
499 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);\r
500 } else {\r
501 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);\r
502 }\r
503 ASSERT_EFI_ERROR (Status);\r
504 Entry = Entry->ForwardLink;\r
505 }\r
506 //\r
507 // Dump the RegisterTable\r
508 //\r
509 DumpRegisterTableOnProcessor (ProcessorNumber);\r
510 }\r
511}\r
512\r
513/**\r
514 Initialize the CPU registers from a register table.\r
515\r
516 @param[in] ProcessorNumber The index of the CPU executing this function.\r
517\r
518 @note This service could be called by BSP/APs.\r
519**/\r
520VOID\r
521ProgramProcessorRegister (\r
522 IN UINTN ProcessorNumber\r
523 )\r
524{\r
525 CPU_FEATURES_DATA *CpuFeaturesData;\r
526 CPU_REGISTER_TABLE *RegisterTable;\r
527 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
528 UINTN Index;\r
529 UINTN Value;\r
530 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
531\r
532 CpuFeaturesData = GetCpuFeaturesData ();\r
533 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
534\r
535 //\r
536 // Traverse Register Table of this logical processor\r
537 //\r
538 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
539\r
540 for (Index = 0; Index < RegisterTable->TableLength; Index++) {\r
541\r
542 RegisterTableEntry = &RegisterTableEntryHead[Index];\r
543\r
544 //\r
545 // Check the type of specified register\r
546 //\r
547 switch (RegisterTableEntry->RegisterType) {\r
548 //\r
549 // The specified register is Control Register\r
550 //\r
551 case ControlRegister:\r
552 switch (RegisterTableEntry->Index) {\r
553 case 0:\r
554 Value = AsmReadCr0 ();\r
555 Value = (UINTN) BitFieldWrite64 (\r
556 Value,\r
557 RegisterTableEntry->ValidBitStart,\r
558 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
559 RegisterTableEntry->Value\r
560 );\r
561 AsmWriteCr0 (Value);\r
562 break;\r
563 case 2:\r
564 Value = AsmReadCr2 ();\r
565 Value = (UINTN) BitFieldWrite64 (\r
566 Value,\r
567 RegisterTableEntry->ValidBitStart,\r
568 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
569 RegisterTableEntry->Value\r
570 );\r
571 AsmWriteCr2 (Value);\r
572 break;\r
573 case 3:\r
574 Value = AsmReadCr3 ();\r
575 Value = (UINTN) BitFieldWrite64 (\r
576 Value,\r
577 RegisterTableEntry->ValidBitStart,\r
578 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
579 RegisterTableEntry->Value\r
580 );\r
581 AsmWriteCr3 (Value);\r
582 break;\r
583 case 4:\r
584 Value = AsmReadCr4 ();\r
585 Value = (UINTN) BitFieldWrite64 (\r
586 Value,\r
587 RegisterTableEntry->ValidBitStart,\r
588 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
589 RegisterTableEntry->Value\r
590 );\r
591 AsmWriteCr4 (Value);\r
592 break;\r
593 case 8:\r
594 //\r
595 // Do we need to support CR8?\r
596 //\r
597 break;\r
598 default:\r
599 break;\r
600 }\r
601 break;\r
602 //\r
603 // The specified register is Model Specific Register\r
604 //\r
605 case Msr:\r
606 //\r
607 // Get lock to avoid Package/Core scope MSRs programming issue in parallel execution mode\r
608 //\r
609 AcquireSpinLock (&CpuFeaturesData->MsrLock);\r
610 if (RegisterTableEntry->ValidBitLength >= 64) {\r
611 //\r
612 // If length is not less than 64 bits, then directly write without reading\r
613 //\r
614 AsmWriteMsr64 (\r
615 RegisterTableEntry->Index,\r
616 RegisterTableEntry->Value\r
617 );\r
618 } else {\r
619 //\r
620 // Set the bit section according to bit start and length\r
621 //\r
622 AsmMsrBitFieldWrite64 (\r
623 RegisterTableEntry->Index,\r
624 RegisterTableEntry->ValidBitStart,\r
625 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
626 RegisterTableEntry->Value\r
627 );\r
628 }\r
629 ReleaseSpinLock (&CpuFeaturesData->MsrLock);\r
630 break;\r
631 //\r
632 // MemoryMapped operations\r
633 //\r
634 case MemoryMapped:\r
635 AcquireSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
636 MmioBitFieldWrite32 (\r
637 (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),\r
638 RegisterTableEntry->ValidBitStart,\r
639 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
640 (UINT32)RegisterTableEntry->Value\r
641 );\r
642 ReleaseSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
643 break;\r
644 //\r
645 // Enable or disable cache\r
646 //\r
647 case CacheControl:\r
648 //\r
649 // If value of the entry is 0, then disable cache. Otherwise, enable cache.\r
650 //\r
651 if (RegisterTableEntry->Value == 0) {\r
652 AsmDisableCache ();\r
653 } else {\r
654 AsmEnableCache ();\r
655 }\r
656 break;\r
657\r
658 default:\r
659 break;\r
660 }\r
661 }\r
662}\r
663\r
664/**\r
665 Programs registers for the calling processor.\r
666\r
667 @param[in,out] Buffer The pointer to private data buffer.\r
668\r
669**/\r
670VOID\r
671EFIAPI\r
672SetProcessorRegister (\r
673 IN OUT VOID *Buffer\r
674 )\r
675{\r
676 UINTN ProcessorNumber;\r
677\r
678 ProcessorNumber = GetProcessorIndex ();\r
679 ProgramProcessorRegister (ProcessorNumber);\r
680}\r
681\r
682/**\r
683 Performs CPU features detection.\r
684\r
685 This service will invoke MP service to check CPU features'\r
686 capabilities on BSP/APs.\r
687\r
688 @note This service could be called by BSP only.\r
689**/\r
690VOID\r
691EFIAPI\r
692CpuFeaturesDetect (\r
693 VOID\r
694 )\r
695{\r
696 UINTN NumberOfCpus;\r
697 UINTN NumberOfEnabledProcessors;\r
698\r
699 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
700\r
701 CpuInitDataInitialize (NumberOfCpus);\r
702\r
703 //\r
704 // Wakeup all APs for data collection.\r
705 //\r
706 StartupAPsWorker (CollectProcessorData);\r
707\r
708 //\r
709 // Collect data on BSP\r
710 //\r
711 CollectProcessorData (NULL);\r
712\r
713 AnalysisProcessorFeatures (NumberOfCpus);\r
714}\r
715\r
716/**\r
717 Performs CPU features Initialization.\r
718\r
719 This service will invoke MP service to perform CPU features\r
720 initialization on BSP/APs per user configuration.\r
721\r
722 @note This service could be called by BSP only.\r
723**/\r
724VOID\r
725EFIAPI\r
726CpuFeaturesInitialize (\r
727 VOID\r
728 )\r
729{\r
730 CPU_FEATURES_DATA *CpuFeaturesData;\r
731 UINTN OldBspNumber;\r
732\r
733 CpuFeaturesData = GetCpuFeaturesData ();\r
734\r
735 OldBspNumber = GetProcessorIndex();\r
736 CpuFeaturesData->BspNumber = OldBspNumber;\r
737 //\r
738 // Wakeup all APs for programming.\r
739 //\r
740 StartupAPsWorker (SetProcessorRegister);\r
741 //\r
742 // Programming BSP\r
743 //\r
744 SetProcessorRegister (NULL);\r
745 //\r
746 // Switch to new BSP if required\r
747 //\r
748 if (CpuFeaturesData->BspNumber != OldBspNumber) {\r
749 SwitchNewBsp (CpuFeaturesData->BspNumber);\r
750 }\r
751}\r