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