3 Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php.
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Library/BaseLib.h>
16 #include <Library/CacheLib.h>
17 #include <Library/CacheAsRamLib.h>
18 #include "CacheLibInternal.h"
21 Calculate the maximum value which is a power of 2, but less the Input.
23 @param[in] Input The number to pass in.
24 @return The maximum value which is align to power of 2 and less the Input
32 Search the memory cache type for specific memory from MTRR.
34 @param[in] MemoryAddress the address of target memory
35 @param[in] MemoryLength the length of target memory
36 @param[in] ValidMtrrAddressMask the MTRR address mask
37 @param[out] UsedMsrNum the used MSR number
38 @param[out] UsedMemoryCacheType the cache type for the target memory
40 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
41 @retval EFI_NOT_FOUND The memory is not found in MTRR
46 IN EFI_PHYSICAL_ADDRESS MemoryAddress
,
47 IN UINT64 MemoryLength
,
48 IN UINT64 ValidMtrrAddressMask
,
49 OUT UINT32
*UsedMsrNum
,
50 OUT EFI_MEMORY_CACHE_TYPE
*MemoryCacheType
54 Check if CacheType match current default setting.
56 @param[in] MemoryCacheType input cache type to be checked.
58 @retval TRUE MemoryCacheType is default MTRR setting.
59 @retval TRUE MemoryCacheType is NOT default MTRR setting.
63 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
67 Return MTRR alignment requirement for base address and size.
69 @param[in] BaseAddress Base address.
72 @retval Zero Alligned.
73 @retval Non-Zero Not alligned.
78 IN UINT64 BaseAddress
,
88 EFI_FIXED_MTRR mFixedMtrrTable
[] = {
89 { EFI_MSR_IA32_MTRR_FIX64K_00000
, 0, 0x10000},
90 { EFI_MSR_IA32_MTRR_FIX16K_80000
, 0x80000, 0x4000},
91 { EFI_MSR_IA32_MTRR_FIX16K_A0000
, 0xA0000, 0x4000},
92 { EFI_MSR_IA32_MTRR_FIX4K_C0000
, 0xC0000, 0x1000},
93 { EFI_MSR_IA32_MTRR_FIX4K_C8000
, 0xC8000, 0x1000},
94 { EFI_MSR_IA32_MTRR_FIX4K_D0000
, 0xD0000, 0x1000},
95 { EFI_MSR_IA32_MTRR_FIX4K_D8000
, 0xD8000, 0x1000},
96 { EFI_MSR_IA32_MTRR_FIX4K_E0000
, 0xE0000, 0x1000},
97 { EFI_MSR_IA32_MTRR_FIX4K_E8000
, 0xE8000, 0x1000},
98 { EFI_MSR_IA32_MTRR_FIX4K_F0000
, 0xF0000, 0x1000},
99 { EFI_MSR_IA32_MTRR_FIX4K_F8000
, 0xF8000, 0x1000}
103 Given the input, check if the number of MTRR is lesser.
104 if positive or subtractive.
106 @param[in] Input Length of Memory to program MTRR.
108 @retval Zero do positive.
109 @retval Non-Zero do subtractive.
121 Disable cache and its mtrr.
123 @param[out] OldMtrr To return the Old MTRR value
127 EfiDisableCacheMtrr (
134 // Disable Cache MTRR
136 *OldMtrr
= AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
);
137 TempQword
= (*OldMtrr
) & ~B_EFI_MSR_GLOBAL_MTRR_ENABLE
& ~B_EFI_MSR_FIXED_MTRR_ENABLE
;
138 AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
, TempQword
);
145 @param[in] EnableMtrr Whether to enable the MTRR
146 @param[in] OldMtrr The saved old MTRR value to restore when not to enable the MTRR
150 EfiRecoverCacheMtrr (
151 IN BOOLEAN EnableMtrr
,
161 TempQword
= AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
);
162 TempQword
|= (UINT64
)(B_EFI_MSR_GLOBAL_MTRR_ENABLE
| B_EFI_MSR_FIXED_MTRR_ENABLE
);
167 AsmWriteMsr64 (EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
, TempQword
);
173 Programming MTRR according to Memory address, length, and type.
175 @param[in] MtrrNumber the variable MTRR index number
176 @param[in] MemoryAddress the address of target memory
177 @param[in] MemoryLength the length of target memory
178 @param[in] MemoryCacheType the cache type of target memory
179 @param[in] ValidMtrrAddressMask the MTRR address mask
185 IN EFI_PHYSICAL_ADDRESS MemoryAddress
,
186 IN UINT64 MemoryLength
,
187 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
,
188 IN UINT64 ValidMtrrAddressMask
194 if (MemoryLength
== 0) {
198 EfiDisableCacheMtrr (&OldMtrr
);
201 // MTRR Physical Base
203 TempQword
= (MemoryAddress
& ValidMtrrAddressMask
) | MemoryCacheType
;
204 AsmWriteMsr64 (MtrrNumber
, TempQword
);
207 // MTRR Physical Mask
209 TempQword
= ~(MemoryLength
- 1);
210 AsmWriteMsr64 (MtrrNumber
+ 1, (TempQword
& ValidMtrrAddressMask
) | B_EFI_MSR_CACHE_MTRR_VALID
);
212 EfiRecoverCacheMtrr (TRUE
, OldMtrr
);
216 Calculate the maximum value which is a power of 2, but less the MemoryLength.
218 @param[in] MemoryAddress Memory address.
219 @param[in] MemoryLength The number to pass in.
221 @return The maximum value which is align to power of 2 and less the MemoryLength
226 IN UINT64 MemoryAddress
,
227 IN UINT64 MemoryLength
232 if (MemoryLength
== 0) {
233 return EFI_INVALID_PARAMETER
;
237 // Compute inital power of 2 size to return
239 if (RShiftU64(MemoryLength
, 32)) {
240 Result
= LShiftU64((UINT64
)SetPower2((UINT32
) RShiftU64(MemoryLength
, 32)), 32);
242 Result
= (UINT64
)SetPower2((UINT32
)MemoryLength
);
246 // Special case base of 0 as all ranges are valid
248 if (MemoryAddress
== 0) {
253 // Loop till a value that can be mapped to this base address is found
255 while (CheckMtrrAlignment (MemoryAddress
, Result
) != 0) {
257 // Need to try the next smaller power of 2
259 Result
= RShiftU64 (Result
, 1);
266 Return MTRR alignment requirement for base address and size.
268 @param[in] BaseAddress Base address.
269 @param[in] Size Size.
271 @retval Zero Alligned.
272 @retval Non-Zero Not alligned.
277 IN UINT64 BaseAddress
,
285 // Shift base and size right 12 bits to allow for larger memory sizes. The
286 // MTRRs do not use the first 12 bits so this is safe for now. Only supports
287 // up to 52 bits of physical address space.
289 ShiftedBase
= (UINT32
) RShiftU64 (BaseAddress
, 12);
290 ShiftedSize
= (UINT32
) RShiftU64 (Size
, 12);
293 // Return the results to the caller of the MOD
295 return ShiftedBase
% ShiftedSize
;
299 Calculate the maximum value which is a power of 2, but less the Input.
301 @param[in] Input The number to pass in.
303 @return The maximum value which is align to power of 2 and less the Input.
320 #elif defined(_MSC_VER)
330 Programs fixed MTRRs registers.
332 @param[in] MemoryCacheType The memory type to set.
333 @param[in] Base The base address of memory range.
334 @param[in] Length The length of memory range.
336 @retval RETURN_SUCCESS The cache type was updated successfully
337 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
343 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
,
358 for (MsrNum
= 0; MsrNum
< V_EFI_FIXED_MTRR_NUMBER
; MsrNum
++) {
359 if ((*Base
>= mFixedMtrrTable
[MsrNum
].BaseAddress
) &&
360 (*Base
< (mFixedMtrrTable
[MsrNum
].BaseAddress
+ 8 * mFixedMtrrTable
[MsrNum
].Length
))) {
364 if (MsrNum
== V_EFI_FIXED_MTRR_NUMBER
) {
365 return EFI_DEVICE_ERROR
;
368 // We found the fixed MTRR to be programmed
370 for (ByteShift
=0; ByteShift
< 8; ByteShift
++) {
371 if ( *Base
== (mFixedMtrrTable
[MsrNum
].BaseAddress
+ ByteShift
* mFixedMtrrTable
[MsrNum
].Length
)) {
375 if (ByteShift
== 8 ) {
376 return EFI_DEVICE_ERROR
;
378 for (; ((ByteShift
<8) && (*Len
>= mFixedMtrrTable
[MsrNum
].Length
));ByteShift
++) {
379 OrMask
|= LShiftU64((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
380 ClearMask
|= LShiftU64((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
381 *Len
-= mFixedMtrrTable
[MsrNum
].Length
;
382 *Base
+= mFixedMtrrTable
[MsrNum
].Length
;
384 TempQword
= AsmReadMsr64 (mFixedMtrrTable
[MsrNum
].Msr
) & (~ClearMask
| OrMask
);
385 AsmWriteMsr64 (mFixedMtrrTable
[MsrNum
].Msr
, TempQword
);
391 Check if there is a valid variable MTRR that overlaps the given range.
393 @param[in] Start Base Address of the range to check.
394 @param[in] End End address of the range to check.
396 @retval TRUE Mtrr overlap.
397 @retval FALSE Mtrr not overlap.
401 IN EFI_PHYSICAL_ADDRESS Start
,
402 IN EFI_PHYSICAL_ADDRESS End
409 Given the memory range and cache type, programs the MTRRs.
411 @param[in] MemoryAddress Base Address of Memory to program MTRR.
412 @param[in] MemoryLength Length of Memory to program MTRR.
413 @param[in] MemoryCacheType Cache Type.
415 @retval EFI_SUCCESS Mtrr are set successfully.
416 @retval EFI_LOAD_ERROR No empty MTRRs to use.
417 @retval EFI_INVALID_PARAMETER The input parameter is not valid.
418 @retval others An error occurs when setting MTTR.
424 IN EFI_PHYSICAL_ADDRESS MemoryAddress
,
425 IN UINT64 MemoryLength
,
426 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
430 UINT32 MsrNum
, MsrNumEnd
;
432 UINT32 LastVariableMtrrForBios
;
435 EFI_MEMORY_CACHE_TYPE UsedMemoryCacheType
;
436 UINT64 ValidMtrrAddressMask
;
439 AsmCpuid (CPUID_EXTENDED_FUNCTION
, &Cpuid_RegEax
, NULL
, NULL
, NULL
);
440 if (Cpuid_RegEax
>= CPUID_VIR_PHY_ADDRESS_SIZE
) {
441 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE
, &Cpuid_RegEax
, NULL
, NULL
, NULL
);
442 ValidMtrrAddressMask
= (LShiftU64((UINT64
) 1, (Cpuid_RegEax
& 0xFF)) - 1) & (~(UINT64
)0x0FFF);
444 ValidMtrrAddressMask
= (LShiftU64((UINT64
) 1, 36) - 1) & (~(UINT64
)0x0FFF);
448 // Check for invalid parameter
450 if ((MemoryAddress
& ~ValidMtrrAddressMask
) != 0 || (MemoryLength
& ~ValidMtrrAddressMask
) != 0) {
451 return EFI_INVALID_PARAMETER
;
454 if (MemoryLength
== 0) {
455 return EFI_INVALID_PARAMETER
;
458 switch (MemoryCacheType
) {
459 case EFI_CACHE_UNCACHEABLE
:
460 case EFI_CACHE_WRITECOMBINING
:
461 case EFI_CACHE_WRITETHROUGH
:
462 case EFI_CACHE_WRITEPROTECTED
:
463 case EFI_CACHE_WRITEBACK
:
467 return EFI_INVALID_PARAMETER
;
471 // Check if Fixed MTRR
473 if ((MemoryAddress
+ MemoryLength
) <= (1 << 20)) {
474 Status
= EFI_SUCCESS
;
475 EfiDisableCacheMtrr (&OldMtrr
);
476 while ((MemoryLength
> 0) && (Status
== EFI_SUCCESS
)) {
477 Status
= ProgramFixedMtrr (MemoryCacheType
, &MemoryAddress
, &MemoryLength
);
479 EfiRecoverCacheMtrr (TRUE
, OldMtrr
);
484 // Search if the range attribute has been set before
486 Status
= SearchForExactMtrr(
489 ValidMtrrAddressMask
,
494 if (!EFI_ERROR(Status
)) {
496 // Compare if it has the same type as current setting
498 if (UsedMemoryCacheType
== MemoryCacheType
) {
506 // Check if the set type is the same as Default Type
508 if (IsDefaultType(MemoryCacheType
)) {
512 AsmWriteMsr64(UsedMsrNum
, 0);
513 AsmWriteMsr64(UsedMsrNum
+ 1, 0);
518 // Modify the MTRR type
520 EfiProgramMtrr(UsedMsrNum
,
533 // @bug - Need to create memory map so that when checking for overlap we
534 // can determine if an overlap exists based on all caching requests.
536 // Don't waste a variable MTRR if the caching attrib is same as default in MTRR_DEF_TYPE
538 if (MemoryCacheType
== (AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
) & B_EFI_MSR_CACHE_MEMORY_TYPE
)) {
539 if (!CheckMtrrOverlap (MemoryAddress
, MemoryAddress
+MemoryLength
-1)) {
546 // Find first unused MTRR
548 MsrNumEnd
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
+ (2 * (UINT32
)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP
) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT
));
549 for (MsrNum
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
; MsrNum
< MsrNumEnd
; MsrNum
+=2) {
550 if ((AsmReadMsr64(MsrNum
+1) & B_EFI_MSR_CACHE_MTRR_VALID
) == 0 ) {
556 // Reserve 1 MTRR pair for OS.
558 LastVariableMtrrForBios
= MsrNumEnd
- 1 - (EFI_CACHE_NUM_VAR_MTRR_PAIRS_FOR_OS
* 2);
559 if (MsrNum
> LastVariableMtrrForBios
) {
560 return EFI_LOAD_ERROR
;
564 // Special case for 1 MB base address
566 if (MemoryAddress
== BASE_1MB
) {
573 TempQword
= MemoryLength
;
575 if (TempQword
== Power2MaxMemory(MemoryAddress
, TempQword
)) {
576 EfiProgramMtrr(MsrNum
,
585 // Fill in MTRRs with values. Direction can not be checked for this method
586 // as we are using WB as the default cache type and only setting areas to UC.
590 // Do boundary check so we don't go past last MTRR register
591 // for BIOS use. Leave one MTRR pair for OS use.
593 if (MsrNum
> LastVariableMtrrForBios
) {
594 return EFI_LOAD_ERROR
;
598 // Set next power of 2 region
600 MemoryLength
= Power2MaxMemory(MemoryAddress
, TempQword
);
601 EfiProgramMtrr(MsrNum
,
607 MemoryAddress
+= MemoryLength
;
608 TempQword
-= MemoryLength
;
610 } while (TempQword
!= 0);
617 Reset all the MTRRs to a known state.
619 @retval EFI_SUCCESS All MTRRs have been reset successfully.
624 ResetCacheAttributes (
628 UINT32 MsrNum
, MsrNumEnd
;
637 // Determine default cache type
639 CacheType
= EFI_CACHE_UNCACHEABLE
;
642 // Set default cache type
644 AsmWriteMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
, CacheType
);
649 DisableCacheAsRam (DisableCar
);
651 EfiDisableCacheMtrr (&OldMtrr
);
656 for (Index
= 0; Index
< V_EFI_FIXED_MTRR_NUMBER
; Index
++) {
657 AsmWriteMsr64 (mFixedMtrrTable
[Index
].Msr
, 0);
661 // Reset Variable MTRRs
663 MsrNumEnd
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
+ (2 * (UINT32
)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP
) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT
));
664 for (MsrNum
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
; MsrNum
< MsrNumEnd
; MsrNum
++) {
665 AsmWriteMsr64 (MsrNum
, 0);
669 // Enable Fixed and Variable MTRRs
671 EfiRecoverCacheMtrr (TRUE
, OldMtrr
);
677 Search the memory cache type for specific memory from MTRR.
679 @param[in] MemoryAddress the address of target memory
680 @param[in] MemoryLength the length of target memory
681 @param[in] ValidMtrrAddressMask the MTRR address mask
682 @param[out] UsedMsrNum the used MSR number
683 @param[out] UsedMemoryCacheType the cache type for the target memory
685 @retval EFI_SUCCESS The memory is found in MTRR and cache type is returned
686 @retval EFI_NOT_FOUND The memory is not found in MTRR
691 IN EFI_PHYSICAL_ADDRESS MemoryAddress
,
692 IN UINT64 MemoryLength
,
693 IN UINT64 ValidMtrrAddressMask
,
694 OUT UINT32
*UsedMsrNum
,
695 OUT EFI_MEMORY_CACHE_TYPE
*UsedMemoryCacheType
698 UINT32 MsrNum
, MsrNumEnd
;
701 if (MemoryLength
== 0) {
702 return EFI_INVALID_PARAMETER
;
705 MsrNumEnd
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
+ (2 * (UINT32
)(AsmReadMsr64(EFI_MSR_IA32_MTRR_CAP
) & B_EFI_MSR_IA32_MTRR_CAP_VARIABLE_SUPPORT
));
706 for (MsrNum
= EFI_MSR_CACHE_VARIABLE_MTRR_BASE
; MsrNum
< MsrNumEnd
; MsrNum
+=2) {
707 TempQword
= AsmReadMsr64(MsrNum
+1);
708 if ((TempQword
& B_EFI_MSR_CACHE_MTRR_VALID
) == 0) {
712 if ((TempQword
& ValidMtrrAddressMask
) != ((~(MemoryLength
- 1)) & ValidMtrrAddressMask
)) {
716 TempQword
= AsmReadMsr64 (MsrNum
);
717 if ((TempQword
& ValidMtrrAddressMask
) != (MemoryAddress
& ValidMtrrAddressMask
)) {
721 *UsedMemoryCacheType
= (EFI_MEMORY_CACHE_TYPE
)(TempQword
& B_EFI_MSR_CACHE_MEMORY_TYPE
);
722 *UsedMsrNum
= MsrNum
;
727 return EFI_NOT_FOUND
;
731 Check if CacheType match current default setting.
733 @param[in] MemoryCacheType input cache type to be checked.
735 @retval TRUE MemoryCacheType is default MTRR setting.
736 @retval TRUE MemoryCacheType is NOT default MTRR setting.
740 IN EFI_MEMORY_CACHE_TYPE MemoryCacheType
743 if ((AsmReadMsr64(EFI_MSR_CACHE_IA32_MTRR_DEF_TYPE
) & B_EFI_MSR_CACHE_MEMORY_TYPE
) != MemoryCacheType
) {