]>
Commit | Line | Data |
---|---|---|
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 | 11 | CHAR16 *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 |
20 | VOID\r | |
21 | SetCapabilityPcd (\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 |
38 | VOID\r | |
39 | SetSettingPcd (\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 | |
55 | VOID\r | |
56 | FillProcessorInfo (\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 |
90 | VOID\r | |
91 | CpuInitDataInitialize (\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 |
321 | VOID\r | |
322 | SupportedMaskOr (\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 |
347 | VOID\r | |
348 | SupportedMaskAnd (\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 |
372 | VOID\r | |
373 | SupportedMaskCleanBit (\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 | |
403 | BOOLEAN\r | |
404 | IsBitMaskMatch (\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 | |
429 | VOID\r | |
430 | EFIAPI\r | |
431 | CollectProcessorData (\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 | |
478 | VOID\r | |
479 | DumpRegisterTableOnProcessor (\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 | |
578 | CPU_FEATURE_DEPENDENCE_TYPE\r | |
579 | BiggestDep (\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 | |
599 | VOID\r | |
600 | AnalysisProcessorFeatures (\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 | |
786 | VOID\r | |
787 | LibReleaseSemaphore (\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 | |
804 | VOID\r | |
805 | LibWaitForSemaphore (\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 | |
830 | UINTN\r | |
831 | ReadWriteCr (\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 | |
883 | VOID\r | |
884 | ProgramProcessorRegister (\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 | |
1111 | VOID\r | |
1112 | EFIAPI\r | |
1113 | SetProcessorRegister (\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 | |
1158 | VOID\r | |
1159 | EFIAPI\r | |
1160 | CpuFeaturesDetect (\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 |