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