]> git.proxmox.com Git - mirror_edk2.git/blame - IntelFsp2Pkg/Library/BaseCacheLib/CacheLib.c
IntelFsp2Pkg: Apply uncrustify changes
[mirror_edk2.git] / IntelFsp2Pkg / Library / BaseCacheLib / CacheLib.c
CommitLineData
cf1d4549
JY
1/** @file\r
2\r
91f5d3b4 3 Copyright (c) 2014 - 2021, Intel Corporation. All rights reserved.<BR>\r
9672cd30 4 SPDX-License-Identifier: BSD-2-Clause-Patent\r
cf1d4549
JY
5\r
6**/\r
7\r
8#include <Uefi.h>\r
9#include <Library/BaseLib.h>\r
10#include <Library/CacheLib.h>\r
11#include <Library/CacheAsRamLib.h>\r
12#include "CacheLibInternal.h"\r
13\r
14/**\r
15 Search the memory cache type for specific memory from MTRR.\r
16\r
17 @param[in] MemoryAddress the address of target memory\r
18 @param[in] MemoryLength the length of target memory\r
19 @param[in] ValidMtrrAddressMask the MTRR address mask\r
20 @param[out] UsedMsrNum the used MSR number\r
21 @param[out] UsedMemoryCacheType the cache type for the target memory\r
22\r
23 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned\r
24 @retval EFI_NOT_FOUND The memory is not found in MTRR\r
25\r
26**/\r
27EFI_STATUS\r
28SearchForExactMtrr (\r
111f2228
MK
29 IN EFI_PHYSICAL_ADDRESS MemoryAddress,\r
30 IN UINT64 MemoryLength,\r
31 IN UINT64 ValidMtrrAddressMask,\r
32 OUT UINT32 *UsedMsrNum,\r
33 OUT EFI_MEMORY_CACHE_TYPE *MemoryCacheType\r
cf1d4549
JY
34 );\r
35\r
36/**\r
37 Check if CacheType match current default setting.\r
38\r
39 @param[in] MemoryCacheType input cache type to be checked.\r
40\r
41 @retval TRUE MemoryCacheType is default MTRR setting.\r
42 @retval FALSE MemoryCacheType is NOT default MTRR setting.\r
43**/\r
44BOOLEAN\r
45IsDefaultType (\r
111f2228 46 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType\r
cf1d4549
JY
47 );\r
48\r
49/**\r
50 Return MTRR alignment requirement for base address and size.\r
51\r
52 @param[in] BaseAddress Base address.\r
53 @param[in] Size Size.\r
54\r
91cc60ba
AC
55 @retval Zero Aligned.\r
56 @retval Non-Zero Not aligned.\r
cf1d4549
JY
57\r
58**/\r
59UINT32\r
60CheckMtrrAlignment (\r
111f2228
MK
61 IN UINT64 BaseAddress,\r
62 IN UINT64 Size\r
cf1d4549
JY
63 );\r
64\r
65typedef struct {\r
66 UINT32 Msr;\r
67 UINT32 BaseAddress;\r
68 UINT32 Length;\r
69} EFI_FIXED_MTRR;\r
70\r
111f2228
MK
71EFI_FIXED_MTRR mFixedMtrrTable[] = {\r
72 { EFI_MSR_IA32_MTRR_FIX64K_00000, 0, 0x10000 },\r
73 { EFI_MSR_IA32_MTRR_FIX16K_80000, 0x80000, 0x4000 },\r
74 { EFI_MSR_IA32_MTRR_FIX16K_A0000, 0xA0000, 0x4000 },\r
75 { EFI_MSR_IA32_MTRR_FIX4K_C0000, 0xC0000, 0x1000 },\r
76 { EFI_MSR_IA32_MTRR_FIX4K_C8000, 0xC8000, 0x1000 },\r
77 { EFI_MSR_IA32_MTRR_FIX4K_D0000, 0xD0000, 0x1000 },\r
78 { EFI_MSR_IA32_MTRR_FIX4K_D8000, 0xD8000, 0x1000 },\r
79 { EFI_MSR_IA32_MTRR_FIX4K_E0000, 0xE0000, 0x1000 },\r
80 { EFI_MSR_IA32_MTRR_FIX4K_E8000, 0xE8000, 0x1000 },\r
81 { EFI_MSR_IA32_MTRR_FIX4K_F0000, 0xF0000, 0x1000 },\r
82 { EFI_MSR_IA32_MTRR_FIX4K_F8000, 0xF8000, 0x1000 }\r
cf1d4549
JY
83};\r
84\r
85/**\r
86 Given the input, check if the number of MTRR is lesser.\r
87 if positive or subtractive.\r
88\r
89 @param[in] Input Length of Memory to program MTRR.\r
90\r
91 @retval Zero do positive.\r
92 @retval Non-Zero do subtractive.\r
93\r
94**/\r
95INT8\r
96CheckDirection (\r
111f2228 97 IN UINT64 Input\r
cf1d4549
JY
98 )\r
99{\r
100 return 0;\r
101}\r
102\r
103/**\r
104 Disable cache and its mtrr.\r
105\r
106 @param[out] OldMtrr To return the Old MTRR value\r
107\r
108**/\r
109VOID\r
110EfiDisableCacheMtrr (\r
111f2228 111 OUT UINT64 *OldMtrr\r
cf1d4549
JY
112 )\r
113{\r
114 UINT64 TempQword;\r
115\r
116 //\r
117 // Disable Cache MTRR\r
118 //\r
111f2228 119 *OldMtrr = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);\r
cf1d4549 120 TempQword = (*OldMtrr) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE & ~B_EFI_MSR_FIXED_MTRR_ENABLE;\r
111f2228 121 AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);\r
cf1d4549
JY
122 AsmDisableCache ();\r
123}\r
124\r
125/**\r
126 Recover cache MTRR.\r
127\r
128 @param[in] EnableMtrr Whether to enable the MTRR\r
129 @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR\r
130\r
131**/\r
132VOID\r
133EfiRecoverCacheMtrr (\r
111f2228
MK
134 IN BOOLEAN EnableMtrr,\r
135 IN UINT64 OldMtrr\r
cf1d4549
JY
136 )\r
137{\r
138 UINT64 TempQword;\r
139\r
140 //\r
141 // Enable Cache MTRR\r
142 //\r
143 if (EnableMtrr) {\r
111f2228 144 TempQword = AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE);\r
cf1d4549
JY
145 TempQword |= (UINT64)(B_EFI_MSR_GLOBAL_MTRR_ENABLE | B_EFI_MSR_FIXED_MTRR_ENABLE);\r
146 } else {\r
147 TempQword = OldMtrr;\r
148 }\r
149\r
150 AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, TempQword);\r
151\r
152 AsmEnableCache ();\r
153}\r
154\r
155/**\r
156 Programming MTRR according to Memory address, length, and type.\r
157\r
158 @param[in] MtrrNumber the variable MTRR index number\r
159 @param[in] MemoryAddress the address of target memory\r
160 @param[in] MemoryLength the length of target memory\r
161 @param[in] MemoryCacheType the cache type of target memory\r
162 @param[in] ValidMtrrAddressMask the MTRR address mask\r
163\r
164**/\r
165VOID\r
166EfiProgramMtrr (\r
111f2228
MK
167 IN UINT32 MtrrNumber,\r
168 IN EFI_PHYSICAL_ADDRESS MemoryAddress,\r
169 IN UINT64 MemoryLength,\r
170 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,\r
171 IN UINT64 ValidMtrrAddressMask\r
cf1d4549
JY
172 )\r
173{\r
111f2228
MK
174 UINT64 TempQword;\r
175 UINT64 OldMtrr;\r
cf1d4549
JY
176\r
177 if (MemoryLength == 0) {\r
178 return;\r
179 }\r
180\r
181 EfiDisableCacheMtrr (&OldMtrr);\r
182\r
183 //\r
184 // MTRR Physical Base\r
185 //\r
186 TempQword = (MemoryAddress & ValidMtrrAddressMask) | MemoryCacheType;\r
187 AsmWriteMsr64 (MtrrNumber, TempQword);\r
188\r
189 //\r
190 // MTRR Physical Mask\r
191 //\r
192 TempQword = ~(MemoryLength - 1);\r
193 AsmWriteMsr64 (MtrrNumber + 1, (TempQword & ValidMtrrAddressMask) | B_EFI_MSR_CACHE_MTRR_VALID);\r
194\r
195 EfiRecoverCacheMtrr (TRUE, OldMtrr);\r
196}\r
197\r
198/**\r
199 Calculate the maximum value which is a power of 2, but less the MemoryLength.\r
200\r
201 @param[in] MemoryAddress Memory address.\r
202 @param[in] MemoryLength The number to pass in.\r
203\r
204 @return The maximum value which is align to power of 2 and less the MemoryLength\r
205\r
206**/\r
207UINT64\r
208Power2MaxMemory (\r
111f2228
MK
209 IN UINT64 MemoryAddress,\r
210 IN UINT64 MemoryLength\r
cf1d4549
JY
211 )\r
212{\r
111f2228 213 UINT64 Result;\r
cf1d4549
JY
214\r
215 if (MemoryLength == 0) {\r
216 return EFI_INVALID_PARAMETER;\r
217 }\r
218\r
219 //\r
91cc60ba 220 // Compute initial power of 2 size to return\r
cf1d4549 221 //\r
111f2228 222 Result = GetPowerOfTwo64 (MemoryLength);\r
cf1d4549
JY
223\r
224 //\r
225 // Special case base of 0 as all ranges are valid\r
226 //\r
227 if (MemoryAddress == 0) {\r
228 return Result;\r
229 }\r
230\r
231 //\r
232 // Loop till a value that can be mapped to this base address is found\r
233 //\r
234 while (CheckMtrrAlignment (MemoryAddress, Result) != 0) {\r
235 //\r
236 // Need to try the next smaller power of 2\r
237 //\r
238 Result = RShiftU64 (Result, 1);\r
239 }\r
240\r
241 return Result;\r
242}\r
243\r
244/**\r
245 Return MTRR alignment requirement for base address and size.\r
246\r
247 @param[in] BaseAddress Base address.\r
248 @param[in] Size Size.\r
249\r
91cc60ba
AC
250 @retval Zero Aligned.\r
251 @retval Non-Zero Not aligned.\r
cf1d4549
JY
252\r
253**/\r
254UINT32\r
255CheckMtrrAlignment (\r
111f2228
MK
256 IN UINT64 BaseAddress,\r
257 IN UINT64 Size\r
cf1d4549
JY
258 )\r
259{\r
111f2228
MK
260 UINT32 ShiftedBase;\r
261 UINT32 ShiftedSize;\r
cf1d4549
JY
262\r
263 //\r
264 // Shift base and size right 12 bits to allow for larger memory sizes. The\r
265 // MTRRs do not use the first 12 bits so this is safe for now. Only supports\r
266 // up to 52 bits of physical address space.\r
267 //\r
111f2228
MK
268 ShiftedBase = (UINT32)RShiftU64 (BaseAddress, 12);\r
269 ShiftedSize = (UINT32)RShiftU64 (Size, 12);\r
cf1d4549
JY
270\r
271 //\r
272 // Return the results to the caller of the MOD\r
273 //\r
274 return ShiftedBase % ShiftedSize;\r
275}\r
276\r
277/**\r
278 Programs fixed MTRRs registers.\r
279\r
280 @param[in] MemoryCacheType The memory type to set.\r
281 @param[in] Base The base address of memory range.\r
282 @param[in] Length The length of memory range.\r
283\r
284 @retval RETURN_SUCCESS The cache type was updated successfully\r
285 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid\r
286 for the fixed MTRRs.\r
287\r
288**/\r
289EFI_STATUS\r
290ProgramFixedMtrr (\r
111f2228
MK
291 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType,\r
292 IN UINT64 *Base,\r
293 IN UINT64 *Len\r
cf1d4549
JY
294 )\r
295{\r
111f2228
MK
296 UINT32 MsrNum;\r
297 UINT32 ByteShift;\r
298 UINT64 TempQword;\r
299 UINT64 OrMask;\r
300 UINT64 ClearMask;\r
cf1d4549
JY
301\r
302 TempQword = 0;\r
111f2228 303 OrMask = 0;\r
cf1d4549
JY
304 ClearMask = 0;\r
305\r
306 for (MsrNum = 0; MsrNum < V_EFI_FIXED_MTRR_NUMBER; MsrNum++) {\r
307 if ((*Base >= mFixedMtrrTable[MsrNum].BaseAddress) &&\r
111f2228
MK
308 (*Base < (mFixedMtrrTable[MsrNum].BaseAddress + 8 * mFixedMtrrTable[MsrNum].Length)))\r
309 {\r
cf1d4549
JY
310 break;\r
311 }\r
312 }\r
111f2228 313\r
cf1d4549
JY
314 if (MsrNum == V_EFI_FIXED_MTRR_NUMBER ) {\r
315 return EFI_DEVICE_ERROR;\r
316 }\r
111f2228 317\r
cf1d4549
JY
318 //\r
319 // We found the fixed MTRR to be programmed\r
320 //\r
111f2228 321 for (ByteShift = 0; ByteShift < 8; ByteShift++) {\r
cf1d4549
JY
322 if ( *Base == (mFixedMtrrTable[MsrNum].BaseAddress + ByteShift * mFixedMtrrTable[MsrNum].Length)) {\r
323 break;\r
324 }\r
325 }\r
111f2228 326\r
cf1d4549
JY
327 if (ByteShift == 8 ) {\r
328 return EFI_DEVICE_ERROR;\r
329 }\r
111f2228
MK
330\r
331 for ( ; ((ByteShift < 8) && (*Len >= mFixedMtrrTable[MsrNum].Length)); ByteShift++) {\r
332 OrMask |= LShiftU64 ((UINT64)MemoryCacheType, (UINT32)(ByteShift* 8));\r
333 ClearMask |= LShiftU64 ((UINT64)0xFF, (UINT32)(ByteShift * 8));\r
334 *Len -= mFixedMtrrTable[MsrNum].Length;\r
335 *Base += mFixedMtrrTable[MsrNum].Length;\r
cf1d4549 336 }\r
111f2228 337\r
cf1d4549
JY
338 TempQword = (AsmReadMsr64 (mFixedMtrrTable[MsrNum].Msr) & (~ClearMask)) | OrMask;\r
339 AsmWriteMsr64 (mFixedMtrrTable[MsrNum].Msr, TempQword);\r
340\r
341 return EFI_SUCCESS;\r
342}\r
343\r
344/**\r
345 Check if there is a valid variable MTRR that overlaps the given range.\r
346\r
347 @param[in] Start Base Address of the range to check.\r
348 @param[in] End End address of the range to check.\r
349\r
350 @retval TRUE Mtrr overlap.\r
351 @retval FALSE Mtrr not overlap.\r
352**/\r
353BOOLEAN\r
354CheckMtrrOverlap (\r
111f2228
MK
355 IN EFI_PHYSICAL_ADDRESS Start,\r
356 IN EFI_PHYSICAL_ADDRESS End\r
cf1d4549
JY
357 )\r
358{\r
359 return FALSE;\r
360}\r
361\r
362/**\r
363 Given the memory range and cache type, programs the MTRRs.\r
364\r
365 @param[in] MemoryAddress Base Address of Memory to program MTRR.\r
366 @param[in] MemoryLength Length of Memory to program MTRR.\r
367 @param[in] MemoryCacheType Cache Type.\r
368\r
369 @retval EFI_SUCCESS Mtrr are set successfully.\r
370 @retval EFI_LOAD_ERROR No empty MTRRs to use.\r
371 @retval EFI_INVALID_PARAMETER The input parameter is not valid.\r
372 @retval others An error occurs when setting MTTR.\r
373\r
374**/\r
375EFI_STATUS\r
376EFIAPI\r
377SetCacheAttributes (\r
111f2228
MK
378 IN EFI_PHYSICAL_ADDRESS MemoryAddress,\r
379 IN UINT64 MemoryLength,\r
380 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType\r
cf1d4549
JY
381 )\r
382{\r
111f2228
MK
383 EFI_STATUS Status;\r
384 UINT32 MsrNum, MsrNumEnd;\r
385 UINT64 TempQword;\r
386 UINT32 LastVariableMtrrForBios;\r
387 UINT64 OldMtrr;\r
388 UINT32 UsedMsrNum;\r
389 EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType;\r
390 UINT64 ValidMtrrAddressMask;\r
391 UINT32 Cpuid_RegEax;\r
cf1d4549
JY
392\r
393 AsmCpuid (CPUID_EXTENDED_FUNCTION, &Cpuid_RegEax, NULL, NULL, NULL);\r
394 if (Cpuid_RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) {\r
395 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &Cpuid_RegEax, NULL, NULL, NULL);\r
111f2228 396 ValidMtrrAddressMask = (LShiftU64 ((UINT64)1, (Cpuid_RegEax & 0xFF)) - 1) & (~(UINT64)0x0FFF);\r
cf1d4549 397 } else {\r
111f2228 398 ValidMtrrAddressMask = (LShiftU64 ((UINT64)1, 36) - 1) & (~(UINT64)0x0FFF);\r
cf1d4549
JY
399 }\r
400\r
401 //\r
402 // Check for invalid parameter\r
403 //\r
111f2228 404 if (((MemoryAddress & ~ValidMtrrAddressMask) != 0) || ((MemoryLength & ~ValidMtrrAddressMask) != 0)) {\r
cf1d4549
JY
405 return EFI_INVALID_PARAMETER;\r
406 }\r
407\r
408 if (MemoryLength == 0) {\r
409 return EFI_INVALID_PARAMETER;\r
410 }\r
411\r
412 switch (MemoryCacheType) {\r
413 case EFI_CACHE_UNCACHEABLE:\r
414 case EFI_CACHE_WRITECOMBINING:\r
415 case EFI_CACHE_WRITETHROUGH:\r
416 case EFI_CACHE_WRITEPROTECTED:\r
417 case EFI_CACHE_WRITEBACK:\r
418 break;\r
419\r
420 default:\r
421 return EFI_INVALID_PARAMETER;\r
422 }\r
423\r
424 //\r
425 // Check if Fixed MTRR\r
426 //\r
427 if ((MemoryAddress + MemoryLength) <= (1 << 20)) {\r
428 Status = EFI_SUCCESS;\r
429 EfiDisableCacheMtrr (&OldMtrr);\r
430 while ((MemoryLength > 0) && (Status == EFI_SUCCESS)) {\r
431 Status = ProgramFixedMtrr (MemoryCacheType, &MemoryAddress, &MemoryLength);\r
432 }\r
111f2228 433\r
cf1d4549
JY
434 EfiRecoverCacheMtrr (TRUE, OldMtrr);\r
435 return Status;\r
436 }\r
437\r
438 //\r
439 // Search if the range attribute has been set before\r
440 //\r
111f2228
MK
441 Status = SearchForExactMtrr (\r
442 MemoryAddress,\r
443 MemoryLength,\r
444 ValidMtrrAddressMask,\r
445 &UsedMsrNum,\r
446 &UsedMemoryCacheType\r
447 );\r
cf1d4549 448\r
111f2228 449 if (!EFI_ERROR (Status)) {\r
cf1d4549
JY
450 //\r
451 // Compare if it has the same type as current setting\r
452 //\r
453 if (UsedMemoryCacheType == MemoryCacheType) {\r
454 return EFI_SUCCESS;\r
455 } else {\r
456 //\r
457 // Different type\r
458 //\r
459\r
460 //\r
461 // Check if the set type is the same as Default Type\r
462 //\r
111f2228 463 if (IsDefaultType (MemoryCacheType)) {\r
cf1d4549
JY
464 //\r
465 // Clear the MTRR\r
466 //\r
111f2228
MK
467 AsmWriteMsr64 (UsedMsrNum, 0);\r
468 AsmWriteMsr64 (UsedMsrNum + 1, 0);\r
cf1d4549
JY
469\r
470 return EFI_SUCCESS;\r
471 } else {\r
472 //\r
473 // Modify the MTRR type\r
474 //\r
111f2228
MK
475 EfiProgramMtrr (\r
476 UsedMsrNum,\r
477 MemoryAddress,\r
478 MemoryLength,\r
479 MemoryCacheType,\r
480 ValidMtrrAddressMask\r
481 );\r
cf1d4549
JY
482 return EFI_SUCCESS;\r
483 }\r
484 }\r
485 }\r
486\r
111f2228 487 #if 0\r
cf1d4549
JY
488 //\r
489 // @bug - Need to create memory map so that when checking for overlap we\r
490 // can determine if an overlap exists based on all caching requests.\r
491 //\r
492 // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE\r
493 //\r
111f2228 494 if (MemoryCacheType == (AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE)) {\r
cf1d4549
JY
495 if (!CheckMtrrOverlap (MemoryAddress, MemoryAddress+MemoryLength-1)) {\r
496 return EFI_SUCCESS;\r
497 }\r
498 }\r
111f2228
MK
499\r
500 #endif\r
cf1d4549
JY
501\r
502 //\r
503 // Find first unused MTRR\r
504 //\r
111f2228
MK
505 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64 (EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));\r
506 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum += 2) {\r
507 if ((AsmReadMsr64 (MsrNum+1) & B_EFI_MSR_CACHE_MTRR_VALID) == 0 ) {\r
cf1d4549
JY
508 break;\r
509 }\r
510 }\r
511\r
512 //\r
513 // Reserve 1 MTRR pair for OS.\r
514 //\r
515 LastVariableMtrrForBios = MsrNumEnd - 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS * 2);\r
516 if (MsrNum > LastVariableMtrrForBios) {\r
517 return EFI_LOAD_ERROR;\r
518 }\r
519\r
520 //\r
521 // Special case for 1 MB base address\r
522 //\r
523 if (MemoryAddress == BASE_1MB) {\r
524 MemoryAddress = 0;\r
525 }\r
526\r
527 //\r
528 // Program MTRRs\r
529 //\r
530 TempQword = MemoryLength;\r
531\r
111f2228
MK
532 if (TempQword == Power2MaxMemory (MemoryAddress, TempQword)) {\r
533 EfiProgramMtrr (\r
534 MsrNum,\r
535 MemoryAddress,\r
536 MemoryLength,\r
537 MemoryCacheType,\r
538 ValidMtrrAddressMask\r
539 );\r
cf1d4549
JY
540 } else {\r
541 //\r
542 // Fill in MTRRs with values. Direction can not be checked for this method\r
543 // as we are using WB as the default cache type and only setting areas to UC.\r
544 //\r
545 do {\r
546 //\r
547 // Do boundary check so we don't go past last MTRR register\r
548 // for BIOS use. Leave one MTRR pair for OS use.\r
549 //\r
550 if (MsrNum > LastVariableMtrrForBios) {\r
551 return EFI_LOAD_ERROR;\r
552 }\r
553\r
554 //\r
555 // Set next power of 2 region\r
556 //\r
111f2228
MK
557 MemoryLength = Power2MaxMemory (MemoryAddress, TempQword);\r
558 EfiProgramMtrr (\r
559 MsrNum,\r
560 MemoryAddress,\r
561 MemoryLength,\r
562 MemoryCacheType,\r
563 ValidMtrrAddressMask\r
564 );\r
cf1d4549 565 MemoryAddress += MemoryLength;\r
111f2228
MK
566 TempQword -= MemoryLength;\r
567 MsrNum += 2;\r
cf1d4549
JY
568 } while (TempQword != 0);\r
569 }\r
570\r
571 return EFI_SUCCESS;\r
572}\r
573\r
574/**\r
575 Reset all the MTRRs to a known state.\r
576\r
577 @retval EFI_SUCCESS All MTRRs have been reset successfully.\r
578\r
579**/\r
580EFI_STATUS\r
581EFIAPI\r
582ResetCacheAttributes (\r
583 VOID\r
584 )\r
585{\r
111f2228
MK
586 UINT32 MsrNum, MsrNumEnd;\r
587 UINT16 Index;\r
588 UINT64 OldMtrr;\r
589 UINT64 CacheType;\r
590 BOOLEAN DisableCar;\r
591\r
592 Index = 0;\r
cf1d4549
JY
593 DisableCar = TRUE;\r
594\r
595 //\r
596 // Determine default cache type\r
597 //\r
598 CacheType = EFI_CACHE_UNCACHEABLE;\r
599\r
600 //\r
601 // Set default cache type\r
602 //\r
111f2228 603 AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE, CacheType);\r
cf1d4549
JY
604\r
605 //\r
606 // Disable CAR\r
607 //\r
608 DisableCacheAsRam (DisableCar);\r
609\r
610 EfiDisableCacheMtrr (&OldMtrr);\r
611\r
612 //\r
613 // Reset Fixed MTRRs\r
614 //\r
615 for (Index = 0; Index < V_EFI_FIXED_MTRR_NUMBER; Index++) {\r
616 AsmWriteMsr64 (mFixedMtrrTable[Index].Msr, 0);\r
617 }\r
618\r
619 //\r
620 // Reset Variable MTRRs\r
621 //\r
111f2228 622 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64 (EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));\r
cf1d4549
JY
623 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum++) {\r
624 AsmWriteMsr64 (MsrNum, 0);\r
625 }\r
626\r
627 //\r
628 // Enable Fixed and Variable MTRRs\r
629 //\r
630 EfiRecoverCacheMtrr (TRUE, OldMtrr);\r
631\r
632 return EFI_SUCCESS;\r
633}\r
634\r
635/**\r
636 Search the memory cache type for specific memory from MTRR.\r
637\r
638 @param[in] MemoryAddress the address of target memory\r
639 @param[in] MemoryLength the length of target memory\r
640 @param[in] ValidMtrrAddressMask the MTRR address mask\r
641 @param[out] UsedMsrNum the used MSR number\r
642 @param[out] UsedMemoryCacheType the cache type for the target memory\r
643\r
644 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned\r
645 @retval EFI_NOT_FOUND The memory is not found in MTRR\r
646\r
647**/\r
648EFI_STATUS\r
649SearchForExactMtrr (\r
111f2228
MK
650 IN EFI_PHYSICAL_ADDRESS MemoryAddress,\r
651 IN UINT64 MemoryLength,\r
652 IN UINT64 ValidMtrrAddressMask,\r
653 OUT UINT32 *UsedMsrNum,\r
654 OUT EFI_MEMORY_CACHE_TYPE *UsedMemoryCacheType\r
cf1d4549
JY
655 )\r
656{\r
111f2228
MK
657 UINT32 MsrNum, MsrNumEnd;\r
658 UINT64 TempQword;\r
cf1d4549
JY
659\r
660 if (MemoryLength == 0) {\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
111f2228
MK
664 MsrNumEnd = EFI_MSR_CACHE_VARIABLE_MTRR_BASE + (2 * (UINT32)(AsmReadMsr64 (EFI_MSR_IA32_MTRR_CAP) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT));\r
665 for (MsrNum = EFI_MSR_CACHE_VARIABLE_MTRR_BASE; MsrNum < MsrNumEnd; MsrNum += 2) {\r
666 TempQword = AsmReadMsr64 (MsrNum+1);\r
cf1d4549
JY
667 if ((TempQword & B_EFI_MSR_CACHE_MTRR_VALID) == 0) {\r
668 continue;\r
669 }\r
670\r
671 if ((TempQword & ValidMtrrAddressMask) != ((~(MemoryLength - 1)) & ValidMtrrAddressMask)) {\r
672 continue;\r
673 }\r
674\r
675 TempQword = AsmReadMsr64 (MsrNum);\r
676 if ((TempQword & ValidMtrrAddressMask) != (MemoryAddress & ValidMtrrAddressMask)) {\r
677 continue;\r
678 }\r
679\r
680 *UsedMemoryCacheType = (EFI_MEMORY_CACHE_TYPE)(TempQword & B_EFI_MSR_CACHE_MEMORY_TYPE);\r
111f2228 681 *UsedMsrNum = MsrNum;\r
cf1d4549
JY
682\r
683 return EFI_SUCCESS;\r
684 }\r
685\r
686 return EFI_NOT_FOUND;\r
687}\r
688\r
689/**\r
690 Check if CacheType match current default setting.\r
691\r
692 @param[in] MemoryCacheType input cache type to be checked.\r
693\r
694 @retval TRUE MemoryCacheType is default MTRR setting.\r
695 @retval TRUE MemoryCacheType is NOT default MTRR setting.\r
696**/\r
697BOOLEAN\r
698IsDefaultType (\r
111f2228 699 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType\r
cf1d4549
JY
700 )\r
701{\r
111f2228 702 if ((AsmReadMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE) & B_EFI_MSR_CACHE_MEMORY_TYPE) != MemoryCacheType) {\r
cf1d4549
JY
703 return FALSE;\r
704 }\r
705\r
706 return TRUE;\r
707}\r