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