4 Copyright (c) 2008 - 2015, Intel Corporation. All rights reserved.<BR>
5 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 // Context to save and restore when MTRRs are programmed
28 BOOLEAN InterruptState
;
32 // This table defines the offset, base and length of the fixed MTRRs
34 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
36 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
41 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
46 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
51 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
56 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
61 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
66 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
71 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
76 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
81 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
86 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
93 // Lookup table used to print MTRRs
95 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
96 "UC", // CacheUncacheable
97 "WC", // CacheWriteCombining
100 "WT", // CacheWriteThrough
101 "WP", // CacheWriteProtected
102 "WB", // CacheWriteBack
107 Worker function returns the variable MTRR count for the CPU.
109 @return Variable MTRR count
113 GetVariableMtrrCountWorker (
117 UINT32 VariableMtrrCount
;
119 VariableMtrrCount
= (UINT32
)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK
);
120 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
121 return VariableMtrrCount
;
125 Returns the variable MTRR count for the CPU.
127 @return Variable MTRR count
132 GetVariableMtrrCount (
136 if (!IsMtrrSupported ()) {
139 return GetVariableMtrrCountWorker ();
143 Worker function returns the firmware usable variable MTRR count for the CPU.
145 @return Firmware usable variable MTRR count
149 GetFirmwareVariableMtrrCountWorker (
153 UINT32 VariableMtrrCount
;
154 UINT32 ReservedMtrrNumber
;
156 VariableMtrrCount
= GetVariableMtrrCountWorker ();
157 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
158 if (VariableMtrrCount
< ReservedMtrrNumber
) {
162 return VariableMtrrCount
- ReservedMtrrNumber
;
166 Returns the firmware usable variable MTRR count for the CPU.
168 @return Firmware usable variable MTRR count
173 GetFirmwareVariableMtrrCount (
177 if (!IsMtrrSupported ()) {
180 return GetFirmwareVariableMtrrCountWorker ();
184 Worker function returns the default MTRR cache type for the system.
186 @return The default MTRR cache type.
189 MTRR_MEMORY_CACHE_TYPE
190 MtrrGetDefaultMemoryTypeWorker (
194 return (MTRR_MEMORY_CACHE_TYPE
) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0x7);
199 Returns the default MTRR cache type for the system.
201 @return The default MTRR cache type.
204 MTRR_MEMORY_CACHE_TYPE
206 MtrrGetDefaultMemoryType (
210 if (!IsMtrrSupported ()) {
211 return CacheUncacheable
;
213 return MtrrGetDefaultMemoryTypeWorker ();
217 Preparation before programming MTRR.
219 This function will do some preparation for programming MTRRs:
220 disable cache, invalid cache and disable MTRR caching functionality
222 @param[out] MtrrContext Pointer to context to save
227 OUT MTRR_CONTEXT
*MtrrContext
231 // Disable interrupts and save current interrupt state
233 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
236 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
241 // Save original CR4 value and clear PGE flag (Bit 7)
243 MtrrContext
->Cr4
= AsmReadCr4 ();
244 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
254 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
258 Cleaning up after programming MTRRs.
260 This function will do some clean up after programming MTRRs:
261 Flush all TLBs, re-enable caching, restore CR4.
263 @param[in] MtrrContext Pointer to context to restore
267 PostMtrrChangeEnableCache (
268 IN MTRR_CONTEXT
*MtrrContext
277 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
282 // Restore original CR4 value
284 AsmWriteCr4 (MtrrContext
->Cr4
);
287 // Restore original interrupt state
289 SetInterruptState (MtrrContext
->InterruptState
);
293 Cleaning up after programming MTRRs.
295 This function will do some clean up after programming MTRRs:
296 enable MTRR caching functionality, and enable cache
298 @param[in] MtrrContext Pointer to context to restore
303 IN MTRR_CONTEXT
*MtrrContext
309 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
311 PostMtrrChangeEnableCache (MtrrContext
);
315 Worker function gets the content in fixed MTRRs
317 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
319 @retval The pointer of FixedSettings
323 MtrrGetFixedMtrrWorker (
324 OUT MTRR_FIXED_SETTINGS
*FixedSettings
329 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
330 FixedSettings
->Mtrr
[Index
] =
331 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
334 return FixedSettings
;
339 This function gets the content in fixed MTRRs
341 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
343 @retval The pointer of FixedSettings
349 OUT MTRR_FIXED_SETTINGS
*FixedSettings
352 if (!IsMtrrSupported ()) {
353 return FixedSettings
;
356 return MtrrGetFixedMtrrWorker (FixedSettings
);
361 Worker function will get the raw value in variable MTRRs
363 @param[out] VariableSettings A buffer to hold variable MTRRs content.
365 @return The VariableSettings input pointer
368 MTRR_VARIABLE_SETTINGS
*
369 MtrrGetVariableMtrrWorker (
370 IN UINT32 VariableMtrrCount
,
371 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
376 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
378 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
379 VariableSettings
->Mtrr
[Index
].Base
=
380 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
381 VariableSettings
->Mtrr
[Index
].Mask
=
382 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
385 return VariableSettings
;
389 This function will get the raw value in variable MTRRs
391 @param[out] VariableSettings A buffer to hold variable MTRRs content.
393 @return The VariableSettings input pointer
396 MTRR_VARIABLE_SETTINGS
*
398 MtrrGetVariableMtrr (
399 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
402 if (!IsMtrrSupported ()) {
403 return VariableSettings
;
406 return MtrrGetVariableMtrrWorker (
407 GetVariableMtrrCountWorker (),
413 Programs fixed MTRRs registers.
415 @param[in] MemoryCacheType The memory type to set.
416 @param[in, out] Base The base address of memory range.
417 @param[in, out] Length The length of memory range.
418 @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.
419 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
420 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
422 @retval RETURN_SUCCESS The cache type was updated successfully
423 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
429 IN UINT64 MemoryCacheType
,
431 IN OUT UINT64
*Length
,
432 OUT UINT32
*ReturnMsrNum
,
433 OUT UINT64
*ReturnClearMask
,
434 OUT UINT64
*ReturnOrMask
447 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
448 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
451 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
452 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
460 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
461 return RETURN_UNSUPPORTED
;
465 // We found the fixed MTRR to be programmed
467 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
470 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
471 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
478 if (ByteShift
== 8) {
479 return RETURN_UNSUPPORTED
;
484 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
487 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
488 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
489 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
490 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
493 if (ByteShift
< 8 && (*Length
!= 0)) {
494 return RETURN_UNSUPPORTED
;
497 *ReturnMsrNum
= MsrNum
;
498 *ReturnClearMask
= ClearMask
;
499 *ReturnOrMask
= OrMask
;
501 return RETURN_SUCCESS
;
506 Worker function gets the attribute of variable MTRRs.
508 This function shadows the content of variable MTRRs into an
509 internal array: VariableMtrr.
511 @param[in] VariableSettings The variable MTRR values to shadow
512 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
513 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
514 @param[in] MtrrValidAddressMask The valid address mask for MTRR
515 @param[out] VariableMtrr The array to shadow variable MTRRs content
517 @return The return value of this parameter indicates the
518 number of MTRRs which has been used.
522 MtrrGetMemoryAttributeInVariableMtrrWorker (
523 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
524 IN UINTN FirmwareVariableMtrrCount
,
525 IN UINT64 MtrrValidBitsMask
,
526 IN UINT64 MtrrValidAddressMask
,
527 OUT VARIABLE_MTRR
*VariableMtrr
533 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
534 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
535 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
536 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
537 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
538 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
539 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
540 VariableMtrr
[Index
].Valid
= TRUE
;
541 VariableMtrr
[Index
].Used
= TRUE
;
550 Gets the attribute of variable MTRRs.
552 This function shadows the content of variable MTRRs into an
553 internal array: VariableMtrr.
555 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
556 @param[in] MtrrValidAddressMask The valid address mask for MTRR
557 @param[out] VariableMtrr The array to shadow variable MTRRs content
559 @return The return value of this paramter indicates the
560 number of MTRRs which has been used.
565 MtrrGetMemoryAttributeInVariableMtrr (
566 IN UINT64 MtrrValidBitsMask
,
567 IN UINT64 MtrrValidAddressMask
,
568 OUT VARIABLE_MTRR
*VariableMtrr
571 MTRR_VARIABLE_SETTINGS VariableSettings
;
573 if (!IsMtrrSupported ()) {
577 MtrrGetVariableMtrrWorker (
578 GetVariableMtrrCountWorker (),
582 return MtrrGetMemoryAttributeInVariableMtrrWorker (
584 GetFirmwareVariableMtrrCountWorker (),
586 MtrrValidAddressMask
,
593 Checks overlap between given memory range and MTRRs.
595 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
597 @param[in] Start The start address of memory range.
598 @param[in] End The end address of memory range.
599 @param[in] VariableMtrr The array to shadow variable MTRRs content
601 @retval TRUE Overlap exists.
602 @retval FALSE No overlap.
606 CheckMemoryAttributeOverlap (
607 IN UINTN FirmwareVariableMtrrCount
,
608 IN PHYSICAL_ADDRESS Start
,
609 IN PHYSICAL_ADDRESS End
,
610 IN VARIABLE_MTRR
*VariableMtrr
615 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
617 VariableMtrr
[Index
].Valid
&&
619 (Start
> (VariableMtrr
[Index
].BaseAddress
+
620 VariableMtrr
[Index
].Length
- 1)
622 (End
< VariableMtrr
[Index
].BaseAddress
)
634 Marks a variable MTRR as non-valid.
636 @param[in] Index The index of the array VariableMtrr to be invalidated
637 @param[in] VariableMtrr The array to shadow variable MTRRs content
638 @param[out] UsedMtrr The number of MTRRs which has already been used
642 InvalidateShadowMtrr (
644 IN VARIABLE_MTRR
*VariableMtrr
,
648 VariableMtrr
[Index
].Valid
= FALSE
;
649 *UsedMtrr
= *UsedMtrr
- 1;
654 Combines memory attributes.
656 If overlap exists between given memory range and MTRRs, try to combine them.
658 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
659 available to firmware.
660 @param[in] Attributes The memory type to set.
661 @param[in, out] Base The base address of memory range.
662 @param[in, out] Length The length of memory range.
663 @param[in] VariableMtrr The array to shadow variable MTRRs content
664 @param[in, out] UsedMtrr The number of MTRRs which has already been used
665 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
667 @retval EFI_SUCCESS Memory region successfully combined.
668 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
672 CombineMemoryAttribute (
673 IN UINT32 FirmwareVariableMtrrCount
,
674 IN UINT64 Attributes
,
676 IN OUT UINT64
*Length
,
677 IN VARIABLE_MTRR
*VariableMtrr
,
678 IN OUT UINT32
*UsedMtrr
,
679 OUT BOOLEAN
*OverwriteExistingMtrr
687 BOOLEAN CoveredByExistingMtrr
;
689 *OverwriteExistingMtrr
= FALSE
;
690 CoveredByExistingMtrr
= FALSE
;
691 EndAddress
= *Base
+*Length
- 1;
693 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
695 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
697 !VariableMtrr
[Index
].Valid
||
700 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
707 // Combine same attribute MTRR range
709 if (Attributes
== VariableMtrr
[Index
].Type
) {
711 // if the MTRR range contain the request range, set a flag, then continue to
712 // invalidate any MTRR of the same request range with higher priority cache type.
714 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
715 CoveredByExistingMtrr
= TRUE
;
719 // invalid this MTRR, and program the combine range
722 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
724 VariableMtrr
[Index
].BaseAddress
;
725 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
728 // Record the MTRR usage status in VariableMtrr array.
730 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
731 *Base
= CombineStart
;
732 *Length
= CombineEnd
- CombineStart
+ 1;
733 EndAddress
= CombineEnd
;
734 *OverwriteExistingMtrr
= TRUE
;
738 // The cache type is different, but the range is convered by one MTRR
740 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
741 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
747 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
748 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
749 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
750 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
751 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
752 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
754 *OverwriteExistingMtrr
= TRUE
;
758 // Other type memory overlap is invalid
760 return RETURN_ACCESS_DENIED
;
763 if (CoveredByExistingMtrr
) {
767 return RETURN_SUCCESS
;
772 Calculates the maximum value which is a power of 2, but less the MemoryLength.
774 @param[in] MemoryLength The number to pass in.
776 @return The maximum value which is align to power of 2 and less the MemoryLength
781 IN UINT64 MemoryLength
786 if (RShiftU64 (MemoryLength
, 32) != 0) {
788 (UINT64
) GetPowerOfTwo32 (
789 (UINT32
) RShiftU64 (MemoryLength
, 32)
794 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
802 Determines the MTRR numbers used to program a memory range.
804 This function first checks the alignment of the base address.
805 If the alignment of the base address <= Length, cover the memory range
806 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
807 Length -= alignment. Repeat the step until alignment > Length.
809 Then this function determines which direction of programming the variable
810 MTRRs for the remaining length will use fewer MTRRs.
812 @param[in] BaseAddress Length of Memory to program MTRR
813 @param[in] Length Length of Memory to program MTRR
814 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
816 @retval TRUE Positive direction is better.
817 FALSE Negative direction is better.
821 GetMtrrNumberAndDirection (
822 IN UINT64 BaseAddress
,
834 if (BaseAddress
!= 0) {
837 // Calculate the alignment of the base address.
839 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
841 if (Alignment
> Length
) {
846 BaseAddress
+= Alignment
;
860 TempQword
-= Power2MaxMemory (TempQword
);
862 } while (TempQword
!= 0);
864 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
867 TempQword
-= Power2MaxMemory (TempQword
);
869 } while (TempQword
!= 0);
871 if (Positive
<= Subtractive
) {
872 *MtrrNumber
+= Positive
;
875 *MtrrNumber
+= Subtractive
;
881 Invalid variable MTRRs according to the value in the shadow array.
883 This function programs MTRRs according to the values specified
886 @param[in, out] VariableSettings Variable MTRR settings
887 @param[in] VariableMtrrCount Number of variable MTRRs
888 @param[in, out] VariableMtrr Shadow of variable MTRR contents
893 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
894 IN UINTN VariableMtrrCount
,
895 IN OUT VARIABLE_MTRR
*VariableMtrr
900 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
901 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
902 VariableSettings
->Mtrr
[Index
].Base
= 0;
903 VariableSettings
->Mtrr
[Index
].Mask
= 0;
904 VariableMtrr
[Index
].Used
= FALSE
;
911 Programs variable MTRRs
913 This function programs variable MTRRs
915 @param[in, out] VariableSettings Variable MTRR settings.
916 @param[in] MtrrNumber Index of MTRR to program.
917 @param[in] BaseAddress Base address of memory region.
918 @param[in] Length Length of memory region.
919 @param[in] MemoryCacheType Memory type to set.
920 @param[in] MtrrValidAddressMask The valid address mask for MTRR
924 ProgramVariableMtrr (
925 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
927 IN PHYSICAL_ADDRESS BaseAddress
,
929 IN UINT64 MemoryCacheType
,
930 IN UINT64 MtrrValidAddressMask
936 // MTRR Physical Base
938 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
939 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
942 // MTRR Physical Mask
944 TempQword
= ~(Length
- 1);
945 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
950 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
952 @param[in] MtrrType MTRR memory type
954 @return The enum item in MTRR_MEMORY_CACHE_TYPE
957 MTRR_MEMORY_CACHE_TYPE
958 GetMemoryCacheTypeFromMtrrType (
963 case MTRR_CACHE_UNCACHEABLE
:
964 return CacheUncacheable
;
965 case MTRR_CACHE_WRITE_COMBINING
:
966 return CacheWriteCombining
;
967 case MTRR_CACHE_WRITE_THROUGH
:
968 return CacheWriteThrough
;
969 case MTRR_CACHE_WRITE_PROTECTED
:
970 return CacheWriteProtected
;
971 case MTRR_CACHE_WRITE_BACK
:
972 return CacheWriteBack
;
975 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
976 // no MTRR covers the range
978 return MtrrGetDefaultMemoryType ();
983 Initializes the valid bits mask and valid address mask for MTRRs.
985 This function initializes the valid bits mask and valid address mask for MTRRs.
987 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
988 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
992 MtrrLibInitializeMtrrMask (
993 OUT UINT64
*MtrrValidBitsMask
,
994 OUT UINT64
*MtrrValidAddressMask
998 UINT8 PhysicalAddressBits
;
1000 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1002 if (RegEax
>= 0x80000008) {
1003 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1005 PhysicalAddressBits
= (UINT8
) RegEax
;
1007 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1008 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1010 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1011 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1017 Determines the real attribute of a memory range.
1019 This function is to arbitrate the real attribute of the memory when
1020 there are 2 MTRRs covers the same memory range. For further details,
1021 please refer the IA32 Software Developer's Manual, Volume 3,
1024 @param[in] MtrrType1 The first kind of Memory type
1025 @param[in] MtrrType2 The second kind of memory type
1030 IN UINT64 MtrrType1
,
1036 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1037 switch (MtrrType1
) {
1038 case MTRR_CACHE_UNCACHEABLE
:
1039 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1041 case MTRR_CACHE_WRITE_COMBINING
:
1043 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1044 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1046 MtrrType
= MtrrType2
;
1049 case MTRR_CACHE_WRITE_THROUGH
:
1051 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1052 MtrrType2
==MTRR_CACHE_WRITE_BACK
1054 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1055 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1056 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1059 case MTRR_CACHE_WRITE_PROTECTED
:
1060 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1061 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1062 MtrrType
= MtrrType2
;
1065 case MTRR_CACHE_WRITE_BACK
:
1067 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1068 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1069 MtrrType2
== MTRR_CACHE_WRITE_BACK
1071 MtrrType
= MtrrType2
;
1074 case MTRR_CACHE_INVALID_TYPE
:
1075 MtrrType
= MtrrType2
;
1081 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1082 MtrrType
= MtrrType1
;
1090 This function will get the memory cache type of the specific address.
1092 This function is mainly for debug purpose.
1094 @param[in] Address The specific address
1096 @return Memory cache type of the specific address
1099 MTRR_MEMORY_CACHE_TYPE
1101 MtrrGetMemoryAttribute (
1102 IN PHYSICAL_ADDRESS Address
1109 UINT64 TempMtrrType
;
1110 MTRR_MEMORY_CACHE_TYPE CacheType
;
1111 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1112 UINT64 MtrrValidBitsMask
;
1113 UINT64 MtrrValidAddressMask
;
1114 UINTN VariableMtrrCount
;
1115 MTRR_VARIABLE_SETTINGS VariableSettings
;
1117 if (!IsMtrrSupported ()) {
1118 return CacheUncacheable
;
1122 // Check if MTRR is enabled, if not, return UC as attribute
1124 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1125 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1127 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1128 return CacheUncacheable
;
1132 // If address is less than 1M, then try to go through the fixed MTRR
1134 if (Address
< BASE_1MB
) {
1135 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1137 // Go through the fixed MTRR
1139 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1140 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1142 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1143 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1147 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1148 mMtrrLibFixedMtrrTable
[Index
].Length
;
1149 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1150 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1151 return GetMemoryCacheTypeFromMtrrType (MtrrType
);
1156 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1158 MtrrGetVariableMtrrWorker (
1159 GetVariableMtrrCountWorker (),
1163 MtrrGetMemoryAttributeInVariableMtrrWorker (
1165 GetFirmwareVariableMtrrCountWorker (),
1167 MtrrValidAddressMask
,
1172 // Go through the variable MTRR
1174 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1175 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1177 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1178 if (VariableMtrr
[Index
].Valid
) {
1179 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1180 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1181 TempMtrrType
= VariableMtrr
[Index
].Type
;
1182 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1186 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrType
);
1194 This function prints all MTRRs for debugging.
1198 MtrrDebugPrintAllMtrrs (
1203 MTRR_SETTINGS MtrrSettings
;
1206 UINTN VariableMtrrCount
;
1214 UINT64 NoRangeLimit
;
1217 UINTN PreviousMemoryType
;
1220 if (!IsMtrrSupported ()) {
1224 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1225 DEBUG((DEBUG_CACHE
, "=============\n"));
1227 MtrrGetAllMtrrs (&MtrrSettings
);
1228 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", MtrrSettings
.MtrrDefType
));
1229 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1230 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, MtrrSettings
.Fixed
.Mtrr
[Index
]));
1233 VariableMtrrCount
= GetVariableMtrrCount ();
1234 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1235 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1237 MtrrSettings
.Variables
.Mtrr
[Index
].Base
,
1238 MtrrSettings
.Variables
.Mtrr
[Index
].Mask
1241 DEBUG((DEBUG_CACHE
, "\n"));
1242 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1243 DEBUG((DEBUG_CACHE
, "====================================\n"));
1246 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1247 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1248 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1249 for (Index1
= 0; Index1
< 8; Index1
++) {
1250 MemoryType
= (UINTN
)(RShiftU64 (MtrrSettings
.Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1251 if (MemoryType
> CacheWriteBack
) {
1252 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1254 if (MemoryType
!= PreviousMemoryType
) {
1255 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1256 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1258 PreviousMemoryType
= MemoryType
;
1259 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1261 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1264 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1266 VariableMtrrCount
= GetVariableMtrrCount ();
1269 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1270 if (RegEax
>= 0x80000008) {
1271 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1272 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1275 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1277 MemoryType
= MtrrGetMemoryAttribute (Base
);
1278 if (MemoryType
> CacheWriteBack
) {
1279 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1282 if (MemoryType
!= PreviousMemoryType
) {
1283 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1284 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1286 PreviousMemoryType
= MemoryType
;
1287 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1290 RangeBase
= BASE_1MB
;
1291 NoRangeBase
= BASE_1MB
;
1293 NoRangeLimit
= Limit
;
1295 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1296 if ((MtrrSettings
.Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1298 // If mask is not valid, then do not display range
1302 MtrrBase
= (MtrrSettings
.Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1303 MtrrLimit
= MtrrBase
+ ((~(MtrrSettings
.Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1305 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1309 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1310 RangeBase
= MtrrBase
;
1312 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1313 RangeBase
= MtrrLimit
+ 1;
1315 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1316 RangeLimit
= MtrrBase
- 1;
1318 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1319 RangeLimit
= MtrrLimit
;
1322 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1323 NoRangeBase
= MtrrLimit
+ 1;
1325 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1326 NoRangeLimit
= MtrrBase
- 1;
1331 Base
= RangeLimit
+ 1;
1333 Base
= NoRangeLimit
+ 1;
1335 } while (Base
< Limit
);
1336 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1340 This function attempts to set the attributes for a memory range.
1342 @param[in] BaseAddress The physical address that is the start
1343 address of a memory region.
1344 @param[in] Length The size in bytes of the memory region.
1345 @param[in] Attribute The bit mask of attributes to set for the
1348 @retval RETURN_SUCCESS The attributes were set for the memory
1350 @retval RETURN_INVALID_PARAMETER Length is zero.
1351 @retval RETURN_UNSUPPORTED The processor does not support one or
1352 more bytes of the memory resource range
1353 specified by BaseAddress and Length.
1354 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1355 for the memory resource range specified
1356 by BaseAddress and Length.
1357 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1358 range specified by BaseAddress and Length
1360 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1361 modify the attributes of the memory
1367 MtrrSetMemoryAttribute (
1368 IN PHYSICAL_ADDRESS BaseAddress
,
1370 IN MTRR_MEMORY_CACHE_TYPE Attribute
1374 RETURN_STATUS Status
;
1381 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1383 UINT64 MtrrValidBitsMask
;
1384 UINT64 MtrrValidAddressMask
;
1385 BOOLEAN OverwriteExistingMtrr
;
1386 UINT32 FirmwareVariableMtrrCount
;
1387 MTRR_CONTEXT MtrrContext
;
1388 BOOLEAN MtrrContextValid
;
1389 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1390 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1391 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1392 UINT32 VariableMtrrCount
;
1393 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1394 BOOLEAN ProgramVariableSettings
;
1395 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1400 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1402 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1403 MtrrContextValid
= FALSE
;
1404 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1405 FixedSettingsValid
[Index
] = FALSE
;
1406 FixedSettingsModified
[Index
] = FALSE
;
1408 ProgramVariableSettings
= FALSE
;
1410 if (!IsMtrrSupported ()) {
1411 Status
= RETURN_UNSUPPORTED
;
1415 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1418 MemoryType
= (UINT64
)Attribute
;
1419 OverwriteExistingMtrr
= FALSE
;
1422 // Check for an invalid parameter
1425 Status
= RETURN_INVALID_PARAMETER
;
1430 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1431 (Length
& ~MtrrValidAddressMask
) != 0
1433 Status
= RETURN_UNSUPPORTED
;
1438 // Check if Fixed MTRR
1440 Status
= RETURN_SUCCESS
;
1441 if (BaseAddress
< BASE_1MB
) {
1442 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1443 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1444 if (RETURN_ERROR (Status
)) {
1447 if (!FixedSettingsValid
[MsrNum
]) {
1448 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1449 FixedSettingsValid
[MsrNum
] = TRUE
;
1451 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1452 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1453 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1454 FixedSettingsModified
[MsrNum
] = TRUE
;
1460 // A Length of 0 can only make sense for fixed MTTR ranges.
1461 // Since we just handled the fixed MTRRs, we can skip the
1462 // variable MTRR section.
1469 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1470 // we can set the base to 0 to save variable MTRRs.
1472 if (BaseAddress
== BASE_1MB
) {
1478 // Read all variable MTRRs
1480 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1481 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1482 MtrrGetVariableMtrrWorker (VariableMtrrCount
, &OriginalVariableSettings
);
1483 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1484 ProgramVariableSettings
= TRUE
;
1485 VariableSettings
= &WorkingVariableSettings
;
1488 // Check for overlap
1490 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1492 FirmwareVariableMtrrCount
,
1494 MtrrValidAddressMask
,
1497 OverLap
= CheckMemoryAttributeOverlap (
1498 FirmwareVariableMtrrCount
,
1500 BaseAddress
+ Length
- 1,
1504 Status
= CombineMemoryAttribute (
1505 FirmwareVariableMtrrCount
,
1511 &OverwriteExistingMtrr
1513 if (RETURN_ERROR (Status
)) {
1519 // Combined successfully, invalidate the now-unused MTRRs
1521 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1522 Status
= RETURN_SUCCESS
;
1528 // The memory type is the same with the type specified by
1529 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1531 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1533 // Invalidate the now-unused MTRRs
1535 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1539 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1541 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1542 Status
= RETURN_OUT_OF_RESOURCES
;
1547 // Invalidate the now-unused MTRRs
1549 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1552 // Find first unused MTRR
1554 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1555 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1560 if (BaseAddress
!= 0) {
1563 // Calculate the alignment of the base address.
1565 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1567 if (Alignment
> Length
) {
1574 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1575 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1580 ProgramVariableMtrr (
1586 MtrrValidAddressMask
1588 BaseAddress
+= Alignment
;
1589 Length
-= Alignment
;
1600 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1605 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1606 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1611 ProgramVariableMtrr (
1617 MtrrValidAddressMask
1619 BaseAddress
+= Length
;
1620 TempQword
= Length
- TempQword
;
1621 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1628 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1629 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1634 Length
= Power2MaxMemory (TempQword
);
1636 BaseAddress
-= Length
;
1639 ProgramVariableMtrr (
1645 MtrrValidAddressMask
1649 BaseAddress
+= Length
;
1651 TempQword
-= Length
;
1653 } while (TempQword
> 0);
1658 // Write fixed MTRRs that have been modified
1660 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1661 if (FixedSettingsModified
[Index
]) {
1662 if (!MtrrContextValid
) {
1663 PreMtrrChange (&MtrrContext
);
1664 MtrrContextValid
= TRUE
;
1667 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1668 WorkingFixedSettings
.Mtrr
[Index
]
1674 // Write variable MTRRs
1676 if (ProgramVariableSettings
) {
1677 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1678 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1679 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1680 if (!MtrrContextValid
) {
1681 PreMtrrChange (&MtrrContext
);
1682 MtrrContextValid
= TRUE
;
1685 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1686 WorkingVariableSettings
.Mtrr
[Index
].Base
1689 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1690 WorkingVariableSettings
.Mtrr
[Index
].Mask
1695 if (MtrrContextValid
) {
1696 PostMtrrChange (&MtrrContext
);
1699 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1700 if (!RETURN_ERROR (Status
)) {
1701 MtrrDebugPrintAllMtrrs ();
1707 Worker function setting variable MTRRs
1709 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1713 MtrrSetVariableMtrrWorker (
1714 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1718 UINT32 VariableMtrrCount
;
1720 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1721 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1723 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1725 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1726 VariableSettings
->Mtrr
[Index
].Base
1729 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1730 VariableSettings
->Mtrr
[Index
].Mask
1737 This function sets variable MTRRs
1739 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1741 @return The pointer of VariableSettings
1744 MTRR_VARIABLE_SETTINGS
*
1746 MtrrSetVariableMtrr (
1747 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1750 MTRR_CONTEXT MtrrContext
;
1752 if (!IsMtrrSupported ()) {
1753 return VariableSettings
;
1756 PreMtrrChange (&MtrrContext
);
1757 MtrrSetVariableMtrrWorker (VariableSettings
);
1758 PostMtrrChange (&MtrrContext
);
1759 return VariableSettings
;
1763 Worker function setting fixed MTRRs
1765 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1769 MtrrSetFixedMtrrWorker (
1770 IN MTRR_FIXED_SETTINGS
*FixedSettings
1775 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1777 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1778 FixedSettings
->Mtrr
[Index
]
1785 This function sets fixed MTRRs
1787 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1789 @retval The pointer of FixedSettings
1792 MTRR_FIXED_SETTINGS
*
1795 IN MTRR_FIXED_SETTINGS
*FixedSettings
1798 MTRR_CONTEXT MtrrContext
;
1800 if (!IsMtrrSupported ()) {
1801 return FixedSettings
;
1804 PreMtrrChange (&MtrrContext
);
1805 MtrrSetFixedMtrrWorker (FixedSettings
);
1806 PostMtrrChange (&MtrrContext
);
1808 return FixedSettings
;
1813 This function gets the content in all MTRRs (variable and fixed)
1815 @param[out] MtrrSetting A buffer to hold all MTRRs content.
1817 @retval the pointer of MtrrSetting
1823 OUT MTRR_SETTINGS
*MtrrSetting
1826 if (!IsMtrrSupported ()) {
1833 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
1836 // Get variable MTRRs
1838 MtrrGetVariableMtrrWorker (
1839 GetVariableMtrrCountWorker (),
1840 &MtrrSetting
->Variables
1844 // Get MTRR_DEF_TYPE value
1846 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1853 This function sets all MTRRs (variable and fixed)
1855 @param[in] MtrrSetting A buffer holding all MTRRs content.
1857 @retval The pointer of MtrrSetting
1863 IN MTRR_SETTINGS
*MtrrSetting
1866 MTRR_CONTEXT MtrrContext
;
1868 if (!IsMtrrSupported ()) {
1872 PreMtrrChange (&MtrrContext
);
1877 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
1880 // Set variable MTRRs
1882 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
1885 // Set MTRR_DEF_TYPE value
1887 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
1889 PostMtrrChangeEnableCache (&MtrrContext
);
1895 Checks if MTRR is supported.
1897 @retval TRUE MTRR is supported.
1898 @retval FALSE MTRR is not supported.
1911 // Check CPUID(1).EDX[12] for MTRR capability
1913 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
1914 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
1919 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
1920 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
1921 // exist, return false.
1923 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
1924 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {