4 Copyright (c) 2008 - 2009, Intel Corporation
5 All rights reserved. This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/MtrrLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/CpuLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
24 // This table defines the offset, base and length of the fixed MTRRs
27 FIXED_MTRR MtrrLibFixedMtrrTable
[] = {
29 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
34 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
39 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
44 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
49 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
54 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
59 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
64 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
69 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
74 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
79 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
87 Returns the default MTRR cache type for the system.
89 @return MTRR default type
93 GetMtrrDefaultMemoryType (
97 return (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0xff);
102 Preparation before programming MTRR.
104 This function will do some preparation for programming MTRRs:
105 disable cache, invalid cache and disable MTRR caching functionality
107 @return CR4 value before changing.
118 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
120 Value
= AsmReadCr0 ();
121 Value
= (UINTN
) BitFieldWrite64 (Value
, 30, 30, 1);
122 Value
= (UINTN
) BitFieldWrite64 (Value
, 29, 29, 0);
129 // Clear PGE flag Bit 7
131 Value
= AsmReadCr4 ();
132 AsmWriteCr4 ((UINTN
) BitFieldWrite64 (Value
, 7, 7, 0));
140 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
147 Cleaning up after programming MTRRs.
149 This function will do some clean up after programming MTRRs:
150 enable MTRR caching functionality, and enable cache
152 @param Cr4 CR4 value to restore
165 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
168 // Flush all TLBs and cache the second time
174 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
176 Value
= AsmReadCr0 ();
177 Value
= (UINTN
) BitFieldWrite64 (Value
, 30, 30, 0);
178 Value
= (UINTN
) BitFieldWrite64 (Value
, 29, 29, 0);
188 Programs fixed MTRRs registers.
190 @param MemoryCacheType The memory type to set.
191 @param Base The base address of memory range.
192 @param Length The length of memory range.
194 @retval RETURN_SUCCESS The cache type was updated successfully
195 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
201 IN UINT64 MemoryCacheType
,
203 IN OUT UINT64
*Length
216 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
217 if ((*Base
>= MtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
220 MtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
221 (8 * MtrrLibFixedMtrrTable
[MsrNum
].Length
)
229 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
230 return RETURN_UNSUPPORTED
;
234 // We found the fixed MTRR to be programmed
236 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
239 MtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
240 (ByteShift
* MtrrLibFixedMtrrTable
[MsrNum
].Length
)
247 if (ByteShift
== 8) {
248 return RETURN_UNSUPPORTED
;
253 ((ByteShift
< 8) && (*Length
>= MtrrLibFixedMtrrTable
[MsrNum
].Length
));
256 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
257 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
258 *Length
-= MtrrLibFixedMtrrTable
[MsrNum
].Length
;
259 *Base
+= MtrrLibFixedMtrrTable
[MsrNum
].Length
;
262 if (ByteShift
< 8 && (*Length
!= 0)) {
263 return RETURN_UNSUPPORTED
;
267 (AsmReadMsr64 (MtrrLibFixedMtrrTable
[MsrNum
].Msr
) & ~ClearMask
) | OrMask
;
268 AsmWriteMsr64 (MtrrLibFixedMtrrTable
[MsrNum
].Msr
, TempQword
);
269 return RETURN_SUCCESS
;
274 Get the attribute of variable MTRRs.
276 This function shadows the content of variable MTRRs into an
277 internal array: VariableMtrr.
279 @param MtrrValidBitsMask The mask for the valid bit of the MTRR
280 @param MtrrValidAddressMask The valid address mask for MTRR
281 @param VariableMtrr The array to shadow variable MTRRs content
283 @return The return value of this paramter indicates the
284 number of MTRRs which has been used.
289 MtrrGetMemoryAttributeInVariableMtrr (
290 IN UINT64 MtrrValidBitsMask
,
291 IN UINT64 MtrrValidAddressMask
,
292 OUT VARIABLE_MTRR
*VariableMtrr
299 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
302 for (MsrNum
= MTRR_LIB_IA32_VARIABLE_MTRR_BASE
, Index
= 0;
304 (MsrNum
< MTRR_LIB_IA32_VARIABLE_MTRR_END
) &&
305 (Index
< FIRMWARE_VARIABLE_MTRR_NUMBER
)
309 if ((AsmReadMsr64 (MsrNum
+ 1) & MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
310 VariableMtrr
[Index
].Msr
= MsrNum
;
311 VariableMtrr
[Index
].BaseAddress
= (AsmReadMsr64 (MsrNum
) &
312 MtrrValidAddressMask
);
313 VariableMtrr
[Index
].Length
= ((~(AsmReadMsr64 (MsrNum
+ 1) &
314 MtrrValidAddressMask
)
318 VariableMtrr
[Index
].Type
= (AsmReadMsr64 (MsrNum
) & 0x0ff);
319 VariableMtrr
[Index
].Valid
= TRUE
;
320 VariableMtrr
[Index
].Used
= TRUE
;
321 UsedMtrr
= UsedMtrr
+ 1;
330 Checks overlap between given memory range and MTRRs.
332 @param Start The start address of memory range.
333 @param End The end address of memory range.
334 @param VariableMtrr The array to shadow variable MTRRs content
336 @retval TRUE Overlap exists.
337 @retval FALSE No overlap.
341 CheckMemoryAttributeOverlap (
342 IN PHYSICAL_ADDRESS Start
,
343 IN PHYSICAL_ADDRESS End
,
344 IN VARIABLE_MTRR
*VariableMtrr
349 for (Index
= 0; Index
< 6; Index
++) {
351 VariableMtrr
[Index
].Valid
&&
353 (Start
> (VariableMtrr
[Index
].BaseAddress
+
354 VariableMtrr
[Index
].Length
- 1)
356 (End
< VariableMtrr
[Index
].BaseAddress
)
368 Marks a variable MTRR as non-valid.
370 @param Index The index of the array VariableMtrr to be invalidated
371 @param VariableMtrr The array to shadow variable MTRRs content
372 @param UsedMtrr The number of MTRRs which has already been used
376 InvalidateShadowMtrr (
378 IN VARIABLE_MTRR
*VariableMtrr
,
382 VariableMtrr
[Index
].Valid
= FALSE
;
383 *UsedMtrr
= *UsedMtrr
- 1;
388 Combine memory attributes.
390 If overlap exists between given memory range and MTRRs, try to combine them.
392 @param Attributes The memory type to set.
393 @param Base The base address of memory range.
394 @param Length The length of memory range.
395 @param VariableMtrr The array to shadow variable MTRRs content
396 @param UsedMtrr The number of MTRRs which has already been used
397 @param OverwriteExistingMtrr Returns whether an existing MTRR was used
399 @retval EFI_SUCCESS Memory region successfully combined.
400 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
404 CombineMemoryAttribute (
405 IN UINT64 Attributes
,
407 IN OUT UINT64
*Length
,
408 IN VARIABLE_MTRR
*VariableMtrr
,
409 IN OUT UINT32
*UsedMtrr
,
410 OUT BOOLEAN
*OverwriteExistingMtrr
419 *OverwriteExistingMtrr
= FALSE
;
420 EndAddress
= *Base
+*Length
- 1;
422 for (Index
= 0; Index
< FIRMWARE_VARIABLE_MTRR_NUMBER
; Index
++) {
424 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
426 !VariableMtrr
[Index
].Valid
||
429 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
436 // Combine same attribute MTRR range
438 if (Attributes
== VariableMtrr
[Index
].Type
) {
440 // if the Mtrr range contain the request range, return RETURN_SUCCESS
442 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
444 return RETURN_SUCCESS
;
447 // invalid this MTRR, and program the combine range
450 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
452 VariableMtrr
[Index
].BaseAddress
;
453 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
456 // Record the MTRR usage status in VariableMtrr array.
458 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
459 *Base
= CombineStart
;
460 *Length
= CombineEnd
- CombineStart
+ 1;
461 EndAddress
= CombineEnd
;
462 *OverwriteExistingMtrr
= TRUE
;
466 // The cache type is different, but the range is convered by one MTRR
468 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
469 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
475 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
476 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
477 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
478 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
479 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
480 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
482 *OverwriteExistingMtrr
= TRUE
;
486 // Other type memory overlap is invalid
488 return RETURN_ACCESS_DENIED
;
491 return RETURN_SUCCESS
;
496 Calculate the maximum value which is a power of 2, but less the MemoryLength.
498 @param MemoryLength The number to pass in.
499 @return The maximum value which is align to power of 2 and less the MemoryLength
504 IN UINT64 MemoryLength
509 if (RShiftU64 (MemoryLength
, 32)) {
511 (UINT64
) GetPowerOfTwo32 (
512 (UINT32
) RShiftU64 (MemoryLength
, 32)
517 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
525 Check the direction to program variable MTRRs.
527 This function determines which direction of programming the variable
528 MTRRs will use fewer MTRRs.
530 @param Input Length of Memory to program MTRR
531 @param MtrrNumber Pointer to the number of necessary MTRRs
533 @retval TRUE Positive direction is better.
534 FALSE Negtive direction is better.
552 TempQword
-= Power2MaxMemory (TempQword
);
554 } while (TempQword
!= 0);
556 TempQword
= Power2MaxMemory (LShiftU64 (Input
, 1)) - Input
;
559 TempQword
-= Power2MaxMemory (TempQword
);
561 } while (TempQword
!= 0);
563 if (Positive
<= Subtractive
) {
564 *MtrrNumber
= Positive
;
567 *MtrrNumber
= Subtractive
;
573 Invalid variable MTRRs according to the value in the shadow array.
575 This function programs MTRRs according to the values specified
578 @param VariableMtrr The array to shadow variable MTRRs content
584 IN VARIABLE_MTRR
*VariableMtrr
590 Cr4
= PreMtrrChange ();
592 while (Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
) {
593 if (VariableMtrr
[Index
].Valid
== FALSE
&& VariableMtrr
[Index
].Used
== TRUE
) {
594 AsmWriteMsr64 (VariableMtrr
[Index
].Msr
, 0);
595 AsmWriteMsr64 (VariableMtrr
[Index
].Msr
+ 1, 0);
596 VariableMtrr
[Index
].Used
= FALSE
;
600 PostMtrrChange (Cr4
);
605 Programs variable MTRRs
607 This function programs variable MTRRs
609 @param MtrrNumber Index of MTRR to program.
610 @param BaseAddress Base address of memory region.
611 @param Length Length of memory region.
612 @param MemoryCacheType Memory type to set.
613 @param MtrrValidAddressMask The valid address mask for MTRR
618 ProgramVariableMtrr (
620 IN PHYSICAL_ADDRESS BaseAddress
,
622 IN UINT64 MemoryCacheType
,
623 IN UINT64 MtrrValidAddressMask
629 Cr4
= PreMtrrChange ();
632 // MTRR Physical Base
634 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
635 AsmWriteMsr64 ((UINT32
) MtrrNumber
, TempQword
);
638 // MTRR Physical Mask
640 TempQword
= ~(Length
- 1);
642 (UINT32
) (MtrrNumber
+ 1),
643 (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
646 PostMtrrChange (Cr4
);
651 Convert the Memory attibute value to MTRR_MEMORY_CACHE_TYPE.
653 @param MtrrType MTRR memory type
655 @return The enum item in MTRR_MEMORY_CACHE_TYPE
659 MTRR_MEMORY_CACHE_TYPE
660 GetMemoryCacheTypeFromMtrrType (
665 case MTRR_CACHE_UNCACHEABLE
:
666 return CacheUncacheable
;
667 case MTRR_CACHE_WRITE_COMBINING
:
668 return CacheWriteCombining
;
669 case MTRR_CACHE_WRITE_THROUGH
:
670 return CacheWriteThrough
;
671 case MTRR_CACHE_WRITE_PROTECTED
:
672 return CacheWriteProtected
;
673 case MTRR_CACHE_WRITE_BACK
:
674 return CacheWriteBack
;
677 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
678 // no mtrr covers the range
680 return CacheUncacheable
;
685 Initializes the valid bits mask and valid address mask for MTRRs.
687 This function initializes the valid bits mask and valid address mask for MTRRs.
689 @param MtrrValidBitsMask The mask for the valid bit of the MTRR
690 @param MtrrValidAddressMask The valid address mask for the MTRR
695 MtrrLibInitializeMtrrMask (
696 OUT UINT64
*MtrrValidBitsMask
,
697 OUT UINT64
*MtrrValidAddressMask
701 UINT8 PhysicalAddressBits
;
703 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
705 if (RegEax
>= 0x80000008) {
706 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
708 PhysicalAddressBits
= (UINT8
) RegEax
;
710 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
711 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
713 *MtrrValidBitsMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
714 *MtrrValidAddressMask
= 0xFFFFFFFF;
720 Determing the real attribute of a memory range.
722 This function is to arbitrate the real attribute of the memory when
723 there are 2 MTRR covers the same memory range. For further details,
724 please refer the IA32 Software Developer's Manual, Volume 3,
727 @param MtrrType1 the first kind of Memory type
728 @param MtrrType2 the second kind of memory type
739 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
741 case MTRR_CACHE_UNCACHEABLE
:
742 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
744 case MTRR_CACHE_WRITE_COMBINING
:
746 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
747 MtrrType2
==MTRR_CACHE_UNCACHEABLE
749 MtrrType
= MtrrType2
;
752 case MTRR_CACHE_WRITE_THROUGH
:
754 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
755 MtrrType2
==MTRR_CACHE_WRITE_BACK
757 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
758 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
759 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
762 case MTRR_CACHE_WRITE_PROTECTED
:
763 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
764 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
765 MtrrType
= MtrrType2
;
768 case MTRR_CACHE_WRITE_BACK
:
770 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
771 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
772 MtrrType2
== MTRR_CACHE_WRITE_BACK
774 MtrrType
= MtrrType2
;
777 case MTRR_CACHE_INVALID_TYPE
:
778 MtrrType
= MtrrType2
;
784 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
785 MtrrType
= MtrrType1
;
792 This function attempts to set the attributes for a memory range.
794 @param BaseAddress The physical address that is the start
795 address of a memory region.
796 @param Length The size in bytes of the memory region.
797 @param Attributes The bit mask of attributes to set for the
800 @retval RETURN_SUCCESS The attributes were set for the memory
802 @retval RETURN_INVALID_PARAMETER Length is zero.
803 @retval RETURN_UNSUPPORTED The processor does not support one or
804 more bytes of the memory resource range
805 specified by BaseAddress and Length.
806 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
807 for the memory resource range specified
808 by BaseAddress and Length.
809 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
810 range specified by BaseAddress and Length
812 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
813 modify the attributes of the memory
819 MtrrSetMemoryAttribute (
820 IN PHYSICAL_ADDRESS BaseAddress
,
822 IN MTRR_MEMORY_CACHE_TYPE Attribute
826 RETURN_STATUS Status
;
833 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
835 UINT64 MtrrValidBitsMask
;
836 UINT64 MtrrValidAddressMask
;
838 BOOLEAN OverwriteExistingMtrr
;
840 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
843 MemoryType
= (UINT64
)Attribute
;
844 OverwriteExistingMtrr
= FALSE
;
847 // Check for an invalid parameter
850 return RETURN_INVALID_PARAMETER
;
854 (BaseAddress
&~MtrrValidAddressMask
) != 0 ||
855 (Length
&~MtrrValidAddressMask
) != 0
857 return RETURN_UNSUPPORTED
;
861 // Check if Fixed MTRR
863 Status
= RETURN_SUCCESS
;
864 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
865 Cr4
= PreMtrrChange ();
866 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
);
867 PostMtrrChange (Cr4
);
868 if (RETURN_ERROR (Status
)) {
875 // A Length of 0 can only make sense for fixed MTTR ranges.
876 // Since we just handled the fixed MTRRs, we can skip the
877 // variable MTRR section.
883 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
884 // we can set the bade to 0 to save variable MTRRs.
886 if (BaseAddress
== BASE_1MB
) {
892 // Check memory base address alignment
894 DivU64x64Remainder (BaseAddress
, Power2MaxMemory (LShiftU64 (Length
, 1)), &Remainder
);
895 if (Remainder
!= 0) {
896 DivU64x64Remainder (BaseAddress
, Power2MaxMemory (Length
), &Remainder
);
897 if (Remainder
!= 0) {
898 Status
= RETURN_UNSUPPORTED
;
906 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask
, MtrrValidAddressMask
, VariableMtrr
);
907 OverLap
= CheckMemoryAttributeOverlap (BaseAddress
, BaseAddress
+ Length
- 1, VariableMtrr
);
909 Status
= CombineMemoryAttribute (MemoryType
, &BaseAddress
, &Length
, VariableMtrr
, &UsedMtrr
, &OverwriteExistingMtrr
);
910 if (RETURN_ERROR (Status
)) {
916 // Combined successfully
918 Status
= RETURN_SUCCESS
;
924 // Program Variable MTRRs
926 // Avoid hardcode here and read data dynamically
928 if (UsedMtrr
>= FIRMWARE_VARIABLE_MTRR_NUMBER
) {
929 Status
= RETURN_OUT_OF_RESOURCES
;
934 // The memory type is the same with the type specified by
935 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
937 if ((!OverwriteExistingMtrr
) && (Attribute
== GetMtrrDefaultMemoryType ())) {
939 // Invalidate the now-unused MTRRs
941 InvalidateMtrr(VariableMtrr
);
948 if (TempQword
== Power2MaxMemory (TempQword
)) {
950 // Invalidate the now-unused MTRRs
952 InvalidateMtrr(VariableMtrr
);
955 // Find first unused MTRR
957 for (MsrNum
= MTRR_LIB_IA32_VARIABLE_MTRR_BASE
;
958 MsrNum
< MTRR_LIB_IA32_VARIABLE_MTRR_END
;
961 if ((AsmReadMsr64 (MsrNum
+ 1) & MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
966 ProgramVariableMtrr (
975 Positive
= GetDirection (TempQword
, &MtrrNumber
);
977 if ((UsedMtrr
+ MtrrNumber
) > FIRMWARE_VARIABLE_MTRR_NUMBER
) {
978 Status
= RETURN_OUT_OF_RESOURCES
;
983 // Invalidate the now-unused MTRRs
985 InvalidateMtrr(VariableMtrr
);
988 // Find first unused MTRR
990 for (MsrNum
= MTRR_LIB_IA32_VARIABLE_MTRR_BASE
;
991 MsrNum
< MTRR_LIB_IA32_VARIABLE_MTRR_END
;
994 if ((AsmReadMsr64 (MsrNum
+ 1) & MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1000 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1001 ProgramVariableMtrr (
1006 MtrrValidAddressMask
1008 BaseAddress
+= Length
;
1009 TempQword
= Length
- TempQword
;
1010 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1017 for (; MsrNum
< MTRR_LIB_IA32_VARIABLE_MTRR_END
; MsrNum
+= 2) {
1018 if ((AsmReadMsr64 (MsrNum
+ 1) & MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1023 Length
= Power2MaxMemory (TempQword
);
1025 BaseAddress
-= Length
;
1028 ProgramVariableMtrr (
1033 MtrrValidAddressMask
1037 BaseAddress
+= Length
;
1039 TempQword
-= Length
;
1041 } while (TempQword
> 0);
1051 This function will get the memory cache type of the specific address.
1053 This function is mainly for debug purpose.
1055 @param Address The specific address
1057 @return Memory cache type of the sepcific address
1060 MTRR_MEMORY_CACHE_TYPE
1062 MtrrGetMemoryAttribute (
1063 IN PHYSICAL_ADDRESS Address
1070 UINT64 TempMtrrType
;
1071 MTRR_MEMORY_CACHE_TYPE CacheType
;
1072 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1073 UINT64 MtrrValidBitsMask
;
1074 UINT64 MtrrValidAddressMask
;
1077 // Check if MTRR is enabled, if not, return UC as attribute
1079 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1080 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1082 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1083 return CacheUncacheable
;
1087 // If address is less than 1M, then try to go through the fixed MTRR
1089 if (Address
< BASE_1MB
) {
1090 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1092 // Go through the fixed MTRR
1094 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1095 if (Address
>= MtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1097 MtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1098 (MtrrLibFixedMtrrTable
[Index
].Length
* 8)
1102 ((UINTN
)Address
- MtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1103 MtrrLibFixedMtrrTable
[Index
].Length
;
1104 TempQword
= AsmReadMsr64 (MtrrLibFixedMtrrTable
[Index
].Msr
);
1105 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1106 return GetMemoryCacheTypeFromMtrrType (MtrrType
);
1111 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1112 MtrrGetMemoryAttributeInVariableMtrr(
1114 MtrrValidAddressMask
,
1119 // Go through the variable MTRR
1121 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
1122 if (VariableMtrr
[Index
].Valid
) {
1123 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1124 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1125 TempMtrrType
= VariableMtrr
[Index
].Type
;
1126 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1130 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrType
);
1137 This function will get the raw value in variable MTRRs
1139 @param VariableSettings A buffer to hold variable MTRRs content.
1141 @return The VariableSettings input pointer
1144 MTRR_VARIABLE_SETTINGS
*
1146 MtrrGetVariableMtrr (
1147 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
1152 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
1153 VariableSettings
->Mtrr
[Index
].Base
=
1154 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
1155 VariableSettings
->Mtrr
[Index
].Mask
=
1156 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
1159 return VariableSettings
;
1164 Worker function setting variable MTRRs
1166 @param VariableSettings A buffer to hold variable MTRRs content.
1170 MtrrSetVariableMtrrWorker (
1171 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1176 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
1178 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1179 VariableSettings
->Mtrr
[Index
].Base
1182 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1183 VariableSettings
->Mtrr
[Index
].Mask
1190 This function sets variable MTRRs
1192 @param VariableSettings A buffer to hold variable MTRRs content.
1194 @return The pointer of VariableSettings
1197 MTRR_VARIABLE_SETTINGS
*
1199 MtrrSetVariableMtrr (
1200 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1205 Cr4
= PreMtrrChange ();
1206 MtrrSetVariableMtrrWorker (VariableSettings
);
1207 PostMtrrChange (Cr4
);
1208 return VariableSettings
;
1213 This function gets the content in fixed MTRRs
1215 @param FixedSettings A buffer to hold fixed Mtrrs content.
1217 @retval The pointer of FixedSettings
1220 MTRR_FIXED_SETTINGS
*
1223 OUT MTRR_FIXED_SETTINGS
*FixedSettings
1228 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1229 FixedSettings
->Mtrr
[Index
] =
1230 AsmReadMsr64 (MtrrLibFixedMtrrTable
[Index
].Msr
);
1233 return FixedSettings
;
1237 Worker function setting fixed MTRRs
1239 @param FixedSettings A buffer to hold fixed Mtrrs content.
1243 MtrrSetFixedMtrrWorker (
1244 IN MTRR_FIXED_SETTINGS
*FixedSettings
1249 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1251 MtrrLibFixedMtrrTable
[Index
].Msr
,
1252 FixedSettings
->Mtrr
[Index
]
1259 This function sets fixed MTRRs
1261 @param FixedSettings A buffer to hold fixed Mtrrs content.
1263 @retval The pointer of FixedSettings
1266 MTRR_FIXED_SETTINGS
*
1269 IN MTRR_FIXED_SETTINGS
*FixedSettings
1274 Cr4
= PreMtrrChange ();
1275 MtrrSetFixedMtrrWorker (FixedSettings
);
1276 PostMtrrChange (Cr4
);
1278 return FixedSettings
;
1283 This function gets the content in all MTRRs (variable and fixed)
1285 @param MtrrSetting A buffer to hold all Mtrrs content.
1287 @retval the pointer of MtrrSetting
1293 OUT MTRR_SETTINGS
*MtrrSetting
1299 MtrrGetFixedMtrr (&MtrrSetting
->Fixed
);
1302 // Get variable MTRRs
1304 MtrrGetVariableMtrr (&MtrrSetting
->Variables
);
1307 // Get MTRR_DEF_TYPE value
1309 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1316 This function sets all MTRRs (variable and fixed)
1318 @param MtrrSetting A buffer holding all MTRRs content.
1320 @retval The pointer of MtrrSetting
1326 IN MTRR_SETTINGS
*MtrrSetting
1331 Cr4
= PreMtrrChange ();
1336 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
1339 // Set variable MTRRs
1341 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
1344 // Set MTRR_DEF_TYPE value
1346 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
1348 PostMtrrChange (Cr4
);
1355 This function prints all MTRRs for debugging.
1358 MtrrDebugPrintAllMtrrs (
1363 MTRR_SETTINGS MtrrSettings
;
1366 MtrrGetAllMtrrs (&MtrrSettings
);
1367 DEBUG((EFI_D_ERROR
, "DefaultType = %016lx\n", MtrrSettings
.MtrrDefType
));
1368 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1370 EFI_D_ERROR
, "Fixed[%02d] = %016lx\n",
1372 MtrrSettings
.Fixed
.Mtrr
[Index
]
1375 for (Index
= 0; Index
< MTRR_NUMBER_OF_VARIABLE_MTRR
; Index
++) {
1377 EFI_D_ERROR
, "Variable[%02d] = %016lx, %016lx\n",
1379 MtrrSettings
.Variables
.Mtrr
[Index
].Base
,
1380 MtrrSettings
.Variables
.Mtrr
[Index
].Mask