]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
UefiCpuPkg: Replace BSD License with BSD+Patent License
[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
3b341e26 661 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
80c4b236
JF
662 }\r
663 ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r
664\r
665 FeatureExist = FALSE;\r
666 CpuFeatureEntry = NULL;\r
667 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
668 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
669 CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
670 if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {\r
671 //\r
672 // If this feature already registered\r
673 //\r
674 FeatureExist = TRUE;\r
675 break;\r
676 }\r
677 Entry = Entry->ForwardLink;\r
678 }\r
679\r
680 if (!FeatureExist) {\r
681 DEBUG ((DEBUG_INFO, "[NEW] "));\r
682 DumpCpuFeature (CpuFeature);\r
683 InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);\r
684 CpuFeaturesData->FeaturesCount++;\r
685 } else {\r
686 DEBUG ((DEBUG_INFO, "[OVERRIDE] "));\r
687 DumpCpuFeature (CpuFeature);\r
688 ASSERT (CpuFeatureEntry != NULL);\r
689 //\r
690 // Overwrite original parameters of CPU feature\r
691 //\r
692 if (CpuFeature->GetConfigDataFunc != NULL) {\r
693 CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;\r
694 }\r
695 if (CpuFeature->SupportFunc != NULL) {\r
696 CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;\r
697 }\r
698 if (CpuFeature->InitializeFunc != NULL) {\r
699 CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;\r
700 }\r
701 if (CpuFeature->FeatureName != NULL) {\r
702 if (CpuFeatureEntry->FeatureName == NULL) {\r
703 CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
704 ASSERT (CpuFeatureEntry->FeatureName != NULL);\r
705 }\r
706 Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);\r
707 ASSERT_EFI_ERROR (Status);\r
708 FreePool (CpuFeature->FeatureName);\r
709 }\r
710 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
711 if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {\r
712 FreePool (CpuFeatureEntry->BeforeFeatureBitMask);\r
713 }\r
714 CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;\r
715 }\r
716 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
717 if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {\r
718 FreePool (CpuFeatureEntry->AfterFeatureBitMask);\r
719 }\r
720 CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r
721 }\r
b3c71b47
ED
722 if (CpuFeature->CoreBeforeFeatureBitMask != NULL) {\r
723 if (CpuFeatureEntry->CoreBeforeFeatureBitMask != NULL) {\r
724 FreePool (CpuFeatureEntry->CoreBeforeFeatureBitMask);\r
725 }\r
726 CpuFeatureEntry->CoreBeforeFeatureBitMask = CpuFeature->CoreBeforeFeatureBitMask;\r
727 }\r
728 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
729 if (CpuFeatureEntry->CoreAfterFeatureBitMask != NULL) {\r
730 FreePool (CpuFeatureEntry->CoreAfterFeatureBitMask);\r
731 }\r
732 CpuFeatureEntry->CoreAfterFeatureBitMask = CpuFeature->CoreAfterFeatureBitMask;\r
733 }\r
734 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
735 if (CpuFeatureEntry->PackageBeforeFeatureBitMask != NULL) {\r
736 FreePool (CpuFeatureEntry->PackageBeforeFeatureBitMask);\r
737 }\r
738 CpuFeatureEntry->PackageBeforeFeatureBitMask = CpuFeature->PackageBeforeFeatureBitMask;\r
739 }\r
740 if (CpuFeature->PackageAfterFeatureBitMask != NULL) {\r
741 if (CpuFeatureEntry->PackageAfterFeatureBitMask != NULL) {\r
742 FreePool (CpuFeatureEntry->PackageAfterFeatureBitMask);\r
743 }\r
744 CpuFeatureEntry->PackageAfterFeatureBitMask = CpuFeature->PackageAfterFeatureBitMask;\r
745 }\r
746\r
80c4b236
JF
747 CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r
748 CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;\r
749\r
750 FreePool (CpuFeature->FeatureMask);\r
751 FreePool (CpuFeature);\r
752 }\r
753 //\r
754 // Verify CPU features dependency can change CPU feature order\r
755 //\r
756 CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);\r
757 return RETURN_SUCCESS;\r
758}\r
759\r
760/**\r
761 Sets CPU feature bit mask in CPU feature bit mask buffer.\r
762\r
763 @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer\r
764 @param[in] Feature The bit number of the CPU feature\r
765 @param[in] BitMaskSize CPU feature bit mask buffer size\r
766**/\r
767VOID\r
768SetCpuFeaturesBitMask (\r
769 IN UINT8 **FeaturesBitMask,\r
770 IN UINT32 Feature,\r
771 IN UINTN BitMaskSize\r
772 )\r
773{\r
774 UINT8 *CpuFeaturesBitMask;\r
775\r
776 ASSERT (FeaturesBitMask != NULL);\r
777 CpuFeaturesBitMask = *FeaturesBitMask;\r
778 if (CpuFeaturesBitMask == NULL) {\r
779 CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);\r
780 ASSERT (CpuFeaturesBitMask != NULL);\r
781 *FeaturesBitMask = CpuFeaturesBitMask;\r
782 }\r
783\r
784 CpuFeaturesBitMask += (Feature / 8);\r
785 *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));\r
786}\r
787\r
788/**\r
789 Registers a CPU Feature.\r
790\r
791 @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature\r
792 name.\r
793 @param[in] GetConfigDataFunc CPU feature get configuration data function. This\r
794 is an optional parameter that may be NULL. If NULL,\r
795 then the most recently registered function for the\r
796 CPU feature is used. If no functions are registered\r
797 for a CPU feature, then the CPU configuration data\r
798 for the registered feature is NULL.\r
799 @param[in] SupportFunc CPU feature support function. This is an optional\r
800 parameter that may be NULL. If NULL, then the most\r
801 recently registered function for the CPU feature is\r
802 used. If no functions are registered for a CPU\r
803 feature, then the CPU feature is assumed to be\r
804 supported by all CPUs.\r
805 @param[in] InitializeFunc CPU feature initialize function. This is an optional\r
806 parameter that may be NULL. If NULL, then the most\r
807 recently registered function for the CPU feature is\r
808 used. If no functions are registered for a CPU\r
809 feature, then the CPU feature initialization is\r
810 skipped.\r
811 @param[in] ... Variable argument list of UINT32 CPU feature value.\r
812 Values with no modifiers are the features provided\r
813 by the registered functions.\r
814 Values with CPU_FEATURE_BEFORE modifier are features\r
815 that must be initialized after the features provided\r
816 by the registered functions are used.\r
817 Values with CPU_FEATURE_AFTER modifier are features\r
818 that must be initialized before the features provided\r
819 by the registered functions are used.\r
820 The last argument in this variable argument list must\r
821 always be CPU_FEATURE_END.\r
822\r
823 @retval RETURN_SUCCESS The CPU feature was successfully registered.\r
824 @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r
825 the CPU feature.\r
826 @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r
827 supported due to a circular dependency between\r
828 BEFORE and AFTER features.\r
b3c71b47
ED
829 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration\r
830 not updated by Platform driver yet.\r
80c4b236
JF
831\r
832 @note This service could be called by BSP only.\r
833**/\r
834RETURN_STATUS\r
835EFIAPI\r
836RegisterCpuFeature (\r
837 IN CHAR8 *FeatureName, OPTIONAL\r
838 IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL\r
839 IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL\r
840 IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL\r
841 ...\r
842 )\r
843{\r
844 EFI_STATUS Status;\r
845 VA_LIST Marker;\r
846 UINT32 Feature;\r
847 UINTN BitMaskSize;\r
848 CPU_FEATURES_ENTRY *CpuFeature;\r
849 UINT8 *FeatureMask;\r
850 UINT8 *BeforeFeatureBitMask;\r
851 UINT8 *AfterFeatureBitMask;\r
b3c71b47
ED
852 UINT8 *CoreBeforeFeatureBitMask;\r
853 UINT8 *CoreAfterFeatureBitMask;\r
854 UINT8 *PackageBeforeFeatureBitMask;\r
855 UINT8 *PackageAfterFeatureBitMask;\r
80c4b236
JF
856 BOOLEAN BeforeAll;\r
857 BOOLEAN AfterAll;\r
858\r
b3c71b47
ED
859 FeatureMask = NULL;\r
860 BeforeFeatureBitMask = NULL;\r
861 AfterFeatureBitMask = NULL;\r
862 CoreBeforeFeatureBitMask = NULL;\r
863 CoreAfterFeatureBitMask = NULL;\r
864 PackageBeforeFeatureBitMask = NULL;\r
865 PackageAfterFeatureBitMask = NULL;\r
80c4b236
JF
866 BeforeAll = FALSE;\r
867 AfterAll = FALSE;\r
868\r
001c2c80 869 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
80c4b236
JF
870\r
871 VA_START (Marker, InitializeFunc);\r
872 Feature = VA_ARG (Marker, UINT32);\r
873 while (Feature != CPU_FEATURE_END) {\r
874 ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))\r
875 != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r
876 ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r
877 != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r
b3c71b47
ED
878 ASSERT ((Feature & (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER))\r
879 != (CPU_FEATURE_CORE_BEFORE | CPU_FEATURE_CORE_AFTER));\r
880 ASSERT ((Feature & (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER))\r
881 != (CPU_FEATURE_PACKAGE_BEFORE | CPU_FEATURE_PACKAGE_AFTER));\r
80c4b236
JF
882 if (Feature < CPU_FEATURE_BEFORE) {\r
883 BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r
884 AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r
885 Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);\r
886 ASSERT (FeatureMask == NULL);\r
887 SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);\r
888 } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {\r
889 SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r
890 } else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r
891 SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r
b3c71b47
ED
892 } else if ((Feature & CPU_FEATURE_CORE_BEFORE) != 0) {\r
893 SetCpuFeaturesBitMask (&CoreBeforeFeatureBitMask, Feature & ~CPU_FEATURE_CORE_BEFORE, BitMaskSize);\r
894 } else if ((Feature & CPU_FEATURE_CORE_AFTER) != 0) {\r
895 SetCpuFeaturesBitMask (&CoreAfterFeatureBitMask, Feature & ~CPU_FEATURE_CORE_AFTER, BitMaskSize);\r
896 } else if ((Feature & CPU_FEATURE_PACKAGE_BEFORE) != 0) {\r
897 SetCpuFeaturesBitMask (&PackageBeforeFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_BEFORE, BitMaskSize);\r
898 } else if ((Feature & CPU_FEATURE_PACKAGE_AFTER) != 0) {\r
899 SetCpuFeaturesBitMask (&PackageAfterFeatureBitMask, Feature & ~CPU_FEATURE_PACKAGE_AFTER, BitMaskSize);\r
80c4b236
JF
900 }\r
901 Feature = VA_ARG (Marker, UINT32);\r
902 }\r
903 VA_END (Marker);\r
904\r
905 CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r
906 ASSERT (CpuFeature != NULL);\r
b3c71b47
ED
907 CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r
908 CpuFeature->FeatureMask = FeatureMask;\r
909 CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r
910 CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r
911 CpuFeature->CoreBeforeFeatureBitMask = CoreBeforeFeatureBitMask;\r
912 CpuFeature->CoreAfterFeatureBitMask = CoreAfterFeatureBitMask;\r
913 CpuFeature->PackageBeforeFeatureBitMask = PackageBeforeFeatureBitMask;\r
914 CpuFeature->PackageAfterFeatureBitMask = PackageAfterFeatureBitMask;\r
915 CpuFeature->BeforeAll = BeforeAll;\r
916 CpuFeature->AfterAll = AfterAll;\r
917 CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r
918 CpuFeature->SupportFunc = SupportFunc;\r
919 CpuFeature->InitializeFunc = InitializeFunc;\r
80c4b236
JF
920 if (FeatureName != NULL) {\r
921 CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r
922 ASSERT (CpuFeature->FeatureName != NULL);\r
923 Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);\r
924 ASSERT_EFI_ERROR (Status);\r
925 }\r
926\r
927 Status = RegisterCpuFeatureWorker (CpuFeature);\r
928 ASSERT_EFI_ERROR (Status);\r
929\r
930 return RETURN_SUCCESS;\r
931}\r
932\r
a6daab1f 933/**\r
b3c71b47 934 Return ACPI_CPU_DATA data.\r
a6daab1f 935\r
b3c71b47 936 @return Pointer to ACPI_CPU_DATA data.\r
a6daab1f 937**/\r
a6daab1f 938ACPI_CPU_DATA *\r
b3c71b47 939GetAcpiCpuData (\r
a6daab1f
ED
940 VOID\r
941 )\r
942{\r
943 EFI_STATUS Status;\r
944 UINTN NumberOfCpus;\r
945 UINTN NumberOfEnabledProcessors;\r
946 ACPI_CPU_DATA *AcpiCpuData;\r
947 UINTN TableSize;\r
948 CPU_REGISTER_TABLE *RegisterTable;\r
949 UINTN Index;\r
950 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
951\r
b3c71b47
ED
952 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
953 if (AcpiCpuData != NULL) {\r
954 return AcpiCpuData;\r
955 }\r
956\r
a6daab1f
ED
957 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));\r
958 ASSERT (AcpiCpuData != NULL);\r
959\r
b3c71b47
ED
960 //\r
961 // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r
962 //\r
963 Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r
964 ASSERT_EFI_ERROR (Status);\r
965\r
a6daab1f
ED
966 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
967 AcpiCpuData->NumberOfCpus = (UINT32)NumberOfCpus;\r
968\r
969 //\r
970 // Allocate buffer for empty RegisterTable and PreSmmInitRegisterTable for all CPUs\r
e23d9c3e 971 //\r
a6daab1f
ED
972 TableSize = 2 * NumberOfCpus * sizeof (CPU_REGISTER_TABLE);\r
973 RegisterTable = AllocatePages (EFI_SIZE_TO_PAGES (TableSize));\r
974 ASSERT (RegisterTable != NULL);\r
975\r
976 for (Index = 0; Index < NumberOfCpus; Index++) {\r
977 Status = GetProcessorInformation (Index, &ProcessorInfoBuffer);\r
978 ASSERT_EFI_ERROR (Status);\r
979\r
980 RegisterTable[Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
981 RegisterTable[Index].TableLength = 0;\r
982 RegisterTable[Index].AllocatedSize = 0;\r
983 RegisterTable[Index].RegisterTableEntry = 0;\r
984\r
985 RegisterTable[NumberOfCpus + Index].InitialApicId = (UINT32)ProcessorInfoBuffer.ProcessorId;\r
986 RegisterTable[NumberOfCpus + Index].TableLength = 0;\r
987 RegisterTable[NumberOfCpus + Index].AllocatedSize = 0;\r
988 RegisterTable[NumberOfCpus + Index].RegisterTableEntry = 0;\r
989 }\r
990 AcpiCpuData->RegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)RegisterTable;\r
991 AcpiCpuData->PreSmmInitRegisterTable = (EFI_PHYSICAL_ADDRESS)(UINTN)(RegisterTable + NumberOfCpus);\r
992\r
993 return AcpiCpuData;\r
994}\r
995\r
996/**\r
997 Enlarges CPU register table for each processor.\r
998\r
999 @param[in, out] RegisterTable Pointer processor's CPU register table\r
1000**/\r
1001STATIC\r
1002VOID\r
1003EnlargeRegisterTable (\r
1004 IN OUT CPU_REGISTER_TABLE *RegisterTable\r
1005 )\r
1006{\r
1007 EFI_PHYSICAL_ADDRESS Address;\r
1008 UINTN UsedPages;\r
1009\r
1010 UsedPages = RegisterTable->AllocatedSize / EFI_PAGE_SIZE;\r
1011 Address = (UINTN)AllocatePages (UsedPages + 1);\r
1012 ASSERT (Address != 0);\r
1013\r
1014 //\r
1015 // If there are records existing in the register table, then copy its contents\r
1016 // to new region and free the old one.\r
1017 //\r
1018 if (RegisterTable->AllocatedSize > 0) {\r
1019 CopyMem (\r
1020 (VOID *) (UINTN) Address,\r
1021 (VOID *) (UINTN) RegisterTable->RegisterTableEntry,\r
1022 RegisterTable->AllocatedSize\r
1023 );\r
1024\r
1025 FreePages ((VOID *)(UINTN)RegisterTable->RegisterTableEntry, UsedPages);\r
1026 }\r
1027\r
1028 //\r
1029 // Adjust the allocated size and register table base address.\r
1030 //\r
1031 RegisterTable->AllocatedSize += EFI_PAGE_SIZE;\r
1032 RegisterTable->RegisterTableEntry = Address;\r
1033}\r
1034\r
80c4b236
JF
1035/**\r
1036 Add an entry in specified register table.\r
1037\r
1038 This function adds an entry in specified register table, with given register type,\r
1039 register index, bit section and value.\r
1040\r
1041 @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table\r
1042 If FALSE, entry will be added into register table\r
1043 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
1044 @param[in] RegisterType Type of the register to program\r
1045 @param[in] Index Index of the register to program\r
1046 @param[in] ValidBitStart Start of the bit section\r
1047 @param[in] ValidBitLength Length of the bit section\r
1048 @param[in] Value Value to write\r
1049**/\r
1050VOID\r
1051CpuRegisterTableWriteWorker (\r
1052 IN BOOLEAN PreSmmFlag,\r
1053 IN UINTN ProcessorNumber,\r
1054 IN REGISTER_TYPE RegisterType,\r
1055 IN UINT64 Index,\r
1056 IN UINT8 ValidBitStart,\r
1057 IN UINT8 ValidBitLength,\r
1058 IN UINT64 Value\r
1059 )\r
1060{\r
80c4b236
JF
1061 CPU_FEATURES_DATA *CpuFeaturesData;\r
1062 ACPI_CPU_DATA *AcpiCpuData;\r
1063 CPU_REGISTER_TABLE *RegisterTable;\r
1064 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
1065\r
1066 CpuFeaturesData = GetCpuFeaturesData ();\r
1067 if (CpuFeaturesData->RegisterTable == NULL) {\r
b3c71b47
ED
1068 AcpiCpuData = GetAcpiCpuData ();\r
1069 ASSERT ((AcpiCpuData != NULL) && (AcpiCpuData->RegisterTable != 0));\r
80c4b236
JF
1070 CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r
1071 CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r
1072 }\r
1073\r
1074 if (PreSmmFlag) {\r
1075 RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];\r
1076 } else {\r
1077 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
1078 }\r
1079\r
1080 if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {\r
1081 EnlargeRegisterTable (RegisterTable);\r
1082 }\r
1083\r
1084 //\r
1085 // Append entry in the register table.\r
1086 //\r
1087 RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r
1088 RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;\r
1089 RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;\r
1090 RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);\r
1091 RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;\r
1092 RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;\r
1093 RegisterTableEntry[RegisterTable->TableLength].Value = Value;\r
1094\r
1095 RegisterTable->TableLength++;\r
1096}\r
1097\r
1098/**\r
1099 Adds an entry in specified register table.\r
1100\r
1101 This function adds an entry in specified register table, with given register type,\r
1102 register index, bit section and value.\r
1103\r
1104 @param[in] ProcessorNumber The index of the CPU to add a register table entry\r
1105 @param[in] RegisterType Type of the register to program\r
1106 @param[in] Index Index of the register to program\r
1107 @param[in] ValueMask Mask of bits in register to write\r
1108 @param[in] Value Value to write\r
1109\r
1110 @note This service could be called by BSP only.\r
1111**/\r
1112VOID\r
1113EFIAPI\r
1114CpuRegisterTableWrite (\r
1115 IN UINTN ProcessorNumber,\r
1116 IN REGISTER_TYPE RegisterType,\r
1117 IN UINT64 Index,\r
1118 IN UINT64 ValueMask,\r
1119 IN UINT64 Value\r
1120 )\r
1121{\r
1122 UINT8 Start;\r
1123 UINT8 End;\r
1124 UINT8 Length;\r
1125\r
1126 Start = (UINT8)LowBitSet64 (ValueMask);\r
1127 End = (UINT8)HighBitSet64 (ValueMask);\r
1128 Length = End - Start + 1;\r
1129 CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
1130}\r
1131\r
1132/**\r
1133 Adds an entry in specified Pre-SMM register table.\r
1134\r
1135 This function adds an entry in specified register table, with given register type,\r
1136 register index, bit section and value.\r
1137\r
1138 @param[in] ProcessorNumber The index of the CPU to add a register table entry.\r
1139 @param[in] RegisterType Type of the register to program\r
1140 @param[in] Index Index of the register to program\r
1141 @param[in] ValueMask Mask of bits in register to write\r
1142 @param[in] Value Value to write\r
1143\r
1144 @note This service could be called by BSP only.\r
1145**/\r
1146VOID\r
1147EFIAPI\r
1148PreSmmCpuRegisterTableWrite (\r
1149 IN UINTN ProcessorNumber,\r
1150 IN REGISTER_TYPE RegisterType,\r
1151 IN UINT64 Index,\r
1152 IN UINT64 ValueMask,\r
1153 IN UINT64 Value\r
1154 )\r
1155{\r
1156 UINT8 Start;\r
1157 UINT8 End;\r
1158 UINT8 Length;\r
1159\r
1160 Start = (UINT8)LowBitSet64 (ValueMask);\r
1161 End = (UINT8)HighBitSet64 (ValueMask);\r
1162 Length = End - Start + 1;\r
1163 CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r
1164}\r
1165\r
1166/**\r
1167 Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.\r
1168\r
1169 @param[in] CpuBitMask CPU feature bit mask buffer\r
1170 @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer\r
1171 @param[in] Feature The bit number of the CPU feature\r
1172\r
f664032e
ED
1173 @retval TRUE The CPU feature is set in CpuBitMask.\r
1174 @retval FALSE The CPU feature is not set in CpuBitMask.\r
80c4b236
JF
1175\r
1176**/\r
1177BOOLEAN\r
1178IsCpuFeatureSetInCpuPcd (\r
1179 IN UINT8 *CpuBitMask,\r
1180 IN UINTN CpuBitMaskSize,\r
1181 IN UINT32 Feature\r
1182 )\r
1183{\r
1184 if ((Feature >> 3) >= CpuBitMaskSize) {\r
1185 return FALSE;\r
1186 }\r
1187 return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);\r
1188}\r
1189\r
1190/**\r
1191 Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.\r
1192 If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data\r
1193 associated with that feature should be optimized away if compiler\r
1194 optimizations are enabled.\r
1195\r
1196 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1197 PcdCpuFeaturesSupport\r
1198\r
1199 @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r
1200 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r
1201\r
1202 @note This service could be called by BSP only.\r
1203**/\r
1204BOOLEAN\r
1205EFIAPI\r
1206IsCpuFeatureSupported (\r
1207 IN UINT32 Feature\r
1208 )\r
1209{\r
1210 return IsCpuFeatureSetInCpuPcd (\r
1211 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),\r
1212 PcdGetSize (PcdCpuFeaturesSupport),\r
1213 Feature\r
1214 );\r
1215}\r
1216\r
1217/**\r
1218 Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.\r
1219\r
1220 @param[in] Feature The bit number of the CPU feature to check in the PCD\r
1221 PcdCpuFeaturesSetting\r
1222\r
1223 @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.\r
1224 @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.\r
1225\r
1226 @note This service could be called by BSP only.\r
1227**/\r
1228BOOLEAN\r
1229EFIAPI\r
1230IsCpuFeatureInSetting (\r
1231 IN UINT32 Feature\r
1232 )\r
1233{\r
1234 return IsCpuFeatureSetInCpuPcd (\r
1235 (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),\r
1236 PcdGetSize (PcdCpuFeaturesSetting),\r
1237 Feature\r
1238 );\r
1239}\r
1240\r
80c4b236
JF
1241/**\r
1242 Switches to assigned BSP after CPU features initialization.\r
1243\r
1244 @param[in] ProcessorNumber The index of the CPU executing this function.\r
1245\r
1246 @note This service could be called by BSP only.\r
1247**/\r
1248VOID\r
1249EFIAPI\r
1250SwitchBspAfterFeaturesInitialize (\r
1251 IN UINTN ProcessorNumber\r
1252 )\r
1253{\r
1254 CPU_FEATURES_DATA *CpuFeaturesData;\r
1255\r
1256 CpuFeaturesData = GetCpuFeaturesData ();\r
1257 CpuFeaturesData->BspNumber = ProcessorNumber;\r
1258}\r
1259\r