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