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