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