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