]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - UefiCpuPkg/Library/RegisterCpuFeaturesLib/RegisterCpuFeaturesLib.c
UefiCpuPkg/RegisterCpuFeaturesLib: Avoid AP calls PeiServices table.
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / RegisterCpuFeaturesLib.c
... / ...
CommitLineData
1/** @file\r
2 CPU Register Table Library functions.\r
3\r
4 Copyright (c) 2017 - 2019, Intel Corporation. All rights reserved.<BR>\r
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
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
26 UINTN BitMaskSize;\r
27\r
28 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
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
48 UINTN BitMaskSize;\r
49\r
50 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
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
97 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
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
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
178/**\r
179 Return feature dependence result.\r
180\r
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
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
190 IN BOOLEAN Before,\r
191 IN UINT8 *NextCpuFeatureMask\r
192 )\r
193{\r
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
207 if (Before) {\r
208 if ((CpuFeature->PackageBeforeFeatureBitMask != NULL) &&\r
209 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageBeforeFeatureBitMask)) {\r
210 return PackageDepType;\r
211 }\r
212\r
213 if ((CpuFeature->CoreBeforeFeatureBitMask != NULL) &&\r
214 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreBeforeFeatureBitMask)) {\r
215 return CoreDepType;\r
216 }\r
217\r
218 if ((CpuFeature->BeforeFeatureBitMask != NULL) &&\r
219 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r
220 return ThreadDepType;\r
221 }\r
222\r
223 return NoneDepType;\r
224 }\r
225\r
226 if ((CpuFeature->PackageAfterFeatureBitMask != NULL) &&\r
227 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->PackageAfterFeatureBitMask)) {\r
228 return PackageDepType;\r
229 }\r
230\r
231 if ((CpuFeature->CoreAfterFeatureBitMask != NULL) &&\r
232 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->CoreAfterFeatureBitMask)) {\r
233 return CoreDepType;\r
234 }\r
235\r
236 if ((CpuFeature->AfterFeatureBitMask != NULL) &&\r
237 IsBitMaskMatchCheck (NextCpuFeatureMask, CpuFeature->AfterFeatureBitMask)) {\r
238 return ThreadDepType;\r
239 }\r
240\r
241 return NoneDepType;\r
242}\r
243\r
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
297/**\r
298 Base on dependence relationship to asjust feature dependence.\r
299\r
300 ONLY when the feature before(or after) the find feature also has\r
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
305 @param[in, out] PreviousFeature CPU feature current before the find one.\r
306 @param[in, out] CurrentFeature Cpu feature need to adjust.\r
307 @param[in] FindFeature Cpu feature which current feature depends.\r
308 @param[in] Before Before or after dependence relationship.\r
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
320 IN CPU_FEATURES_ENTRY *FindFeature,\r
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
327 PreDependType = DetectFeatureScope(PreviousFeature, Before, FindFeature->FeatureMask);\r
328 CurrentDependType = DetectFeatureScope(CurrentFeature, Before, FindFeature->FeatureMask);\r
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
339 // If both feature have dependence, keep the one which needs use more\r
340 // processors and clear the dependence for the other one.\r
341 //\r
342 if (PreDependType >= CurrentDependType) {\r
343 return TRUE;\r
344 } else {\r
345 return FALSE;\r
346 }\r
347}\r
348\r
349/**\r
350 Base on dependence relationship to asjust feature order.\r
351\r
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
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
369 CPU_FEATURES_ENTRY *FindFeature;\r
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
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
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
386 } else {\r
387\r
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
408 FindFeature = CPU_FEATURE_ENTRY_FROM_LINK (FindEntry);\r
409\r
410 if (AdjustFeaturesDependence (PreviousFeature, CurrentFeature, FindFeature, Before)) {\r
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
429}\r
430\r
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
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
526 LIST_ENTRY *NextEntry;\r
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
532 NextEntry = CurrentEntry->ForwardLink;\r
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
553 CurrentEntry = NextEntry;\r
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
580 CurrentEntry = NextEntry;\r
581 continue;\r
582 }\r
583 }\r
584\r
585 if (CpuFeature->BeforeFeatureBitMask != NULL) {\r
586 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->BeforeFeatureBitMask);\r
587 if (Swapped) {\r
588 continue;\r
589 }\r
590 }\r
591\r
592 if (CpuFeature->AfterFeatureBitMask != NULL) {\r
593 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->AfterFeatureBitMask);\r
594 if (Swapped) {\r
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
602 continue;\r
603 }\r
604 }\r
605\r
606 if (CpuFeature->CoreAfterFeatureBitMask != NULL) {\r
607 Swapped = InsertToAfterEntry (FeatureList, CurrentEntry, CpuFeature->CoreAfterFeatureBitMask);\r
608 if (Swapped) {\r
609 continue;\r
610 }\r
611 }\r
612\r
613 if (CpuFeature->PackageBeforeFeatureBitMask != NULL) {\r
614 Swapped = InsertToBeforeEntry (FeatureList, CurrentEntry, CpuFeature->PackageBeforeFeatureBitMask);\r
615 if (Swapped) {\r
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
623 continue;\r
624 }\r
625 }\r
626\r
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
652 UINTN BitMaskSize;\r
653 BOOLEAN FeatureExist;\r
654\r
655 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
656 CpuFeaturesData = GetCpuFeaturesData ();\r
657 if (CpuFeaturesData->FeaturesCount == 0) {\r
658 InitializeListHead (&CpuFeaturesData->FeatureList);\r
659 InitializeSpinLock (&CpuFeaturesData->CpuFlags.MemoryMappedLock);\r
660 InitializeSpinLock (&CpuFeaturesData->CpuFlags.ConsoleLogLock);\r
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
666 CpuFeaturesData->BitMaskSize = (UINT32) BitMaskSize;\r
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
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
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
834 @retval RETURN_NOT_READY CPU feature PCD PcdCpuFeaturesUserConfiguration\r
835 not updated by Platform driver yet.\r
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
857 UINT8 *CoreBeforeFeatureBitMask;\r
858 UINT8 *CoreAfterFeatureBitMask;\r
859 UINT8 *PackageBeforeFeatureBitMask;\r
860 UINT8 *PackageAfterFeatureBitMask;\r
861 BOOLEAN BeforeAll;\r
862 BOOLEAN AfterAll;\r
863\r
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
871 BeforeAll = FALSE;\r
872 AfterAll = FALSE;\r
873\r
874 BitMaskSize = PcdGetSize (PcdCpuFeaturesSetting);\r
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
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
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
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
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
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
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
938/**\r
939 Return ACPI_CPU_DATA data.\r
940\r
941 @return Pointer to ACPI_CPU_DATA data.\r
942**/\r
943ACPI_CPU_DATA *\r
944GetAcpiCpuData (\r
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
957 AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r
958 if (AcpiCpuData != NULL) {\r
959 return AcpiCpuData;\r
960 }\r
961\r
962 AcpiCpuData = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (ACPI_CPU_DATA)));\r
963 ASSERT (AcpiCpuData != NULL);\r
964\r
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
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
976 //\r
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
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
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
1073 AcpiCpuData = GetAcpiCpuData ();\r
1074 ASSERT ((AcpiCpuData != NULL) && (AcpiCpuData->RegisterTable != 0));\r
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
1178 @retval TRUE The CPU feature is set in CpuBitMask.\r
1179 @retval FALSE The CPU feature is not set in CpuBitMask.\r
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
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