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