Revert "UefiCpuPkg: Check invalid RegisterCpuFeature parameter"
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
CommitLineData
80c4b236
JF
1/** @file\r
2 CPU Register Table Library 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 Checks if two CPU feature bit masks are equal.\r
19\r
20 @param[in] FirstFeatureMask The first input CPU feature bit mask\r
21 @param[in] SecondFeatureMask The second input CPU feature bit mask\r
22\r
23 @retval TRUE Two CPU feature bit masks are equal.\r
24 @retval FALSE Two CPU feature bit masks are not equal.\r
25**/\r
26BOOLEAN\r
27IsCpuFeatureMatch (\r
28 IN UINT8 *FirstFeatureMask,\r
29 IN UINT8 *SecondFeatureMask\r
30 )\r
31{\r
3b341e26 32 UINTN BitMaskSize;\r
80c4b236
JF
33\r
34 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
35 if (CompareMem (FirstFeatureMask, SecondFeatureMask, BitMaskSize) == 0) {\r
36 return TRUE;\r
37 } else {\r
38 return FALSE;\r
39 }\r
40}\r
41\r
42/**\r
43 Function that uses DEBUG() macros to display the contents of a a CPU feature bit mask.\r
44\r
45 @param[in] FeatureMask A pointer to the CPU feature bit mask.\r
46**/\r
47VOID\r
48DumpCpuFeatureMask (\r
49 IN UINT8 *FeatureMask\r
50 )\r
51{\r
52 UINTN Index;\r
53 UINT8 *Data8;\r
3b341e26 54 UINTN BitMaskSize;\r
80c4b236
JF
55\r
56 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
57 Data8 = (UINT8 *) FeatureMask;\r
58 for (Index = 0; Index < BitMaskSize; Index++) {\r
59 DEBUG ((DEBUG_INFO, " %02x ", *Data8++));\r
60 }\r
61 DEBUG ((DEBUG_INFO, "\n"));\r
62}\r
63\r
64/**\r
65 Dump CPU feature name or CPU feature bit mask.\r
66\r
67 @param[in] CpuFeature Pointer to CPU_FEATURES_ENTRY\r
68**/\r
69VOID\r
70DumpCpuFeature (\r
71 IN CPU_FEATURES_ENTRY *CpuFeature\r
72 )\r
73{\r
74\r
75 if (CpuFeature->FeatureName != NULL) {\r
76 DEBUG ((DEBUG_INFO, "FeatureName: %a\n", CpuFeature->FeatureName));\r
77 } else {\r
78 DEBUG ((DEBUG_INFO, "FeatureMask = "));\r
79 DumpCpuFeatureMask (CpuFeature->FeatureMask);\r
80 }\r
81}\r
82\r
83/**\r
84 Determines if the feature bit mask is in dependent CPU feature bit mask buffer.\r
85\r
86 @param[in] FeatureMask Pointer to CPU feature bit mask\r
87 @param[in] DependentBitMask Pointer to dependent CPU feature bit mask buffer\r
88\r
89 @retval TRUE The feature bit mask is in dependent CPU feature bit mask buffer.\r
90 @retval FALSE The feature bit mask is not in dependent CPU feature bit mask buffer.\r
91**/\r
92BOOLEAN\r
93IsBitMaskMatchCheck (\r
94 IN UINT8 *FeatureMask,\r
95 IN UINT8 *DependentBitMask\r
96 )\r
97{\r
98 UINTN Index;\r
99 UINTN BitMaskSize;\r
100 UINT8 *Data1;\r
101 UINT8 *Data2;\r
102\r
103 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
104\r
105 Data1 = FeatureMask;\r
106 Data2 = DependentBitMask;\r
107 for (Index = 0; Index < BitMaskSize; Index++) {\r
108 if (((*(Data1++)) & (*(Data2++))) != 0) {\r
109 return TRUE;\r
110 }\r
111 }\r
112 return FALSE;\r
113}\r
114\r
115/**\r
116 Checks and adjusts CPU features order per dependency relationship.\r
117\r
118 @param[in] FeatureList Pointer to CPU feature list\r
119**/\r
120VOID\r
121CheckCpuFeaturesDependency (\r
122 IN LIST_ENTRY *FeatureList\r
123 )\r
124{\r
125 LIST_ENTRY *CurrentEntry;\r
126 CPU_FEATURES_ENTRY *CpuFeature;\r
127 LIST_ENTRY *CheckEntry;\r
128 CPU_FEATURES_ENTRY *CheckFeature;\r
129 BOOLEAN Swapped;\r
130 LIST_ENTRY *TempEntry;\r
131\r
132 CurrentEntry = GetFirstNode (FeatureList);\r
133 while (!IsNull (FeatureList, CurrentEntry)) {\r
134 Swapped = FALSE;\r
135 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
136 if (CpuFeature->BeforeAll) {\r
137 //\r
138 // Check all features dispatched before this entry\r
139 //\r
140 CheckEntry = GetFirstNode (FeatureList);\r
141 while (CheckEntry != CurrentEntry) {\r
142 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
143 if (!CheckFeature->BeforeAll) {\r
144 //\r
145 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,\r
146 // insert currentEntry before Checked feature\r
147 //\r
148 RemoveEntryList (CurrentEntry);\r
149 InsertTailList (CheckEntry, CurrentEntry);\r
150 Swapped = TRUE;\r
151 break;\r
152 }\r
153 CheckEntry = CheckEntry->ForwardLink;\r
154 }\r
155 if (Swapped) {\r
156 continue;\r
157 }\r
158 }\r
159\r
160 if (CpuFeature->AfterAll) {\r
161 //\r
162 // Check all features dispatched after this entry\r
163 //\r
164 CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
165 while (!IsNull (FeatureList, CheckEntry)) {\r
166 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
167 if (!CheckFeature->AfterAll) {\r
168 //\r
169 // If this feature has no AfterAll flag and is dispatched after CpuFeature,\r
170 // insert currentEntry after Checked feature\r
171 //\r
172 TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
173 RemoveEntryList (CurrentEntry);\r
174 InsertHeadList (CheckEntry, CurrentEntry);\r
175 CurrentEntry = TempEntry;\r
176 Swapped = TRUE;\r
177 break;\r
178 }\r
179 CheckEntry = CheckEntry->ForwardLink;\r
180 }\r
181 if (Swapped) {\r
182 continue;\r
183 }\r
184 }\r
185\r
186 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
187 //\r
188 // Check all features dispatched before this entry\r
189 //\r
190 CheckEntry = GetFirstNode (FeatureList);\r
191 while (CheckEntry != CurrentEntry) {\r
192 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
193 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r
194 //\r
195 // If there is dependency, swap them\r
196 //\r
197 RemoveEntryList (CurrentEntry);\r
198 InsertTailList (CheckEntry, CurrentEntry);\r
199 Swapped = TRUE;\r
200 break;\r
201 }\r
202 CheckEntry = CheckEntry->ForwardLink;\r
203 }\r
204 if (Swapped) {\r
205 continue;\r
206 }\r
207 }\r
208\r
209 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
210 //\r
211 // Check all features dispatched after this entry\r
212 //\r
213 CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
214 while (!IsNull (FeatureList, CheckEntry)) {\r
215 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
216 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {\r
217 //\r
218 // If there is dependency, swap them\r
219 //\r
220 TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
221 RemoveEntryList (CurrentEntry);\r
222 InsertHeadList (CheckEntry, CurrentEntry);\r
223 CurrentEntry = TempEntry;\r
224 Swapped = TRUE;\r
225 break;\r
226 }\r
227 CheckEntry = CheckEntry->ForwardLink;\r
228 }\r
229 if (Swapped) {\r
230 continue;\r
231 }\r
232 }\r
233 //\r
234 // No swap happened, check the next feature\r
235 //\r
236 CurrentEntry = CurrentEntry->ForwardLink;\r
237 }\r
238}\r
239\r
240/**\r
241 Worker function to register CPU Feature.\r
242\r
243 @param[in] CpuFeature Pointer to CPU feature entry\r
244\r
245 @retval RETURN_SUCCESS The CPU feature was successfully registered.\r
246 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r
247 the CPU feature.\r
248 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
249 supported due to a circular dependency between\r
250 BEFORE and AFTER features.\r
251**/\r
252RETURN_STATUS\r
253RegisterCpuFeatureWorker (\r
254 IN CPU_FEATURES_ENTRY *CpuFeature\r
255 )\r
256{\r
257 EFI_STATUS Status;\r
258 CPU_FEATURES_DATA *CpuFeaturesData;\r
259 CPU_FEATURES_ENTRY *CpuFeatureEntry;\r
260 LIST_ENTRY *Entry;\r
3b341e26 261 UINTN BitMaskSize;\r
80c4b236
JF
262 BOOLEAN FeatureExist;\r
263\r
264 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
265 CpuFeaturesData = GetCpuFeaturesData ();\r
266 if (CpuFeaturesData->FeaturesCount == 0) {\r
267 InitializeListHead (&CpuFeaturesData->FeatureList);\r
268 InitializeSpinLock (&CpuFeaturesData->MsrLock);\r
269 InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);\r
3b341e26 270 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
80c4b236
JF
271 }\r
272 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r
273\r
274 FeatureExist = FALSE;\r
275 CpuFeatureEntry = NULL;\r
276 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
277 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
278 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
279 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {\r
280 //\r
281 // If this feature already registered\r
282 //\r
283 FeatureExist = TRUE;\r
284 break;\r
285 }\r
286 Entry = Entry->ForwardLink;\r
287 }\r
288\r
289 if (!FeatureExist) {\r
290 DEBUG ((DEBUG_INFO, "[NEW] "));\r
291 DumpCpuFeature (CpuFeature);\r
292 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);\r
293 CpuFeaturesData->FeaturesCount++;\r
294 } else {\r
295 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));\r
296 DumpCpuFeature (CpuFeature);\r
297 ASSERT (CpuFeatureEntry != NULL);\r
298 //\r
299 // Overwrite original parameters of CPU feature\r
300 //\r
301 if (CpuFeature->GetConfigDataFunc != NULL) {\r
302 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;\r
303 }\r
304 if (CpuFeature->SupportFunc != NULL) {\r
305 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;\r
306 }\r
307 if (CpuFeature->InitializeFunc != NULL) {\r
308 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;\r
309 }\r
310 if (CpuFeature->FeatureName != NULL) {\r
311 if (CpuFeatureEntry->FeatureName == NULL) {\r
312 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
313 ASSERT (CpuFeatureEntry->FeatureName != NULL);\r
314 }\r
315 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);\r
316 ASSERT_EFI_ERROR (Status);\r
317 FreePool (CpuFeature->FeatureName);\r
318 }\r
319 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
320 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {\r
321 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);\r
322 }\r
323 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;\r
324 }\r
325 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
326 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {\r
327 FreePool (CpuFeatureEntry->AfterFeatureBitMask);\r
328 }\r
329 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r
330 }\r
331 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r
332 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;\r
333\r
334 FreePool (CpuFeature->FeatureMask);\r
335 FreePool (CpuFeature);\r
336 }\r
337 //\r
338 // Verify CPU features dependency can change CPU feature order\r
339 //\r
340 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);\r
341 return RETURN_SUCCESS;\r
342}\r
343\r
344/**\r
345 Sets CPU feature bit mask in CPU feature bit mask buffer.\r
346\r
347 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer\r
348 @param[in] Feature The bit number of the CPU feature\r
349 @param[in] BitMaskSize CPU feature bit mask buffer size\r
350**/\r
351VOID\r
352SetCpuFeaturesBitMask (\r
353 IN UINT8 **FeaturesBitMask,\r
354 IN UINT32 Feature,\r
355 IN UINTN BitMaskSize\r
356 )\r
357{\r
358 UINT8 *CpuFeaturesBitMask;\r
359\r
360 ASSERT (FeaturesBitMask != NULL);\r
361 CpuFeaturesBitMask = *FeaturesBitMask;\r
362 if (CpuFeaturesBitMask == NULL) {\r
363 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);\r
364 ASSERT (CpuFeaturesBitMask != NULL);\r
365 *FeaturesBitMask = CpuFeaturesBitMask;\r
366 }\r
367\r
368 CpuFeaturesBitMask += (Feature / 8);\r
369 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));\r
370}\r
371\r
372/**\r
373 Registers a CPU Feature.\r
374\r
375 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature\r
376 name.\r
377 @param[in] GetConfigDataFunc CPU feature get configuration data function. This\r
378 is an optional parameter that may be NULL. If NULL,\r
379 then the most recently registered function for the\r
380 CPU feature is used. If no functions are registered\r
381 for a CPU feature, then the CPU configuration data\r
382 for the registered feature is NULL.\r
383 @param[in] SupportFunc CPU feature support function. This is an optional\r
384 parameter that may be NULL. If NULL, then the most\r
385 recently registered function for the CPU feature is\r
386 used. If no functions are registered for a CPU\r
387 feature, then the CPU feature is assumed to be\r
388 supported by all CPUs.\r
389 @param[in] InitializeFunc CPU feature initialize function. This is an optional\r
390 parameter that may be NULL. If NULL, then the most\r
391 recently registered function for the CPU feature is\r
392 used. If no functions are registered for a CPU\r
393 feature, then the CPU feature initialization is\r
394 skipped.\r
395 @param[in] ... Variable argument list of UINT32 CPU feature value.\r
396 Values with no modifiers are the features provided\r
397 by the registered functions.\r
398 Values with CPU_FEATURE_BEFORE modifier are features\r
399 that must be initialized after the features provided\r
400 by the registered functions are used.\r
401 Values with CPU_FEATURE_AFTER modifier are features\r
402 that must be initialized before the features provided\r
403 by the registered functions are used.\r
404 The last argument in this variable argument list must\r
405 always be CPU_FEATURE_END.\r
406\r
407 @retval RETURN_SUCCESS The CPU feature was successfully registered.\r
408 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r
409 the CPU feature.\r
410 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
411 supported due to a circular dependency between\r
412 BEFORE and AFTER features.\r
413\r
414 @note This service could be called by BSP only.\r
415**/\r
416RETURN_STATUS\r
417EFIAPI\r
418RegisterCpuFeature (\r
419 IN CHAR8 *FeatureName, OPTIONAL\r
420 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL\r
421 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL\r
422 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL\r
423 ...\r
424 )\r
425{\r
426 EFI_STATUS Status;\r
427 VA_LIST Marker;\r
428 UINT32 Feature;\r
429 UINTN BitMaskSize;\r
430 CPU_FEATURES_ENTRY *CpuFeature;\r
431 UINT8 *FeatureMask;\r
432 UINT8 *BeforeFeatureBitMask;\r
433 UINT8 *AfterFeatureBitMask;\r
434 BOOLEAN BeforeAll;\r
435 BOOLEAN AfterAll;\r
436\r
437 FeatureMask = NULL;\r
438 BeforeFeatureBitMask = NULL;\r
439 AfterFeatureBitMask = NULL;\r
440 BeforeAll = FALSE;\r
441 AfterAll = FALSE;\r
442\r
443 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
444\r
445 VA_START (Marker, InitializeFunc);\r
446 Feature = VA_ARG (Marker, UINT32);\r
447 while (Feature != CPU_FEATURE_END) {\r
448 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))\r
449 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r
450 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r
451 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r
452 if (Feature < CPU_FEATURE_BEFORE) {\r
453 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r
454 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r
455 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);\r
456 ASSERT (FeatureMask == NULL);\r
457 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);\r
458 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {\r
459 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r
460 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r
461 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r
462 }\r
463 Feature = VA_ARG (Marker, UINT32);\r
464 }\r
465 VA_END (Marker);\r
466\r
467 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r
468 ASSERT (CpuFeature != NULL);\r
469 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r
470 CpuFeature->FeatureMask = FeatureMask;\r
471 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
472 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r
473 CpuFeature->BeforeAll = BeforeAll;\r
474 CpuFeature->AfterAll = AfterAll;\r
475 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r
476 CpuFeature->SupportFunc = SupportFunc;\r
477 CpuFeature->InitializeFunc = InitializeFunc;\r
478 if (FeatureName != NULL) {\r
479 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
480 ASSERT (CpuFeature->FeatureName != NULL);\r
481 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);\r
482 ASSERT_EFI_ERROR (Status);\r
483 }\r
484\r
485 Status = RegisterCpuFeatureWorker (CpuFeature);\r
486 ASSERT_EFI_ERROR (Status);\r
487\r
488 return RETURN_SUCCESS;\r
489}\r
490\r
491/**\r
492 Add an entry in specified register table.\r
493\r
494 This function adds an entry in specified register table, with given register type,\r
495 register index, bit section and value.\r
496\r
497 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table\r
498 If FALSE, entry will be added into register table\r
499 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
500 @param[in] RegisterType Type of the register to program\r
501 @param[in] Index Index of the register to program\r
502 @param[in] ValidBitStart Start of the bit section\r
503 @param[in] ValidBitLength Length of the bit section\r
504 @param[in] Value Value to write\r
505**/\r
506VOID\r
507CpuRegisterTableWriteWorker (\r
508 IN BOOLEAN PreSmmFlag,\r
509 IN UINTN ProcessorNumber,\r
510 IN REGISTER_TYPE RegisterType,\r
511 IN UINT64 Index,\r
512 IN UINT8 ValidBitStart,\r
513 IN UINT8 ValidBitLength,\r
514 IN UINT64 Value\r
515 )\r
516{\r
517 EFI_STATUS Status;\r
518 CPU_FEATURES_DATA *CpuFeaturesData;\r
519 ACPI_CPU_DATA *AcpiCpuData;\r
520 CPU_REGISTER_TABLE *RegisterTable;\r
521 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
522\r
523 CpuFeaturesData = GetCpuFeaturesData ();\r
524 if (CpuFeaturesData->RegisterTable == NULL) {\r
525 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
526 if (AcpiCpuData == NULL) {\r
527 AcpiCpuData = AllocateAcpiCpuData ();\r
528 ASSERT (AcpiCpuData != NULL);\r
529 //\r
530 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
531 //\r
532 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
533 ASSERT_EFI_ERROR (Status);\r
534 }\r
535 ASSERT (AcpiCpuData->RegisterTable != 0);\r
536 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r
537 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r
538 }\r
539\r
540 if (PreSmmFlag) {\r
541 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];\r
542 } else {\r
543 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
544 }\r
545\r
546 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {\r
547 EnlargeRegisterTable (RegisterTable);\r
548 }\r
549\r
550 //\r
551 // Append entry in the register table.\r
552 //\r
553 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
554 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;\r
555 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;\r
556 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);\r
557 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;\r
558 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;\r
559 RegisterTableEntry[RegisterTable->TableLength].Value = Value;\r
560\r
561 RegisterTable->TableLength++;\r
562}\r
563\r
564/**\r
565 Adds an entry in specified register table.\r
566\r
567 This function adds an entry in specified register table, with given register type,\r
568 register index, bit section and value.\r
569\r
570 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
571 @param[in] RegisterType Type of the register to program\r
572 @param[in] Index Index of the register to program\r
573 @param[in] ValueMask Mask of bits in register to write\r
574 @param[in] Value Value to write\r
575\r
576 @note This service could be called by BSP only.\r
577**/\r
578VOID\r
579EFIAPI\r
580CpuRegisterTableWrite (\r
581 IN UINTN ProcessorNumber,\r
582 IN REGISTER_TYPE RegisterType,\r
583 IN UINT64 Index,\r
584 IN UINT64 ValueMask,\r
585 IN UINT64 Value\r
586 )\r
587{\r
588 UINT8 Start;\r
589 UINT8 End;\r
590 UINT8 Length;\r
591\r
592 Start = (UINT8)LowBitSet64 (ValueMask);\r
593 End = (UINT8)HighBitSet64 (ValueMask);\r
594 Length = End - Start + 1;\r
595 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
596}\r
597\r
598/**\r
599 Adds an entry in specified Pre-SMM register table.\r
600\r
601 This function adds an entry in specified register table, with given register type,\r
602 register index, bit section and value.\r
603\r
604 @param[in] ProcessorNumber The index of the CPU to add a register table entry.\r
605 @param[in] RegisterType Type of the register to program\r
606 @param[in] Index Index of the register to program\r
607 @param[in] ValueMask Mask of bits in register to write\r
608 @param[in] Value Value to write\r
609\r
610 @note This service could be called by BSP only.\r
611**/\r
612VOID\r
613EFIAPI\r
614PreSmmCpuRegisterTableWrite (\r
615 IN UINTN ProcessorNumber,\r
616 IN REGISTER_TYPE RegisterType,\r
617 IN UINT64 Index,\r
618 IN UINT64 ValueMask,\r
619 IN UINT64 Value\r
620 )\r
621{\r
622 UINT8 Start;\r
623 UINT8 End;\r
624 UINT8 Length;\r
625\r
626 Start = (UINT8)LowBitSet64 (ValueMask);\r
627 End = (UINT8)HighBitSet64 (ValueMask);\r
628 Length = End - Start + 1;\r
629 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
630}\r
631\r
632/**\r
633 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.\r
634\r
635 @param[in] CpuBitMask CPU feature bit mask buffer\r
636 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer\r
637 @param[in] Feature The bit number of the CPU feature\r
638\r
639 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r
640 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r
641\r
642**/\r
643BOOLEAN\r
644IsCpuFeatureSetInCpuPcd (\r
645 IN UINT8 *CpuBitMask,\r
646 IN UINTN CpuBitMaskSize,\r
647 IN UINT32 Feature\r
648 )\r
649{\r
650 if ((Feature >> 3) >= CpuBitMaskSize) {\r
651 return FALSE;\r
652 }\r
653 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);\r
654}\r
655\r
656/**\r
657 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.\r
658 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data\r
659 associated with that feature should be optimized away if compiler\r
660 optimizations are enabled.\r
661\r
662 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
663 PcdCpuFeaturesSupport\r
664\r
665 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r
666 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r
667\r
668 @note This service could be called by BSP only.\r
669**/\r
670BOOLEAN\r
671EFIAPI\r
672IsCpuFeatureSupported (\r
673 IN UINT32 Feature\r
674 )\r
675{\r
676 return IsCpuFeatureSetInCpuPcd (\r
677 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),\r
678 PcdGetSize (PcdCpuFeaturesSupport),\r
679 Feature\r
680 );\r
681}\r
682\r
683/**\r
684 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.\r
685\r
686 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
687 PcdCpuFeaturesSetting\r
688\r
689 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.\r
690 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.\r
691\r
692 @note This service could be called by BSP only.\r
693**/\r
694BOOLEAN\r
695EFIAPI\r
696IsCpuFeatureInSetting (\r
697 IN UINT32 Feature\r
698 )\r
699{\r
700 return IsCpuFeatureSetInCpuPcd (\r
701 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),\r
702 PcdGetSize (PcdCpuFeaturesSetting),\r
703 Feature\r
704 );\r
705}\r
706\r
707/**\r
708 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.\r
709\r
710 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
711 PcdCpuFeaturesCapability\r
712\r
713 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.\r
714 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.\r
715\r
716 @note This service could be called by BSP only.\r
717**/\r
718BOOLEAN\r
719EFIAPI\r
720IsCpuFeatureCapability (\r
721 IN UINT32 Feature\r
722 )\r
723{\r
724 return IsCpuFeatureSetInCpuPcd (\r
725 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),\r
726 PcdGetSize (PcdCpuFeaturesCapability),\r
727 Feature\r
728 );\r
729\r
730}\r
731\r
732/**\r
733 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.\r
734\r
735 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
736 PcdCpuFeaturesUserConfiguration\r
737\r
738 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.\r
739 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.\r
740\r
741 @note This service could be called by BSP only.\r
742**/\r
743BOOLEAN\r
744EFIAPI\r
745IsCpuFeatureUserConfiguration (\r
746 IN UINT32 Feature\r
747 )\r
748{\r
749 return IsCpuFeatureSetInCpuPcd (\r
750 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),\r
751 PcdGetSize (PcdCpuFeaturesUserConfiguration),\r
752 Feature\r
753 );\r
754\r
755}\r
756\r
757/**\r
758 Switches to assigned BSP after CPU features initialization.\r
759\r
760 @param[in] ProcessorNumber The index of the CPU executing this function.\r
761\r
762 @note This service could be called by BSP only.\r
763**/\r
764VOID\r
765EFIAPI\r
766SwitchBspAfterFeaturesInitialize (\r
767 IN UINTN ProcessorNumber\r
768 )\r
769{\r
770 CPU_FEATURES_DATA *CpuFeaturesData;\r
771\r
772 CpuFeaturesData = GetCpuFeaturesData ();\r
773 CpuFeaturesData->BspNumber = ProcessorNumber;\r
774}\r
775\r