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