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 If MtrrSetting is not NULL, returns the default MTRR cache type from input
187 MTRR settings buffer.
188 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
190 @param[in] MtrrSetting A buffer holding all MTRRs content.
192 @return The default MTRR cache type.
195 MTRR_MEMORY_CACHE_TYPE
196 MtrrGetDefaultMemoryTypeWorker (
197 IN MTRR_SETTINGS
*MtrrSetting
200 if (MtrrSetting
== NULL
) {
201 return (MTRR_MEMORY_CACHE_TYPE
) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0x7);
203 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
209 Returns the default MTRR cache type for the system.
211 @return The default MTRR cache type.
214 MTRR_MEMORY_CACHE_TYPE
216 MtrrGetDefaultMemoryType (
220 if (!IsMtrrSupported ()) {
221 return CacheUncacheable
;
223 return MtrrGetDefaultMemoryTypeWorker (NULL
);
227 Preparation before programming MTRR.
229 This function will do some preparation for programming MTRRs:
230 disable cache, invalid cache and disable MTRR caching functionality
232 @param[out] MtrrContext Pointer to context to save
237 OUT MTRR_CONTEXT
*MtrrContext
241 // Disable interrupts and save current interrupt state
243 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
246 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
251 // Save original CR4 value and clear PGE flag (Bit 7)
253 MtrrContext
->Cr4
= AsmReadCr4 ();
254 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
264 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
268 Cleaning up after programming MTRRs.
270 This function will do some clean up after programming MTRRs:
271 Flush all TLBs, re-enable caching, restore CR4.
273 @param[in] MtrrContext Pointer to context to restore
277 PostMtrrChangeEnableCache (
278 IN MTRR_CONTEXT
*MtrrContext
287 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
292 // Restore original CR4 value
294 AsmWriteCr4 (MtrrContext
->Cr4
);
297 // Restore original interrupt state
299 SetInterruptState (MtrrContext
->InterruptState
);
303 Cleaning up after programming MTRRs.
305 This function will do some clean up after programming MTRRs:
306 enable MTRR caching functionality, and enable cache
308 @param[in] MtrrContext Pointer to context to restore
313 IN MTRR_CONTEXT
*MtrrContext
319 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
321 PostMtrrChangeEnableCache (MtrrContext
);
325 Worker function gets the content in fixed MTRRs
327 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
329 @retval The pointer of FixedSettings
333 MtrrGetFixedMtrrWorker (
334 OUT MTRR_FIXED_SETTINGS
*FixedSettings
339 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
340 FixedSettings
->Mtrr
[Index
] =
341 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
344 return FixedSettings
;
349 This function gets the content in fixed MTRRs
351 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
353 @retval The pointer of FixedSettings
359 OUT MTRR_FIXED_SETTINGS
*FixedSettings
362 if (!IsMtrrSupported ()) {
363 return FixedSettings
;
366 return MtrrGetFixedMtrrWorker (FixedSettings
);
371 Worker function will get the raw value in variable MTRRs
373 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
374 MTRR settings buffer.
375 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
377 @param[in] MtrrSetting A buffer holding all MTRRs content.
378 @param[in] VariableMtrrCount Number of variable MTRRs.
379 @param[out] VariableSettings A buffer to hold variable MTRRs content.
381 @return The VariableSettings input pointer
384 MTRR_VARIABLE_SETTINGS
*
385 MtrrGetVariableMtrrWorker (
386 IN MTRR_SETTINGS
*MtrrSetting
,
387 IN UINT32 VariableMtrrCount
,
388 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
393 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
395 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
396 if (MtrrSetting
== NULL
) {
397 VariableSettings
->Mtrr
[Index
].Base
=
398 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
399 VariableSettings
->Mtrr
[Index
].Mask
=
400 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
402 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
403 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
407 return VariableSettings
;
411 This function will get the raw value in variable MTRRs
413 @param[out] VariableSettings A buffer to hold variable MTRRs content.
415 @return The VariableSettings input pointer
418 MTRR_VARIABLE_SETTINGS
*
420 MtrrGetVariableMtrr (
421 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
424 if (!IsMtrrSupported ()) {
425 return VariableSettings
;
428 return MtrrGetVariableMtrrWorker (
430 GetVariableMtrrCountWorker (),
436 Programs fixed MTRRs registers.
438 @param[in] MemoryCacheType The memory type to set.
439 @param[in, out] Base The base address of memory range.
440 @param[in, out] Length The length of memory range.
441 @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.
442 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
443 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
445 @retval RETURN_SUCCESS The cache type was updated successfully
446 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
452 IN UINT64 MemoryCacheType
,
454 IN OUT UINT64
*Length
,
455 OUT UINT32
*ReturnMsrNum
,
456 OUT UINT64
*ReturnClearMask
,
457 OUT UINT64
*ReturnOrMask
470 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
471 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
474 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
475 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
483 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
484 return RETURN_UNSUPPORTED
;
488 // We found the fixed MTRR to be programmed
490 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
493 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
494 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
501 if (ByteShift
== 8) {
502 return RETURN_UNSUPPORTED
;
507 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
510 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
511 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
512 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
513 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
516 if (ByteShift
< 8 && (*Length
!= 0)) {
517 return RETURN_UNSUPPORTED
;
520 *ReturnMsrNum
= MsrNum
;
521 *ReturnClearMask
= ClearMask
;
522 *ReturnOrMask
= OrMask
;
524 return RETURN_SUCCESS
;
529 Worker function gets the attribute of variable MTRRs.
531 This function shadows the content of variable MTRRs into an
532 internal array: VariableMtrr.
534 @param[in] VariableSettings The variable MTRR values to shadow
535 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
536 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
537 @param[in] MtrrValidAddressMask The valid address mask for MTRR
538 @param[out] VariableMtrr The array to shadow variable MTRRs content
540 @return The return value of this parameter indicates the
541 number of MTRRs which has been used.
545 MtrrGetMemoryAttributeInVariableMtrrWorker (
546 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
547 IN UINTN FirmwareVariableMtrrCount
,
548 IN UINT64 MtrrValidBitsMask
,
549 IN UINT64 MtrrValidAddressMask
,
550 OUT VARIABLE_MTRR
*VariableMtrr
556 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
557 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
558 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
559 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
560 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
561 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
562 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
563 VariableMtrr
[Index
].Valid
= TRUE
;
564 VariableMtrr
[Index
].Used
= TRUE
;
573 Gets the attribute of variable MTRRs.
575 This function shadows the content of variable MTRRs into an
576 internal array: VariableMtrr.
578 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
579 @param[in] MtrrValidAddressMask The valid address mask for MTRR
580 @param[out] VariableMtrr The array to shadow variable MTRRs content
582 @return The return value of this paramter indicates the
583 number of MTRRs which has been used.
588 MtrrGetMemoryAttributeInVariableMtrr (
589 IN UINT64 MtrrValidBitsMask
,
590 IN UINT64 MtrrValidAddressMask
,
591 OUT VARIABLE_MTRR
*VariableMtrr
594 MTRR_VARIABLE_SETTINGS VariableSettings
;
596 if (!IsMtrrSupported ()) {
600 MtrrGetVariableMtrrWorker (
602 GetVariableMtrrCountWorker (),
606 return MtrrGetMemoryAttributeInVariableMtrrWorker (
608 GetFirmwareVariableMtrrCountWorker (),
610 MtrrValidAddressMask
,
617 Checks overlap between given memory range and MTRRs.
619 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
621 @param[in] Start The start address of memory range.
622 @param[in] End The end address of memory range.
623 @param[in] VariableMtrr The array to shadow variable MTRRs content
625 @retval TRUE Overlap exists.
626 @retval FALSE No overlap.
630 CheckMemoryAttributeOverlap (
631 IN UINTN FirmwareVariableMtrrCount
,
632 IN PHYSICAL_ADDRESS Start
,
633 IN PHYSICAL_ADDRESS End
,
634 IN VARIABLE_MTRR
*VariableMtrr
639 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
641 VariableMtrr
[Index
].Valid
&&
643 (Start
> (VariableMtrr
[Index
].BaseAddress
+
644 VariableMtrr
[Index
].Length
- 1)
646 (End
< VariableMtrr
[Index
].BaseAddress
)
658 Marks a variable MTRR as non-valid.
660 @param[in] Index The index of the array VariableMtrr to be invalidated
661 @param[in] VariableMtrr The array to shadow variable MTRRs content
662 @param[out] UsedMtrr The number of MTRRs which has already been used
666 InvalidateShadowMtrr (
668 IN VARIABLE_MTRR
*VariableMtrr
,
672 VariableMtrr
[Index
].Valid
= FALSE
;
673 *UsedMtrr
= *UsedMtrr
- 1;
678 Combines memory attributes.
680 If overlap exists between given memory range and MTRRs, try to combine them.
682 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
683 available to firmware.
684 @param[in] Attributes The memory type to set.
685 @param[in, out] Base The base address of memory range.
686 @param[in, out] Length The length of memory range.
687 @param[in] VariableMtrr The array to shadow variable MTRRs content
688 @param[in, out] UsedMtrr The number of MTRRs which has already been used
689 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
691 @retval EFI_SUCCESS Memory region successfully combined.
692 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
696 CombineMemoryAttribute (
697 IN UINT32 FirmwareVariableMtrrCount
,
698 IN UINT64 Attributes
,
700 IN OUT UINT64
*Length
,
701 IN VARIABLE_MTRR
*VariableMtrr
,
702 IN OUT UINT32
*UsedMtrr
,
703 OUT BOOLEAN
*OverwriteExistingMtrr
711 BOOLEAN CoveredByExistingMtrr
;
713 *OverwriteExistingMtrr
= FALSE
;
714 CoveredByExistingMtrr
= FALSE
;
715 EndAddress
= *Base
+*Length
- 1;
717 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
719 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
721 !VariableMtrr
[Index
].Valid
||
724 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
731 // Combine same attribute MTRR range
733 if (Attributes
== VariableMtrr
[Index
].Type
) {
735 // if the MTRR range contain the request range, set a flag, then continue to
736 // invalidate any MTRR of the same request range with higher priority cache type.
738 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
739 CoveredByExistingMtrr
= TRUE
;
743 // invalid this MTRR, and program the combine range
746 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
748 VariableMtrr
[Index
].BaseAddress
;
749 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
752 // Record the MTRR usage status in VariableMtrr array.
754 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
755 *Base
= CombineStart
;
756 *Length
= CombineEnd
- CombineStart
+ 1;
757 EndAddress
= CombineEnd
;
758 *OverwriteExistingMtrr
= TRUE
;
762 // The cache type is different, but the range is convered by one MTRR
764 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
765 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
771 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
772 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
773 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
774 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
775 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
776 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
778 *OverwriteExistingMtrr
= TRUE
;
782 // Other type memory overlap is invalid
784 return RETURN_ACCESS_DENIED
;
787 if (CoveredByExistingMtrr
) {
791 return RETURN_SUCCESS
;
796 Calculates the maximum value which is a power of 2, but less the MemoryLength.
798 @param[in] MemoryLength The number to pass in.
800 @return The maximum value which is align to power of 2 and less the MemoryLength
805 IN UINT64 MemoryLength
810 if (RShiftU64 (MemoryLength
, 32) != 0) {
812 (UINT64
) GetPowerOfTwo32 (
813 (UINT32
) RShiftU64 (MemoryLength
, 32)
818 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
826 Determines the MTRR numbers used to program a memory range.
828 This function first checks the alignment of the base address.
829 If the alignment of the base address <= Length, cover the memory range
830 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
831 Length -= alignment. Repeat the step until alignment > Length.
833 Then this function determines which direction of programming the variable
834 MTRRs for the remaining length will use fewer MTRRs.
836 @param[in] BaseAddress Length of Memory to program MTRR
837 @param[in] Length Length of Memory to program MTRR
838 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
840 @retval TRUE Positive direction is better.
841 FALSE Negative direction is better.
845 GetMtrrNumberAndDirection (
846 IN UINT64 BaseAddress
,
858 if (BaseAddress
!= 0) {
861 // Calculate the alignment of the base address.
863 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
865 if (Alignment
> Length
) {
870 BaseAddress
+= Alignment
;
884 TempQword
-= Power2MaxMemory (TempQword
);
886 } while (TempQword
!= 0);
888 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
891 TempQword
-= Power2MaxMemory (TempQword
);
893 } while (TempQword
!= 0);
895 if (Positive
<= Subtractive
) {
896 *MtrrNumber
+= Positive
;
899 *MtrrNumber
+= Subtractive
;
905 Invalid variable MTRRs according to the value in the shadow array.
907 This function programs MTRRs according to the values specified
910 @param[in, out] VariableSettings Variable MTRR settings
911 @param[in] VariableMtrrCount Number of variable MTRRs
912 @param[in, out] VariableMtrr Shadow of variable MTRR contents
917 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
918 IN UINTN VariableMtrrCount
,
919 IN OUT VARIABLE_MTRR
*VariableMtrr
924 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
925 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
926 VariableSettings
->Mtrr
[Index
].Base
= 0;
927 VariableSettings
->Mtrr
[Index
].Mask
= 0;
928 VariableMtrr
[Index
].Used
= FALSE
;
935 Programs variable MTRRs
937 This function programs variable MTRRs
939 @param[in, out] VariableSettings Variable MTRR settings.
940 @param[in] MtrrNumber Index of MTRR to program.
941 @param[in] BaseAddress Base address of memory region.
942 @param[in] Length Length of memory region.
943 @param[in] MemoryCacheType Memory type to set.
944 @param[in] MtrrValidAddressMask The valid address mask for MTRR
948 ProgramVariableMtrr (
949 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
951 IN PHYSICAL_ADDRESS BaseAddress
,
953 IN UINT64 MemoryCacheType
,
954 IN UINT64 MtrrValidAddressMask
960 // MTRR Physical Base
962 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
963 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
966 // MTRR Physical Mask
968 TempQword
= ~(Length
- 1);
969 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
974 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
976 If MtrrSetting is not NULL, gets the default memory attribute from input
977 MTRR settings buffer.
978 If MtrrSetting is NULL, gets the default memory attribute from MSR.
980 @param[in] MtrrSetting A buffer holding all MTRRs content.
981 @param[in] MtrrType MTRR memory type
983 @return The enum item in MTRR_MEMORY_CACHE_TYPE
986 MTRR_MEMORY_CACHE_TYPE
987 GetMemoryCacheTypeFromMtrrType (
988 IN MTRR_SETTINGS
*MtrrSetting
,
993 case MTRR_CACHE_UNCACHEABLE
:
994 return CacheUncacheable
;
995 case MTRR_CACHE_WRITE_COMBINING
:
996 return CacheWriteCombining
;
997 case MTRR_CACHE_WRITE_THROUGH
:
998 return CacheWriteThrough
;
999 case MTRR_CACHE_WRITE_PROTECTED
:
1000 return CacheWriteProtected
;
1001 case MTRR_CACHE_WRITE_BACK
:
1002 return CacheWriteBack
;
1005 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1006 // no MTRR covers the range
1008 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1013 Initializes the valid bits mask and valid address mask for MTRRs.
1015 This function initializes the valid bits mask and valid address mask for MTRRs.
1017 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1018 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1022 MtrrLibInitializeMtrrMask (
1023 OUT UINT64
*MtrrValidBitsMask
,
1024 OUT UINT64
*MtrrValidAddressMask
1028 UINT8 PhysicalAddressBits
;
1030 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1032 if (RegEax
>= 0x80000008) {
1033 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1035 PhysicalAddressBits
= (UINT8
) RegEax
;
1037 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1038 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1040 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1041 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1047 Determines the real attribute of a memory range.
1049 This function is to arbitrate the real attribute of the memory when
1050 there are 2 MTRRs covers the same memory range. For further details,
1051 please refer the IA32 Software Developer's Manual, Volume 3,
1054 @param[in] MtrrType1 The first kind of Memory type
1055 @param[in] MtrrType2 The second kind of memory type
1060 IN UINT64 MtrrType1
,
1066 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1067 switch (MtrrType1
) {
1068 case MTRR_CACHE_UNCACHEABLE
:
1069 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1071 case MTRR_CACHE_WRITE_COMBINING
:
1073 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1074 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1076 MtrrType
= MtrrType2
;
1079 case MTRR_CACHE_WRITE_THROUGH
:
1081 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1082 MtrrType2
==MTRR_CACHE_WRITE_BACK
1084 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1085 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1086 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1089 case MTRR_CACHE_WRITE_PROTECTED
:
1090 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1091 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1092 MtrrType
= MtrrType2
;
1095 case MTRR_CACHE_WRITE_BACK
:
1097 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1098 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1099 MtrrType2
== MTRR_CACHE_WRITE_BACK
1101 MtrrType
= MtrrType2
;
1104 case MTRR_CACHE_INVALID_TYPE
:
1105 MtrrType
= MtrrType2
;
1111 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1112 MtrrType
= MtrrType1
;
1118 Worker function will get the memory cache type of the specific address.
1120 If MtrrSetting is not NULL, gets the memory cache type from input
1121 MTRR settings buffer.
1122 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1124 @param[in] MtrrSetting A buffer holding all MTRRs content.
1125 @param[in] Address The specific address
1127 @return Memory cache type of the specific address
1130 MTRR_MEMORY_CACHE_TYPE
1131 MtrrGetMemoryAttributeByAddressWorker (
1132 IN MTRR_SETTINGS
*MtrrSetting
,
1133 IN PHYSICAL_ADDRESS Address
1140 UINT64 TempMtrrType
;
1141 MTRR_MEMORY_CACHE_TYPE CacheType
;
1142 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1143 UINT64 MtrrValidBitsMask
;
1144 UINT64 MtrrValidAddressMask
;
1145 UINTN VariableMtrrCount
;
1146 MTRR_VARIABLE_SETTINGS VariableSettings
;
1149 // Check if MTRR is enabled, if not, return UC as attribute
1151 if (MtrrSetting
== NULL
) {
1152 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1154 TempQword
= MtrrSetting
->MtrrDefType
;
1156 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1158 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1159 return CacheUncacheable
;
1163 // If address is less than 1M, then try to go through the fixed MTRR
1165 if (Address
< BASE_1MB
) {
1166 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1168 // Go through the fixed MTRR
1170 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1171 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1173 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1174 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1178 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1179 mMtrrLibFixedMtrrTable
[Index
].Length
;
1180 if (MtrrSetting
== NULL
) {
1181 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1183 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1185 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1186 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1191 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1193 MtrrGetVariableMtrrWorker (
1195 GetVariableMtrrCountWorker (),
1199 MtrrGetMemoryAttributeInVariableMtrrWorker (
1201 GetFirmwareVariableMtrrCountWorker (),
1203 MtrrValidAddressMask
,
1208 // Go through the variable MTRR
1210 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1211 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1213 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1214 if (VariableMtrr
[Index
].Valid
) {
1215 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1216 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1217 TempMtrrType
= VariableMtrr
[Index
].Type
;
1218 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1222 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1229 This function will get the memory cache type of the specific address.
1231 This function is mainly for debug purpose.
1233 @param[in] Address The specific address
1235 @return Memory cache type of the specific address
1238 MTRR_MEMORY_CACHE_TYPE
1240 MtrrGetMemoryAttribute (
1241 IN PHYSICAL_ADDRESS Address
1244 if (!IsMtrrSupported ()) {
1245 return CacheUncacheable
;
1248 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1252 Worker function prints all MTRRs for debugging.
1254 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1256 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1258 @param MtrrSetting A buffer holding all MTRRs content.
1261 MtrrDebugPrintAllMtrrsWorker (
1262 IN MTRR_SETTINGS
*MtrrSetting
1266 MTRR_SETTINGS LocalMtrrs
;
1267 MTRR_SETTINGS
*Mtrrs
;
1270 UINTN VariableMtrrCount
;
1278 UINT64 NoRangeLimit
;
1281 UINTN PreviousMemoryType
;
1284 if (!IsMtrrSupported ()) {
1288 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1289 DEBUG((DEBUG_CACHE
, "=============\n"));
1291 if (MtrrSetting
!= NULL
) {
1292 Mtrrs
= MtrrSetting
;
1294 MtrrGetAllMtrrs (&LocalMtrrs
);
1295 Mtrrs
= &LocalMtrrs
;
1298 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1299 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1300 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1303 VariableMtrrCount
= GetVariableMtrrCount ();
1304 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1305 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1307 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1308 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1311 DEBUG((DEBUG_CACHE
, "\n"));
1312 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1313 DEBUG((DEBUG_CACHE
, "====================================\n"));
1316 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1317 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1318 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1319 for (Index1
= 0; Index1
< 8; Index1
++) {
1320 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1321 if (MemoryType
> CacheWriteBack
) {
1322 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1324 if (MemoryType
!= PreviousMemoryType
) {
1325 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1326 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1328 PreviousMemoryType
= MemoryType
;
1329 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1331 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1334 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1336 VariableMtrrCount
= GetVariableMtrrCount ();
1339 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1340 if (RegEax
>= 0x80000008) {
1341 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1342 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1345 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1347 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1348 if (MemoryType
> CacheWriteBack
) {
1349 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1352 if (MemoryType
!= PreviousMemoryType
) {
1353 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1354 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1356 PreviousMemoryType
= MemoryType
;
1357 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1360 RangeBase
= BASE_1MB
;
1361 NoRangeBase
= BASE_1MB
;
1363 NoRangeLimit
= Limit
;
1365 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1366 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1368 // If mask is not valid, then do not display range
1372 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1373 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1375 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1379 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1380 RangeBase
= MtrrBase
;
1382 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1383 RangeBase
= MtrrLimit
+ 1;
1385 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1386 RangeLimit
= MtrrBase
- 1;
1388 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1389 RangeLimit
= MtrrLimit
;
1392 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1393 NoRangeBase
= MtrrLimit
+ 1;
1395 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1396 NoRangeLimit
= MtrrBase
- 1;
1401 Base
= RangeLimit
+ 1;
1403 Base
= NoRangeLimit
+ 1;
1405 } while (Base
< Limit
);
1406 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1412 This function prints all MTRRs for debugging.
1416 MtrrDebugPrintAllMtrrs (
1420 MtrrDebugPrintAllMtrrsWorker (NULL
);
1425 Worker function attempts to set the attributes for a memory range.
1427 @param[in] BaseAddress The physical address that is the start
1428 address of a memory region.
1429 @param[in] Length The size in bytes of the memory region.
1430 @param[in] Attribute The bit mask of attributes to set for the
1433 @retval RETURN_SUCCESS The attributes were set for the memory
1435 @retval RETURN_INVALID_PARAMETER Length is zero.
1436 @retval RETURN_UNSUPPORTED The processor does not support one or
1437 more bytes of the memory resource range
1438 specified by BaseAddress and Length.
1439 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1440 for the memory resource range specified
1441 by BaseAddress and Length.
1442 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1443 range specified by BaseAddress and Length
1445 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1446 modify the attributes of the memory
1452 MtrrSetMemoryAttribute (
1453 IN PHYSICAL_ADDRESS BaseAddress
,
1455 IN MTRR_MEMORY_CACHE_TYPE Attribute
1459 RETURN_STATUS Status
;
1466 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1468 UINT64 MtrrValidBitsMask
;
1469 UINT64 MtrrValidAddressMask
;
1470 BOOLEAN OverwriteExistingMtrr
;
1471 UINT32 FirmwareVariableMtrrCount
;
1472 MTRR_CONTEXT MtrrContext
;
1473 BOOLEAN MtrrContextValid
;
1474 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1475 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1476 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1477 UINT32 VariableMtrrCount
;
1478 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1479 BOOLEAN ProgramVariableSettings
;
1480 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1485 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1487 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1488 MtrrContextValid
= FALSE
;
1489 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1490 FixedSettingsValid
[Index
] = FALSE
;
1491 FixedSettingsModified
[Index
] = FALSE
;
1493 ProgramVariableSettings
= FALSE
;
1495 if (!IsMtrrSupported ()) {
1496 Status
= RETURN_UNSUPPORTED
;
1500 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1503 MemoryType
= (UINT64
)Attribute
;
1504 OverwriteExistingMtrr
= FALSE
;
1507 // Check for an invalid parameter
1510 Status
= RETURN_INVALID_PARAMETER
;
1515 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1516 (Length
& ~MtrrValidAddressMask
) != 0
1518 Status
= RETURN_UNSUPPORTED
;
1523 // Check if Fixed MTRR
1525 Status
= RETURN_SUCCESS
;
1526 if (BaseAddress
< BASE_1MB
) {
1527 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1528 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1529 if (RETURN_ERROR (Status
)) {
1532 if (!FixedSettingsValid
[MsrNum
]) {
1533 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1534 FixedSettingsValid
[MsrNum
] = TRUE
;
1536 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1537 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1538 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1539 FixedSettingsModified
[MsrNum
] = TRUE
;
1545 // A Length of 0 can only make sense for fixed MTTR ranges.
1546 // Since we just handled the fixed MTRRs, we can skip the
1547 // variable MTRR section.
1554 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1555 // we can set the base to 0 to save variable MTRRs.
1557 if (BaseAddress
== BASE_1MB
) {
1563 // Read all variable MTRRs
1565 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1566 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1567 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1568 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1569 ProgramVariableSettings
= TRUE
;
1570 VariableSettings
= &WorkingVariableSettings
;
1573 // Check for overlap
1575 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1577 FirmwareVariableMtrrCount
,
1579 MtrrValidAddressMask
,
1582 OverLap
= CheckMemoryAttributeOverlap (
1583 FirmwareVariableMtrrCount
,
1585 BaseAddress
+ Length
- 1,
1589 Status
= CombineMemoryAttribute (
1590 FirmwareVariableMtrrCount
,
1596 &OverwriteExistingMtrr
1598 if (RETURN_ERROR (Status
)) {
1604 // Combined successfully, invalidate the now-unused MTRRs
1606 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1607 Status
= RETURN_SUCCESS
;
1613 // The memory type is the same with the type specified by
1614 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1616 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1618 // Invalidate the now-unused MTRRs
1620 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1624 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1626 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1627 Status
= RETURN_OUT_OF_RESOURCES
;
1632 // Invalidate the now-unused MTRRs
1634 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1637 // Find first unused MTRR
1639 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1640 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1645 if (BaseAddress
!= 0) {
1648 // Calculate the alignment of the base address.
1650 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1652 if (Alignment
> Length
) {
1659 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1660 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1665 ProgramVariableMtrr (
1671 MtrrValidAddressMask
1673 BaseAddress
+= Alignment
;
1674 Length
-= Alignment
;
1685 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1690 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1691 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1696 ProgramVariableMtrr (
1702 MtrrValidAddressMask
1704 BaseAddress
+= Length
;
1705 TempQword
= Length
- TempQword
;
1706 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1713 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1714 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1719 Length
= Power2MaxMemory (TempQword
);
1721 BaseAddress
-= Length
;
1724 ProgramVariableMtrr (
1730 MtrrValidAddressMask
1734 BaseAddress
+= Length
;
1736 TempQword
-= Length
;
1738 } while (TempQword
> 0);
1743 // Write fixed MTRRs that have been modified
1745 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1746 if (FixedSettingsModified
[Index
]) {
1747 if (!MtrrContextValid
) {
1748 PreMtrrChange (&MtrrContext
);
1749 MtrrContextValid
= TRUE
;
1752 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1753 WorkingFixedSettings
.Mtrr
[Index
]
1759 // Write variable MTRRs
1761 if (ProgramVariableSettings
) {
1762 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1763 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1764 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1765 if (!MtrrContextValid
) {
1766 PreMtrrChange (&MtrrContext
);
1767 MtrrContextValid
= TRUE
;
1770 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1771 WorkingVariableSettings
.Mtrr
[Index
].Base
1774 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1775 WorkingVariableSettings
.Mtrr
[Index
].Mask
1780 if (MtrrContextValid
) {
1781 PostMtrrChange (&MtrrContext
);
1784 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1785 if (!RETURN_ERROR (Status
)) {
1786 MtrrDebugPrintAllMtrrs ();
1792 Worker function setting variable MTRRs
1794 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1798 MtrrSetVariableMtrrWorker (
1799 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1803 UINT32 VariableMtrrCount
;
1805 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1806 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1808 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1810 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1811 VariableSettings
->Mtrr
[Index
].Base
1814 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1815 VariableSettings
->Mtrr
[Index
].Mask
1822 This function sets variable MTRRs
1824 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1826 @return The pointer of VariableSettings
1829 MTRR_VARIABLE_SETTINGS
*
1831 MtrrSetVariableMtrr (
1832 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1835 MTRR_CONTEXT MtrrContext
;
1837 if (!IsMtrrSupported ()) {
1838 return VariableSettings
;
1841 PreMtrrChange (&MtrrContext
);
1842 MtrrSetVariableMtrrWorker (VariableSettings
);
1843 PostMtrrChange (&MtrrContext
);
1844 MtrrDebugPrintAllMtrrs ();
1846 return VariableSettings
;
1850 Worker function setting fixed MTRRs
1852 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1856 MtrrSetFixedMtrrWorker (
1857 IN MTRR_FIXED_SETTINGS
*FixedSettings
1862 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1864 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1865 FixedSettings
->Mtrr
[Index
]
1872 This function sets fixed MTRRs
1874 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1876 @retval The pointer of FixedSettings
1879 MTRR_FIXED_SETTINGS
*
1882 IN MTRR_FIXED_SETTINGS
*FixedSettings
1885 MTRR_CONTEXT MtrrContext
;
1887 if (!IsMtrrSupported ()) {
1888 return FixedSettings
;
1891 PreMtrrChange (&MtrrContext
);
1892 MtrrSetFixedMtrrWorker (FixedSettings
);
1893 PostMtrrChange (&MtrrContext
);
1894 MtrrDebugPrintAllMtrrs ();
1896 return FixedSettings
;
1901 This function gets the content in all MTRRs (variable and fixed)
1903 @param[out] MtrrSetting A buffer to hold all MTRRs content.
1905 @retval the pointer of MtrrSetting
1911 OUT MTRR_SETTINGS
*MtrrSetting
1914 if (!IsMtrrSupported ()) {
1921 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
1924 // Get variable MTRRs
1926 MtrrGetVariableMtrrWorker (
1928 GetVariableMtrrCountWorker (),
1929 &MtrrSetting
->Variables
1933 // Get MTRR_DEF_TYPE value
1935 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1942 This function sets all MTRRs (variable and fixed)
1944 @param[in] MtrrSetting A buffer holding all MTRRs content.
1946 @retval The pointer of MtrrSetting
1952 IN MTRR_SETTINGS
*MtrrSetting
1955 MTRR_CONTEXT MtrrContext
;
1957 if (!IsMtrrSupported ()) {
1961 PreMtrrChange (&MtrrContext
);
1966 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
1969 // Set variable MTRRs
1971 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
1974 // Set MTRR_DEF_TYPE value
1976 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
1978 PostMtrrChangeEnableCache (&MtrrContext
);
1980 MtrrDebugPrintAllMtrrs ();
1987 Checks if MTRR is supported.
1989 @retval TRUE MTRR is supported.
1990 @retval FALSE MTRR is not supported.
2003 // Check CPUID(1).EDX[12] for MTRR capability
2005 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
2006 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
2011 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2012 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2013 // exist, return false.
2015 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
2016 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {