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