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