]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
StandaloneMmPkg: Apply uncrustify changes
[mirror_edk2.git] / UefiCpuPkg / Library / CpuCacheInfoLib / CpuCacheInfoLib.c
CommitLineData
83facfd1
LY
1/** @file\r
2 Provides cache info for each package, core type, cache level and cache type.\r
3\r
e4ff3773 4 Copyright (c) 2020 - 2021, Intel Corporation. All rights reserved.<BR>\r
83facfd1
LY
5 SPDX-License-Identifier: BSD-2-Clause-Patent\r
6\r
7**/\r
8\r
9#include "InternalCpuCacheInfoLib.h"\r
10\r
11/**\r
12 Print CpuCacheInfo array.\r
13\r
14 @param[in] CpuCacheInfo Pointer to the CpuCacheInfo array.\r
15 @param[in] CpuCacheInfoCount The length of CpuCacheInfo array.\r
16\r
17**/\r
18VOID\r
19CpuCacheInfoPrintCpuCacheInfoTable (\r
20 IN CPU_CACHE_INFO *CpuCacheInfo,\r
21 IN UINTN CpuCacheInfoCount\r
22 )\r
23{\r
24 UINTN Index;\r
25\r
e4ff3773
LY
26 DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));\r
27 DEBUG ((DEBUG_INFO, "| Index | Packge CoreType CacheLevel CacheType CacheWays (FA|DM) CacheSizeinKB CacheCount |\n"));\r
28 DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));\r
83facfd1
LY
29\r
30 for (Index = 0; Index < CpuCacheInfoCount; Index++) {\r
e4ff3773
LY
31 DEBUG ((DEBUG_INFO, "| %4x | %4x %2x %2x %2x %4x ( %x| %x) %8x %4x |\n",\r
32 Index, CpuCacheInfo[Index].Package, CpuCacheInfo[Index].CoreType, CpuCacheInfo[Index].CacheLevel,\r
33 CpuCacheInfo[Index].CacheType, CpuCacheInfo[Index].CacheWays, CpuCacheInfo[Index].FullyAssociativeCache,\r
34 CpuCacheInfo[Index].DirectMappedCache, CpuCacheInfo[Index].CacheSizeinKB, CpuCacheInfo[Index].CacheCount));\r
83facfd1
LY
35 }\r
36\r
e4ff3773 37 DEBUG ((DEBUG_INFO, "+-------+--------------------------------------------------------------------------------------+\n"));\r
83facfd1
LY
38}\r
39\r
4de77ae9
LY
40/**\r
41 Function to compare CPU package ID, core type, cache level and cache type for use in QuickSort.\r
42\r
43 @param[in] Buffer1 pointer to CPU_CACHE_INFO poiner to compare\r
44 @param[in] Buffer2 pointer to second CPU_CACHE_INFO pointer to compare\r
45\r
46 @retval 0 Buffer1 equal to Buffer2\r
47 @retval 1 Buffer1 is greater than Buffer2\r
48 @retval -1 Buffer1 is less than Buffer2\r
49**/\r
50INTN\r
51EFIAPI\r
52CpuCacheInfoCompare (\r
53 IN CONST VOID *Buffer1,\r
54 IN CONST VOID *Buffer2\r
55 )\r
56{\r
57 CPU_CACHE_INFO_COMPARATOR Comparator1, Comparator2;\r
58\r
59 ZeroMem (&Comparator1, sizeof (Comparator1));\r
60 ZeroMem (&Comparator2, sizeof (Comparator2));\r
61\r
62 Comparator1.Bits.Package = ((CPU_CACHE_INFO*)Buffer1)->Package;\r
63 Comparator1.Bits.CoreType = ((CPU_CACHE_INFO*)Buffer1)->CoreType;\r
64 Comparator1.Bits.CacheLevel = ((CPU_CACHE_INFO*)Buffer1)->CacheLevel;\r
65 Comparator1.Bits.CacheType = ((CPU_CACHE_INFO*)Buffer1)->CacheType;\r
66\r
67 Comparator2.Bits.Package = ((CPU_CACHE_INFO*)Buffer2)->Package;\r
68 Comparator2.Bits.CoreType = ((CPU_CACHE_INFO*)Buffer2)->CoreType;\r
69 Comparator2.Bits.CacheLevel = ((CPU_CACHE_INFO*)Buffer2)->CacheLevel;\r
70 Comparator2.Bits.CacheType = ((CPU_CACHE_INFO*)Buffer2)->CacheType;\r
71\r
72 if (Comparator1.Uint64 == Comparator2.Uint64) {\r
73 return 0;\r
74 } else if (Comparator1.Uint64 > Comparator2.Uint64) {\r
75 return 1;\r
76 } else {\r
77 return -1;\r
78 }\r
79}\r
80\r
83facfd1
LY
81/**\r
82 Get the total number of package and package ID in the platform.\r
83\r
84 @param[in] ProcessorInfo Pointer to the ProcessorInfo array.\r
85 @param[in] NumberOfProcessors Total number of logical processors in the platform.\r
86 @param[in, out] Package Pointer to the Package array.\r
87\r
88 @retval Return the total number of package and package ID in the platform.\r
89**/\r
90UINT32\r
91CpuCacheInfoGetNumberOfPackages (\r
92 IN CPUID_PROCESSOR_INFO *ProcessorInfo,\r
93 IN UINTN NumberOfProcessors,\r
94 IN OUT UINT32 *Package\r
95 )\r
96{\r
97 UINTN ProcessorIndex;\r
98 UINT32 PackageIndex;\r
99 UINT32 PackageCount;\r
100 UINT32 CurrentPackage;\r
101\r
102 PackageCount = 0;\r
103\r
104 for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {\r
105 CurrentPackage = ProcessorInfo[ProcessorIndex].Package;\r
106\r
107 //\r
108 // For the package that already exists in Package array, break out the loop.\r
109 //\r
110 for (PackageIndex = 0; PackageIndex < PackageCount; PackageIndex++) {\r
111 if (CurrentPackage == Package[PackageIndex]) {\r
112 break;\r
113 }\r
114 }\r
115\r
116 //\r
117 // For the new package, save it in Package array.\r
118 //\r
119 if (PackageIndex == PackageCount) {\r
120 ASSERT (PackageCount < MAX_NUM_OF_PACKAGE);\r
121 Package[PackageCount++] = CurrentPackage;\r
122 }\r
123 }\r
124\r
125 return PackageCount;\r
126}\r
127\r
128/**\r
129 Get the number of CoreType of requested package.\r
130\r
131 @param[in] ProcessorInfo Pointer to the ProcessorInfo array.\r
132 @param[in] NumberOfProcessors Total number of logical processors in the platform.\r
133 @param[in] Package The requested package number.\r
134\r
135 @retval Return the number of CoreType of requested package.\r
136**/\r
137UINTN\r
138CpuCacheInfoGetNumberOfCoreTypePerPackage(\r
139 IN CPUID_PROCESSOR_INFO *ProcessorInfo,\r
140 IN UINTN NumberOfProcessors,\r
141 IN UINTN Package\r
142 )\r
143{\r
144 UINTN ProcessorIndex;\r
145 //\r
146 // Core Type value comes from CPUID.1Ah.EAX[31:24].\r
147 // So max number of core types should be MAX_UINT8.\r
148 //\r
149 UINT8 CoreType[MAX_UINT8];\r
150 UINTN CoreTypeIndex;\r
151 UINTN CoreTypeCount;\r
152 UINT8 CurrentCoreType;\r
153\r
154 //\r
155 // CoreType array is empty.\r
156 //\r
157 CoreTypeCount = 0;\r
158\r
159 for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {\r
160 CurrentCoreType = ProcessorInfo[ProcessorIndex].CoreType;\r
161\r
162 if (ProcessorInfo[ProcessorIndex].Package != Package) {\r
163 continue;\r
164 }\r
165\r
166 //\r
167 // For the type that already exists in CoreType array, break out the loop.\r
168 //\r
169 for (CoreTypeIndex = 0; CoreTypeIndex < CoreTypeCount; CoreTypeIndex++) {\r
170 if (CurrentCoreType == CoreType[CoreTypeIndex]) {\r
171 break;\r
172 }\r
173 }\r
174\r
175 //\r
176 // For the new type, save it in CoreType array.\r
177 //\r
178 if (CoreTypeIndex == CoreTypeCount) {\r
179 ASSERT (CoreTypeCount < MAX_UINT8);\r
180 CoreType[CoreTypeCount++] = CurrentCoreType;\r
181 }\r
182 }\r
183\r
184 return CoreTypeCount;\r
185}\r
186\r
187/**\r
188 Collect core and cache information of calling processor via CPUID instructions.\r
189\r
190 @param[in, out] Buffer The pointer to private data buffer.\r
191**/\r
192VOID\r
193EFIAPI\r
194CpuCacheInfoCollectCoreAndCacheData (\r
195 IN OUT VOID *Buffer\r
196 )\r
197{\r
198 UINTN ProcessorIndex;\r
199 UINT32 CpuidMaxInput;\r
200 UINT8 CacheParamLeafIndex;\r
201 CPUID_CACHE_PARAMS_EAX CacheParamEax;\r
202 CPUID_CACHE_PARAMS_EBX CacheParamEbx;\r
203 UINT32 CacheParamEcx;\r
e4ff3773 204 CPUID_CACHE_PARAMS_EDX CacheParamEdx;\r
83facfd1
LY
205 CPUID_NATIVE_MODEL_ID_AND_CORE_TYPE_EAX NativeModelIdAndCoreTypeEax;\r
206 COLLECT_CPUID_CACHE_DATA_CONTEXT *Context;\r
207 CPUID_CACHE_DATA *CacheData;\r
208\r
209 Context = (COLLECT_CPUID_CACHE_DATA_CONTEXT *)Buffer;\r
210 ProcessorIndex = CpuCacheInfoWhoAmI (Context->MpServices);\r
211 CacheData = &Context->CacheData[MAX_NUM_OF_CACHE_PARAMS_LEAF * ProcessorIndex];\r
212\r
213 AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);\r
214\r
215 //\r
216 // get CoreType if CPUID_HYBRID_INFORMATION leaf is supported.\r
217 //\r
218 Context->ProcessorInfo[ProcessorIndex].CoreType = 0;\r
219 if (CpuidMaxInput >= CPUID_HYBRID_INFORMATION) {\r
2d6fc9d3 220 AsmCpuidEx (CPUID_HYBRID_INFORMATION, CPUID_HYBRID_INFORMATION_MAIN_LEAF, &NativeModelIdAndCoreTypeEax.Uint32, NULL, NULL, NULL);\r
83facfd1
LY
221 Context->ProcessorInfo[ProcessorIndex].CoreType = (UINT8) NativeModelIdAndCoreTypeEax.Bits.CoreType;\r
222 }\r
223\r
224 //\r
225 // cache hierarchy starts with an index value of 0.\r
226 //\r
227 CacheParamLeafIndex = 0;\r
228\r
229 while (CacheParamLeafIndex < MAX_NUM_OF_CACHE_PARAMS_LEAF) {\r
e4ff3773 230 AsmCpuidEx (CPUID_CACHE_PARAMS, CacheParamLeafIndex, &CacheParamEax.Uint32, &CacheParamEbx.Uint32, &CacheParamEcx, &CacheParamEdx.Uint32);\r
83facfd1
LY
231\r
232 if (CacheParamEax.Bits.CacheType == 0) {\r
233 break;\r
234 }\r
235\r
e4ff3773
LY
236 CacheData[CacheParamLeafIndex].CacheLevel = (UINT8)CacheParamEax.Bits.CacheLevel;\r
237 CacheData[CacheParamLeafIndex].CacheType = (UINT8)CacheParamEax.Bits.CacheType;\r
238 CacheData[CacheParamLeafIndex].CacheWays = (UINT16)CacheParamEbx.Bits.Ways;\r
239 CacheData[CacheParamLeafIndex].FullyAssociativeCache = (UINT8)CacheParamEax.Bits.FullyAssociativeCache;\r
8dd4fc5b 240 CacheData[CacheParamLeafIndex].DirectMappedCache = (UINT8)(CacheParamEdx.Bits.ComplexCacheIndexing == 0);\r
e4ff3773
LY
241 CacheData[CacheParamLeafIndex].CacheShareBits = (UINT16)CacheParamEax.Bits.MaximumAddressableIdsForLogicalProcessors;\r
242 CacheData[CacheParamLeafIndex].CacheSizeinKB = (CacheParamEbx.Bits.Ways + 1) *\r
83facfd1
LY
243 (CacheParamEbx.Bits.LinePartitions + 1) * (CacheParamEbx.Bits.LineSize + 1) * (CacheParamEcx + 1) / SIZE_1KB;\r
244\r
245 CacheParamLeafIndex++;\r
246 }\r
247}\r
248\r
249/**\r
250 Collect CacheInfo data from the CacheData.\r
251\r
252 @param[in] CacheData Pointer to the CacheData array.\r
253 @param[in] ProcessorInfo Pointer to the ProcessorInfo array.\r
254 @param[in] NumberOfProcessors Total number of logical processors in the platform.\r
255 @param[in, out] CacheInfo Pointer to the CacheInfo array.\r
256 @param[in, out] CacheInfoCount As input, point to the length of response CacheInfo array.\r
257 As output, point to the actual length of response CacheInfo array.\r
258\r
259 @retval EFI_SUCCESS Function completed successfully.\r
260 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
261 @retval EFI_BUFFER_TOO_SMALL CacheInfoCount is too small to hold the response CacheInfo\r
262 array. CacheInfoCount has been updated with the length needed\r
263 to complete the request.\r
264**/\r
265EFI_STATUS\r
266CpuCacheInfoCollectCpuCacheInfoData (\r
267 IN CPUID_CACHE_DATA *CacheData,\r
268 IN CPUID_PROCESSOR_INFO *ProcessorInfo,\r
269 IN UINTN NumberOfProcessors,\r
270 IN OUT CPU_CACHE_INFO *CacheInfo,\r
271 IN OUT UINTN *CacheInfoCount\r
272 )\r
273{\r
274 EFI_STATUS Status;\r
275 UINT32 NumberOfPackage;\r
276 UINT32 Package[MAX_NUM_OF_PACKAGE];\r
277 UINTN PackageIndex;\r
278 UINTN TotalNumberOfCoreType;\r
279 UINTN MaxCacheInfoCount;\r
280 CPU_CACHE_INFO *LocalCacheInfo;\r
281 UINTN CacheInfoIndex;\r
282 UINTN LocalCacheInfoCount;\r
283 UINTN Index;\r
284 UINTN NextIndex;\r
305fd6be 285 CPU_CACHE_INFO SortBuffer;\r
83facfd1
LY
286\r
287 //\r
288 // Get number of Packages and Package ID.\r
289 //\r
290 NumberOfPackage = CpuCacheInfoGetNumberOfPackages (ProcessorInfo, NumberOfProcessors, Package);\r
291\r
292 //\r
293 // Get number of core types for each package and count the total number.\r
294 // E.g. If Package1 and Package2 both have 2 core types, the total number is 4.\r
295 //\r
296 TotalNumberOfCoreType = 0;\r
297 for (PackageIndex = 0; PackageIndex < NumberOfPackage; PackageIndex++) {\r
298 TotalNumberOfCoreType += CpuCacheInfoGetNumberOfCoreTypePerPackage (ProcessorInfo, NumberOfProcessors, Package[PackageIndex]);\r
299 }\r
300\r
301 MaxCacheInfoCount = TotalNumberOfCoreType * MAX_NUM_OF_CACHE_PARAMS_LEAF;\r
302 LocalCacheInfo = AllocatePages (EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));\r
303 ASSERT (LocalCacheInfo != NULL);\r
304 if (LocalCacheInfo == NULL) {\r
305 return EFI_OUT_OF_RESOURCES;\r
306 }\r
307\r
308 LocalCacheInfoCount = 0;\r
309\r
310 for (Index = 0; Index < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; Index++) {\r
311 if (CacheData[Index].CacheSizeinKB == 0) {\r
312 continue;\r
313 }\r
314\r
315 //\r
316 // For the sharing caches, clear their CacheSize.\r
317 //\r
318 for (NextIndex = Index + 1; NextIndex < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; NextIndex++) {\r
319 if (CacheData[NextIndex].CacheSizeinKB == 0) {\r
320 continue;\r
321 }\r
322\r
323 if (CacheData[Index].CacheLevel == CacheData[NextIndex].CacheLevel &&\r
324 CacheData[Index].CacheType == CacheData[NextIndex].CacheType &&\r
325 ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&\r
326 ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&\r
327 (ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[Index].CacheShareBits) ==\r
328 (ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[NextIndex].CacheShareBits)) {\r
329 CacheData[NextIndex].CacheSizeinKB = 0; // uses the sharing cache\r
330 }\r
331 }\r
332\r
333 //\r
334 // For the cache that already exists in LocalCacheInfo, increase its CacheCount.\r
335 //\r
336 for (CacheInfoIndex = 0; CacheInfoIndex < LocalCacheInfoCount; CacheInfoIndex++) {\r
337 if (LocalCacheInfo[CacheInfoIndex].Package == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&\r
338 LocalCacheInfo[CacheInfoIndex].CoreType == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&\r
339 LocalCacheInfo[CacheInfoIndex].CacheLevel == CacheData[Index].CacheLevel &&\r
340 LocalCacheInfo[CacheInfoIndex].CacheType == CacheData[Index].CacheType) {\r
341 LocalCacheInfo[CacheInfoIndex].CacheCount++;\r
342 break;\r
343 }\r
344 }\r
345\r
346 //\r
347 // For the new cache with different Package, CoreType, CacheLevel or CacheType, copy its\r
348 // data into LocalCacheInfo buffer.\r
349 //\r
350 if (CacheInfoIndex == LocalCacheInfoCount) {\r
351 ASSERT (LocalCacheInfoCount < MaxCacheInfoCount);\r
352\r
e4ff3773
LY
353 LocalCacheInfo[LocalCacheInfoCount].Package = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package;\r
354 LocalCacheInfo[LocalCacheInfoCount].CoreType = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType;\r
355 LocalCacheInfo[LocalCacheInfoCount].CacheLevel = CacheData[Index].CacheLevel;\r
356 LocalCacheInfo[LocalCacheInfoCount].CacheType = CacheData[Index].CacheType;\r
357 LocalCacheInfo[LocalCacheInfoCount].CacheWays = CacheData[Index].CacheWays;\r
358 LocalCacheInfo[LocalCacheInfoCount].FullyAssociativeCache = CacheData[Index].FullyAssociativeCache;\r
359 LocalCacheInfo[LocalCacheInfoCount].DirectMappedCache = CacheData[Index].DirectMappedCache;\r
360 LocalCacheInfo[LocalCacheInfoCount].CacheSizeinKB = CacheData[Index].CacheSizeinKB;\r
361 LocalCacheInfo[LocalCacheInfoCount].CacheCount = 1;\r
83facfd1
LY
362\r
363 LocalCacheInfoCount++;\r
364 }\r
365 }\r
366\r
367 if (*CacheInfoCount < LocalCacheInfoCount) {\r
368 Status = EFI_BUFFER_TOO_SMALL;\r
369 } else {\r
4de77ae9
LY
370 //\r
371 // Sort LocalCacheInfo array by CPU package ID, core type, cache level and cache type.\r
372 //\r
305fd6be 373 QuickSort (LocalCacheInfo, LocalCacheInfoCount, sizeof (*LocalCacheInfo), CpuCacheInfoCompare, (VOID*) &SortBuffer);\r
83facfd1
LY
374 CopyMem (CacheInfo, LocalCacheInfo, sizeof (*CacheInfo) * LocalCacheInfoCount);\r
375 DEBUG_CODE (\r
376 CpuCacheInfoPrintCpuCacheInfoTable (CacheInfo, LocalCacheInfoCount);\r
377 );\r
378 Status = EFI_SUCCESS;\r
379 }\r
380\r
381 *CacheInfoCount = LocalCacheInfoCount;\r
382\r
383 FreePages (LocalCacheInfo, EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));\r
384\r
385 return Status;\r
386}\r
387\r
388/**\r
4de77ae9 389 Get CpuCacheInfo data array. The array is sorted by CPU package ID, core type, cache level and cache type.\r
83facfd1
LY
390\r
391 @param[in, out] CpuCacheInfo Pointer to the CpuCacheInfo array.\r
392 @param[in, out] CpuCacheInfoCount As input, point to the length of response CpuCacheInfo array.\r
393 As output, point to the actual length of response CpuCacheInfo array.\r
394\r
395 @retval EFI_SUCCESS Function completed successfully.\r
396 @retval EFI_INVALID_PARAMETER CpuCacheInfoCount is NULL.\r
397 @retval EFI_INVALID_PARAMETER CpuCacheInfo is NULL while CpuCacheInfoCount contains the value\r
398 greater than zero.\r
399 @retval EFI_UNSUPPORTED Processor does not support CPUID_CACHE_PARAMS Leaf.\r
83facfd1
LY
400 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
401 @retval EFI_BUFFER_TOO_SMALL CpuCacheInfoCount is too small to hold the response CpuCacheInfo\r
402 array. CpuCacheInfoCount has been updated with the length needed\r
403 to complete the request.\r
404**/\r
405EFI_STATUS\r
406EFIAPI\r
407GetCpuCacheInfo (\r
408 IN OUT CPU_CACHE_INFO *CpuCacheInfo,\r
409 IN OUT UINTN *CpuCacheInfoCount\r
410 )\r
411{\r
412 EFI_STATUS Status;\r
413 UINT32 CpuidMaxInput;\r
414 UINT32 NumberOfProcessors;\r
415 UINTN CacheDataCount;\r
416 UINTN ProcessorIndex;\r
417 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
418 COLLECT_CPUID_CACHE_DATA_CONTEXT Context;\r
419\r
420 if (CpuCacheInfoCount == NULL) {\r
421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 if (*CpuCacheInfoCount != 0 && CpuCacheInfo == NULL) {\r
425 return EFI_INVALID_PARAMETER;\r
426 }\r
427\r
428 AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);\r
429 if (CpuidMaxInput < CPUID_CACHE_PARAMS) {\r
430 return EFI_UNSUPPORTED;\r
431 }\r
432\r
433 //\r
434 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.MpServices.\r
435 //\r
51b96e4b 436 CpuCacheInfoGetMpServices (&Context.MpServices);\r
83facfd1
LY
437\r
438 NumberOfProcessors = CpuCacheInfoGetNumberOfProcessors (Context.MpServices);\r
439\r
440 //\r
441 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.ProcessorInfo.\r
442 //\r
443 Context.ProcessorInfo = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
444 ASSERT (Context.ProcessorInfo != NULL);\r
445 if (Context.ProcessorInfo == NULL) {\r
446 return EFI_OUT_OF_RESOURCES;\r
447 }\r
448 //\r
449 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.CacheData.\r
450 // CacheData array consists of CPUID_CACHE_DATA data structure for each Cpuid Cache Parameter Leaf\r
451 // per logical processor. The array begin with data of each Cache Parameter Leaf of processor 0, followed\r
452 // by data of each Cache Parameter Leaf of processor 1 ...\r
453 //\r
454 CacheDataCount = NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF;\r
455 Context.CacheData = AllocatePages (EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));\r
456 ASSERT (Context.CacheData != NULL);\r
457 if (Context.CacheData == NULL) {\r
458 FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
459 return EFI_OUT_OF_RESOURCES;\r
460 }\r
461\r
462 ZeroMem (Context.CacheData, CacheDataCount * sizeof (*Context.CacheData));\r
463\r
464 //\r
465 // Collect Package ID and APIC ID of all processors.\r
466 //\r
467 for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {\r
468 CpuCacheInfoGetProcessorInfo (Context.MpServices, ProcessorIndex, &ProcessorInfo);\r
469 Context.ProcessorInfo[ProcessorIndex].Package = ProcessorInfo.Location.Package;\r
470 Context.ProcessorInfo[ProcessorIndex].ApicId = (UINT32) ProcessorInfo.ProcessorId;\r
471 }\r
472\r
473 //\r
474 // Wakeup all processors for CacheData(core type and cache data) collection.\r
475 //\r
476 CpuCacheInfoStartupAllCPUs (Context.MpServices, CpuCacheInfoCollectCoreAndCacheData, &Context);\r
477\r
478 //\r
479 // Collect CpuCacheInfo data from CacheData.\r
480 //\r
481 Status = CpuCacheInfoCollectCpuCacheInfoData (Context.CacheData, Context.ProcessorInfo, NumberOfProcessors, CpuCacheInfo, CpuCacheInfoCount);\r
482\r
483 FreePages (Context.CacheData, EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));\r
484 FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
485\r
486 return Status;\r
487}\r