]>
Commit | Line | Data |
---|---|---|
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 | |
26 | BOOLEAN\r | |
27 | IsCpuFeatureMatch (\r | |
28 | IN UINT8 *FirstFeatureMask,\r | |
29 | IN UINT8 *SecondFeatureMask\r | |
30 | )\r | |
31 | {\r | |
32 | UINT32 BitMaskSize;\r | |
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 | |
47 | VOID\r | |
48 | DumpCpuFeatureMask (\r | |
49 | IN UINT8 *FeatureMask\r | |
50 | )\r | |
51 | {\r | |
52 | UINTN Index;\r | |
53 | UINT8 *Data8;\r | |
54 | UINT32 BitMaskSize;\r | |
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 | |
69 | VOID\r | |
70 | DumpCpuFeature (\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 | |
92 | BOOLEAN\r | |
93 | IsBitMaskMatchCheck (\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 | |
115 | /**\r | |
116 | Checks and adjusts CPU features order per dependency relationship.\r | |
117 | \r | |
118 | @param[in] FeatureList Pointer to CPU feature list\r | |
119 | **/\r | |
120 | VOID\r | |
121 | CheckCpuFeaturesDependency (\r | |
122 | IN LIST_ENTRY *FeatureList\r | |
123 | )\r | |
124 | {\r | |
125 | LIST_ENTRY *CurrentEntry;\r | |
126 | CPU_FEATURES_ENTRY *CpuFeature;\r | |
127 | LIST_ENTRY *CheckEntry;\r | |
128 | CPU_FEATURES_ENTRY *CheckFeature;\r | |
129 | BOOLEAN Swapped;\r | |
130 | LIST_ENTRY *TempEntry;\r | |
131 | \r | |
132 | CurrentEntry = GetFirstNode (FeatureList);\r | |
133 | while (!IsNull (FeatureList, CurrentEntry)) {\r | |
134 | Swapped = FALSE;\r | |
135 | CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (CurrentEntry);\r | |
136 | if (CpuFeature->BeforeAll) {\r | |
137 | //\r | |
138 | // Check all features dispatched before this entry\r | |
139 | //\r | |
140 | CheckEntry = GetFirstNode (FeatureList);\r | |
141 | while (CheckEntry != CurrentEntry) {\r | |
142 | CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r | |
143 | if (!CheckFeature->BeforeAll) {\r | |
144 | //\r | |
145 | // If this feature has no BeforeAll flag and is dispatched before CpuFeature,\r | |
146 | // insert currentEntry before Checked feature\r | |
147 | //\r | |
148 | RemoveEntryList (CurrentEntry);\r | |
149 | InsertTailList (CheckEntry, CurrentEntry);\r | |
150 | Swapped = TRUE;\r | |
151 | break;\r | |
152 | }\r | |
153 | CheckEntry = CheckEntry->ForwardLink;\r | |
154 | }\r | |
155 | if (Swapped) {\r | |
156 | continue;\r | |
157 | }\r | |
158 | }\r | |
159 | \r | |
160 | if (CpuFeature->AfterAll) {\r | |
161 | //\r | |
162 | // Check all features dispatched after this entry\r | |
163 | //\r | |
164 | CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r | |
165 | while (!IsNull (FeatureList, CheckEntry)) {\r | |
166 | CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r | |
167 | if (!CheckFeature->AfterAll) {\r | |
168 | //\r | |
169 | // If this feature has no AfterAll flag and is dispatched after CpuFeature,\r | |
170 | // insert currentEntry after Checked feature\r | |
171 | //\r | |
172 | TempEntry = GetNextNode (FeatureList, CurrentEntry);\r | |
173 | RemoveEntryList (CurrentEntry);\r | |
174 | InsertHeadList (CheckEntry, CurrentEntry);\r | |
175 | CurrentEntry = TempEntry;\r | |
176 | Swapped = TRUE;\r | |
177 | break;\r | |
178 | }\r | |
179 | CheckEntry = CheckEntry->ForwardLink;\r | |
180 | }\r | |
181 | if (Swapped) {\r | |
182 | continue;\r | |
183 | }\r | |
184 | }\r | |
185 | \r | |
186 | if (CpuFeature->BeforeFeatureBitMask != NULL) {\r | |
187 | //\r | |
188 | // Check all features dispatched before this entry\r | |
189 | //\r | |
190 | CheckEntry = GetFirstNode (FeatureList);\r | |
191 | while (CheckEntry != CurrentEntry) {\r | |
192 | CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r | |
193 | if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->BeforeFeatureBitMask)) {\r | |
194 | //\r | |
195 | // If there is dependency, swap them\r | |
196 | //\r | |
197 | RemoveEntryList (CurrentEntry);\r | |
198 | InsertTailList (CheckEntry, CurrentEntry);\r | |
199 | Swapped = TRUE;\r | |
200 | break;\r | |
201 | }\r | |
202 | CheckEntry = CheckEntry->ForwardLink;\r | |
203 | }\r | |
204 | if (Swapped) {\r | |
205 | continue;\r | |
206 | }\r | |
207 | }\r | |
208 | \r | |
209 | if (CpuFeature->AfterFeatureBitMask != NULL) {\r | |
210 | //\r | |
211 | // Check all features dispatched after this entry\r | |
212 | //\r | |
213 | CheckEntry = GetNextNode (FeatureList, CurrentEntry);\r | |
214 | while (!IsNull (FeatureList, CheckEntry)) {\r | |
215 | CheckFeature = CPU_FEATURE_ENTRY_FROM_LINK (CheckEntry);\r | |
216 | if (IsBitMaskMatchCheck (CheckFeature->FeatureMask, CpuFeature->AfterFeatureBitMask)) {\r | |
217 | //\r | |
218 | // If there is dependency, swap them\r | |
219 | //\r | |
220 | TempEntry = GetNextNode (FeatureList, CurrentEntry);\r | |
221 | RemoveEntryList (CurrentEntry);\r | |
222 | InsertHeadList (CheckEntry, CurrentEntry);\r | |
223 | CurrentEntry = TempEntry;\r | |
224 | Swapped = TRUE;\r | |
225 | break;\r | |
226 | }\r | |
227 | CheckEntry = CheckEntry->ForwardLink;\r | |
228 | }\r | |
229 | if (Swapped) {\r | |
230 | continue;\r | |
231 | }\r | |
232 | }\r | |
233 | //\r | |
234 | // No swap happened, check the next feature\r | |
235 | //\r | |
236 | CurrentEntry = CurrentEntry->ForwardLink;\r | |
237 | }\r | |
238 | }\r | |
239 | \r | |
240 | /**\r | |
241 | Worker function to register CPU Feature.\r | |
242 | \r | |
243 | @param[in] CpuFeature Pointer to CPU feature entry\r | |
244 | \r | |
245 | @retval RETURN_SUCCESS The CPU feature was successfully registered.\r | |
246 | @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r | |
247 | the CPU feature.\r | |
248 | @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r | |
249 | supported due to a circular dependency between\r | |
250 | BEFORE and AFTER features.\r | |
251 | **/\r | |
252 | RETURN_STATUS\r | |
253 | RegisterCpuFeatureWorker (\r | |
254 | IN CPU_FEATURES_ENTRY *CpuFeature\r | |
255 | )\r | |
256 | {\r | |
257 | EFI_STATUS Status;\r | |
258 | CPU_FEATURES_DATA *CpuFeaturesData;\r | |
259 | CPU_FEATURES_ENTRY *CpuFeatureEntry;\r | |
260 | LIST_ENTRY *Entry;\r | |
261 | UINT32 BitMaskSize;\r | |
262 | BOOLEAN FeatureExist;\r | |
263 | \r | |
264 | BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r | |
265 | CpuFeaturesData = GetCpuFeaturesData ();\r | |
266 | if (CpuFeaturesData->FeaturesCount == 0) {\r | |
267 | InitializeListHead (&CpuFeaturesData->FeatureList);\r | |
268 | InitializeSpinLock (&CpuFeaturesData->MsrLock);\r | |
269 | InitializeSpinLock (&CpuFeaturesData->MemoryMappedLock);\r | |
270 | CpuFeaturesData->BitMaskSize = BitMaskSize;\r | |
271 | }\r | |
272 | ASSERT (CpuFeaturesData->BitMaskSize == BitMaskSize);\r | |
273 | \r | |
274 | FeatureExist = FALSE;\r | |
275 | CpuFeatureEntry = NULL;\r | |
276 | Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r | |
277 | while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r | |
278 | CpuFeatureEntry = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r | |
279 | if (IsCpuFeatureMatch (CpuFeature->FeatureMask, CpuFeatureEntry->FeatureMask)) {\r | |
280 | //\r | |
281 | // If this feature already registered\r | |
282 | //\r | |
283 | FeatureExist = TRUE;\r | |
284 | break;\r | |
285 | }\r | |
286 | Entry = Entry->ForwardLink;\r | |
287 | }\r | |
288 | \r | |
289 | if (!FeatureExist) {\r | |
290 | DEBUG ((DEBUG_INFO, "[NEW] "));\r | |
291 | DumpCpuFeature (CpuFeature);\r | |
292 | InsertTailList (&CpuFeaturesData->FeatureList, &CpuFeature->Link);\r | |
293 | CpuFeaturesData->FeaturesCount++;\r | |
294 | } else {\r | |
295 | DEBUG ((DEBUG_INFO, "[OVERRIDE] "));\r | |
296 | DumpCpuFeature (CpuFeature);\r | |
297 | ASSERT (CpuFeatureEntry != NULL);\r | |
298 | //\r | |
299 | // Overwrite original parameters of CPU feature\r | |
300 | //\r | |
301 | if (CpuFeature->GetConfigDataFunc != NULL) {\r | |
302 | CpuFeatureEntry->GetConfigDataFunc = CpuFeature->GetConfigDataFunc;\r | |
303 | }\r | |
304 | if (CpuFeature->SupportFunc != NULL) {\r | |
305 | CpuFeatureEntry->SupportFunc = CpuFeature->SupportFunc;\r | |
306 | }\r | |
307 | if (CpuFeature->InitializeFunc != NULL) {\r | |
308 | CpuFeatureEntry->InitializeFunc = CpuFeature->InitializeFunc;\r | |
309 | }\r | |
310 | if (CpuFeature->FeatureName != NULL) {\r | |
311 | if (CpuFeatureEntry->FeatureName == NULL) {\r | |
312 | CpuFeatureEntry->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r | |
313 | ASSERT (CpuFeatureEntry->FeatureName != NULL);\r | |
314 | }\r | |
315 | Status = AsciiStrCpyS (CpuFeatureEntry->FeatureName, CPU_FEATURE_NAME_SIZE, CpuFeature->FeatureName);\r | |
316 | ASSERT_EFI_ERROR (Status);\r | |
317 | FreePool (CpuFeature->FeatureName);\r | |
318 | }\r | |
319 | if (CpuFeature->BeforeFeatureBitMask != NULL) {\r | |
320 | if (CpuFeatureEntry->BeforeFeatureBitMask != NULL) {\r | |
321 | FreePool (CpuFeatureEntry->BeforeFeatureBitMask);\r | |
322 | }\r | |
323 | CpuFeatureEntry->BeforeFeatureBitMask = CpuFeature->BeforeFeatureBitMask;\r | |
324 | }\r | |
325 | if (CpuFeature->AfterFeatureBitMask != NULL) {\r | |
326 | if (CpuFeatureEntry->AfterFeatureBitMask != NULL) {\r | |
327 | FreePool (CpuFeatureEntry->AfterFeatureBitMask);\r | |
328 | }\r | |
329 | CpuFeatureEntry->AfterFeatureBitMask = CpuFeature->AfterFeatureBitMask;\r | |
330 | }\r | |
331 | CpuFeatureEntry->BeforeAll = CpuFeature->BeforeAll;\r | |
332 | CpuFeatureEntry->AfterAll = CpuFeature->AfterAll;\r | |
333 | \r | |
334 | FreePool (CpuFeature->FeatureMask);\r | |
335 | FreePool (CpuFeature);\r | |
336 | }\r | |
337 | //\r | |
338 | // Verify CPU features dependency can change CPU feature order\r | |
339 | //\r | |
340 | CheckCpuFeaturesDependency (&CpuFeaturesData->FeatureList);\r | |
341 | return RETURN_SUCCESS;\r | |
342 | }\r | |
343 | \r | |
344 | /**\r | |
345 | Sets CPU feature bit mask in CPU feature bit mask buffer.\r | |
346 | \r | |
347 | @param[in] FeaturesBitMask Pointer to CPU feature bit mask buffer\r | |
348 | @param[in] Feature The bit number of the CPU feature\r | |
349 | @param[in] BitMaskSize CPU feature bit mask buffer size\r | |
350 | **/\r | |
351 | VOID\r | |
352 | SetCpuFeaturesBitMask (\r | |
353 | IN UINT8 **FeaturesBitMask,\r | |
354 | IN UINT32 Feature,\r | |
355 | IN UINTN BitMaskSize\r | |
356 | )\r | |
357 | {\r | |
358 | UINT8 *CpuFeaturesBitMask;\r | |
359 | \r | |
360 | ASSERT (FeaturesBitMask != NULL);\r | |
361 | CpuFeaturesBitMask = *FeaturesBitMask;\r | |
362 | if (CpuFeaturesBitMask == NULL) {\r | |
363 | CpuFeaturesBitMask = AllocateZeroPool (BitMaskSize);\r | |
364 | ASSERT (CpuFeaturesBitMask != NULL);\r | |
365 | *FeaturesBitMask = CpuFeaturesBitMask;\r | |
366 | }\r | |
367 | \r | |
368 | CpuFeaturesBitMask += (Feature / 8);\r | |
369 | *CpuFeaturesBitMask |= (UINT8) (1 << (Feature % 8));\r | |
370 | }\r | |
371 | \r | |
372 | /**\r | |
373 | Registers a CPU Feature.\r | |
374 | \r | |
375 | @param[in] FeatureName A Null-terminated Ascii string indicates CPU feature\r | |
376 | name.\r | |
377 | @param[in] GetConfigDataFunc CPU feature get configuration data function. This\r | |
378 | is an optional parameter that may be NULL. If NULL,\r | |
379 | then the most recently registered function for the\r | |
380 | CPU feature is used. If no functions are registered\r | |
381 | for a CPU feature, then the CPU configuration data\r | |
382 | for the registered feature is NULL.\r | |
383 | @param[in] SupportFunc CPU feature support function. This is an optional\r | |
384 | parameter that may be NULL. If NULL, then the most\r | |
385 | recently registered function for the CPU feature is\r | |
386 | used. If no functions are registered for a CPU\r | |
387 | feature, then the CPU feature is assumed to be\r | |
388 | supported by all CPUs.\r | |
389 | @param[in] InitializeFunc CPU feature initialize function. This is an optional\r | |
390 | parameter that may be NULL. If NULL, then the most\r | |
391 | recently registered function for the CPU feature is\r | |
392 | used. If no functions are registered for a CPU\r | |
393 | feature, then the CPU feature initialization is\r | |
394 | skipped.\r | |
395 | @param[in] ... Variable argument list of UINT32 CPU feature value.\r | |
396 | Values with no modifiers are the features provided\r | |
397 | by the registered functions.\r | |
398 | Values with CPU_FEATURE_BEFORE modifier are features\r | |
399 | that must be initialized after the features provided\r | |
400 | by the registered functions are used.\r | |
401 | Values with CPU_FEATURE_AFTER modifier are features\r | |
402 | that must be initialized before the features provided\r | |
403 | by the registered functions are used.\r | |
404 | The last argument in this variable argument list must\r | |
405 | always be CPU_FEATURE_END.\r | |
406 | \r | |
407 | @retval RETURN_SUCCESS The CPU feature was successfully registered.\r | |
408 | @retval RETURN_OUT_OF_RESOURCES There are not enough resources to register\r | |
409 | the CPU feature.\r | |
410 | @retval RETURN_UNSUPPORTED Registration of the CPU feature is not\r | |
411 | supported due to a circular dependency between\r | |
412 | BEFORE and AFTER features.\r | |
413 | \r | |
414 | @note This service could be called by BSP only.\r | |
415 | **/\r | |
416 | RETURN_STATUS\r | |
417 | EFIAPI\r | |
418 | RegisterCpuFeature (\r | |
419 | IN CHAR8 *FeatureName, OPTIONAL\r | |
420 | IN CPU_FEATURE_GET_CONFIG_DATA GetConfigDataFunc, OPTIONAL\r | |
421 | IN CPU_FEATURE_SUPPORT SupportFunc, OPTIONAL\r | |
422 | IN CPU_FEATURE_INITIALIZE InitializeFunc, OPTIONAL\r | |
423 | ...\r | |
424 | )\r | |
425 | {\r | |
426 | EFI_STATUS Status;\r | |
427 | VA_LIST Marker;\r | |
428 | UINT32 Feature;\r | |
429 | UINTN BitMaskSize;\r | |
430 | CPU_FEATURES_ENTRY *CpuFeature;\r | |
431 | UINT8 *FeatureMask;\r | |
432 | UINT8 *BeforeFeatureBitMask;\r | |
433 | UINT8 *AfterFeatureBitMask;\r | |
434 | BOOLEAN BeforeAll;\r | |
435 | BOOLEAN AfterAll;\r | |
436 | \r | |
437 | FeatureMask = NULL;\r | |
438 | BeforeFeatureBitMask = NULL;\r | |
439 | AfterFeatureBitMask = NULL;\r | |
440 | BeforeAll = FALSE;\r | |
441 | AfterAll = FALSE;\r | |
442 | \r | |
443 | BitMaskSize = PcdGetSize (PcdCpuFeaturesSupport);\r | |
444 | \r | |
445 | VA_START (Marker, InitializeFunc);\r | |
446 | Feature = VA_ARG (Marker, UINT32);\r | |
447 | while (Feature != CPU_FEATURE_END) {\r | |
448 | ASSERT ((Feature & (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER))\r | |
449 | != (CPU_FEATURE_BEFORE | CPU_FEATURE_AFTER));\r | |
450 | ASSERT ((Feature & (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL))\r | |
451 | != (CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL));\r | |
452 | if (Feature < CPU_FEATURE_BEFORE) {\r | |
453 | BeforeAll = ((Feature & CPU_FEATURE_BEFORE_ALL) != 0) ? TRUE : FALSE;\r | |
454 | AfterAll = ((Feature & CPU_FEATURE_AFTER_ALL) != 0) ? TRUE : FALSE;\r | |
455 | Feature &= ~(CPU_FEATURE_BEFORE_ALL | CPU_FEATURE_AFTER_ALL);\r | |
456 | ASSERT (FeatureMask == NULL);\r | |
457 | SetCpuFeaturesBitMask (&FeatureMask, Feature, BitMaskSize);\r | |
458 | } else if ((Feature & CPU_FEATURE_BEFORE) != 0) {\r | |
459 | SetCpuFeaturesBitMask (&BeforeFeatureBitMask, Feature & ~CPU_FEATURE_BEFORE, BitMaskSize);\r | |
460 | } else if ((Feature & CPU_FEATURE_AFTER) != 0) {\r | |
461 | SetCpuFeaturesBitMask (&AfterFeatureBitMask, Feature & ~CPU_FEATURE_AFTER, BitMaskSize);\r | |
462 | }\r | |
463 | Feature = VA_ARG (Marker, UINT32);\r | |
464 | }\r | |
465 | VA_END (Marker);\r | |
466 | \r | |
467 | CpuFeature = AllocateZeroPool (sizeof (CPU_FEATURES_ENTRY));\r | |
468 | ASSERT (CpuFeature != NULL);\r | |
469 | CpuFeature->Signature = CPU_FEATURE_ENTRY_SIGNATURE;\r | |
470 | CpuFeature->FeatureMask = FeatureMask;\r | |
471 | CpuFeature->BeforeFeatureBitMask = BeforeFeatureBitMask;\r | |
472 | CpuFeature->AfterFeatureBitMask = AfterFeatureBitMask;\r | |
473 | CpuFeature->BeforeAll = BeforeAll;\r | |
474 | CpuFeature->AfterAll = AfterAll;\r | |
475 | CpuFeature->GetConfigDataFunc = GetConfigDataFunc;\r | |
476 | CpuFeature->SupportFunc = SupportFunc;\r | |
477 | CpuFeature->InitializeFunc = InitializeFunc;\r | |
478 | if (FeatureName != NULL) {\r | |
479 | CpuFeature->FeatureName = AllocatePool (CPU_FEATURE_NAME_SIZE);\r | |
480 | ASSERT (CpuFeature->FeatureName != NULL);\r | |
481 | Status = AsciiStrCpyS (CpuFeature->FeatureName, CPU_FEATURE_NAME_SIZE, FeatureName);\r | |
482 | ASSERT_EFI_ERROR (Status);\r | |
483 | }\r | |
484 | \r | |
485 | Status = RegisterCpuFeatureWorker (CpuFeature);\r | |
486 | ASSERT_EFI_ERROR (Status);\r | |
487 | \r | |
488 | return RETURN_SUCCESS;\r | |
489 | }\r | |
490 | \r | |
491 | /**\r | |
492 | Add an entry in specified register table.\r | |
493 | \r | |
494 | This function adds an entry in specified register table, with given register type,\r | |
495 | register index, bit section and value.\r | |
496 | \r | |
497 | @param[in] PreSmmFlag If TRUE, entry will be added into PreSmm register table\r | |
498 | If FALSE, entry will be added into register table\r | |
499 | @param[in] ProcessorNumber The index of the CPU to add a register table entry\r | |
500 | @param[in] RegisterType Type of the register to program\r | |
501 | @param[in] Index Index of the register to program\r | |
502 | @param[in] ValidBitStart Start of the bit section\r | |
503 | @param[in] ValidBitLength Length of the bit section\r | |
504 | @param[in] Value Value to write\r | |
505 | **/\r | |
506 | VOID\r | |
507 | CpuRegisterTableWriteWorker (\r | |
508 | IN BOOLEAN PreSmmFlag,\r | |
509 | IN UINTN ProcessorNumber,\r | |
510 | IN REGISTER_TYPE RegisterType,\r | |
511 | IN UINT64 Index,\r | |
512 | IN UINT8 ValidBitStart,\r | |
513 | IN UINT8 ValidBitLength,\r | |
514 | IN UINT64 Value\r | |
515 | )\r | |
516 | {\r | |
517 | EFI_STATUS Status;\r | |
518 | CPU_FEATURES_DATA *CpuFeaturesData;\r | |
519 | ACPI_CPU_DATA *AcpiCpuData;\r | |
520 | CPU_REGISTER_TABLE *RegisterTable;\r | |
521 | CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r | |
522 | \r | |
523 | CpuFeaturesData = GetCpuFeaturesData ();\r | |
524 | if (CpuFeaturesData->RegisterTable == NULL) {\r | |
525 | AcpiCpuData = (ACPI_CPU_DATA *) (UINTN) PcdGet64 (PcdCpuS3DataAddress);\r | |
526 | if (AcpiCpuData == NULL) {\r | |
527 | AcpiCpuData = AllocateAcpiCpuData ();\r | |
528 | ASSERT (AcpiCpuData != NULL);\r | |
529 | //\r | |
530 | // Set PcdCpuS3DataAddress to the base address of the ACPI_CPU_DATA structure\r | |
531 | //\r | |
532 | Status = PcdSet64S (PcdCpuS3DataAddress, (UINT64)(UINTN)AcpiCpuData);\r | |
533 | ASSERT_EFI_ERROR (Status);\r | |
534 | }\r | |
535 | ASSERT (AcpiCpuData->RegisterTable != 0);\r | |
536 | CpuFeaturesData->RegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->RegisterTable;\r | |
537 | CpuFeaturesData->PreSmmRegisterTable = (CPU_REGISTER_TABLE *) (UINTN) AcpiCpuData->PreSmmInitRegisterTable;\r | |
538 | }\r | |
539 | \r | |
540 | if (PreSmmFlag) {\r | |
541 | RegisterTable = &CpuFeaturesData->PreSmmRegisterTable[ProcessorNumber];\r | |
542 | } else {\r | |
543 | RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r | |
544 | }\r | |
545 | \r | |
546 | if (RegisterTable->TableLength == RegisterTable->AllocatedSize / sizeof (CPU_REGISTER_TABLE_ENTRY)) {\r | |
547 | EnlargeRegisterTable (RegisterTable);\r | |
548 | }\r | |
549 | \r | |
550 | //\r | |
551 | // Append entry in the register table.\r | |
552 | //\r | |
553 | RegisterTableEntry = (CPU_REGISTER_TABLE_ENTRY *) (UINTN) RegisterTable->RegisterTableEntry;\r | |
554 | RegisterTableEntry[RegisterTable->TableLength].RegisterType = RegisterType;\r | |
555 | RegisterTableEntry[RegisterTable->TableLength].Index = (UINT32) Index;\r | |
556 | RegisterTableEntry[RegisterTable->TableLength].HighIndex = (UINT32) RShiftU64 (Index, 32);\r | |
557 | RegisterTableEntry[RegisterTable->TableLength].ValidBitStart = ValidBitStart;\r | |
558 | RegisterTableEntry[RegisterTable->TableLength].ValidBitLength = ValidBitLength;\r | |
559 | RegisterTableEntry[RegisterTable->TableLength].Value = Value;\r | |
560 | \r | |
561 | RegisterTable->TableLength++;\r | |
562 | }\r | |
563 | \r | |
564 | /**\r | |
565 | Adds an entry in specified register table.\r | |
566 | \r | |
567 | This function adds an entry in specified register table, with given register type,\r | |
568 | register index, bit section and value.\r | |
569 | \r | |
570 | @param[in] ProcessorNumber The index of the CPU to add a register table entry\r | |
571 | @param[in] RegisterType Type of the register to program\r | |
572 | @param[in] Index Index of the register to program\r | |
573 | @param[in] ValueMask Mask of bits in register to write\r | |
574 | @param[in] Value Value to write\r | |
575 | \r | |
576 | @note This service could be called by BSP only.\r | |
577 | **/\r | |
578 | VOID\r | |
579 | EFIAPI\r | |
580 | CpuRegisterTableWrite (\r | |
581 | IN UINTN ProcessorNumber,\r | |
582 | IN REGISTER_TYPE RegisterType,\r | |
583 | IN UINT64 Index,\r | |
584 | IN UINT64 ValueMask,\r | |
585 | IN UINT64 Value\r | |
586 | )\r | |
587 | {\r | |
588 | UINT8 Start;\r | |
589 | UINT8 End;\r | |
590 | UINT8 Length;\r | |
591 | \r | |
592 | Start = (UINT8)LowBitSet64 (ValueMask);\r | |
593 | End = (UINT8)HighBitSet64 (ValueMask);\r | |
594 | Length = End - Start + 1;\r | |
595 | CpuRegisterTableWriteWorker (FALSE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r | |
596 | }\r | |
597 | \r | |
598 | /**\r | |
599 | Adds an entry in specified Pre-SMM register table.\r | |
600 | \r | |
601 | This function adds an entry in specified register table, with given register type,\r | |
602 | register index, bit section and value.\r | |
603 | \r | |
604 | @param[in] ProcessorNumber The index of the CPU to add a register table entry.\r | |
605 | @param[in] RegisterType Type of the register to program\r | |
606 | @param[in] Index Index of the register to program\r | |
607 | @param[in] ValueMask Mask of bits in register to write\r | |
608 | @param[in] Value Value to write\r | |
609 | \r | |
610 | @note This service could be called by BSP only.\r | |
611 | **/\r | |
612 | VOID\r | |
613 | EFIAPI\r | |
614 | PreSmmCpuRegisterTableWrite (\r | |
615 | IN UINTN ProcessorNumber,\r | |
616 | IN REGISTER_TYPE RegisterType,\r | |
617 | IN UINT64 Index,\r | |
618 | IN UINT64 ValueMask,\r | |
619 | IN UINT64 Value\r | |
620 | )\r | |
621 | {\r | |
622 | UINT8 Start;\r | |
623 | UINT8 End;\r | |
624 | UINT8 Length;\r | |
625 | \r | |
626 | Start = (UINT8)LowBitSet64 (ValueMask);\r | |
627 | End = (UINT8)HighBitSet64 (ValueMask);\r | |
628 | Length = End - Start + 1;\r | |
629 | CpuRegisterTableWriteWorker (TRUE, ProcessorNumber, RegisterType, Index, Start, Length, Value);\r | |
630 | }\r | |
631 | \r | |
632 | /**\r | |
633 | Worker function to determine if a CPU feature is set in input CPU feature bit mask buffer.\r | |
634 | \r | |
635 | @param[in] CpuBitMask CPU feature bit mask buffer\r | |
636 | @param[in] CpuBitMaskSize The size of CPU feature bit mask buffer\r | |
637 | @param[in] Feature The bit number of the CPU feature\r | |
638 | \r | |
639 | @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r | |
640 | @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r | |
641 | \r | |
642 | **/\r | |
643 | BOOLEAN\r | |
644 | IsCpuFeatureSetInCpuPcd (\r | |
645 | IN UINT8 *CpuBitMask,\r | |
646 | IN UINTN CpuBitMaskSize,\r | |
647 | IN UINT32 Feature\r | |
648 | )\r | |
649 | {\r | |
650 | if ((Feature >> 3) >= CpuBitMaskSize) {\r | |
651 | return FALSE;\r | |
652 | }\r | |
653 | return ((*(CpuBitMask + (Feature >> 3)) & (1 << (Feature & 0x07))) != 0);\r | |
654 | }\r | |
655 | \r | |
656 | /**\r | |
657 | Determines if a CPU feature is enabled in PcdCpuFeaturesSupport bit mask.\r | |
658 | If a CPU feature is disabled in PcdCpuFeaturesSupport then all the code/data\r | |
659 | associated with that feature should be optimized away if compiler\r | |
660 | optimizations are enabled.\r | |
661 | \r | |
662 | @param[in] Feature The bit number of the CPU feature to check in the PCD\r | |
663 | PcdCpuFeaturesSupport\r | |
664 | \r | |
665 | @retval TRUE The CPU feature is set in PcdCpuFeaturesSupport.\r | |
666 | @retval FALSE The CPU feature is not set in PcdCpuFeaturesSupport.\r | |
667 | \r | |
668 | @note This service could be called by BSP only.\r | |
669 | **/\r | |
670 | BOOLEAN\r | |
671 | EFIAPI\r | |
672 | IsCpuFeatureSupported (\r | |
673 | IN UINT32 Feature\r | |
674 | )\r | |
675 | {\r | |
676 | return IsCpuFeatureSetInCpuPcd (\r | |
677 | (UINT8 *)PcdGetPtr (PcdCpuFeaturesSupport),\r | |
678 | PcdGetSize (PcdCpuFeaturesSupport),\r | |
679 | Feature\r | |
680 | );\r | |
681 | }\r | |
682 | \r | |
683 | /**\r | |
684 | Determines if a CPU feature is set in PcdCpuFeaturesSetting bit mask.\r | |
685 | \r | |
686 | @param[in] Feature The bit number of the CPU feature to check in the PCD\r | |
687 | PcdCpuFeaturesSetting\r | |
688 | \r | |
689 | @retval TRUE The CPU feature is set in PcdCpuFeaturesSetting.\r | |
690 | @retval FALSE The CPU feature is not set in PcdCpuFeaturesSetting.\r | |
691 | \r | |
692 | @note This service could be called by BSP only.\r | |
693 | **/\r | |
694 | BOOLEAN\r | |
695 | EFIAPI\r | |
696 | IsCpuFeatureInSetting (\r | |
697 | IN UINT32 Feature\r | |
698 | )\r | |
699 | {\r | |
700 | return IsCpuFeatureSetInCpuPcd (\r | |
701 | (UINT8 *)PcdGetPtr (PcdCpuFeaturesSetting),\r | |
702 | PcdGetSize (PcdCpuFeaturesSetting),\r | |
703 | Feature\r | |
704 | );\r | |
705 | }\r | |
706 | \r | |
707 | /**\r | |
708 | Determines if a CPU feature is set in PcdCpuFeaturesCapability bit mask.\r | |
709 | \r | |
710 | @param[in] Feature The bit number of the CPU feature to check in the PCD\r | |
711 | PcdCpuFeaturesCapability\r | |
712 | \r | |
713 | @retval TRUE The CPU feature is set in PcdCpuFeaturesCapability.\r | |
714 | @retval FALSE The CPU feature is not set in PcdCpuFeaturesCapability.\r | |
715 | \r | |
716 | @note This service could be called by BSP only.\r | |
717 | **/\r | |
718 | BOOLEAN\r | |
719 | EFIAPI\r | |
720 | IsCpuFeatureCapability (\r | |
721 | IN UINT32 Feature\r | |
722 | )\r | |
723 | {\r | |
724 | return IsCpuFeatureSetInCpuPcd (\r | |
725 | (UINT8 *)PcdGetPtr (PcdCpuFeaturesCapability),\r | |
726 | PcdGetSize (PcdCpuFeaturesCapability),\r | |
727 | Feature\r | |
728 | );\r | |
729 | \r | |
730 | }\r | |
731 | \r | |
732 | /**\r | |
733 | Determines if a CPU feature is set in PcdCpuFeaturesUserConfiguration bit mask.\r | |
734 | \r | |
735 | @param[in] Feature The bit number of the CPU feature to check in the PCD\r | |
736 | PcdCpuFeaturesUserConfiguration\r | |
737 | \r | |
738 | @retval TRUE The CPU feature is set in PcdCpuFeaturesUserConfiguration.\r | |
739 | @retval FALSE The CPU feature is not set in PcdCpuFeaturesUserConfiguration.\r | |
740 | \r | |
741 | @note This service could be called by BSP only.\r | |
742 | **/\r | |
743 | BOOLEAN\r | |
744 | EFIAPI\r | |
745 | IsCpuFeatureUserConfiguration (\r | |
746 | IN UINT32 Feature\r | |
747 | )\r | |
748 | {\r | |
749 | return IsCpuFeatureSetInCpuPcd (\r | |
750 | (UINT8 *)PcdGetPtr (PcdCpuFeaturesUserConfiguration),\r | |
751 | PcdGetSize (PcdCpuFeaturesUserConfiguration),\r | |
752 | Feature\r | |
753 | );\r | |
754 | \r | |
755 | }\r | |
756 | \r | |
757 | /**\r | |
758 | Switches to assigned BSP after CPU features initialization.\r | |
759 | \r | |
760 | @param[in] ProcessorNumber The index of the CPU executing this function.\r | |
761 | \r | |
762 | @note This service could be called by BSP only.\r | |
763 | **/\r | |
764 | VOID\r | |
765 | EFIAPI\r | |
766 | SwitchBspAfterFeaturesInitialize (\r | |
767 | IN UINTN ProcessorNumber\r | |
768 | )\r | |
769 | {\r | |
770 | CPU_FEATURES_DATA *CpuFeaturesData;\r | |
771 | \r | |
772 | CpuFeaturesData = GetCpuFeaturesData ();\r | |
773 | CpuFeaturesData->BspNumber = ProcessorNumber;\r | |
774 | }\r | |
775 | \r |