4 Copyright (c) 2008 - 2016, 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[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.
442 On return, the current index of the fixed MTRR MSR to program.
443 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
444 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
446 @retval RETURN_SUCCESS The cache type was updated successfully
447 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
453 IN UINT64 MemoryCacheType
,
455 IN OUT UINT64
*Length
,
456 IN OUT UINT32
*LastMsrNum
,
457 OUT UINT64
*ReturnClearMask
,
458 OUT UINT64
*ReturnOrMask
469 for (MsrNum
= *LastMsrNum
+ 1; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
470 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
473 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
474 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
482 if (MsrNum
>= MTRR_NUMBER_OF_FIXED_MTRR
) {
483 return RETURN_UNSUPPORTED
;
487 // We found the fixed MTRR to be programmed
489 ByteShift
= ((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
)
490 / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
492 if (ByteShift
>= 8) {
493 return RETURN_UNSUPPORTED
;
498 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
501 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
502 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
503 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
504 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
507 if (ByteShift
< 8 && (*Length
!= 0)) {
508 return RETURN_UNSUPPORTED
;
511 *LastMsrNum
= MsrNum
;
512 *ReturnClearMask
= ClearMask
;
513 *ReturnOrMask
= OrMask
;
515 return RETURN_SUCCESS
;
520 Worker function gets the attribute of variable MTRRs.
522 This function shadows the content of variable MTRRs into an
523 internal array: VariableMtrr.
525 @param[in] VariableSettings The variable MTRR values to shadow
526 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
527 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
528 @param[in] MtrrValidAddressMask The valid address mask for MTRR
529 @param[out] VariableMtrr The array to shadow variable MTRRs content
531 @return The return value of this parameter indicates the
532 number of MTRRs which has been used.
536 MtrrGetMemoryAttributeInVariableMtrrWorker (
537 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
538 IN UINTN FirmwareVariableMtrrCount
,
539 IN UINT64 MtrrValidBitsMask
,
540 IN UINT64 MtrrValidAddressMask
,
541 OUT VARIABLE_MTRR
*VariableMtrr
547 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
548 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
549 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
550 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
551 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
552 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
553 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
554 VariableMtrr
[Index
].Valid
= TRUE
;
555 VariableMtrr
[Index
].Used
= TRUE
;
564 Gets the attribute of variable MTRRs.
566 This function shadows the content of variable MTRRs into an
567 internal array: VariableMtrr.
569 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
570 @param[in] MtrrValidAddressMask The valid address mask for MTRR
571 @param[out] VariableMtrr The array to shadow variable MTRRs content
573 @return The return value of this paramter indicates the
574 number of MTRRs which has been used.
579 MtrrGetMemoryAttributeInVariableMtrr (
580 IN UINT64 MtrrValidBitsMask
,
581 IN UINT64 MtrrValidAddressMask
,
582 OUT VARIABLE_MTRR
*VariableMtrr
585 MTRR_VARIABLE_SETTINGS VariableSettings
;
587 if (!IsMtrrSupported ()) {
591 MtrrGetVariableMtrrWorker (
593 GetVariableMtrrCountWorker (),
597 return MtrrGetMemoryAttributeInVariableMtrrWorker (
599 GetFirmwareVariableMtrrCountWorker (),
601 MtrrValidAddressMask
,
608 Checks overlap between given memory range and MTRRs.
610 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
612 @param[in] Start The start address of memory range.
613 @param[in] End The end address of memory range.
614 @param[in] VariableMtrr The array to shadow variable MTRRs content
616 @retval TRUE Overlap exists.
617 @retval FALSE No overlap.
621 CheckMemoryAttributeOverlap (
622 IN UINTN FirmwareVariableMtrrCount
,
623 IN PHYSICAL_ADDRESS Start
,
624 IN PHYSICAL_ADDRESS End
,
625 IN VARIABLE_MTRR
*VariableMtrr
630 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
632 VariableMtrr
[Index
].Valid
&&
634 (Start
> (VariableMtrr
[Index
].BaseAddress
+
635 VariableMtrr
[Index
].Length
- 1)
637 (End
< VariableMtrr
[Index
].BaseAddress
)
649 Marks a variable MTRR as non-valid.
651 @param[in] Index The index of the array VariableMtrr to be invalidated
652 @param[in] VariableMtrr The array to shadow variable MTRRs content
653 @param[out] UsedMtrr The number of MTRRs which has already been used
657 InvalidateShadowMtrr (
659 IN VARIABLE_MTRR
*VariableMtrr
,
663 VariableMtrr
[Index
].Valid
= FALSE
;
664 *UsedMtrr
= *UsedMtrr
- 1;
669 Combines memory attributes.
671 If overlap exists between given memory range and MTRRs, try to combine them.
673 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
674 available to firmware.
675 @param[in] Attributes The memory type to set.
676 @param[in, out] Base The base address of memory range.
677 @param[in, out] Length The length of memory range.
678 @param[in] VariableMtrr The array to shadow variable MTRRs content
679 @param[in, out] UsedMtrr The number of MTRRs which has already been used
680 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
682 @retval EFI_SUCCESS Memory region successfully combined.
683 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
687 CombineMemoryAttribute (
688 IN UINT32 FirmwareVariableMtrrCount
,
689 IN UINT64 Attributes
,
691 IN OUT UINT64
*Length
,
692 IN VARIABLE_MTRR
*VariableMtrr
,
693 IN OUT UINT32
*UsedMtrr
,
694 OUT BOOLEAN
*OverwriteExistingMtrr
702 BOOLEAN CoveredByExistingMtrr
;
704 *OverwriteExistingMtrr
= FALSE
;
705 CoveredByExistingMtrr
= FALSE
;
706 EndAddress
= *Base
+*Length
- 1;
708 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
710 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
712 !VariableMtrr
[Index
].Valid
||
715 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
722 // Combine same attribute MTRR range
724 if (Attributes
== VariableMtrr
[Index
].Type
) {
726 // if the MTRR range contain the request range, set a flag, then continue to
727 // invalidate any MTRR of the same request range with higher priority cache type.
729 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
730 CoveredByExistingMtrr
= TRUE
;
734 // invalid this MTRR, and program the combine range
737 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
739 VariableMtrr
[Index
].BaseAddress
;
740 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
743 // Record the MTRR usage status in VariableMtrr array.
745 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
746 *Base
= CombineStart
;
747 *Length
= CombineEnd
- CombineStart
+ 1;
748 EndAddress
= CombineEnd
;
749 *OverwriteExistingMtrr
= TRUE
;
753 // The cache type is different, but the range is convered by one MTRR
755 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
756 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
762 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
763 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
764 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
765 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
766 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
767 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
769 *OverwriteExistingMtrr
= TRUE
;
773 // Other type memory overlap is invalid
775 return RETURN_ACCESS_DENIED
;
778 if (CoveredByExistingMtrr
) {
782 return RETURN_SUCCESS
;
787 Calculates the maximum value which is a power of 2, but less the MemoryLength.
789 @param[in] MemoryLength The number to pass in.
791 @return The maximum value which is align to power of 2 and less the MemoryLength
796 IN UINT64 MemoryLength
801 if (RShiftU64 (MemoryLength
, 32) != 0) {
803 (UINT64
) GetPowerOfTwo32 (
804 (UINT32
) RShiftU64 (MemoryLength
, 32)
809 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
817 Determines the MTRR numbers used to program a memory range.
819 This function first checks the alignment of the base address.
820 If the alignment of the base address <= Length, cover the memory range
821 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
822 Length -= alignment. Repeat the step until alignment > Length.
824 Then this function determines which direction of programming the variable
825 MTRRs for the remaining length will use fewer MTRRs.
827 @param[in] BaseAddress Length of Memory to program MTRR
828 @param[in] Length Length of Memory to program MTRR
829 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
831 @retval TRUE Positive direction is better.
832 FALSE Negative direction is better.
836 GetMtrrNumberAndDirection (
837 IN UINT64 BaseAddress
,
849 if (BaseAddress
!= 0) {
852 // Calculate the alignment of the base address.
854 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
856 if (Alignment
> Length
) {
861 BaseAddress
+= Alignment
;
875 TempQword
-= Power2MaxMemory (TempQword
);
877 } while (TempQword
!= 0);
879 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
882 TempQword
-= Power2MaxMemory (TempQword
);
884 } while (TempQword
!= 0);
886 if (Positive
<= Subtractive
) {
887 *MtrrNumber
+= Positive
;
890 *MtrrNumber
+= Subtractive
;
896 Invalid variable MTRRs according to the value in the shadow array.
898 This function programs MTRRs according to the values specified
901 @param[in, out] VariableSettings Variable MTRR settings
902 @param[in] VariableMtrrCount Number of variable MTRRs
903 @param[in, out] VariableMtrr Shadow of variable MTRR contents
908 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
909 IN UINTN VariableMtrrCount
,
910 IN OUT VARIABLE_MTRR
*VariableMtrr
915 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
916 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
917 VariableSettings
->Mtrr
[Index
].Base
= 0;
918 VariableSettings
->Mtrr
[Index
].Mask
= 0;
919 VariableMtrr
[Index
].Used
= FALSE
;
926 Programs variable MTRRs
928 This function programs variable MTRRs
930 @param[in, out] VariableSettings Variable MTRR settings.
931 @param[in] MtrrNumber Index of MTRR to program.
932 @param[in] BaseAddress Base address of memory region.
933 @param[in] Length Length of memory region.
934 @param[in] MemoryCacheType Memory type to set.
935 @param[in] MtrrValidAddressMask The valid address mask for MTRR
939 ProgramVariableMtrr (
940 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
942 IN PHYSICAL_ADDRESS BaseAddress
,
944 IN UINT64 MemoryCacheType
,
945 IN UINT64 MtrrValidAddressMask
951 // MTRR Physical Base
953 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
954 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
957 // MTRR Physical Mask
959 TempQword
= ~(Length
- 1);
960 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
965 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
967 If MtrrSetting is not NULL, gets the default memory attribute from input
968 MTRR settings buffer.
969 If MtrrSetting is NULL, gets the default memory attribute from MSR.
971 @param[in] MtrrSetting A buffer holding all MTRRs content.
972 @param[in] MtrrType MTRR memory type
974 @return The enum item in MTRR_MEMORY_CACHE_TYPE
977 MTRR_MEMORY_CACHE_TYPE
978 GetMemoryCacheTypeFromMtrrType (
979 IN MTRR_SETTINGS
*MtrrSetting
,
984 case MTRR_CACHE_UNCACHEABLE
:
985 return CacheUncacheable
;
986 case MTRR_CACHE_WRITE_COMBINING
:
987 return CacheWriteCombining
;
988 case MTRR_CACHE_WRITE_THROUGH
:
989 return CacheWriteThrough
;
990 case MTRR_CACHE_WRITE_PROTECTED
:
991 return CacheWriteProtected
;
992 case MTRR_CACHE_WRITE_BACK
:
993 return CacheWriteBack
;
996 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
997 // no MTRR covers the range
999 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1004 Initializes the valid bits mask and valid address mask for MTRRs.
1006 This function initializes the valid bits mask and valid address mask for MTRRs.
1008 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1009 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1013 MtrrLibInitializeMtrrMask (
1014 OUT UINT64
*MtrrValidBitsMask
,
1015 OUT UINT64
*MtrrValidAddressMask
1019 UINT8 PhysicalAddressBits
;
1021 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1023 if (RegEax
>= 0x80000008) {
1024 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1026 PhysicalAddressBits
= (UINT8
) RegEax
;
1028 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1029 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1031 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1032 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1038 Determines the real attribute of a memory range.
1040 This function is to arbitrate the real attribute of the memory when
1041 there are 2 MTRRs covers the same memory range. For further details,
1042 please refer the IA32 Software Developer's Manual, Volume 3,
1045 @param[in] MtrrType1 The first kind of Memory type
1046 @param[in] MtrrType2 The second kind of memory type
1051 IN UINT64 MtrrType1
,
1057 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1058 switch (MtrrType1
) {
1059 case MTRR_CACHE_UNCACHEABLE
:
1060 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1062 case MTRR_CACHE_WRITE_COMBINING
:
1064 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1065 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1067 MtrrType
= MtrrType2
;
1070 case MTRR_CACHE_WRITE_THROUGH
:
1072 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1073 MtrrType2
==MTRR_CACHE_WRITE_BACK
1075 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1076 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1077 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1080 case MTRR_CACHE_WRITE_PROTECTED
:
1081 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1082 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1083 MtrrType
= MtrrType2
;
1086 case MTRR_CACHE_WRITE_BACK
:
1088 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1089 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1090 MtrrType2
== MTRR_CACHE_WRITE_BACK
1092 MtrrType
= MtrrType2
;
1095 case MTRR_CACHE_INVALID_TYPE
:
1096 MtrrType
= MtrrType2
;
1102 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1103 MtrrType
= MtrrType1
;
1109 Worker function will get the memory cache type of the specific address.
1111 If MtrrSetting is not NULL, gets the memory cache type from input
1112 MTRR settings buffer.
1113 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1115 @param[in] MtrrSetting A buffer holding all MTRRs content.
1116 @param[in] Address The specific address
1118 @return Memory cache type of the specific address
1121 MTRR_MEMORY_CACHE_TYPE
1122 MtrrGetMemoryAttributeByAddressWorker (
1123 IN MTRR_SETTINGS
*MtrrSetting
,
1124 IN PHYSICAL_ADDRESS Address
1131 UINT64 TempMtrrType
;
1132 MTRR_MEMORY_CACHE_TYPE CacheType
;
1133 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1134 UINT64 MtrrValidBitsMask
;
1135 UINT64 MtrrValidAddressMask
;
1136 UINTN VariableMtrrCount
;
1137 MTRR_VARIABLE_SETTINGS VariableSettings
;
1140 // Check if MTRR is enabled, if not, return UC as attribute
1142 if (MtrrSetting
== NULL
) {
1143 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1145 TempQword
= MtrrSetting
->MtrrDefType
;
1147 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1149 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1150 return CacheUncacheable
;
1154 // If address is less than 1M, then try to go through the fixed MTRR
1156 if (Address
< BASE_1MB
) {
1157 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1159 // Go through the fixed MTRR
1161 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1162 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1164 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1165 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1169 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1170 mMtrrLibFixedMtrrTable
[Index
].Length
;
1171 if (MtrrSetting
== NULL
) {
1172 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1174 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1176 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1177 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1182 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1184 MtrrGetVariableMtrrWorker (
1186 GetVariableMtrrCountWorker (),
1190 MtrrGetMemoryAttributeInVariableMtrrWorker (
1192 GetFirmwareVariableMtrrCountWorker (),
1194 MtrrValidAddressMask
,
1199 // Go through the variable MTRR
1201 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1202 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1204 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1205 if (VariableMtrr
[Index
].Valid
) {
1206 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1207 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1208 TempMtrrType
= VariableMtrr
[Index
].Type
;
1209 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1213 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1220 This function will get the memory cache type of the specific address.
1222 This function is mainly for debug purpose.
1224 @param[in] Address The specific address
1226 @return Memory cache type of the specific address
1229 MTRR_MEMORY_CACHE_TYPE
1231 MtrrGetMemoryAttribute (
1232 IN PHYSICAL_ADDRESS Address
1235 if (!IsMtrrSupported ()) {
1236 return CacheUncacheable
;
1239 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1243 Worker function prints all MTRRs for debugging.
1245 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1247 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1249 @param MtrrSetting A buffer holding all MTRRs content.
1252 MtrrDebugPrintAllMtrrsWorker (
1253 IN MTRR_SETTINGS
*MtrrSetting
1257 MTRR_SETTINGS LocalMtrrs
;
1258 MTRR_SETTINGS
*Mtrrs
;
1261 UINTN VariableMtrrCount
;
1269 UINT64 NoRangeLimit
;
1272 UINTN PreviousMemoryType
;
1275 if (!IsMtrrSupported ()) {
1279 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1280 DEBUG((DEBUG_CACHE
, "=============\n"));
1282 if (MtrrSetting
!= NULL
) {
1283 Mtrrs
= MtrrSetting
;
1285 MtrrGetAllMtrrs (&LocalMtrrs
);
1286 Mtrrs
= &LocalMtrrs
;
1289 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1290 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1291 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1294 VariableMtrrCount
= GetVariableMtrrCount ();
1295 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1296 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1298 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1299 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1302 DEBUG((DEBUG_CACHE
, "\n"));
1303 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1304 DEBUG((DEBUG_CACHE
, "====================================\n"));
1307 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1308 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1309 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1310 for (Index1
= 0; Index1
< 8; Index1
++) {
1311 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1312 if (MemoryType
> CacheWriteBack
) {
1313 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1315 if (MemoryType
!= PreviousMemoryType
) {
1316 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1317 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1319 PreviousMemoryType
= MemoryType
;
1320 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1322 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1325 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1327 VariableMtrrCount
= GetVariableMtrrCount ();
1330 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1331 if (RegEax
>= 0x80000008) {
1332 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1333 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1336 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1338 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1339 if (MemoryType
> CacheWriteBack
) {
1340 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1343 if (MemoryType
!= PreviousMemoryType
) {
1344 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1345 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1347 PreviousMemoryType
= MemoryType
;
1348 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1351 RangeBase
= BASE_1MB
;
1352 NoRangeBase
= BASE_1MB
;
1354 NoRangeLimit
= Limit
;
1356 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1357 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1359 // If mask is not valid, then do not display range
1363 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1364 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1366 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1370 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1371 RangeBase
= MtrrBase
;
1373 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1374 RangeBase
= MtrrLimit
+ 1;
1376 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1377 RangeLimit
= MtrrBase
- 1;
1379 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1380 RangeLimit
= MtrrLimit
;
1383 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1384 NoRangeBase
= MtrrLimit
+ 1;
1386 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1387 NoRangeLimit
= MtrrBase
- 1;
1392 Base
= RangeLimit
+ 1;
1394 Base
= NoRangeLimit
+ 1;
1396 } while (Base
< Limit
);
1397 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1403 This function prints all MTRRs for debugging.
1407 MtrrDebugPrintAllMtrrs (
1411 MtrrDebugPrintAllMtrrsWorker (NULL
);
1416 Worker function attempts to set the attributes for a memory range.
1418 If MtrrSettings is not NULL, set the attributes into the input MTRR
1420 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1422 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1423 @param[in] BaseAddress The physical address that is the start
1424 address of a memory region.
1425 @param[in] Length The size in bytes of the memory region.
1426 @param[in] Attribute The bit mask of attributes to set for the
1429 @retval RETURN_SUCCESS The attributes were set for the memory
1431 @retval RETURN_INVALID_PARAMETER Length is zero.
1432 @retval RETURN_UNSUPPORTED The processor does not support one or
1433 more bytes of the memory resource range
1434 specified by BaseAddress and Length.
1435 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1436 for the memory resource range specified
1437 by BaseAddress and Length.
1438 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1439 range specified by BaseAddress and Length
1441 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1442 modify the attributes of the memory
1447 MtrrSetMemoryAttributeWorker (
1448 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1449 IN PHYSICAL_ADDRESS BaseAddress
,
1451 IN MTRR_MEMORY_CACHE_TYPE Attribute
1455 RETURN_STATUS Status
;
1462 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1464 UINT64 MtrrValidBitsMask
;
1465 UINT64 MtrrValidAddressMask
;
1466 BOOLEAN OverwriteExistingMtrr
;
1467 UINT32 FirmwareVariableMtrrCount
;
1468 MTRR_CONTEXT MtrrContext
;
1469 BOOLEAN MtrrContextValid
;
1470 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1471 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1472 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1473 UINT32 VariableMtrrCount
;
1474 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1475 BOOLEAN ProgramVariableSettings
;
1476 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1481 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1483 MtrrContextValid
= FALSE
;
1484 VariableMtrrCount
= 0;
1485 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1486 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1487 FixedSettingsValid
[Index
] = FALSE
;
1488 FixedSettingsModified
[Index
] = FALSE
;
1490 ProgramVariableSettings
= FALSE
;
1492 if (!IsMtrrSupported ()) {
1493 Status
= RETURN_UNSUPPORTED
;
1497 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1500 MemoryType
= (UINT64
)Attribute
;
1501 OverwriteExistingMtrr
= FALSE
;
1504 // Check for an invalid parameter
1507 Status
= RETURN_INVALID_PARAMETER
;
1512 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1513 (Length
& ~MtrrValidAddressMask
) != 0
1515 Status
= RETURN_UNSUPPORTED
;
1520 // Check if Fixed MTRR
1522 Status
= RETURN_SUCCESS
;
1523 if (BaseAddress
< BASE_1MB
) {
1524 MsrNum
= (UINT32
)-1;
1525 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1526 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1527 if (RETURN_ERROR (Status
)) {
1530 if (MtrrSetting
!= NULL
) {
1531 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1532 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1534 if (!FixedSettingsValid
[MsrNum
]) {
1535 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1536 FixedSettingsValid
[MsrNum
] = TRUE
;
1538 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1539 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1540 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1541 FixedSettingsModified
[MsrNum
] = TRUE
;
1548 // A Length of 0 can only make sense for fixed MTTR ranges.
1549 // Since we just handled the fixed MTRRs, we can skip the
1550 // variable MTRR section.
1557 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1558 // we can set the base to 0 to save variable MTRRs.
1560 if (BaseAddress
== BASE_1MB
) {
1566 // Read all variable MTRRs
1568 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1569 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1570 if (MtrrSetting
!= NULL
) {
1571 VariableSettings
= &MtrrSetting
->Variables
;
1573 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1574 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1575 ProgramVariableSettings
= TRUE
;
1576 VariableSettings
= &WorkingVariableSettings
;
1580 // Check for overlap
1582 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1584 FirmwareVariableMtrrCount
,
1586 MtrrValidAddressMask
,
1589 OverLap
= CheckMemoryAttributeOverlap (
1590 FirmwareVariableMtrrCount
,
1592 BaseAddress
+ Length
- 1,
1596 Status
= CombineMemoryAttribute (
1597 FirmwareVariableMtrrCount
,
1603 &OverwriteExistingMtrr
1605 if (RETURN_ERROR (Status
)) {
1611 // Combined successfully, invalidate the now-unused MTRRs
1613 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1614 Status
= RETURN_SUCCESS
;
1620 // The memory type is the same with the type specified by
1621 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1623 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1625 // Invalidate the now-unused MTRRs
1627 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1631 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1633 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1634 Status
= RETURN_OUT_OF_RESOURCES
;
1639 // Invalidate the now-unused MTRRs
1641 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1644 // Find first unused MTRR
1646 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1647 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1652 if (BaseAddress
!= 0) {
1655 // Calculate the alignment of the base address.
1657 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1659 if (Alignment
> Length
) {
1666 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1667 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1672 ProgramVariableMtrr (
1678 MtrrValidAddressMask
1680 BaseAddress
+= Alignment
;
1681 Length
-= Alignment
;
1692 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1697 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1698 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1703 ProgramVariableMtrr (
1709 MtrrValidAddressMask
1711 BaseAddress
+= Length
;
1712 TempQword
= Length
- TempQword
;
1713 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1720 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1721 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1726 Length
= Power2MaxMemory (TempQword
);
1728 BaseAddress
-= Length
;
1731 ProgramVariableMtrr (
1737 MtrrValidAddressMask
1741 BaseAddress
+= Length
;
1743 TempQword
-= Length
;
1745 } while (TempQword
> 0);
1750 // Write fixed MTRRs that have been modified
1752 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1753 if (FixedSettingsModified
[Index
]) {
1754 if (!MtrrContextValid
) {
1755 PreMtrrChange (&MtrrContext
);
1756 MtrrContextValid
= TRUE
;
1759 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1760 WorkingFixedSettings
.Mtrr
[Index
]
1766 // Write variable MTRRs
1768 if (ProgramVariableSettings
) {
1769 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1770 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1771 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1772 if (!MtrrContextValid
) {
1773 PreMtrrChange (&MtrrContext
);
1774 MtrrContextValid
= TRUE
;
1777 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1778 WorkingVariableSettings
.Mtrr
[Index
].Base
1781 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1782 WorkingVariableSettings
.Mtrr
[Index
].Mask
1787 if (MtrrContextValid
) {
1788 PostMtrrChange (&MtrrContext
);
1791 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1792 if (!RETURN_ERROR (Status
)) {
1793 if (MtrrSetting
!= NULL
) {
1794 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1796 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1803 This function attempts to set the attributes for a memory range.
1805 @param[in] BaseAddress The physical address that is the start
1806 address of a memory region.
1807 @param[in] Length The size in bytes of the memory region.
1808 @param[in] Attributes The bit mask of attributes to set for the
1811 @retval RETURN_SUCCESS The attributes were set for the memory
1813 @retval RETURN_INVALID_PARAMETER Length is zero.
1814 @retval RETURN_UNSUPPORTED The processor does not support one or
1815 more bytes of the memory resource range
1816 specified by BaseAddress and Length.
1817 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1818 for the memory resource range specified
1819 by BaseAddress and Length.
1820 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1821 range specified by BaseAddress and Length
1823 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1824 modify the attributes of the memory
1830 MtrrSetMemoryAttribute (
1831 IN PHYSICAL_ADDRESS BaseAddress
,
1833 IN MTRR_MEMORY_CACHE_TYPE Attribute
1836 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1837 return MtrrSetMemoryAttributeWorker (
1846 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1848 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1849 @param[in] BaseAddress The physical address that is the start address
1851 @param[in] Length The size in bytes of the memory region.
1852 @param[in] Attribute The bit mask of attributes to set for the
1855 @retval RETURN_SUCCESS The attributes were set for the memory region.
1856 @retval RETURN_INVALID_PARAMETER Length is zero.
1857 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1858 memory resource range specified by BaseAddress and Length.
1859 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1860 range specified by BaseAddress and Length.
1861 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1862 BaseAddress and Length cannot be modified.
1863 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1864 the memory resource range.
1869 MtrrSetMemoryAttributeInMtrrSettings (
1870 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1871 IN PHYSICAL_ADDRESS BaseAddress
,
1873 IN MTRR_MEMORY_CACHE_TYPE Attribute
1876 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1877 return MtrrSetMemoryAttributeWorker (
1886 Worker function setting variable MTRRs
1888 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1892 MtrrSetVariableMtrrWorker (
1893 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1897 UINT32 VariableMtrrCount
;
1899 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1900 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1902 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1904 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1905 VariableSettings
->Mtrr
[Index
].Base
1908 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1909 VariableSettings
->Mtrr
[Index
].Mask
1916 This function sets variable MTRRs
1918 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1920 @return The pointer of VariableSettings
1923 MTRR_VARIABLE_SETTINGS
*
1925 MtrrSetVariableMtrr (
1926 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1929 MTRR_CONTEXT MtrrContext
;
1931 if (!IsMtrrSupported ()) {
1932 return VariableSettings
;
1935 PreMtrrChange (&MtrrContext
);
1936 MtrrSetVariableMtrrWorker (VariableSettings
);
1937 PostMtrrChange (&MtrrContext
);
1938 MtrrDebugPrintAllMtrrs ();
1940 return VariableSettings
;
1944 Worker function setting fixed MTRRs
1946 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1950 MtrrSetFixedMtrrWorker (
1951 IN MTRR_FIXED_SETTINGS
*FixedSettings
1956 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1958 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1959 FixedSettings
->Mtrr
[Index
]
1966 This function sets fixed MTRRs
1968 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1970 @retval The pointer of FixedSettings
1973 MTRR_FIXED_SETTINGS
*
1976 IN MTRR_FIXED_SETTINGS
*FixedSettings
1979 MTRR_CONTEXT MtrrContext
;
1981 if (!IsMtrrSupported ()) {
1982 return FixedSettings
;
1985 PreMtrrChange (&MtrrContext
);
1986 MtrrSetFixedMtrrWorker (FixedSettings
);
1987 PostMtrrChange (&MtrrContext
);
1988 MtrrDebugPrintAllMtrrs ();
1990 return FixedSettings
;
1995 This function gets the content in all MTRRs (variable and fixed)
1997 @param[out] MtrrSetting A buffer to hold all MTRRs content.
1999 @retval the pointer of MtrrSetting
2005 OUT MTRR_SETTINGS
*MtrrSetting
2008 if (!IsMtrrSupported ()) {
2015 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2018 // Get variable MTRRs
2020 MtrrGetVariableMtrrWorker (
2022 GetVariableMtrrCountWorker (),
2023 &MtrrSetting
->Variables
2027 // Get MTRR_DEF_TYPE value
2029 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2036 This function sets all MTRRs (variable and fixed)
2038 @param[in] MtrrSetting A buffer holding all MTRRs content.
2040 @retval The pointer of MtrrSetting
2046 IN MTRR_SETTINGS
*MtrrSetting
2049 MTRR_CONTEXT MtrrContext
;
2051 if (!IsMtrrSupported ()) {
2055 PreMtrrChange (&MtrrContext
);
2060 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2063 // Set variable MTRRs
2065 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2068 // Set MTRR_DEF_TYPE value
2070 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2072 PostMtrrChangeEnableCache (&MtrrContext
);
2074 MtrrDebugPrintAllMtrrs ();
2081 Checks if MTRR is supported.
2083 @retval TRUE MTRR is supported.
2084 @retval FALSE MTRR is not supported.
2097 // Check CPUID(1).EDX[12] for MTRR capability
2099 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
2100 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
2105 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2106 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2107 // exist, return false.
2109 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
2110 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {