]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/RegisterCpuFeaturesLib/CpuFeaturesInitialize.c
UefiCpuPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiCpuPkg / Library / RegisterCpuFeaturesLib / CpuFeaturesInitialize.c
CommitLineData
80c4b236
JF
1/** @file\r
2 CPU Features Initialize functions.\r
3\r
010753b7 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
053e878b 11CHAR16 *mDependTypeStr[] = { L"None", L"Thread", L"Core", L"Package", L"Invalid" };\r
b3c71b47 12\r
80c4b236
JF
13/**\r
14 Worker function to save PcdCpuFeaturesCapability.\r
15\r
16 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
3dafa038 17 @param[in] BitMaskSize CPU feature bits mask buffer size.\r
6214ffb4 18\r
80c4b236
JF
19**/\r
20VOID\r
21SetCapabilityPcd (\r
053e878b
MK
22 IN UINT8 *SupportedFeatureMask,\r
23 IN UINTN BitMaskSize\r
80c4b236
JF
24 )\r
25{\r
053e878b 26 EFI_STATUS Status;\r
6214ffb4 27\r
80c4b236
JF
28 Status = PcdSetPtrS (PcdCpuFeaturesCapability, &BitMaskSize, SupportedFeatureMask);\r
29 ASSERT_EFI_ERROR (Status);\r
30}\r
31\r
32/**\r
33 Worker function to save PcdCpuFeaturesSetting.\r
34\r
35 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
3dafa038 36 @param[in] BitMaskSize CPU feature bits mask buffer size.\r
80c4b236
JF
37**/\r
38VOID\r
39SetSettingPcd (\r
053e878b
MK
40 IN UINT8 *SupportedFeatureMask,\r
41 IN UINTN BitMaskSize\r
80c4b236
JF
42 )\r
43{\r
053e878b 44 EFI_STATUS Status;\r
80c4b236 45\r
80c4b236
JF
46 Status = PcdSetPtrS (PcdCpuFeaturesSetting, &BitMaskSize, SupportedFeatureMask);\r
47 ASSERT_EFI_ERROR (Status);\r
48}\r
49\r
80c4b236
JF
50/**\r
51 Collects CPU type and feature information.\r
52\r
53 @param[in, out] CpuInfo The pointer to CPU feature information\r
54**/\r
55VOID\r
56FillProcessorInfo (\r
053e878b 57 IN OUT REGISTER_CPU_FEATURE_INFORMATION *CpuInfo\r
80c4b236
JF
58 )\r
59{\r
053e878b
MK
60 CPUID_VERSION_INFO_EAX Eax;\r
61 CPUID_VERSION_INFO_ECX Ecx;\r
62 CPUID_VERSION_INFO_EDX Edx;\r
63 UINT32 DisplayedFamily;\r
64 UINT32 DisplayedModel;\r
80c4b236
JF
65\r
66 AsmCpuid (CPUID_VERSION_INFO, &Eax.Uint32, NULL, &Ecx.Uint32, &Edx.Uint32);\r
67\r
68 DisplayedFamily = Eax.Bits.FamilyId;\r
69 if (Eax.Bits.FamilyId == 0x0F) {\r
70 DisplayedFamily |= (Eax.Bits.ExtendedFamilyId << 4);\r
71 }\r
72\r
73 DisplayedModel = Eax.Bits.Model;\r
053e878b 74 if ((Eax.Bits.FamilyId == 0x06) || (Eax.Bits.FamilyId == 0x0f)) {\r
80c4b236
JF
75 DisplayedModel |= (Eax.Bits.ExtendedModelId << 4);\r
76 }\r
77\r
053e878b
MK
78 CpuInfo->DisplayFamily = DisplayedFamily;\r
79 CpuInfo->DisplayModel = DisplayedModel;\r
80 CpuInfo->SteppingId = Eax.Bits.SteppingId;\r
81 CpuInfo->ProcessorType = Eax.Bits.ProcessorType;\r
80c4b236
JF
82 CpuInfo->CpuIdVersionInfoEcx.Uint32 = Ecx.Uint32;\r
83 CpuInfo->CpuIdVersionInfoEdx.Uint32 = Edx.Uint32;\r
84}\r
85\r
86/**\r
87 Prepares for private data used for CPU features.\r
88\r
80c4b236
JF
89**/\r
90VOID\r
91CpuInitDataInitialize (\r
7217b879 92 VOID\r
80c4b236
JF
93 )\r
94{\r
053e878b
MK
95 EFI_STATUS Status;\r
96 UINTN ProcessorNumber;\r
97 EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer;\r
98 CPU_FEATURES_ENTRY *CpuFeature;\r
99 CPU_FEATURES_INIT_ORDER *InitOrder;\r
100 CPU_FEATURES_DATA *CpuFeaturesData;\r
101 LIST_ENTRY *Entry;\r
102 UINT32 Core;\r
103 UINT32 Package;\r
104 UINT32 Thread;\r
105 EFI_CPU_PHYSICAL_LOCATION *Location;\r
106 UINT32 PackageIndex;\r
107 UINT32 CoreIndex;\r
108 UINTN Pages;\r
109 UINT32 FirstPackage;\r
110 UINT32 *FirstCore;\r
111 UINT32 *FirstThread;\r
112 ACPI_CPU_DATA *AcpiCpuData;\r
113 CPU_STATUS_INFORMATION *CpuStatus;\r
114 UINT32 *ThreadCountPerPackage;\r
115 UINT8 *ThreadCountPerCore;\r
116 UINTN NumberOfCpus;\r
117 UINTN NumberOfEnabledProcessors;\r
b3c71b47
ED
118\r
119 Core = 0;\r
120 Package = 0;\r
121 Thread = 0;\r
80c4b236
JF
122\r
123 CpuFeaturesData = GetCpuFeaturesData ();\r
7217b879
ED
124\r
125 //\r
126 // Initialize CpuFeaturesData->MpService as early as possile, so later function can use it.\r
127 //\r
128 CpuFeaturesData->MpService = GetMpService ();\r
129\r
130 GetNumberOfProcessor (&NumberOfCpus, &NumberOfEnabledProcessors);\r
131\r
004f9776 132 CpuFeaturesData->InitOrder = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus));\r
80c4b236 133 ASSERT (CpuFeaturesData->InitOrder != NULL);\r
004f9776 134 ZeroMem (CpuFeaturesData->InitOrder, sizeof (CPU_FEATURES_INIT_ORDER) * NumberOfCpus);\r
80c4b236
JF
135\r
136 //\r
137 // Collect CPU Features information\r
138 //\r
139 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
140 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
141 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
142 ASSERT (CpuFeature->InitializeFunc != NULL);\r
143 if (CpuFeature->GetConfigDataFunc != NULL) {\r
144 CpuFeature->ConfigData = CpuFeature->GetConfigDataFunc (NumberOfCpus);\r
145 }\r
053e878b 146\r
80c4b236
JF
147 Entry = Entry->ForwardLink;\r
148 }\r
149\r
053e878b 150 CpuFeaturesData->NumberOfCpus = (UINT32)NumberOfCpus;\r
b3c71b47
ED
151\r
152 AcpiCpuData = GetAcpiCpuData ();\r
153 ASSERT (AcpiCpuData != NULL);\r
053e878b 154 CpuFeaturesData->AcpiCpuData = AcpiCpuData;\r
b3c71b47 155\r
010753b7 156 CpuStatus = &AcpiCpuData->CpuFeatureInitData.CpuStatus;\r
053e878b 157 Location = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus));\r
b3c71b47 158 ASSERT (Location != NULL);\r
37a33f02 159 ZeroMem (Location, sizeof (EFI_CPU_PHYSICAL_LOCATION) * NumberOfCpus);\r
010753b7 160 AcpiCpuData->CpuFeatureInitData.ApLocation = (EFI_PHYSICAL_ADDRESS)(UINTN)Location;\r
b3c71b47 161\r
80c4b236 162 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
053e878b 163 InitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
80c4b236
JF
164 InitOrder->FeaturesSupportedMask = AllocateZeroPool (CpuFeaturesData->BitMaskSize);\r
165 ASSERT (InitOrder->FeaturesSupportedMask != NULL);\r
166 InitializeListHead (&InitOrder->OrderList);\r
167 Status = GetProcessorInformation (ProcessorNumber, &ProcessorInfoBuffer);\r
168 ASSERT_EFI_ERROR (Status);\r
169 CopyMem (\r
170 &InitOrder->CpuInfo.ProcessorInfo,\r
171 &ProcessorInfoBuffer,\r
172 sizeof (EFI_PROCESSOR_INFORMATION)\r
173 );\r
b3c71b47
ED
174 CopyMem (\r
175 &Location[ProcessorNumber],\r
176 &ProcessorInfoBuffer.Location,\r
177 sizeof (EFI_CPU_PHYSICAL_LOCATION)\r
178 );\r
179\r
180 //\r
181 // Collect CPU package count info.\r
182 //\r
183 if (Package < ProcessorInfoBuffer.Location.Package) {\r
184 Package = ProcessorInfoBuffer.Location.Package;\r
185 }\r
053e878b 186\r
b3c71b47
ED
187 //\r
188 // Collect CPU max core count info.\r
189 //\r
190 if (Core < ProcessorInfoBuffer.Location.Core) {\r
191 Core = ProcessorInfoBuffer.Location.Core;\r
192 }\r
053e878b 193\r
b3c71b47
ED
194 //\r
195 // Collect CPU max thread count info.\r
196 //\r
197 if (Thread < ProcessorInfoBuffer.Location.Thread) {\r
198 Thread = ProcessorInfoBuffer.Location.Thread;\r
199 }\r
80c4b236 200 }\r
053e878b
MK
201\r
202 CpuStatus->PackageCount = Package + 1;\r
203 CpuStatus->MaxCoreCount = Core + 1;\r
204 CpuStatus->MaxThreadCount = Thread + 1;\r
205 DEBUG ((\r
206 DEBUG_INFO,\r
207 "Processor Info: Package: %d, MaxCore : %d, MaxThread: %d\n",\r
208 CpuStatus->PackageCount,\r
209 CpuStatus->MaxCoreCount,\r
210 CpuStatus->MaxThreadCount\r
211 ));\r
b3c71b47
ED
212\r
213 //\r
214 // Collect valid core count in each package because not all cores are valid.\r
215 //\r
37a33f02 216 ThreadCountPerPackage = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT32) * CpuStatus->PackageCount));\r
6af76adb 217 ASSERT (ThreadCountPerPackage != NULL);\r
37a33f02 218 ZeroMem (ThreadCountPerPackage, sizeof (UINT32) * CpuStatus->PackageCount);\r
6af76adb
RN
219 CpuStatus->ThreadCountPerPackage = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerPackage;\r
220\r
37a33f02 221 ThreadCountPerCore = AllocatePages (EFI_SIZE_TO_PAGES (sizeof (UINT8) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount));\r
6af76adb 222 ASSERT (ThreadCountPerCore != NULL);\r
37a33f02 223 ZeroMem (ThreadCountPerCore, sizeof (UINT8) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount);\r
6af76adb
RN
224 CpuStatus->ThreadCountPerCore = (EFI_PHYSICAL_ADDRESS)(UINTN)ThreadCountPerCore;\r
225\r
226 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
227 Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
228 ThreadCountPerPackage[Location->Package]++;\r
229 ThreadCountPerCore[Location->Package * CpuStatus->MaxCoreCount + Location->Core]++;\r
b3c71b47 230 }\r
b3c71b47 231\r
6af76adb
RN
232 for (PackageIndex = 0; PackageIndex < CpuStatus->PackageCount; PackageIndex++) {\r
233 if (ThreadCountPerPackage[PackageIndex] != 0) {\r
234 DEBUG ((DEBUG_INFO, "P%02d: Thread Count = %d\n", PackageIndex, ThreadCountPerPackage[PackageIndex]));\r
235 for (CoreIndex = 0; CoreIndex < CpuStatus->MaxCoreCount; CoreIndex++) {\r
236 if (ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex] != 0) {\r
237 DEBUG ((\r
053e878b
MK
238 DEBUG_INFO,\r
239 " P%02d C%04d, Thread Count = %d\n",\r
240 PackageIndex,\r
241 CoreIndex,\r
6af76adb
RN
242 ThreadCountPerCore[PackageIndex * CpuStatus->MaxCoreCount + CoreIndex]\r
243 ));\r
244 }\r
245 }\r
246 }\r
b3c71b47
ED
247 }\r
248\r
91ff5bba
ED
249 CpuFeaturesData->CpuFlags.CoreSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
250 ASSERT (CpuFeaturesData->CpuFlags.CoreSemaphoreCount != NULL);\r
251 CpuFeaturesData->CpuFlags.PackageSemaphoreCount = AllocateZeroPool (sizeof (UINT32) * CpuStatus->PackageCount * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount);\r
252 ASSERT (CpuFeaturesData->CpuFlags.PackageSemaphoreCount != NULL);\r
534fcb84
RN
253\r
254 //\r
255 // Initialize CpuFeaturesData->InitOrder[].CpuInfo.First\r
793c59da 256 // Use AllocatePages () instead of AllocatePool () because pool cannot be freed in PEI phase but page can.\r
534fcb84 257 //\r
793c59da
RN
258 Pages = EFI_SIZE_TO_PAGES (CpuStatus->PackageCount * sizeof (UINT32) + CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32));\r
259 FirstCore = AllocatePages (Pages);\r
260 ASSERT (FirstCore != NULL);\r
053e878b 261 FirstThread = FirstCore + CpuStatus->PackageCount;\r
534fcb84
RN
262\r
263 //\r
793c59da 264 // Set FirstPackage, FirstCore[], FirstThread[] to maximum package ID, core ID, thread ID.\r
534fcb84 265 //\r
793c59da 266 FirstPackage = MAX_UINT32;\r
053e878b 267 SetMem32 (FirstCore, CpuStatus->PackageCount * sizeof (UINT32), MAX_UINT32);\r
793c59da
RN
268 SetMem32 (FirstThread, CpuStatus->PackageCount * CpuStatus->MaxCoreCount * sizeof (UINT32), MAX_UINT32);\r
269\r
534fcb84
RN
270 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
271 Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
793c59da
RN
272\r
273 //\r
274 // Save the minimum package ID in the platform.\r
275 //\r
053e878b 276 FirstPackage = MIN (Location->Package, FirstPackage);\r
793c59da
RN
277\r
278 //\r
279 // Save the minimum core ID per package.\r
280 //\r
281 FirstCore[Location->Package] = MIN (Location->Core, FirstCore[Location->Package]);\r
282\r
283 //\r
284 // Save the minimum thread ID per core.\r
285 //\r
286 FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core] = MIN (\r
053e878b
MK
287 Location->Thread,\r
288 FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]\r
289 );\r
534fcb84 290 }\r
793c59da
RN
291\r
292 //\r
293 // Update the First field.\r
294 //\r
534fcb84
RN
295 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
296 Location = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.ProcessorInfo.Location;\r
793c59da
RN
297\r
298 if (Location->Package == FirstPackage) {\r
534fcb84
RN
299 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Package = 1;\r
300 }\r
534fcb84 301\r
793c59da
RN
302 //\r
303 // Set First.Die/Tile/Module for each thread assuming:\r
304 // single Die under each package, single Tile under each Die, single Module under each Tile\r
305 //\r
053e878b
MK
306 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Die = 1;\r
307 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Tile = 1;\r
534fcb84 308 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Module = 1;\r
534fcb84 309\r
793c59da
RN
310 if (Location->Core == FirstCore[Location->Package]) {\r
311 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Core = 1;\r
534fcb84 312 }\r
053e878b 313\r
793c59da
RN
314 if (Location->Thread == FirstThread[Location->Package * CpuStatus->MaxCoreCount + Location->Core]) {\r
315 CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo.First.Thread = 1;\r
534fcb84
RN
316 }\r
317 }\r
318\r
793c59da 319 FreePages (FirstCore, Pages);\r
80c4b236
JF
320}\r
321\r
322/**\r
323 Worker function to do OR operation on CPU feature supported bits mask buffer.\r
324\r
325 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
326 @param[in] OrFeatureBitMask The feature bit mask to do OR operation\r
bbd357ae
ED
327 @param[in] BitMaskSize The CPU feature bits mask buffer size.\r
328\r
80c4b236
JF
329**/\r
330VOID\r
331SupportedMaskOr (\r
053e878b
MK
332 IN UINT8 *SupportedFeatureMask,\r
333 IN UINT8 *OrFeatureBitMask,\r
334 IN UINT32 BitMaskSize\r
80c4b236
JF
335 )\r
336{\r
053e878b
MK
337 UINTN Index;\r
338 UINT8 *Data1;\r
339 UINT8 *Data2;\r
80c4b236 340\r
80c4b236
JF
341 Data1 = SupportedFeatureMask;\r
342 Data2 = OrFeatureBitMask;\r
343 for (Index = 0; Index < BitMaskSize; Index++) {\r
344 *(Data1++) |= *(Data2++);\r
345 }\r
346}\r
347\r
348/**\r
349 Worker function to do AND operation on CPU feature supported bits mask buffer.\r
350\r
351 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
352 @param[in] AndFeatureBitMask The feature bit mask to do AND operation\r
3dafa038
ED
353 @param[in] BitMaskSize CPU feature bits mask buffer size.\r
354\r
80c4b236
JF
355**/\r
356VOID\r
357SupportedMaskAnd (\r
053e878b
MK
358 IN UINT8 *SupportedFeatureMask,\r
359 IN CONST UINT8 *AndFeatureBitMask,\r
360 IN UINT32 BitMaskSize\r
80c4b236
JF
361 )\r
362{\r
053e878b
MK
363 UINTN Index;\r
364 UINT8 *Data1;\r
365 CONST UINT8 *Data2;\r
80c4b236 366\r
80c4b236
JF
367 Data1 = SupportedFeatureMask;\r
368 Data2 = AndFeatureBitMask;\r
369 for (Index = 0; Index < BitMaskSize; Index++) {\r
370 *(Data1++) &= *(Data2++);\r
371 }\r
372}\r
373\r
05973f9e
ED
374/**\r
375 Worker function to clean bit operation on CPU feature supported bits mask buffer.\r
376\r
377 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
378 @param[in] AndFeatureBitMask The feature bit mask to do XOR operation\r
3dafa038 379 @param[in] BitMaskSize CPU feature bits mask buffer size.\r
05973f9e
ED
380**/\r
381VOID\r
382SupportedMaskCleanBit (\r
053e878b
MK
383 IN UINT8 *SupportedFeatureMask,\r
384 IN UINT8 *AndFeatureBitMask,\r
385 IN UINT32 BitMaskSize\r
05973f9e
ED
386 )\r
387{\r
053e878b
MK
388 UINTN Index;\r
389 UINT8 *Data1;\r
390 UINT8 *Data2;\r
05973f9e 391\r
05973f9e
ED
392 Data1 = SupportedFeatureMask;\r
393 Data2 = AndFeatureBitMask;\r
394 for (Index = 0; Index < BitMaskSize; Index++) {\r
395 *(Data1++) &= ~(*(Data2++));\r
396 }\r
397}\r
398\r
80c4b236
JF
399/**\r
400 Worker function to check if the compared CPU feature set in the CPU feature\r
401 supported bits mask buffer.\r
402\r
403 @param[in] SupportedFeatureMask The pointer to CPU feature bits mask buffer\r
404 @param[in] ComparedFeatureBitMask The feature bit mask to be compared\r
3dafa038 405 @param[in] BitMaskSize CPU feature bits mask buffer size.\r
80c4b236
JF
406\r
407 @retval TRUE The ComparedFeatureBitMask is set in CPU feature supported bits\r
408 mask buffer.\r
409 @retval FALSE The ComparedFeatureBitMask is not set in CPU feature supported bits\r
410 mask buffer.\r
411**/\r
412BOOLEAN\r
413IsBitMaskMatch (\r
053e878b
MK
414 IN UINT8 *SupportedFeatureMask,\r
415 IN UINT8 *ComparedFeatureBitMask,\r
416 IN UINT32 BitMaskSize\r
80c4b236
JF
417 )\r
418{\r
053e878b
MK
419 UINTN Index;\r
420 UINT8 *Data1;\r
421 UINT8 *Data2;\r
80c4b236 422\r
80c4b236
JF
423 Data1 = SupportedFeatureMask;\r
424 Data2 = ComparedFeatureBitMask;\r
425 for (Index = 0; Index < BitMaskSize; Index++) {\r
426 if (((*(Data1++)) & (*(Data2++))) != 0) {\r
427 return TRUE;\r
428 }\r
429 }\r
053e878b 430\r
80c4b236
JF
431 return FALSE;\r
432}\r
433\r
434/**\r
435 Collects processor data for calling processor.\r
436\r
437 @param[in,out] Buffer The pointer to private data buffer.\r
438**/\r
439VOID\r
440EFIAPI\r
441CollectProcessorData (\r
053e878b 442 IN OUT VOID *Buffer\r
80c4b236
JF
443 )\r
444{\r
053e878b
MK
445 UINTN ProcessorNumber;\r
446 CPU_FEATURES_ENTRY *CpuFeature;\r
447 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
448 LIST_ENTRY *Entry;\r
449 CPU_FEATURES_DATA *CpuFeaturesData;\r
80c4b236 450\r
b3c71b47 451 CpuFeaturesData = (CPU_FEATURES_DATA *)Buffer;\r
7217b879 452 ProcessorNumber = GetProcessorIndex (CpuFeaturesData);\r
053e878b 453 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
80c4b236
JF
454 //\r
455 // collect processor information\r
456 //\r
457 FillProcessorInfo (CpuInfo);\r
458 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
459 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
460 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
001c2c80
ED
461 if (CpuFeature->SupportFunc == NULL) {\r
462 //\r
463 // If SupportFunc is NULL, then the feature is supported.\r
464 //\r
465 SupportedMaskOr (\r
466 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
bbd357ae
ED
467 CpuFeature->FeatureMask,\r
468 CpuFeaturesData->BitMaskSize\r
001c2c80
ED
469 );\r
470 } else if (CpuFeature->SupportFunc (ProcessorNumber, CpuInfo, CpuFeature->ConfigData)) {\r
471 SupportedMaskOr (\r
472 CpuFeaturesData->InitOrder[ProcessorNumber].FeaturesSupportedMask,\r
bbd357ae
ED
473 CpuFeature->FeatureMask,\r
474 CpuFeaturesData->BitMaskSize\r
001c2c80 475 );\r
80c4b236 476 }\r
053e878b 477\r
80c4b236
JF
478 Entry = Entry->ForwardLink;\r
479 }\r
480}\r
481\r
482/**\r
483 Dump the contents of a CPU register table.\r
484\r
485 @param[in] ProcessorNumber The index of the CPU to show the register table contents\r
486\r
487 @note This service could be called by BSP only.\r
488**/\r
489VOID\r
490DumpRegisterTableOnProcessor (\r
053e878b 491 IN UINTN ProcessorNumber\r
80c4b236
JF
492 )\r
493{\r
053e878b
MK
494 CPU_FEATURES_DATA *CpuFeaturesData;\r
495 UINTN FeatureIndex;\r
496 CPU_REGISTER_TABLE *RegisterTable;\r
497 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
498 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
499 UINT32 DebugPrintErrorLevel;\r
80c4b236
JF
500\r
501 DebugPrintErrorLevel = (ProcessorNumber == 0) ? DEBUG_INFO : DEBUG_VERBOSE;\r
502 CpuFeaturesData = GetCpuFeaturesData ();\r
503 //\r
504 // Debug information\r
505 //\r
506 RegisterTable = &CpuFeaturesData->RegisterTable[ProcessorNumber];\r
507 DEBUG ((DebugPrintErrorLevel, "RegisterTable->TableLength = %d\n", RegisterTable->TableLength));\r
508\r
053e878b 509 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *)(UINTN)RegisterTable->RegisterTableEntry;\r
80c4b236
JF
510\r
511 for (FeatureIndex = 0; FeatureIndex < RegisterTable->TableLength; FeatureIndex++) {\r
512 RegisterTableEntry = &RegisterTableEntryHead[FeatureIndex];\r
513 switch (RegisterTableEntry->RegisterType) {\r
053e878b
MK
514 case Msr:\r
515 DEBUG ((\r
516 DebugPrintErrorLevel,\r
517 "Processor: %04d: Index %04d, MSR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
518 (UINT32)ProcessorNumber,\r
519 (UINT32)FeatureIndex,\r
520 RegisterTableEntry->Index,\r
521 RegisterTableEntry->ValidBitStart,\r
522 RegisterTableEntry->ValidBitLength,\r
523 RegisterTableEntry->Value\r
524 ));\r
525 break;\r
526 case ControlRegister:\r
527 DEBUG ((\r
528 DebugPrintErrorLevel,\r
529 "Processor: %04d: Index %04d, CR : %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
530 (UINT32)ProcessorNumber,\r
531 (UINT32)FeatureIndex,\r
532 RegisterTableEntry->Index,\r
533 RegisterTableEntry->ValidBitStart,\r
534 RegisterTableEntry->ValidBitLength,\r
535 RegisterTableEntry->Value\r
536 ));\r
537 break;\r
538 case MemoryMapped:\r
539 DEBUG ((\r
540 DebugPrintErrorLevel,\r
541 "Processor: %04d: Index %04d, MMIO : %016lx, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
542 (UINT32)ProcessorNumber,\r
543 (UINT32)FeatureIndex,\r
544 RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32),\r
545 RegisterTableEntry->ValidBitStart,\r
546 RegisterTableEntry->ValidBitLength,\r
547 RegisterTableEntry->Value\r
548 ));\r
549 break;\r
550 case CacheControl:\r
551 DEBUG ((\r
552 DebugPrintErrorLevel,\r
553 "Processor: %04d: Index %04d, CACHE: %08x, Bit Start: %02d, Bit Length: %02d, Value: %016lx\r\n",\r
554 (UINT32)ProcessorNumber,\r
555 (UINT32)FeatureIndex,\r
556 RegisterTableEntry->Index,\r
557 RegisterTableEntry->ValidBitStart,\r
558 RegisterTableEntry->ValidBitLength,\r
559 RegisterTableEntry->Value\r
560 ));\r
561 break;\r
562 case Semaphore:\r
563 DEBUG ((\r
564 DebugPrintErrorLevel,\r
565 "Processor: %04d: Index %04d, SEMAP: %s\r\n",\r
566 (UINT32)ProcessorNumber,\r
567 (UINT32)FeatureIndex,\r
568 mDependTypeStr[MIN ((UINT32)RegisterTableEntry->Value, InvalidDepType)]\r
569 ));\r
570 break;\r
b3c71b47 571\r
053e878b
MK
572 default:\r
573 break;\r
80c4b236
JF
574 }\r
575 }\r
576}\r
577\r
c1528b85
ED
578/**\r
579 Get the biggest dependence type.\r
580 PackageDepType > CoreDepType > ThreadDepType > NoneDepType.\r
581\r
582 @param[in] BeforeDep Before dependence type.\r
583 @param[in] AfterDep After dependence type.\r
584 @param[in] NoneNeibBeforeDep Before dependence type for not neighborhood features.\r
585 @param[in] NoneNeibAfterDep After dependence type for not neighborhood features.\r
586\r
587 @retval Return the biggest dependence type.\r
588**/\r
589CPU_FEATURE_DEPENDENCE_TYPE\r
590BiggestDep (\r
591 IN CPU_FEATURE_DEPENDENCE_TYPE BeforeDep,\r
592 IN CPU_FEATURE_DEPENDENCE_TYPE AfterDep,\r
593 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep,\r
594 IN CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep\r
595 )\r
596{\r
053e878b 597 CPU_FEATURE_DEPENDENCE_TYPE Bigger;\r
c1528b85
ED
598\r
599 Bigger = MAX (BeforeDep, AfterDep);\r
600 Bigger = MAX (Bigger, NoneNeibBeforeDep);\r
053e878b 601 return MAX (Bigger, NoneNeibAfterDep);\r
c1528b85
ED
602}\r
603\r
80c4b236
JF
604/**\r
605 Analysis register CPU features on each processor and save CPU setting in CPU register table.\r
606\r
607 @param[in] NumberOfCpus Number of processor in system\r
608\r
609**/\r
610VOID\r
611AnalysisProcessorFeatures (\r
053e878b 612 IN UINTN NumberOfCpus\r
80c4b236
JF
613 )\r
614{\r
053e878b
MK
615 EFI_STATUS Status;\r
616 UINTN ProcessorNumber;\r
617 CPU_FEATURES_ENTRY *CpuFeature;\r
618 CPU_FEATURES_ENTRY *CpuFeatureInOrder;\r
619 CPU_FEATURES_INIT_ORDER *CpuInitOrder;\r
620 REGISTER_CPU_FEATURE_INFORMATION *CpuInfo;\r
621 LIST_ENTRY *Entry;\r
622 CPU_FEATURES_DATA *CpuFeaturesData;\r
623 LIST_ENTRY *NextEntry;\r
624 CPU_FEATURES_ENTRY *NextCpuFeatureInOrder;\r
625 BOOLEAN Success;\r
626 CPU_FEATURE_DEPENDENCE_TYPE BeforeDep;\r
627 CPU_FEATURE_DEPENDENCE_TYPE AfterDep;\r
628 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibBeforeDep;\r
629 CPU_FEATURE_DEPENDENCE_TYPE NoneNeibAfterDep;\r
630\r
631 CpuFeaturesData = GetCpuFeaturesData ();\r
7d3a7c22
SB
632 CpuFeaturesData->CapabilityPcd = AllocatePool (CpuFeaturesData->BitMaskSize);\r
633 ASSERT (CpuFeaturesData->CapabilityPcd != NULL);\r
634 SetMem (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize, 0xFF);\r
80c4b236
JF
635 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
636 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
637 //\r
638 // Calculate the last capability on all processors\r
639 //\r
3dafa038 640 SupportedMaskAnd (CpuFeaturesData->CapabilityPcd, CpuInitOrder->FeaturesSupportedMask, CpuFeaturesData->BitMaskSize);\r
80c4b236 641 }\r
053e878b 642\r
80c4b236
JF
643 //\r
644 // Calculate the last setting\r
645 //\r
7d3a7c22
SB
646 CpuFeaturesData->SettingPcd = AllocateCopyPool (CpuFeaturesData->BitMaskSize, CpuFeaturesData->CapabilityPcd);\r
647 ASSERT (CpuFeaturesData->SettingPcd != NULL);\r
3dafa038 648 SupportedMaskAnd (CpuFeaturesData->SettingPcd, PcdGetPtr (PcdCpuFeaturesSetting), CpuFeaturesData->BitMaskSize);\r
80c4b236
JF
649\r
650 //\r
651 // Dump the last CPU feature list\r
652 //\r
7c2a6033 653 DEBUG_CODE_BEGIN ();\r
053e878b
MK
654 DEBUG ((DEBUG_INFO, "Last CPU features list...\n"));\r
655 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
656 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
657 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
658 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize)) {\r
659 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize)) {\r
660 DEBUG ((DEBUG_INFO, "[Enable ] "));\r
80c4b236 661 } else {\r
053e878b 662 DEBUG ((DEBUG_INFO, "[Disable ] "));\r
80c4b236 663 }\r
053e878b
MK
664 } else {\r
665 DEBUG ((DEBUG_INFO, "[Unsupport] "));\r
80c4b236 666 }\r
053e878b
MK
667\r
668 DumpCpuFeature (CpuFeature, CpuFeaturesData->BitMaskSize);\r
669 Entry = Entry->ForwardLink;\r
670 }\r
671\r
672 DEBUG ((DEBUG_INFO, "PcdCpuFeaturesCapability:\n"));\r
673 DumpCpuFeatureMask (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize);\r
674 DEBUG ((DEBUG_INFO, "Origin PcdCpuFeaturesSetting:\n"));\r
675 DumpCpuFeatureMask (PcdGetPtr (PcdCpuFeaturesSetting), CpuFeaturesData->BitMaskSize);\r
676 DEBUG ((DEBUG_INFO, "Final PcdCpuFeaturesSetting:\n"));\r
677 DumpCpuFeatureMask (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
7c2a6033 678 DEBUG_CODE_END ();\r
80c4b236 679\r
6214ffb4
ED
680 //\r
681 // Save PCDs and display CPU PCDs\r
682 //\r
683 SetCapabilityPcd (CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize);\r
3dafa038 684 SetSettingPcd (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
6214ffb4 685\r
80c4b236
JF
686 for (ProcessorNumber = 0; ProcessorNumber < NumberOfCpus; ProcessorNumber++) {\r
687 CpuInitOrder = &CpuFeaturesData->InitOrder[ProcessorNumber];\r
053e878b 688 Entry = GetFirstNode (&CpuFeaturesData->FeatureList);\r
80c4b236
JF
689 while (!IsNull (&CpuFeaturesData->FeatureList, Entry)) {\r
690 //\r
691 // Insert each feature into processor's order list\r
692 //\r
693 CpuFeature = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
3dafa038 694 if (IsBitMaskMatch (CpuFeature->FeatureMask, CpuFeaturesData->CapabilityPcd, CpuFeaturesData->BitMaskSize)) {\r
80c4b236
JF
695 CpuFeatureInOrder = AllocateCopyPool (sizeof (CPU_FEATURES_ENTRY), CpuFeature);\r
696 ASSERT (CpuFeatureInOrder != NULL);\r
697 InsertTailList (&CpuInitOrder->OrderList, &CpuFeatureInOrder->Link);\r
698 }\r
053e878b 699\r
80c4b236
JF
700 Entry = Entry->ForwardLink;\r
701 }\r
053e878b 702\r
80c4b236
JF
703 //\r
704 // Go through ordered feature list to initialize CPU features\r
705 //\r
706 CpuInfo = &CpuFeaturesData->InitOrder[ProcessorNumber].CpuInfo;\r
053e878b 707 Entry = GetFirstNode (&CpuInitOrder->OrderList);\r
80c4b236
JF
708 while (!IsNull (&CpuInitOrder->OrderList, Entry)) {\r
709 CpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (Entry);\r
c1528b85 710\r
b3c71b47 711 Success = FALSE;\r
3dafa038 712 if (IsBitMaskMatch (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize)) {\r
80c4b236 713 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, TRUE);\r
05973f9e
ED
714 if (EFI_ERROR (Status)) {\r
715 //\r
716 // Clean the CpuFeatureInOrder->FeatureMask in setting PCD.\r
717 //\r
3dafa038 718 SupportedMaskCleanBit (CpuFeaturesData->SettingPcd, CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\r
05973f9e 719 if (CpuFeatureInOrder->FeatureName != NULL) {\r
2bda6247 720 DEBUG ((DEBUG_WARN, "Warning :: Failed to enable Feature: Name = %a.\n", CpuFeatureInOrder->FeatureName));\r
05973f9e 721 } else {\r
2bda6247 722 DEBUG ((DEBUG_WARN, "Warning :: Failed to enable Feature: Mask = "));\r
3dafa038 723 DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\r
05973f9e 724 }\r
b3c71b47
ED
725 } else {\r
726 Success = TRUE;\r
05973f9e 727 }\r
80c4b236
JF
728 } else {\r
729 Status = CpuFeatureInOrder->InitializeFunc (ProcessorNumber, CpuInfo, CpuFeatureInOrder->ConfigData, FALSE);\r
852b3935
ED
730 if (EFI_ERROR (Status)) {\r
731 if (CpuFeatureInOrder->FeatureName != NULL) {\r
2bda6247 732 DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Name = %a.\n", CpuFeatureInOrder->FeatureName));\r
852b3935 733 } else {\r
2bda6247 734 DEBUG ((DEBUG_WARN, "Warning :: Failed to disable Feature: Mask = "));\r
3dafa038 735 DumpCpuFeatureMask (CpuFeatureInOrder->FeatureMask, CpuFeaturesData->BitMaskSize);\r
852b3935 736 }\r
b3c71b47
ED
737 } else {\r
738 Success = TRUE;\r
852b3935 739 }\r
80c4b236 740 }\r
b3c71b47
ED
741\r
742 if (Success) {\r
c1528b85
ED
743 NextEntry = Entry->ForwardLink;\r
744 if (!IsNull (&CpuInitOrder->OrderList, NextEntry)) {\r
745 NextCpuFeatureInOrder = CPU_FEATURE_ENTRY_FROM_LINK (NextEntry);\r
746\r
747 //\r
748 // If feature has dependence with the next feature (ONLY care core/package dependency).\r
749 // and feature initialize succeed, add sync semaphere here.\r
750 //\r
1475b83f
ED
751 BeforeDep = DetectFeatureScope (CpuFeatureInOrder, TRUE, NextCpuFeatureInOrder->FeatureMask);\r
752 AfterDep = DetectFeatureScope (NextCpuFeatureInOrder, FALSE, CpuFeatureInOrder->FeatureMask);\r
c1528b85
ED
753 //\r
754 // Check whether next feature has After type dependence with not neighborhood CPU\r
755 // Features in former CPU features.\r
756 //\r
053e878b 757 NoneNeibAfterDep = DetectNoneNeighborhoodFeatureScope (NextCpuFeatureInOrder, FALSE, &CpuInitOrder->OrderList);\r
b3c71b47 758 } else {\r
c1528b85
ED
759 BeforeDep = NoneDepType;\r
760 AfterDep = NoneDepType;\r
761 NoneNeibAfterDep = NoneDepType;\r
b3c71b47 762 }\r
053e878b 763\r
b3c71b47 764 //\r
c1528b85
ED
765 // Check whether current feature has Before type dependence with none neighborhood\r
766 // CPU features in after Cpu features.\r
767 //\r
053e878b 768 NoneNeibBeforeDep = DetectNoneNeighborhoodFeatureScope (CpuFeatureInOrder, TRUE, &CpuInitOrder->OrderList);\r
c1528b85
ED
769\r
770 //\r
771 // Get the biggest dependence and add semaphore for it.\r
772 // PackageDepType > CoreDepType > ThreadDepType > NoneDepType.\r
b3c71b47 773 //\r
053e878b 774 BeforeDep = BiggestDep (BeforeDep, AfterDep, NoneNeibBeforeDep, NoneNeibAfterDep);\r
b3c71b47
ED
775 if (BeforeDep > ThreadDepType) {\r
776 CPU_REGISTER_TABLE_WRITE32 (ProcessorNumber, Semaphore, 0, BeforeDep);\r
777 }\r
b3c71b47
ED
778 }\r
779\r
c1528b85 780 Entry = Entry->ForwardLink;\r
80c4b236 781 }\r
05973f9e
ED
782\r
783 //\r
784 // Dump PcdCpuFeaturesSetting again because this value maybe updated\r
785 // again during initialize the features.\r
786 //\r
787 DEBUG ((DEBUG_INFO, "Dump final value for PcdCpuFeaturesSetting:\n"));\r
3dafa038 788 DumpCpuFeatureMask (CpuFeaturesData->SettingPcd, CpuFeaturesData->BitMaskSize);\r
05973f9e 789\r
80c4b236
JF
790 //\r
791 // Dump the RegisterTable\r
792 //\r
793 DumpRegisterTableOnProcessor (ProcessorNumber);\r
794 }\r
795}\r
796\r
b3c71b47
ED
797/**\r
798 Increment semaphore by 1.\r
799\r
800 @param Sem IN: 32-bit unsigned integer\r
801\r
802**/\r
803VOID\r
804LibReleaseSemaphore (\r
053e878b 805 IN OUT volatile UINT32 *Sem\r
b3c71b47
ED
806 )\r
807{\r
808 InterlockedIncrement (Sem);\r
809}\r
810\r
811/**\r
812 Decrement the semaphore by 1 if it is not zero.\r
813\r
814 Performs an atomic decrement operation for semaphore.\r
815 The compare exchange operation must be performed using\r
816 MP safe mechanisms.\r
817\r
818 @param Sem IN: 32-bit unsigned integer\r
819\r
820**/\r
821VOID\r
822LibWaitForSemaphore (\r
053e878b 823 IN OUT volatile UINT32 *Sem\r
b3c71b47
ED
824 )\r
825{\r
826 UINT32 Value;\r
827\r
828 do {\r
829 Value = *Sem;\r
830 } while (Value == 0 ||\r
831 InterlockedCompareExchange32 (\r
832 Sem,\r
833 Value,\r
834 Value - 1\r
835 ) != Value);\r
836}\r
837\r
6b3645ad
ED
838/**\r
839 Read / write CR value.\r
840\r
841 @param[in] CrIndex The CR index which need to read/write.\r
842 @param[in] Read Read or write. TRUE is read.\r
843 @param[in,out] CrValue CR value.\r
844\r
845 @retval EFI_SUCCESS means read/write success, else return EFI_UNSUPPORTED.\r
846**/\r
847UINTN\r
848ReadWriteCr (\r
053e878b
MK
849 IN UINT32 CrIndex,\r
850 IN BOOLEAN Read,\r
851 IN OUT UINTN *CrValue\r
6b3645ad
ED
852 )\r
853{\r
854 switch (CrIndex) {\r
053e878b
MK
855 case 0:\r
856 if (Read) {\r
857 *CrValue = AsmReadCr0 ();\r
858 } else {\r
859 AsmWriteCr0 (*CrValue);\r
860 }\r
861\r
862 break;\r
863 case 2:\r
864 if (Read) {\r
865 *CrValue = AsmReadCr2 ();\r
866 } else {\r
867 AsmWriteCr2 (*CrValue);\r
868 }\r
869\r
870 break;\r
871 case 3:\r
872 if (Read) {\r
873 *CrValue = AsmReadCr3 ();\r
874 } else {\r
875 AsmWriteCr3 (*CrValue);\r
876 }\r
877\r
878 break;\r
879 case 4:\r
880 if (Read) {\r
881 *CrValue = AsmReadCr4 ();\r
882 } else {\r
883 AsmWriteCr4 (*CrValue);\r
884 }\r
885\r
886 break;\r
887 default:\r
888 return EFI_UNSUPPORTED;\r
6b3645ad
ED
889 }\r
890\r
891 return EFI_SUCCESS;\r
892}\r
893\r
80c4b236
JF
894/**\r
895 Initialize the CPU registers from a register table.\r
896\r
b3c71b47
ED
897 @param[in] RegisterTable The register table for this AP.\r
898 @param[in] ApLocation AP location info for this ap.\r
899 @param[in] CpuStatus CPU status info for this CPU.\r
900 @param[in] CpuFlags Flags data structure used when program the register.\r
80c4b236
JF
901\r
902 @note This service could be called by BSP/APs.\r
903**/\r
904VOID\r
905ProgramProcessorRegister (\r
053e878b
MK
906 IN CPU_REGISTER_TABLE *RegisterTable,\r
907 IN EFI_CPU_PHYSICAL_LOCATION *ApLocation,\r
908 IN CPU_STATUS_INFORMATION *CpuStatus,\r
909 IN PROGRAM_CPU_REGISTER_FLAGS *CpuFlags\r
80c4b236
JF
910 )\r
911{\r
80c4b236
JF
912 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntry;\r
913 UINTN Index;\r
914 UINTN Value;\r
915 CPU_REGISTER_TABLE_ENTRY *RegisterTableEntryHead;\r
b3c71b47
ED
916 volatile UINT32 *SemaphorePtr;\r
917 UINT32 FirstThread;\r
b3c71b47 918 UINT32 CurrentThread;\r
6af76adb 919 UINT32 CurrentCore;\r
b3c71b47 920 UINTN ProcessorIndex;\r
6af76adb
RN
921 UINT32 *ThreadCountPerPackage;\r
922 UINT8 *ThreadCountPerCore;\r
6b3645ad 923 EFI_STATUS Status;\r
95cfe6c2 924 UINT64 CurrentValue;\r
80c4b236
JF
925\r
926 //\r
927 // Traverse Register Table of this logical processor\r
928 //\r
053e878b 929 RegisterTableEntryHead = (CPU_REGISTER_TABLE_ENTRY *)(UINTN)RegisterTable->RegisterTableEntry;\r
80c4b236
JF
930\r
931 for (Index = 0; Index < RegisterTable->TableLength; Index++) {\r
80c4b236
JF
932 RegisterTableEntry = &RegisterTableEntryHead[Index];\r
933\r
934 //\r
935 // Check the type of specified register\r
936 //\r
937 switch (RegisterTableEntry->RegisterType) {\r
053e878b
MK
938 //\r
939 // The specified register is Control Register\r
940 //\r
941 case ControlRegister:\r
942 Status = ReadWriteCr (RegisterTableEntry->Index, TRUE, &Value);\r
943 if (EFI_ERROR (Status)) {\r
95cfe6c2
ED
944 break;\r
945 }\r
95cfe6c2 946\r
053e878b 947 if (RegisterTableEntry->TestThenWrite) {\r
95cfe6c2
ED
948 CurrentValue = BitFieldRead64 (\r
949 Value,\r
950 RegisterTableEntry->ValidBitStart,\r
951 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
952 );\r
953 if (CurrentValue == RegisterTableEntry->Value) {\r
954 break;\r
955 }\r
956 }\r
95cfe6c2 957\r
053e878b
MK
958 Value = (UINTN)BitFieldWrite64 (\r
959 Value,\r
960 RegisterTableEntry->ValidBitStart,\r
961 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
962 RegisterTableEntry->Value\r
963 );\r
964 ReadWriteCr (RegisterTableEntry->Index, FALSE, &Value);\r
965 break;\r
80c4b236 966\r
b3c71b47 967 //\r
053e878b 968 // The specified register is Model Specific Register\r
b3c71b47 969 //\r
053e878b
MK
970 case Msr:\r
971 if (RegisterTableEntry->TestThenWrite) {\r
972 Value = (UINTN)AsmReadMsr64 (RegisterTableEntry->Index);\r
973 if (RegisterTableEntry->ValidBitLength >= 64) {\r
974 if (Value == RegisterTableEntry->Value) {\r
975 break;\r
976 }\r
977 } else {\r
978 CurrentValue = BitFieldRead64 (\r
979 Value,\r
980 RegisterTableEntry->ValidBitStart,\r
981 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1\r
982 );\r
983 if (CurrentValue == RegisterTableEntry->Value) {\r
984 break;\r
985 }\r
986 }\r
987 }\r
988\r
989 if (RegisterTableEntry->ValidBitLength >= 64) {\r
990 //\r
991 // If length is not less than 64 bits, then directly write without reading\r
992 //\r
993 AsmWriteMsr64 (\r
994 RegisterTableEntry->Index,\r
995 RegisterTableEntry->Value\r
996 );\r
997 } else {\r
998 //\r
999 // Set the bit section according to bit start and length\r
1000 //\r
1001 AsmMsrBitFieldWrite64 (\r
1002 RegisterTableEntry->Index,\r
1003 RegisterTableEntry->ValidBitStart,\r
1004 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
1005 RegisterTableEntry->Value\r
1006 );\r
1007 }\r
1008\r
1009 break;\r
b3c71b47 1010 //\r
053e878b 1011 // MemoryMapped operations\r
b3c71b47 1012 //\r
053e878b
MK
1013 case MemoryMapped:\r
1014 AcquireSpinLock (&CpuFlags->MemoryMappedLock);\r
1015 MmioBitFieldWrite32 (\r
1016 (UINTN)(RegisterTableEntry->Index | LShiftU64 (RegisterTableEntry->HighIndex, 32)),\r
1017 RegisterTableEntry->ValidBitStart,\r
1018 RegisterTableEntry->ValidBitStart + RegisterTableEntry->ValidBitLength - 1,\r
1019 (UINT32)RegisterTableEntry->Value\r
1020 );\r
1021 ReleaseSpinLock (&CpuFlags->MemoryMappedLock);\r
1022 break;\r
b3c71b47 1023 //\r
053e878b 1024 // Enable or disable cache\r
b3c71b47 1025 //\r
053e878b 1026 case CacheControl:\r
b3c71b47 1027 //\r
053e878b 1028 // If value of the entry is 0, then disable cache. Otherwise, enable cache.\r
b3c71b47 1029 //\r
053e878b
MK
1030 if (RegisterTableEntry->Value == 0) {\r
1031 AsmDisableCache ();\r
1032 } else {\r
1033 AsmEnableCache ();\r
b3c71b47 1034 }\r
053e878b 1035\r
b3c71b47
ED
1036 break;\r
1037\r
053e878b
MK
1038 case Semaphore:\r
1039 // Semaphore works logic like below:\r
b3c71b47 1040 //\r
053e878b
MK
1041 // V(x) = LibReleaseSemaphore (Semaphore[FirstThread + x]);\r
1042 // P(x) = LibWaitForSemaphore (Semaphore[FirstThread + x]);\r
b3c71b47 1043 //\r
053e878b
MK
1044 // All threads (T0...Tn) waits in P() line and continues running\r
1045 // together.\r
b3c71b47 1046 //\r
b3c71b47 1047 //\r
053e878b 1048 // T0 T1 ... Tn\r
b3c71b47 1049 //\r
053e878b
MK
1050 // V(0...n) V(0...n) ... V(0...n)\r
1051 // n * P(0) n * P(1) ... n * P(n)\r
b3c71b47 1052 //\r
053e878b
MK
1053 switch (RegisterTableEntry->Value) {\r
1054 case CoreDepType:\r
1055 SemaphorePtr = CpuFlags->CoreSemaphoreCount;\r
1056 ThreadCountPerCore = (UINT8 *)(UINTN)CpuStatus->ThreadCountPerCore;\r
1057\r
1058 CurrentCore = ApLocation->Package * CpuStatus->MaxCoreCount + ApLocation->Core;\r
1059 //\r
1060 // Get Offset info for the first thread in the core which current thread belongs to.\r
1061 //\r
1062 FirstThread = CurrentCore * CpuStatus->MaxThreadCount;\r
1063 CurrentThread = FirstThread + ApLocation->Thread;\r
1064\r
1065 //\r
1066 // Different cores may have different valid threads in them. If driver maintail clearly\r
1067 // thread index in different cores, the logic will be much complicated.\r
1068 // Here driver just simply records the max thread number in all cores and use it as expect\r
1069 // thread number for all cores.\r
1070 // In below two steps logic, first current thread will Release semaphore for each thread\r
1071 // in current core. Maybe some threads are not valid in this core, but driver don't\r
1072 // care. Second, driver will let current thread wait semaphore for all valid threads in\r
1073 // current core. Because only the valid threads will do release semaphore for this\r
1074 // thread, driver here only need to wait the valid thread count.\r
1075 //\r
1076\r
1077 //\r
1078 // First Notify ALL THREADs in current Core that this thread is ready.\r
1079 //\r
1080 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount; ProcessorIndex++) {\r
1081 LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
1082 }\r
1083\r
1084 //\r
1085 // Second, check whether all VALID THREADs (not all threads) in current core are ready.\r
1086 //\r
1087 for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerCore[CurrentCore]; ProcessorIndex++) {\r
1088 LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
1089 }\r
b3c71b47 1090\r
053e878b
MK
1091 break;\r
1092\r
1093 case PackageDepType:\r
1094 SemaphorePtr = CpuFlags->PackageSemaphoreCount;\r
1095 ThreadCountPerPackage = (UINT32 *)(UINTN)CpuStatus->ThreadCountPerPackage;\r
1096 //\r
1097 // Get Offset info for the first thread in the package which current thread belongs to.\r
1098 //\r
1099 FirstThread = ApLocation->Package * CpuStatus->MaxCoreCount * CpuStatus->MaxThreadCount;\r
1100 //\r
1101 // Get the possible threads count for current package.\r
1102 //\r
1103 CurrentThread = FirstThread + CpuStatus->MaxThreadCount * ApLocation->Core + ApLocation->Thread;\r
1104\r
1105 //\r
1106 // Different packages may have different valid threads in them. If driver maintail clearly\r
1107 // thread index in different packages, the logic will be much complicated.\r
1108 // Here driver just simply records the max thread number in all packages and use it as expect\r
1109 // thread number for all packages.\r
1110 // In below two steps logic, first current thread will Release semaphore for each thread\r
1111 // in current package. Maybe some threads are not valid in this package, but driver don't\r
1112 // care. Second, driver will let current thread wait semaphore for all valid threads in\r
1113 // current package. Because only the valid threads will do release semaphore for this\r
1114 // thread, driver here only need to wait the valid thread count.\r
1115 //\r
1116\r
1117 //\r
1118 // First Notify ALL THREADS in current package that this thread is ready.\r
1119 //\r
1120 for (ProcessorIndex = 0; ProcessorIndex < CpuStatus->MaxThreadCount * CpuStatus->MaxCoreCount; ProcessorIndex++) {\r
1121 LibReleaseSemaphore (&SemaphorePtr[FirstThread + ProcessorIndex]);\r
1122 }\r
1123\r
1124 //\r
1125 // Second, check whether VALID THREADS (not all threads) in current package are ready.\r
1126 //\r
1127 for (ProcessorIndex = 0; ProcessorIndex < ThreadCountPerPackage[ApLocation->Package]; ProcessorIndex++) {\r
1128 LibWaitForSemaphore (&SemaphorePtr[CurrentThread]);\r
1129 }\r
1130\r
1131 break;\r
1132\r
1133 default:\r
1134 break;\r
b3c71b47 1135 }\r
053e878b 1136\r
b3c71b47
ED
1137 break;\r
1138\r
1139 default:\r
1140 break;\r
80c4b236
JF
1141 }\r
1142 }\r
1143}\r
1144\r
1145/**\r
1146 Programs registers for the calling processor.\r
1147\r
1148 @param[in,out] Buffer The pointer to private data buffer.\r
1149\r
1150**/\r
1151VOID\r
1152EFIAPI\r
1153SetProcessorRegister (\r
053e878b 1154 IN OUT VOID *Buffer\r
80c4b236
JF
1155 )\r
1156{\r
053e878b
MK
1157 CPU_FEATURES_DATA *CpuFeaturesData;\r
1158 CPU_REGISTER_TABLE *RegisterTable;\r
1159 CPU_REGISTER_TABLE *RegisterTables;\r
1160 UINT32 InitApicId;\r
1161 UINTN ProcIndex;\r
1162 UINTN Index;\r
1163 ACPI_CPU_DATA *AcpiCpuData;\r
80c4b236 1164\r
053e878b
MK
1165 CpuFeaturesData = (CPU_FEATURES_DATA *)Buffer;\r
1166 AcpiCpuData = CpuFeaturesData->AcpiCpuData;\r
b3c71b47 1167\r
010753b7 1168 RegisterTables = (CPU_REGISTER_TABLE *)(UINTN)AcpiCpuData->CpuFeatureInitData.RegisterTable;\r
b3c71b47 1169\r
053e878b 1170 InitApicId = GetInitialApicId ();\r
b3c71b47 1171 RegisterTable = NULL;\r
053e878b 1172 ProcIndex = (UINTN)-1;\r
b3c71b47
ED
1173 for (Index = 0; Index < AcpiCpuData->NumberOfCpus; Index++) {\r
1174 if (RegisterTables[Index].InitialApicId == InitApicId) {\r
1175 RegisterTable = &RegisterTables[Index];\r
053e878b 1176 ProcIndex = Index;\r
b3c71b47
ED
1177 break;\r
1178 }\r
1179 }\r
053e878b 1180\r
b3c71b47
ED
1181 ASSERT (RegisterTable != NULL);\r
1182\r
1183 ProgramProcessorRegister (\r
1184 RegisterTable,\r
010753b7
LY
1185 (EFI_CPU_PHYSICAL_LOCATION *)(UINTN)AcpiCpuData->CpuFeatureInitData.ApLocation + ProcIndex,\r
1186 &AcpiCpuData->CpuFeatureInitData.CpuStatus,\r
b3c71b47
ED
1187 &CpuFeaturesData->CpuFlags\r
1188 );\r
80c4b236
JF
1189}\r
1190\r
1191/**\r
1192 Performs CPU features detection.\r
1193\r
1194 This service will invoke MP service to check CPU features'\r
1195 capabilities on BSP/APs.\r
1196\r
1197 @note This service could be called by BSP only.\r
1198**/\r
1199VOID\r
1200EFIAPI\r
1201CpuFeaturesDetect (\r
1202 VOID\r
1203 )\r
1204{\r
053e878b 1205 CPU_FEATURES_DATA *CpuFeaturesData;\r
b3c71b47 1206\r
053e878b 1207 CpuFeaturesData = GetCpuFeaturesData ();\r
80c4b236 1208\r
7217b879 1209 CpuInitDataInitialize ();\r
80c4b236 1210\r
7a0df266
SZ
1211 if (CpuFeaturesData->NumberOfCpus > 1) {\r
1212 //\r
1213 // Wakeup all APs for data collection.\r
1214 //\r
87ad6913 1215 StartupAllAPsWorker (CollectProcessorData, NULL);\r
7a0df266 1216 }\r
80c4b236
JF
1217\r
1218 //\r
1219 // Collect data on BSP\r
1220 //\r
b3c71b47 1221 CollectProcessorData (CpuFeaturesData);\r
80c4b236 1222\r
7217b879 1223 AnalysisProcessorFeatures (CpuFeaturesData->NumberOfCpus);\r
80c4b236 1224}\r