]> git.proxmox.com Git - mirror_edk2.git/blame - UefiCpuPkg/Library/CpuCacheInfoLib/CpuCacheInfoLib.c
UefiCpuPkg/CpuCacheInfoLib: Sort CpuCacheInfo array
[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
240 CacheData[CacheParamLeafIndex].DirectMappedCache = (UINT8)CacheParamEdx.Bits.ComplexCacheIndexing;\r
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
285\r
286 //\r
287 // Get number of Packages and Package ID.\r
288 //\r
289 NumberOfPackage = CpuCacheInfoGetNumberOfPackages (ProcessorInfo, NumberOfProcessors, Package);\r
290\r
291 //\r
292 // Get number of core types for each package and count the total number.\r
293 // E.g. If Package1 and Package2 both have 2 core types, the total number is 4.\r
294 //\r
295 TotalNumberOfCoreType = 0;\r
296 for (PackageIndex = 0; PackageIndex < NumberOfPackage; PackageIndex++) {\r
297 TotalNumberOfCoreType += CpuCacheInfoGetNumberOfCoreTypePerPackage (ProcessorInfo, NumberOfProcessors, Package[PackageIndex]);\r
298 }\r
299\r
300 MaxCacheInfoCount = TotalNumberOfCoreType * MAX_NUM_OF_CACHE_PARAMS_LEAF;\r
301 LocalCacheInfo = AllocatePages (EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));\r
302 ASSERT (LocalCacheInfo != NULL);\r
303 if (LocalCacheInfo == NULL) {\r
304 return EFI_OUT_OF_RESOURCES;\r
305 }\r
306\r
307 LocalCacheInfoCount = 0;\r
308\r
309 for (Index = 0; Index < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; Index++) {\r
310 if (CacheData[Index].CacheSizeinKB == 0) {\r
311 continue;\r
312 }\r
313\r
314 //\r
315 // For the sharing caches, clear their CacheSize.\r
316 //\r
317 for (NextIndex = Index + 1; NextIndex < NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF; NextIndex++) {\r
318 if (CacheData[NextIndex].CacheSizeinKB == 0) {\r
319 continue;\r
320 }\r
321\r
322 if (CacheData[Index].CacheLevel == CacheData[NextIndex].CacheLevel &&\r
323 CacheData[Index].CacheType == CacheData[NextIndex].CacheType &&\r
324 ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&\r
325 ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType == ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&\r
326 (ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[Index].CacheShareBits) ==\r
327 (ProcessorInfo[NextIndex / MAX_NUM_OF_CACHE_PARAMS_LEAF].ApicId & ~CacheData[NextIndex].CacheShareBits)) {\r
328 CacheData[NextIndex].CacheSizeinKB = 0; // uses the sharing cache\r
329 }\r
330 }\r
331\r
332 //\r
333 // For the cache that already exists in LocalCacheInfo, increase its CacheCount.\r
334 //\r
335 for (CacheInfoIndex = 0; CacheInfoIndex < LocalCacheInfoCount; CacheInfoIndex++) {\r
336 if (LocalCacheInfo[CacheInfoIndex].Package == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package &&\r
337 LocalCacheInfo[CacheInfoIndex].CoreType == ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType &&\r
338 LocalCacheInfo[CacheInfoIndex].CacheLevel == CacheData[Index].CacheLevel &&\r
339 LocalCacheInfo[CacheInfoIndex].CacheType == CacheData[Index].CacheType) {\r
340 LocalCacheInfo[CacheInfoIndex].CacheCount++;\r
341 break;\r
342 }\r
343 }\r
344\r
345 //\r
346 // For the new cache with different Package, CoreType, CacheLevel or CacheType, copy its\r
347 // data into LocalCacheInfo buffer.\r
348 //\r
349 if (CacheInfoIndex == LocalCacheInfoCount) {\r
350 ASSERT (LocalCacheInfoCount < MaxCacheInfoCount);\r
351\r
e4ff3773
LY
352 LocalCacheInfo[LocalCacheInfoCount].Package = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].Package;\r
353 LocalCacheInfo[LocalCacheInfoCount].CoreType = ProcessorInfo[Index / MAX_NUM_OF_CACHE_PARAMS_LEAF].CoreType;\r
354 LocalCacheInfo[LocalCacheInfoCount].CacheLevel = CacheData[Index].CacheLevel;\r
355 LocalCacheInfo[LocalCacheInfoCount].CacheType = CacheData[Index].CacheType;\r
356 LocalCacheInfo[LocalCacheInfoCount].CacheWays = CacheData[Index].CacheWays;\r
357 LocalCacheInfo[LocalCacheInfoCount].FullyAssociativeCache = CacheData[Index].FullyAssociativeCache;\r
358 LocalCacheInfo[LocalCacheInfoCount].DirectMappedCache = CacheData[Index].DirectMappedCache;\r
359 LocalCacheInfo[LocalCacheInfoCount].CacheSizeinKB = CacheData[Index].CacheSizeinKB;\r
360 LocalCacheInfo[LocalCacheInfoCount].CacheCount = 1;\r
83facfd1
LY
361\r
362 LocalCacheInfoCount++;\r
363 }\r
364 }\r
365\r
366 if (*CacheInfoCount < LocalCacheInfoCount) {\r
367 Status = EFI_BUFFER_TOO_SMALL;\r
368 } else {\r
4de77ae9
LY
369 //\r
370 // Sort LocalCacheInfo array by CPU package ID, core type, cache level and cache type.\r
371 //\r
372 PerformQuickSort (LocalCacheInfo, LocalCacheInfoCount, sizeof (*LocalCacheInfo), (SORT_COMPARE) CpuCacheInfoCompare);\r
83facfd1
LY
373 CopyMem (CacheInfo, LocalCacheInfo, sizeof (*CacheInfo) * LocalCacheInfoCount);\r
374 DEBUG_CODE (\r
375 CpuCacheInfoPrintCpuCacheInfoTable (CacheInfo, LocalCacheInfoCount);\r
376 );\r
377 Status = EFI_SUCCESS;\r
378 }\r
379\r
380 *CacheInfoCount = LocalCacheInfoCount;\r
381\r
382 FreePages (LocalCacheInfo, EFI_SIZE_TO_PAGES (MaxCacheInfoCount * sizeof (*LocalCacheInfo)));\r
383\r
384 return Status;\r
385}\r
386\r
387/**\r
4de77ae9 388 Get CpuCacheInfo data array. The array is sorted by CPU package ID, core type, cache level and cache type.\r
83facfd1
LY
389\r
390 @param[in, out] CpuCacheInfo Pointer to the CpuCacheInfo array.\r
391 @param[in, out] CpuCacheInfoCount As input, point to the length of response CpuCacheInfo array.\r
392 As output, point to the actual length of response CpuCacheInfo array.\r
393\r
394 @retval EFI_SUCCESS Function completed successfully.\r
395 @retval EFI_INVALID_PARAMETER CpuCacheInfoCount is NULL.\r
396 @retval EFI_INVALID_PARAMETER CpuCacheInfo is NULL while CpuCacheInfoCount contains the value\r
397 greater than zero.\r
398 @retval EFI_UNSUPPORTED Processor does not support CPUID_CACHE_PARAMS Leaf.\r
83facfd1
LY
399 @retval EFI_OUT_OF_RESOURCES Required resources could not be allocated.\r
400 @retval EFI_BUFFER_TOO_SMALL CpuCacheInfoCount is too small to hold the response CpuCacheInfo\r
401 array. CpuCacheInfoCount has been updated with the length needed\r
402 to complete the request.\r
403**/\r
404EFI_STATUS\r
405EFIAPI\r
406GetCpuCacheInfo (\r
407 IN OUT CPU_CACHE_INFO *CpuCacheInfo,\r
408 IN OUT UINTN *CpuCacheInfoCount\r
409 )\r
410{\r
411 EFI_STATUS Status;\r
412 UINT32 CpuidMaxInput;\r
413 UINT32 NumberOfProcessors;\r
414 UINTN CacheDataCount;\r
415 UINTN ProcessorIndex;\r
416 EFI_PROCESSOR_INFORMATION ProcessorInfo;\r
417 COLLECT_CPUID_CACHE_DATA_CONTEXT Context;\r
418\r
419 if (CpuCacheInfoCount == NULL) {\r
420 return EFI_INVALID_PARAMETER;\r
421 }\r
422\r
423 if (*CpuCacheInfoCount != 0 && CpuCacheInfo == NULL) {\r
424 return EFI_INVALID_PARAMETER;\r
425 }\r
426\r
427 AsmCpuid (CPUID_SIGNATURE, &CpuidMaxInput, NULL, NULL, NULL);\r
428 if (CpuidMaxInput < CPUID_CACHE_PARAMS) {\r
429 return EFI_UNSUPPORTED;\r
430 }\r
431\r
432 //\r
433 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.MpServices.\r
434 //\r
51b96e4b 435 CpuCacheInfoGetMpServices (&Context.MpServices);\r
83facfd1
LY
436\r
437 NumberOfProcessors = CpuCacheInfoGetNumberOfProcessors (Context.MpServices);\r
438\r
439 //\r
440 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.ProcessorInfo.\r
441 //\r
442 Context.ProcessorInfo = AllocatePages (EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
443 ASSERT (Context.ProcessorInfo != NULL);\r
444 if (Context.ProcessorInfo == NULL) {\r
445 return EFI_OUT_OF_RESOURCES;\r
446 }\r
447 //\r
448 // Initialize COLLECT_CPUID_CACHE_DATA_CONTEXT.CacheData.\r
449 // CacheData array consists of CPUID_CACHE_DATA data structure for each Cpuid Cache Parameter Leaf\r
450 // per logical processor. The array begin with data of each Cache Parameter Leaf of processor 0, followed\r
451 // by data of each Cache Parameter Leaf of processor 1 ...\r
452 //\r
453 CacheDataCount = NumberOfProcessors * MAX_NUM_OF_CACHE_PARAMS_LEAF;\r
454 Context.CacheData = AllocatePages (EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));\r
455 ASSERT (Context.CacheData != NULL);\r
456 if (Context.CacheData == NULL) {\r
457 FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
458 return EFI_OUT_OF_RESOURCES;\r
459 }\r
460\r
461 ZeroMem (Context.CacheData, CacheDataCount * sizeof (*Context.CacheData));\r
462\r
463 //\r
464 // Collect Package ID and APIC ID of all processors.\r
465 //\r
466 for (ProcessorIndex = 0; ProcessorIndex < NumberOfProcessors; ProcessorIndex++) {\r
467 CpuCacheInfoGetProcessorInfo (Context.MpServices, ProcessorIndex, &ProcessorInfo);\r
468 Context.ProcessorInfo[ProcessorIndex].Package = ProcessorInfo.Location.Package;\r
469 Context.ProcessorInfo[ProcessorIndex].ApicId = (UINT32) ProcessorInfo.ProcessorId;\r
470 }\r
471\r
472 //\r
473 // Wakeup all processors for CacheData(core type and cache data) collection.\r
474 //\r
475 CpuCacheInfoStartupAllCPUs (Context.MpServices, CpuCacheInfoCollectCoreAndCacheData, &Context);\r
476\r
477 //\r
478 // Collect CpuCacheInfo data from CacheData.\r
479 //\r
480 Status = CpuCacheInfoCollectCpuCacheInfoData (Context.CacheData, Context.ProcessorInfo, NumberOfProcessors, CpuCacheInfo, CpuCacheInfoCount);\r
481\r
482 FreePages (Context.CacheData, EFI_SIZE_TO_PAGES (CacheDataCount * sizeof (*Context.CacheData)));\r
483 FreePages (Context.ProcessorInfo, EFI_SIZE_TO_PAGES (NumberOfProcessors * sizeof (*Context.ProcessorInfo)));\r
484\r
485 return Status;\r
486}\r