]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
UefiCpuPkg/RegisterCpuFeaturesLib: Support combo CPU feature style.
[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
b3c71b47
ED
115/**\r
116 Return feature dependence result.\r
117\r
1475b83f
ED
118 @param[in] CpuFeature Pointer to CPU feature.\r
119 @param[in] Before Check before dependence or after.\r
120 @param[in] NextCpuFeatureMask Pointer to next CPU feature Mask.\r
b3c71b47
ED
121\r
122 @retval return the dependence result.\r
123**/\r
124CPU_FEATURE_DEPENDENCE_TYPE\r
125DetectFeatureScope (\r
126 IN CPU_FEATURES_ENTRY *CpuFeature,\r
1475b83f
ED
127 IN BOOLEAN Before,\r
128 IN CHAR8 *NextCpuFeatureMask\r
b3c71b47
ED
129 )\r
130{\r
1475b83f
ED
131 //\r
132 // if need to check before type dependence but the feature after current feature is not\r
133 // exist, means this before type dependence not valid, just return NoneDepType.\r
134 // Just like Feature A has a dependence of feature B, but Feature B not installed, so\r
135 // Feature A maybe insert to the last entry of the list. In this case, for below code,\r
136 // Featrure A has depend of feature B, but it is the last entry of the list, so the\r
137 // NextCpuFeatureMask is NULL, so the dependence for feature A here is useless and code\r
138 // just return NoneDepType.\r
139 //\r
140 if (NextCpuFeatureMask == NULL) {\r
141 return NoneDepType;\r
142 }\r
143\r
b3c71b47 144 if (Before) {\r
1475b83f
ED
145 if ((CpuFeature->PackageBeforeFeatureBitMask != NULL) &&\r
146 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageBeforeFeatureBitMask)) {\r
b3c71b47
ED
147 return PackageDepType;\r
148 }\r
149\r
1475b83f
ED
150 if ((CpuFeature->CoreBeforeFeatureBitMask != NULL) &&\r
151 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreBeforeFeatureBitMask)) {\r
b3c71b47
ED
152 return CoreDepType;\r
153 }\r
154\r
1475b83f
ED
155 if ((CpuFeature->BeforeFeatureBitMask != NULL) &&\r
156 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r
b3c71b47
ED
157 return ThreadDepType;\r
158 }\r
159\r
160 return NoneDepType;\r
161 }\r
162\r
1475b83f
ED
163 if ((CpuFeature->PackageAfterFeatureBitMask != NULL) &&\r
164 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageAfterFeatureBitMask)) {\r
b3c71b47
ED
165 return PackageDepType;\r
166 }\r
167\r
1475b83f
ED
168 if ((CpuFeature->CoreAfterFeatureBitMask != NULL) &&\r
169 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreAfterFeatureBitMask)) {\r
b3c71b47
ED
170 return CoreDepType;\r
171 }\r
172\r
1475b83f
ED
173 if ((CpuFeature->AfterFeatureBitMask != NULL) &&\r
174 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->AfterFeatureBitMask)) {\r
b3c71b47
ED
175 return ThreadDepType;\r
176 }\r
177\r
178 return NoneDepType;\r
179}\r
180\r
b3c71b47
ED
181/**\r
182 Base on dependence relationship to asjust feature dependence.\r
183\r
1c15179c 184 ONLY when the feature before(or after) the find feature also has\r
b3c71b47
ED
185 dependence with the find feature. In this case, driver need to base\r
186 on dependce relationship to decide how to insert current feature and\r
187 adjust the feature dependence.\r
188\r
1c15179c
ED
189 @param[in, out] PreviousFeature CPU feature current before the find one.\r
190 @param[in, out] CurrentFeature Cpu feature need to adjust.\r
1475b83f 191 @param[in] FindFeature Cpu feature which current feature depends.\r
1c15179c 192 @param[in] Before Before or after dependence relationship.\r
b3c71b47
ED
193\r
194 @retval TRUE means the current feature dependence has been adjusted.\r
195\r
196 @retval FALSE means the previous feature dependence has been adjusted.\r
197 or previous feature has no dependence with the find one.\r
198\r
199**/\r
200BOOLEAN\r
201AdjustFeaturesDependence (\r
202 IN OUT CPU_FEATURES_ENTRY *PreviousFeature,\r
203 IN OUT CPU_FEATURES_ENTRY *CurrentFeature,\r
1475b83f 204 IN CPU_FEATURES_ENTRY *FindFeature,\r
b3c71b47
ED
205 IN BOOLEAN Before\r
206 )\r
207{\r
208 CPU_FEATURE_DEPENDENCE_TYPE PreDependType;\r
209 CPU_FEATURE_DEPENDENCE_TYPE CurrentDependType;\r
210\r
1475b83f
ED
211 PreDependType = DetectFeatureScope(PreviousFeature, Before, FindFeature->FeatureMask);\r
212 CurrentDependType = DetectFeatureScope(CurrentFeature, Before, FindFeature->FeatureMask);\r
b3c71b47
ED
213\r
214 //\r
215 // If previous feature has no dependence with the find featue.\r
216 // return FALSE.\r
217 //\r
218 if (PreDependType == NoneDepType) {\r
219 return FALSE;\r
220 }\r
221\r
222 //\r
1c15179c 223 // If both feature have dependence, keep the one which needs use more\r
b3c71b47
ED
224 // processors and clear the dependence for the other one.\r
225 //\r
226 if (PreDependType >= CurrentDependType) {\r
b3c71b47
ED
227 return TRUE;\r
228 } else {\r
b3c71b47
ED
229 return FALSE;\r
230 }\r
231}\r
232\r
233/**\r
234 Base on dependence relationship to asjust feature order.\r
235\r
1c15179c
ED
236 @param[in] FeatureList Pointer to CPU feature list\r
237 @param[in, out] FindEntry The entry this feature depend on.\r
238 @param[in, out] CurrentEntry The entry for this feature.\r
239 @param[in] Before Before or after dependence relationship.\r
b3c71b47
ED
240\r
241**/\r
242VOID\r
243AdjustEntry (\r
244 IN LIST_ENTRY *FeatureList,\r
245 IN OUT LIST_ENTRY *FindEntry,\r
246 IN OUT LIST_ENTRY *CurrentEntry,\r
247 IN BOOLEAN Before\r
248 )\r
249{\r
250 LIST_ENTRY *PreviousEntry;\r
251 CPU_FEATURES_ENTRY *PreviousFeature;\r
252 CPU_FEATURES_ENTRY *CurrentFeature;\r
1475b83f 253 CPU_FEATURES_ENTRY *FindFeature;\r
b3c71b47
ED
254\r
255 //\r
256 // For CPU feature which has core or package type dependence, later code need to insert\r
257 // AcquireSpinLock/ReleaseSpinLock logic to sequency the execute order.\r
258 // So if driver finds both feature A and B need to execute before feature C, driver will\r
259 // base on dependence type of feature A and B to update the logic here.\r
260 // For example, feature A has package type dependence and feature B has core type dependence,\r
261 // because package type dependence need to wait for more processors which has strong dependence\r
1c15179c
ED
262 // than core type dependence. So driver will adjust the feature order to B -> A -> C. and driver\r
263 // will remove the feature dependence in feature B.\r
b3c71b47
ED
264 // Driver just needs to make sure before feature C been executed, feature A has finished its task\r
265 // in all all thread. Feature A finished in all threads also means feature B have finshed in all\r
266 // threads.\r
267 //\r
268 if (Before) {\r
269 PreviousEntry = GetPreviousNode (FeatureList, FindEntry);\r
270 } else {\r\r
271 PreviousEntry = GetNextNode (FeatureList, FindEntry);\r
272 }\r
273\r
274 CurrentFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
275 RemoveEntryList (CurrentEntry);\r
276\r
277 if (IsNull (FeatureList, PreviousEntry)) {\r
278 //\r
279 // If not exist the previous or next entry, just insert the current entry.\r
280 //\r
281 if (Before) {\r
282 InsertTailList (FindEntry, CurrentEntry);\r
283 } else {\r
284 InsertHeadList (FindEntry, CurrentEntry);\r
285 }\r
286 } else {\r
287 //\r
288 // If exist the previous or next entry, need to check it before insert curent entry.\r
289 //\r
290 PreviousFeature = CPU_FEATURE_ENTRY_FROM_LINK (PreviousEntry);\r
1475b83f 291 FindFeature = CPU_FEATURE_ENTRY_FROM_LINK (FindEntry);\r
b3c71b47 292\r
1475b83f 293 if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, FindFeature, Before)) {\r
b3c71b47
ED
294 //\r
295 // Return TRUE means current feature dependence has been cleared and the previous\r
296 // feature dependence has been kept and used. So insert current feature before (or after)\r
297 // the previous feature.\r
298 //\r
299 if (Before) {\r
300 InsertTailList (PreviousEntry, CurrentEntry);\r
301 } else {\r
302 InsertHeadList (PreviousEntry, CurrentEntry);\r
303 }\r
304 } else {\r
305 if (Before) {\r
306 InsertTailList (FindEntry, CurrentEntry);\r
307 } else {\r
308 InsertHeadList (FindEntry, CurrentEntry);\r
309 }\r
310 }\r
311 }\r
312}\r\r
313\r
314/**\r
315 Checks and adjusts current CPU features per dependency relationship.\r
316\r
317 @param[in] FeatureList Pointer to CPU feature list\r
318 @param[in] CurrentEntry Pointer to current checked CPU feature\r
319 @param[in] FeatureMask The feature bit mask.\r
320\r
321 @retval return Swapped info.\r
322**/\r
323BOOLEAN\r
324InsertToBeforeEntry (\r
325 IN LIST_ENTRY *FeatureList,\r
326 IN LIST_ENTRY *CurrentEntry,\r
327 IN UINT8 *FeatureMask\r
328 )\r
329{\r
330 LIST_ENTRY *CheckEntry;\r
331 CPU_FEATURES_ENTRY *CheckFeature;\r
332 BOOLEAN Swapped;\r
333\r
334 Swapped = FALSE;\r
335\r
336 //\r
337 // Check all features dispatched before this entry\r
338 //\r
339 CheckEntry = GetFirstNode (FeatureList);\r
340 while (CheckEntry != CurrentEntry) {\r
341 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
342 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
343 AdjustEntry (FeatureList, CheckEntry, CurrentEntry, TRUE);\r
344 Swapped = TRUE;\r
345 break;\r
346 }\r
347 CheckEntry = CheckEntry->ForwardLink;\r
348 }\r
349\r
350 return Swapped;\r
351}\r
352\r
353/**\r
354 Checks and adjusts current CPU features per dependency relationship.\r
355\r
356 @param[in] FeatureList Pointer to CPU feature list\r
357 @param[in] CurrentEntry Pointer to current checked CPU feature\r
358 @param[in] FeatureMask The feature bit mask.\r
359\r
360 @retval return Swapped info.\r
361**/\r
362BOOLEAN\r
363InsertToAfterEntry (\r
364 IN LIST_ENTRY *FeatureList,\r
365 IN LIST_ENTRY *CurrentEntry,\r
366 IN UINT8 *FeatureMask\r
367 )\r
368{\r
369 LIST_ENTRY *CheckEntry;\r
370 CPU_FEATURES_ENTRY *CheckFeature;\r
371 BOOLEAN Swapped;\r
372\r
373 Swapped = FALSE;\r
374\r
375 //\r
376 // Check all features dispatched after this entry\r
377 //\r
378 CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
379 while (!IsNull (FeatureList, CheckEntry)) {\r
380 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
381 if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, FeatureMask)) {\r
382 AdjustEntry (FeatureList, CheckEntry, CurrentEntry, FALSE);\r
383 Swapped = TRUE;\r
384 break;\r
385 }\r
386 CheckEntry = CheckEntry->ForwardLink;\r
387 }\r
388\r
389 return Swapped;\r
390}\r
391\r
80c4b236
JF
392/**\r
393 Checks and adjusts CPU features order per dependency relationship.\r
394\r
395 @param[in] FeatureList Pointer to CPU feature list\r
396**/\r
397VOID\r
398CheckCpuFeaturesDependency (\r
399 IN LIST_ENTRY *FeatureList\r
400 )\r
401{\r
402 LIST_ENTRY *CurrentEntry;\r
403 CPU_FEATURES_ENTRY *CpuFeature;\r
404 LIST_ENTRY *CheckEntry;\r
405 CPU_FEATURES_ENTRY *CheckFeature;\r
406 BOOLEAN Swapped;\r
407 LIST_ENTRY *TempEntry;\r
b3c71b47 408 LIST_ENTRY *NextEntry;\r
80c4b236
JF
409\r
410 CurrentEntry = GetFirstNode (FeatureList);\r
411 while (!IsNull (FeatureList, CurrentEntry)) {\r
412 Swapped = FALSE;\r
413 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r
b3c71b47 414 NextEntry = CurrentEntry->ForwardLink;\r
80c4b236
JF
415 if (CpuFeature->BeforeAll) {\r
416 //\r
417 // Check all features dispatched before this entry\r
418 //\r
419 CheckEntry = GetFirstNode (FeatureList);\r
420 while (CheckEntry != CurrentEntry) {\r
421 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
422 if (!CheckFeature->BeforeAll) {\r
423 //\r
424 // If this feature has no BeforeAll flag and is dispatched before CpuFeature,\r
425 // insert currentEntry before Checked feature\r
426 //\r
427 RemoveEntryList (CurrentEntry);\r
428 InsertTailList (CheckEntry, CurrentEntry);\r
429 Swapped = TRUE;\r
430 break;\r
431 }\r
432 CheckEntry = CheckEntry->ForwardLink;\r
433 }\r
434 if (Swapped) {\r
b3c71b47 435 CurrentEntry = NextEntry;\r
80c4b236
JF
436 continue;\r
437 }\r
438 }\r
439\r
440 if (CpuFeature->AfterAll) {\r
441 //\r
442 // Check all features dispatched after this entry\r
443 //\r
444 CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r
445 while (!IsNull (FeatureList, CheckEntry)) {\r
446 CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r
447 if (!CheckFeature->AfterAll) {\r
448 //\r
449 // If this feature has no AfterAll flag and is dispatched after CpuFeature,\r
450 // insert currentEntry after Checked feature\r
451 //\r
452 TempEntry = GetNextNode (FeatureList, CurrentEntry);\r
453 RemoveEntryList (CurrentEntry);\r
454 InsertHeadList (CheckEntry, CurrentEntry);\r
455 CurrentEntry = TempEntry;\r
456 Swapped = TRUE;\r
457 break;\r
458 }\r
459 CheckEntry = CheckEntry->ForwardLink;\r
460 }\r
461 if (Swapped) {\r
b3c71b47 462 CurrentEntry = NextEntry;\r
80c4b236
JF
463 continue;\r
464 }\r
465 }\r
466\r
467 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
b3c71b47 468 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);\r
80c4b236
JF
469 if (Swapped) {\r
470 continue;\r
471 }\r
472 }\r
473\r
474 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
b3c71b47
ED
475 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);\r
476 if (Swapped) {\r
b3c71b47
ED
477 continue;\r
478 }\r
479 }\r
480\r
481 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
482 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->CoreBeforeFeatureBitMask);\r
483 if (Swapped) {\r
b3c71b47 484 continue;\r
80c4b236 485 }\r
b3c71b47
ED
486 }\r
487\r
488 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
489 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);\r
80c4b236
JF
490 if (Swapped) {\r
491 continue;\r
492 }\r
493 }\r
b3c71b47
ED
494\r
495 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
496 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);\r
497 if (Swapped) {\r
b3c71b47
ED
498 continue;\r
499 }\r
500 }\r
501\r
502 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
503 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->PackageAfterFeatureBitMask);\r
504 if (Swapped) {\r
b3c71b47
ED
505 continue;\r
506 }\r
507 }\r
508\r
80c4b236
JF
509 CurrentEntry = CurrentEntry->ForwardLink;\r
510 }\r
511}\r
512\r
513/**\r
514 Worker function to register CPU Feature.\r
515\r
516 @param[in] CpuFeature Pointer to CPU feature entry\r
517\r
518 @retval RETURN_SUCCESS The CPU feature was successfully registered.\r
519 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r
520 the CPU feature.\r
521 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
522 supported due to a circular dependency between\r
523 BEFORE and AFTER features.\r
524**/\r
525RETURN_STATUS\r
526RegisterCpuFeatureWorker (\r
527 IN CPU_FEATURES_ENTRY *CpuFeature\r
528 )\r
529{\r
530 EFI_STATUS Status;\r
531 CPU_FEATURES_DATA *CpuFeaturesData;\r
532 CPU_FEATURES_ENTRY *CpuFeatureEntry;\r
533 LIST_ENTRY *Entry;\r
3b341e26 534 UINTN BitMaskSize;\r
80c4b236
JF
535 BOOLEAN FeatureExist;\r
536\r
537 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
538 CpuFeaturesData = GetCpuFeaturesData ();\r
539 if (CpuFeaturesData->FeaturesCount == 0) {\r
540 InitializeListHead (&CpuFeaturesData->FeatureList);\r
b3c71b47
ED
541 InitializeSpinLock (&CpuFeaturesData->CpuFlags.MemoryMappedLock);\r
542 InitializeSpinLock (&CpuFeaturesData->CpuFlags.ConsoleLogLock);\r
3b341e26 543 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
80c4b236
JF
544 }\r
545 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r
546\r
547 FeatureExist = FALSE;\r
548 CpuFeatureEntry = NULL;\r
549 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
550 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
551 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
552 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {\r
553 //\r
554 // If this feature already registered\r
555 //\r
556 FeatureExist = TRUE;\r
557 break;\r
558 }\r
559 Entry = Entry->ForwardLink;\r
560 }\r
561\r
562 if (!FeatureExist) {\r
563 DEBUG ((DEBUG_INFO, "[NEW] "));\r
564 DumpCpuFeature (CpuFeature);\r
565 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);\r
566 CpuFeaturesData->FeaturesCount++;\r
567 } else {\r
568 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));\r
569 DumpCpuFeature (CpuFeature);\r
570 ASSERT (CpuFeatureEntry != NULL);\r
571 //\r
572 // Overwrite original parameters of CPU feature\r
573 //\r
574 if (CpuFeature->GetConfigDataFunc != NULL) {\r
575 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;\r
576 }\r
577 if (CpuFeature->SupportFunc != NULL) {\r
578 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;\r
579 }\r
580 if (CpuFeature->InitializeFunc != NULL) {\r
581 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;\r
582 }\r
583 if (CpuFeature->FeatureName != NULL) {\r
584 if (CpuFeatureEntry->FeatureName == NULL) {\r
585 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
586 ASSERT (CpuFeatureEntry->FeatureName != NULL);\r
587 }\r
588 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);\r
589 ASSERT_EFI_ERROR (Status);\r
590 FreePool (CpuFeature->FeatureName);\r
591 }\r
592 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
593 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {\r
594 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);\r
595 }\r
596 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;\r
597 }\r
598 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
599 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {\r
600 FreePool (CpuFeatureEntry->AfterFeatureBitMask);\r
601 }\r
602 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r
603 }\r
b3c71b47
ED
604 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
605 if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {\r
606 FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);\r
607 }\r
608 CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;\r
609 }\r
610 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
611 if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {\r
612 FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);\r
613 }\r
614 CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;\r
615 }\r
616 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
617 if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {\r
618 FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);\r
619 }\r
620 CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;\r
621 }\r
622 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
623 if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {\r
624 FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);\r
625 }\r
626 CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;\r
627 }\r
628\r
80c4b236
JF
629 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r
630 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;\r
631\r
632 FreePool (CpuFeature->FeatureMask);\r
633 FreePool (CpuFeature);\r
634 }\r
635 //\r
636 // Verify CPU features dependency can change CPU feature order\r
637 //\r
638 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);\r
639 return RETURN_SUCCESS;\r
640}\r
641\r
642/**\r
643 Sets CPU feature bit mask in CPU feature bit mask buffer.\r
644\r
645 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer\r
646 @param[in] Feature The bit number of the CPU feature\r
647 @param[in] BitMaskSize CPU feature bit mask buffer size\r
648**/\r
649VOID\r
650SetCpuFeaturesBitMask (\r
651 IN UINT8 **FeaturesBitMask,\r
652 IN UINT32 Feature,\r
653 IN UINTN BitMaskSize\r
654 )\r
655{\r
656 UINT8 *CpuFeaturesBitMask;\r
657\r
658 ASSERT (FeaturesBitMask != NULL);\r
659 CpuFeaturesBitMask = *FeaturesBitMask;\r
660 if (CpuFeaturesBitMask == NULL) {\r
661 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);\r
662 ASSERT (CpuFeaturesBitMask != NULL);\r
663 *FeaturesBitMask = CpuFeaturesBitMask;\r
664 }\r
665\r
666 CpuFeaturesBitMask += (Feature / 8);\r
667 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));\r
668}\r
669\r
670/**\r
671 Registers a CPU Feature.\r
672\r
673 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature\r
674 name.\r
675 @param[in] GetConfigDataFunc CPU feature get configuration data function. This\r
676 is an optional parameter that may be NULL. If NULL,\r
677 then the most recently registered function for the\r
678 CPU feature is used. If no functions are registered\r
679 for a CPU feature, then the CPU configuration data\r
680 for the registered feature is NULL.\r
681 @param[in] SupportFunc CPU feature support function. This is an optional\r
682 parameter that may be NULL. If NULL, then the most\r
683 recently registered function for the CPU feature is\r
684 used. If no functions are registered for a CPU\r
685 feature, then the CPU feature is assumed to be\r
686 supported by all CPUs.\r
687 @param[in] InitializeFunc CPU feature initialize function. This is an optional\r
688 parameter that may be NULL. If NULL, then the most\r
689 recently registered function for the CPU feature is\r
690 used. If no functions are registered for a CPU\r
691 feature, then the CPU feature initialization is\r
692 skipped.\r
693 @param[in] ... Variable argument list of UINT32 CPU feature value.\r
694 Values with no modifiers are the features provided\r
695 by the registered functions.\r
696 Values with CPU_FEATURE_BEFORE modifier are features\r
697 that must be initialized after the features provided\r
698 by the registered functions are used.\r
699 Values with CPU_FEATURE_AFTER modifier are features\r
700 that must be initialized before the features provided\r
701 by the registered functions are used.\r
702 The last argument in this variable argument list must\r
703 always be CPU_FEATURE_END.\r
704\r
705 @retval RETURN_SUCCESS The CPU feature was successfully registered.\r
706 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r
707 the CPU feature.\r
708 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
709 supported due to a circular dependency between\r
710 BEFORE and AFTER features.\r
b3c71b47
ED
711 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration\r
712 not updated by Platform driver yet.\r
80c4b236
JF
713\r
714 @note This service could be called by BSP only.\r
715**/\r
716RETURN_STATUS\r
717EFIAPI\r
718RegisterCpuFeature (\r
719 IN CHAR8 *FeatureName, OPTIONAL\r
720 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL\r
721 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL\r
722 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL\r
723 ...\r
724 )\r
725{\r
726 EFI_STATUS Status;\r
727 VA_LIST Marker;\r
728 UINT32 Feature;\r
729 UINTN BitMaskSize;\r
730 CPU_FEATURES_ENTRY *CpuFeature;\r
731 UINT8 *FeatureMask;\r
732 UINT8 *BeforeFeatureBitMask;\r
733 UINT8 *AfterFeatureBitMask;\r
b3c71b47
ED
734 UINT8 *CoreBeforeFeatureBitMask;\r
735 UINT8 *CoreAfterFeatureBitMask;\r
736 UINT8 *PackageBeforeFeatureBitMask;\r
737 UINT8 *PackageAfterFeatureBitMask;\r
80c4b236
JF
738 BOOLEAN BeforeAll;\r
739 BOOLEAN AfterAll;\r
740\r
b3c71b47
ED
741 FeatureMask = NULL;\r
742 BeforeFeatureBitMask = NULL;\r
743 AfterFeatureBitMask = NULL;\r
744 CoreBeforeFeatureBitMask = NULL;\r
745 CoreAfterFeatureBitMask = NULL;\r
746 PackageBeforeFeatureBitMask = NULL;\r
747 PackageAfterFeatureBitMask = NULL;\r
80c4b236
JF
748 BeforeAll = FALSE;\r
749 AfterAll = FALSE;\r
750\r
751 BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r
752\r
753 VA_START (Marker, InitializeFunc);\r
754 Feature = VA_ARG (Marker, UINT32);\r
755 while (Feature != CPU_FEATURE_END) {\r
756 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))\r
757 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r
758 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r
759 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r
b3c71b47
ED
760 ASSERT ((Feature & (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER))\r
761 != (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER));\r
762 ASSERT ((Feature & (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER))\r
763 != (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER));\r
80c4b236
JF
764 if (Feature < CPU_FEATURE_BEFORE) {\r
765 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r
766 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r
767 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);\r
768 ASSERT (FeatureMask == NULL);\r
769 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);\r
770 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {\r
771 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r
772 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r
773 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r
b3c71b47
ED
774 } else if ((Feature & CPU_FEATURE_CORE_BEFORE) != 0) {\r
775 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask, Feature & ~CPU_FEATURE_CORE_BEFORE, BitMaskSize);\r
776 } else if ((Feature & CPU_FEATURE_CORE_AFTER) != 0) {\r
777 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask, Feature & ~CPU_FEATURE_CORE_AFTER, BitMaskSize);\r
778 } else if ((Feature & CPU_FEATURE_PACKAGE_BEFORE) != 0) {\r
779 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_BEFORE, BitMaskSize);\r
780 } else if ((Feature & CPU_FEATURE_PACKAGE_AFTER) != 0) {\r
781 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_AFTER, BitMaskSize);\r
80c4b236
JF
782 }\r
783 Feature = VA_ARG (Marker, UINT32);\r
784 }\r
785 VA_END (Marker);\r
786\r
787 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r
788 ASSERT (CpuFeature != NULL);\r
b3c71b47
ED
789 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r
790 CpuFeature->FeatureMask = FeatureMask;\r
791 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
792 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r
793 CpuFeature->CoreBeforeFeatureBitMask = CoreBeforeFeatureBitMask;\r
794 CpuFeature->CoreAfterFeatureBitMask = CoreAfterFeatureBitMask;\r
795 CpuFeature->PackageBeforeFeatureBitMask = PackageBeforeFeatureBitMask;\r
796 CpuFeature->PackageAfterFeatureBitMask = PackageAfterFeatureBitMask;\r
797 CpuFeature->BeforeAll = BeforeAll;\r
798 CpuFeature->AfterAll = AfterAll;\r
799 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r
800 CpuFeature->SupportFunc = SupportFunc;\r
801 CpuFeature->InitializeFunc = InitializeFunc;\r
80c4b236
JF
802 if (FeatureName != NULL) {\r
803 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
804 ASSERT (CpuFeature->FeatureName != NULL);\r
805 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);\r
806 ASSERT_EFI_ERROR (Status);\r
807 }\r
808\r
809 Status = RegisterCpuFeatureWorker (CpuFeature);\r
810 ASSERT_EFI_ERROR (Status);\r
811\r
812 return RETURN_SUCCESS;\r
813}\r
814\r
a6daab1f 815/**\r
b3c71b47 816 Return ACPI_CPU_DATA data.\r
a6daab1f 817\r
b3c71b47 818 @return Pointer to ACPI_CPU_DATA data.\r
a6daab1f 819**/\r
a6daab1f 820ACPI_CPU_DATA *\r
b3c71b47 821GetAcpiCpuData (\r
a6daab1f
ED
822 VOID\r
823 )\r
824{\r
825 EFI_STATUS Status;\r
826 UINTN NumberOfCpus;\r
827 UINTN NumberOfEnabledProcessors;\r
828 ACPI_CPU_DATA *AcpiCpuData;\r
829 UINTN TableSize;\r
830 CPU_REGISTER_TABLE *RegisterTable;\r
831 UINTN Index;\r
832 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
833\r
b3c71b47
ED
834 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
835 if (AcpiCpuData != NULL) {\r
836 return AcpiCpuData;\r
837 }\r
838\r
a6daab1f
ED
839 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));\r
840 ASSERT (AcpiCpuData != NULL);\r
841\r
b3c71b47
ED
842 //\r
843 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
844 //\r
845 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
846 ASSERT_EFI_ERROR (Status);\r
847\r
a6daab1f
ED
848 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
849 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
850\r
851 //\r
852 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs\r
e23d9c3e 853 //\r
a6daab1f
ED
854 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);\r
855 RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));\r
856 ASSERT (RegisterTable != NULL);\r
857\r
858 for (Index = 0; Index < NumberOfCpus; Index++) {\r
859 Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);\r
860 ASSERT_EFI_ERROR (Status);\r
861\r
862 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
863 RegisterTable[Index].TableLength = 0;\r
864 RegisterTable[Index].AllocatedSize = 0;\r
865 RegisterTable[Index].RegisterTableEntry = 0;\r
866\r
867 RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
868 RegisterTable[NumberOfCpus + Index].TableLength = 0;\r
869 RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;\r
870 RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;\r
871 }\r
872 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;\r
873 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);\r
874\r
875 return AcpiCpuData;\r
876}\r
877\r
878/**\r
879 Enlarges CPU register table for each processor.\r
880\r
881 @param[in, out] RegisterTable Pointer processor's CPU register table\r
882**/\r
883STATIC\r
884VOID\r
885EnlargeRegisterTable (\r
886 IN OUT CPU_REGISTER_TABLE *RegisterTable\r
887 )\r
888{\r
889 EFI_PHYSICAL_ADDRESS Address;\r
890 UINTN UsedPages;\r
891\r
892 UsedPages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;\r
893 Address = (UINTN)AllocatePages (UsedPages + 1);\r
894 ASSERT (Address != 0);\r
895\r
896 //\r
897 // If there are records existing in the register table, then copy its contents\r
898 // to new region and free the old one.\r
899 //\r
900 if (RegisterTable->AllocatedSize > 0) {\r
901 CopyMem (\r
902 (VOID *) (UINTN) Address,\r
903 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,\r
904 RegisterTable->AllocatedSize\r
905 );\r
906\r
907 FreePages ((VOID *)(UINTN)RegisterTable->RegisterTableEntry, UsedPages);\r
908 }\r
909\r
910 //\r
911 // Adjust the allocated size and register table base address.\r
912 //\r
913 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;\r
914 RegisterTable->RegisterTableEntry = Address;\r
915}\r
916\r
80c4b236
JF
917/**\r
918 Add an entry in specified register table.\r
919\r
920 This function adds an entry in specified register table, with given register type,\r
921 register index, bit section and value.\r
922\r
923 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table\r
924 If FALSE, entry will be added into register table\r
925 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
926 @param[in] RegisterType Type of the register to program\r
927 @param[in] Index Index of the register to program\r
928 @param[in] ValidBitStart Start of the bit section\r
929 @param[in] ValidBitLength Length of the bit section\r
930 @param[in] Value Value to write\r
931**/\r
932VOID\r
933CpuRegisterTableWriteWorker (\r
934 IN BOOLEAN PreSmmFlag,\r
935 IN UINTN ProcessorNumber,\r
936 IN REGISTER_TYPE RegisterType,\r
937 IN UINT64 Index,\r
938 IN UINT8 ValidBitStart,\r
939 IN UINT8 ValidBitLength,\r
940 IN UINT64 Value\r
941 )\r
942{\r
80c4b236
JF
943 CPU_FEATURES_DATA *CpuFeaturesData;\r
944 ACPI_CPU_DATA *AcpiCpuData;\r
945 CPU_REGISTER_TABLE *RegisterTable;\r
946 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
947\r
948 CpuFeaturesData = GetCpuFeaturesData ();\r
949 if (CpuFeaturesData->RegisterTable == NULL) {\r
b3c71b47
ED
950 AcpiCpuData = GetAcpiCpuData ();\r
951 ASSERT ((AcpiCpuData != NULL) && (AcpiCpuData->RegisterTable != 0));\r
80c4b236
JF
952 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r
953 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r
954 }\r
955\r
956 if (PreSmmFlag) {\r
957 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];\r
958 } else {\r
959 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
960 }\r
961\r
962 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {\r
963 EnlargeRegisterTable (RegisterTable);\r
964 }\r
965\r
966 //\r
967 // Append entry in the register table.\r
968 //\r
969 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
970 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;\r
971 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;\r
972 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);\r
973 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;\r
974 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;\r
975 RegisterTableEntry[RegisterTable->TableLength].Value = Value;\r
976\r
977 RegisterTable->TableLength++;\r
978}\r
979\r
980/**\r
981 Adds an entry in specified register table.\r
982\r
983 This function adds an entry in specified register table, with given register type,\r
984 register index, bit section and value.\r
985\r
986 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
987 @param[in] RegisterType Type of the register to program\r
988 @param[in] Index Index of the register to program\r
989 @param[in] ValueMask Mask of bits in register to write\r
990 @param[in] Value Value to write\r
991\r
992 @note This service could be called by BSP only.\r
993**/\r
994VOID\r
995EFIAPI\r
996CpuRegisterTableWrite (\r
997 IN UINTN ProcessorNumber,\r
998 IN REGISTER_TYPE RegisterType,\r
999 IN UINT64 Index,\r
1000 IN UINT64 ValueMask,\r
1001 IN UINT64 Value\r
1002 )\r
1003{\r
1004 UINT8 Start;\r
1005 UINT8 End;\r
1006 UINT8 Length;\r
1007\r
1008 Start = (UINT8)LowBitSet64 (ValueMask);\r
1009 End = (UINT8)HighBitSet64 (ValueMask);\r
1010 Length = End - Start + 1;\r
1011 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
1012}\r
1013\r
1014/**\r
1015 Adds an entry in specified Pre-SMM register table.\r
1016\r
1017 This function adds an entry in specified register table, with given register type,\r
1018 register index, bit section and value.\r
1019\r
1020 @param[in] ProcessorNumber The index of the CPU to add a register table entry.\r
1021 @param[in] RegisterType Type of the register to program\r
1022 @param[in] Index Index of the register to program\r
1023 @param[in] ValueMask Mask of bits in register to write\r
1024 @param[in] Value Value to write\r
1025\r
1026 @note This service could be called by BSP only.\r
1027**/\r
1028VOID\r
1029EFIAPI\r
1030PreSmmCpuRegisterTableWrite (\r
1031 IN UINTN ProcessorNumber,\r
1032 IN REGISTER_TYPE RegisterType,\r
1033 IN UINT64 Index,\r
1034 IN UINT64 ValueMask,\r
1035 IN UINT64 Value\r
1036 )\r
1037{\r
1038 UINT8 Start;\r
1039 UINT8 End;\r
1040 UINT8 Length;\r
1041\r
1042 Start = (UINT8)LowBitSet64 (ValueMask);\r
1043 End = (UINT8)HighBitSet64 (ValueMask);\r
1044 Length = End - Start + 1;\r
1045 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
1046}\r
1047\r
1048/**\r
1049 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.\r
1050\r
1051 @param[in] CpuBitMask CPU feature bit mask buffer\r
1052 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer\r
1053 @param[in] Feature The bit number of the CPU feature\r
1054\r
1055 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r
1056 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r
1057\r
1058**/\r
1059BOOLEAN\r
1060IsCpuFeatureSetInCpuPcd (\r
1061 IN UINT8 *CpuBitMask,\r
1062 IN UINTN CpuBitMaskSize,\r
1063 IN UINT32 Feature\r
1064 )\r
1065{\r
1066 if ((Feature >> 3) >= CpuBitMaskSize) {\r
1067 return FALSE;\r
1068 }\r
1069 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);\r
1070}\r
1071\r
1072/**\r
1073 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.\r
1074 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data\r
1075 associated with that feature should be optimized away if compiler\r
1076 optimizations are enabled.\r
1077\r
1078 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1079 PcdCpuFeaturesSupport\r
1080\r
1081 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r
1082 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r
1083\r
1084 @note This service could be called by BSP only.\r
1085**/\r
1086BOOLEAN\r
1087EFIAPI\r
1088IsCpuFeatureSupported (\r
1089 IN UINT32 Feature\r
1090 )\r
1091{\r
1092 return IsCpuFeatureSetInCpuPcd (\r
1093 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),\r
1094 PcdGetSize (PcdCpuFeaturesSupport),\r
1095 Feature\r
1096 );\r
1097}\r
1098\r
1099/**\r
1100 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.\r
1101\r
1102 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1103 PcdCpuFeaturesSetting\r
1104\r
1105 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.\r
1106 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.\r
1107\r
1108 @note This service could be called by BSP only.\r
1109**/\r
1110BOOLEAN\r
1111EFIAPI\r
1112IsCpuFeatureInSetting (\r
1113 IN UINT32 Feature\r
1114 )\r
1115{\r
1116 return IsCpuFeatureSetInCpuPcd (\r
1117 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),\r
1118 PcdGetSize (PcdCpuFeaturesSetting),\r
1119 Feature\r
1120 );\r
1121}\r
1122\r
1123/**\r
1124 Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.\r
1125\r
1126 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1127 PcdCpuFeaturesCapability\r
1128\r
1129 @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.\r
1130 @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.\r
1131\r
1132 @note This service could be called by BSP only.\r
1133**/\r
1134BOOLEAN\r
1135EFIAPI\r
1136IsCpuFeatureCapability (\r
1137 IN UINT32 Feature\r
1138 )\r
1139{\r
1140 return IsCpuFeatureSetInCpuPcd (\r
1141 (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),\r
1142 PcdGetSize (PcdCpuFeaturesCapability),\r
1143 Feature\r
1144 );\r
1145\r
1146}\r
1147\r
1148/**\r
1149 Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.\r
1150\r
1151 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1152 PcdCpuFeaturesUserConfiguration\r
1153\r
1154 @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.\r
1155 @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.\r
1156\r
1157 @note This service could be called by BSP only.\r
1158**/\r
1159BOOLEAN\r
1160EFIAPI\r
1161IsCpuFeatureUserConfiguration (\r
1162 IN UINT32 Feature\r
1163 )\r
1164{\r
1165 return IsCpuFeatureSetInCpuPcd (\r
1166 (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),\r
1167 PcdGetSize (PcdCpuFeaturesUserConfiguration),\r
1168 Feature\r
1169 );\r
1170\r
1171}\r
1172\r
1173/**\r
1174 Switches to assigned BSP after CPU features initialization.\r
1175\r
1176 @param[in] ProcessorNumber The index of the CPU executing this function.\r
1177\r
1178 @note This service could be called by BSP only.\r
1179**/\r
1180VOID\r
1181EFIAPI\r
1182SwitchBspAfterFeaturesInitialize (\r
1183 IN UINTN ProcessorNumber\r
1184 )\r
1185{\r
1186 CPU_FEATURES_DATA *CpuFeaturesData;\r
1187\r
1188 CpuFeaturesData = GetCpuFeaturesData ();\r
1189 CpuFeaturesData->BspNumber = ProcessorNumber;\r
1190}\r
1191\r