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 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
492 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
493 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
500 if (ByteShift
== 8) {
501 return RETURN_UNSUPPORTED
;
506 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
509 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
510 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
511 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
512 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
515 if (ByteShift
< 8 && (*Length
!= 0)) {
516 return RETURN_UNSUPPORTED
;
519 *LastMsrNum
= MsrNum
;
520 *ReturnClearMask
= ClearMask
;
521 *ReturnOrMask
= OrMask
;
523 return RETURN_SUCCESS
;
528 Worker function gets the attribute of variable MTRRs.
530 This function shadows the content of variable MTRRs into an
531 internal array: VariableMtrr.
533 @param[in] VariableSettings The variable MTRR values to shadow
534 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
535 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
536 @param[in] MtrrValidAddressMask The valid address mask for MTRR
537 @param[out] VariableMtrr The array to shadow variable MTRRs content
539 @return The return value of this parameter indicates the
540 number of MTRRs which has been used.
544 MtrrGetMemoryAttributeInVariableMtrrWorker (
545 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
546 IN UINTN FirmwareVariableMtrrCount
,
547 IN UINT64 MtrrValidBitsMask
,
548 IN UINT64 MtrrValidAddressMask
,
549 OUT VARIABLE_MTRR
*VariableMtrr
555 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
556 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
557 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
558 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
559 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
560 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
561 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
562 VariableMtrr
[Index
].Valid
= TRUE
;
563 VariableMtrr
[Index
].Used
= TRUE
;
572 Gets the attribute of variable MTRRs.
574 This function shadows the content of variable MTRRs into an
575 internal array: VariableMtrr.
577 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
578 @param[in] MtrrValidAddressMask The valid address mask for MTRR
579 @param[out] VariableMtrr The array to shadow variable MTRRs content
581 @return The return value of this paramter indicates the
582 number of MTRRs which has been used.
587 MtrrGetMemoryAttributeInVariableMtrr (
588 IN UINT64 MtrrValidBitsMask
,
589 IN UINT64 MtrrValidAddressMask
,
590 OUT VARIABLE_MTRR
*VariableMtrr
593 MTRR_VARIABLE_SETTINGS VariableSettings
;
595 if (!IsMtrrSupported ()) {
599 MtrrGetVariableMtrrWorker (
601 GetVariableMtrrCountWorker (),
605 return MtrrGetMemoryAttributeInVariableMtrrWorker (
607 GetFirmwareVariableMtrrCountWorker (),
609 MtrrValidAddressMask
,
616 Checks overlap between given memory range and MTRRs.
618 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
620 @param[in] Start The start address of memory range.
621 @param[in] End The end address of memory range.
622 @param[in] VariableMtrr The array to shadow variable MTRRs content
624 @retval TRUE Overlap exists.
625 @retval FALSE No overlap.
629 CheckMemoryAttributeOverlap (
630 IN UINTN FirmwareVariableMtrrCount
,
631 IN PHYSICAL_ADDRESS Start
,
632 IN PHYSICAL_ADDRESS End
,
633 IN VARIABLE_MTRR
*VariableMtrr
638 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
640 VariableMtrr
[Index
].Valid
&&
642 (Start
> (VariableMtrr
[Index
].BaseAddress
+
643 VariableMtrr
[Index
].Length
- 1)
645 (End
< VariableMtrr
[Index
].BaseAddress
)
657 Marks a variable MTRR as non-valid.
659 @param[in] Index The index of the array VariableMtrr to be invalidated
660 @param[in] VariableMtrr The array to shadow variable MTRRs content
661 @param[out] UsedMtrr The number of MTRRs which has already been used
665 InvalidateShadowMtrr (
667 IN VARIABLE_MTRR
*VariableMtrr
,
671 VariableMtrr
[Index
].Valid
= FALSE
;
672 *UsedMtrr
= *UsedMtrr
- 1;
677 Combines memory attributes.
679 If overlap exists between given memory range and MTRRs, try to combine them.
681 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
682 available to firmware.
683 @param[in] Attributes The memory type to set.
684 @param[in, out] Base The base address of memory range.
685 @param[in, out] Length The length of memory range.
686 @param[in] VariableMtrr The array to shadow variable MTRRs content
687 @param[in, out] UsedMtrr The number of MTRRs which has already been used
688 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
690 @retval EFI_SUCCESS Memory region successfully combined.
691 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
695 CombineMemoryAttribute (
696 IN UINT32 FirmwareVariableMtrrCount
,
697 IN UINT64 Attributes
,
699 IN OUT UINT64
*Length
,
700 IN VARIABLE_MTRR
*VariableMtrr
,
701 IN OUT UINT32
*UsedMtrr
,
702 OUT BOOLEAN
*OverwriteExistingMtrr
710 BOOLEAN CoveredByExistingMtrr
;
712 *OverwriteExistingMtrr
= FALSE
;
713 CoveredByExistingMtrr
= FALSE
;
714 EndAddress
= *Base
+*Length
- 1;
716 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
718 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
720 !VariableMtrr
[Index
].Valid
||
723 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
730 // Combine same attribute MTRR range
732 if (Attributes
== VariableMtrr
[Index
].Type
) {
734 // if the MTRR range contain the request range, set a flag, then continue to
735 // invalidate any MTRR of the same request range with higher priority cache type.
737 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
738 CoveredByExistingMtrr
= TRUE
;
742 // invalid this MTRR, and program the combine range
745 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
747 VariableMtrr
[Index
].BaseAddress
;
748 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
751 // Record the MTRR usage status in VariableMtrr array.
753 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
754 *Base
= CombineStart
;
755 *Length
= CombineEnd
- CombineStart
+ 1;
756 EndAddress
= CombineEnd
;
757 *OverwriteExistingMtrr
= TRUE
;
761 // The cache type is different, but the range is convered by one MTRR
763 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
764 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
770 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
771 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
772 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
773 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
774 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
775 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
777 *OverwriteExistingMtrr
= TRUE
;
781 // Other type memory overlap is invalid
783 return RETURN_ACCESS_DENIED
;
786 if (CoveredByExistingMtrr
) {
790 return RETURN_SUCCESS
;
795 Calculates the maximum value which is a power of 2, but less the MemoryLength.
797 @param[in] MemoryLength The number to pass in.
799 @return The maximum value which is align to power of 2 and less the MemoryLength
804 IN UINT64 MemoryLength
809 if (RShiftU64 (MemoryLength
, 32) != 0) {
811 (UINT64
) GetPowerOfTwo32 (
812 (UINT32
) RShiftU64 (MemoryLength
, 32)
817 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
825 Determines the MTRR numbers used to program a memory range.
827 This function first checks the alignment of the base address.
828 If the alignment of the base address <= Length, cover the memory range
829 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
830 Length -= alignment. Repeat the step until alignment > Length.
832 Then this function determines which direction of programming the variable
833 MTRRs for the remaining length will use fewer MTRRs.
835 @param[in] BaseAddress Length of Memory to program MTRR
836 @param[in] Length Length of Memory to program MTRR
837 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
839 @retval TRUE Positive direction is better.
840 FALSE Negative direction is better.
844 GetMtrrNumberAndDirection (
845 IN UINT64 BaseAddress
,
857 if (BaseAddress
!= 0) {
860 // Calculate the alignment of the base address.
862 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
864 if (Alignment
> Length
) {
869 BaseAddress
+= Alignment
;
883 TempQword
-= Power2MaxMemory (TempQword
);
885 } while (TempQword
!= 0);
887 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
890 TempQword
-= Power2MaxMemory (TempQword
);
892 } while (TempQword
!= 0);
894 if (Positive
<= Subtractive
) {
895 *MtrrNumber
+= Positive
;
898 *MtrrNumber
+= Subtractive
;
904 Invalid variable MTRRs according to the value in the shadow array.
906 This function programs MTRRs according to the values specified
909 @param[in, out] VariableSettings Variable MTRR settings
910 @param[in] VariableMtrrCount Number of variable MTRRs
911 @param[in, out] VariableMtrr Shadow of variable MTRR contents
916 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
917 IN UINTN VariableMtrrCount
,
918 IN OUT VARIABLE_MTRR
*VariableMtrr
923 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
924 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
925 VariableSettings
->Mtrr
[Index
].Base
= 0;
926 VariableSettings
->Mtrr
[Index
].Mask
= 0;
927 VariableMtrr
[Index
].Used
= FALSE
;
934 Programs variable MTRRs
936 This function programs variable MTRRs
938 @param[in, out] VariableSettings Variable MTRR settings.
939 @param[in] MtrrNumber Index of MTRR to program.
940 @param[in] BaseAddress Base address of memory region.
941 @param[in] Length Length of memory region.
942 @param[in] MemoryCacheType Memory type to set.
943 @param[in] MtrrValidAddressMask The valid address mask for MTRR
947 ProgramVariableMtrr (
948 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
950 IN PHYSICAL_ADDRESS BaseAddress
,
952 IN UINT64 MemoryCacheType
,
953 IN UINT64 MtrrValidAddressMask
959 // MTRR Physical Base
961 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
962 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
965 // MTRR Physical Mask
967 TempQword
= ~(Length
- 1);
968 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
973 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
975 If MtrrSetting is not NULL, gets the default memory attribute from input
976 MTRR settings buffer.
977 If MtrrSetting is NULL, gets the default memory attribute from MSR.
979 @param[in] MtrrSetting A buffer holding all MTRRs content.
980 @param[in] MtrrType MTRR memory type
982 @return The enum item in MTRR_MEMORY_CACHE_TYPE
985 MTRR_MEMORY_CACHE_TYPE
986 GetMemoryCacheTypeFromMtrrType (
987 IN MTRR_SETTINGS
*MtrrSetting
,
992 case MTRR_CACHE_UNCACHEABLE
:
993 return CacheUncacheable
;
994 case MTRR_CACHE_WRITE_COMBINING
:
995 return CacheWriteCombining
;
996 case MTRR_CACHE_WRITE_THROUGH
:
997 return CacheWriteThrough
;
998 case MTRR_CACHE_WRITE_PROTECTED
:
999 return CacheWriteProtected
;
1000 case MTRR_CACHE_WRITE_BACK
:
1001 return CacheWriteBack
;
1004 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1005 // no MTRR covers the range
1007 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1012 Initializes the valid bits mask and valid address mask for MTRRs.
1014 This function initializes the valid bits mask and valid address mask for MTRRs.
1016 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1017 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1021 MtrrLibInitializeMtrrMask (
1022 OUT UINT64
*MtrrValidBitsMask
,
1023 OUT UINT64
*MtrrValidAddressMask
1027 UINT8 PhysicalAddressBits
;
1029 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1031 if (RegEax
>= 0x80000008) {
1032 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1034 PhysicalAddressBits
= (UINT8
) RegEax
;
1036 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1037 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1039 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1040 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1046 Determines the real attribute of a memory range.
1048 This function is to arbitrate the real attribute of the memory when
1049 there are 2 MTRRs covers the same memory range. For further details,
1050 please refer the IA32 Software Developer's Manual, Volume 3,
1053 @param[in] MtrrType1 The first kind of Memory type
1054 @param[in] MtrrType2 The second kind of memory type
1059 IN UINT64 MtrrType1
,
1065 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1066 switch (MtrrType1
) {
1067 case MTRR_CACHE_UNCACHEABLE
:
1068 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1070 case MTRR_CACHE_WRITE_COMBINING
:
1072 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1073 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1075 MtrrType
= MtrrType2
;
1078 case MTRR_CACHE_WRITE_THROUGH
:
1080 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1081 MtrrType2
==MTRR_CACHE_WRITE_BACK
1083 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1084 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1085 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1088 case MTRR_CACHE_WRITE_PROTECTED
:
1089 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1090 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1091 MtrrType
= MtrrType2
;
1094 case MTRR_CACHE_WRITE_BACK
:
1096 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1097 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1098 MtrrType2
== MTRR_CACHE_WRITE_BACK
1100 MtrrType
= MtrrType2
;
1103 case MTRR_CACHE_INVALID_TYPE
:
1104 MtrrType
= MtrrType2
;
1110 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1111 MtrrType
= MtrrType1
;
1117 Worker function will get the memory cache type of the specific address.
1119 If MtrrSetting is not NULL, gets the memory cache type from input
1120 MTRR settings buffer.
1121 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1123 @param[in] MtrrSetting A buffer holding all MTRRs content.
1124 @param[in] Address The specific address
1126 @return Memory cache type of the specific address
1129 MTRR_MEMORY_CACHE_TYPE
1130 MtrrGetMemoryAttributeByAddressWorker (
1131 IN MTRR_SETTINGS
*MtrrSetting
,
1132 IN PHYSICAL_ADDRESS Address
1139 UINT64 TempMtrrType
;
1140 MTRR_MEMORY_CACHE_TYPE CacheType
;
1141 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1142 UINT64 MtrrValidBitsMask
;
1143 UINT64 MtrrValidAddressMask
;
1144 UINTN VariableMtrrCount
;
1145 MTRR_VARIABLE_SETTINGS VariableSettings
;
1148 // Check if MTRR is enabled, if not, return UC as attribute
1150 if (MtrrSetting
== NULL
) {
1151 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1153 TempQword
= MtrrSetting
->MtrrDefType
;
1155 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1157 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1158 return CacheUncacheable
;
1162 // If address is less than 1M, then try to go through the fixed MTRR
1164 if (Address
< BASE_1MB
) {
1165 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1167 // Go through the fixed MTRR
1169 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1170 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1172 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1173 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1177 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1178 mMtrrLibFixedMtrrTable
[Index
].Length
;
1179 if (MtrrSetting
== NULL
) {
1180 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1182 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1184 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1185 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1190 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1192 MtrrGetVariableMtrrWorker (
1194 GetVariableMtrrCountWorker (),
1198 MtrrGetMemoryAttributeInVariableMtrrWorker (
1200 GetFirmwareVariableMtrrCountWorker (),
1202 MtrrValidAddressMask
,
1207 // Go through the variable MTRR
1209 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1210 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1212 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1213 if (VariableMtrr
[Index
].Valid
) {
1214 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1215 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1216 TempMtrrType
= VariableMtrr
[Index
].Type
;
1217 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1221 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1228 This function will get the memory cache type of the specific address.
1230 This function is mainly for debug purpose.
1232 @param[in] Address The specific address
1234 @return Memory cache type of the specific address
1237 MTRR_MEMORY_CACHE_TYPE
1239 MtrrGetMemoryAttribute (
1240 IN PHYSICAL_ADDRESS Address
1243 if (!IsMtrrSupported ()) {
1244 return CacheUncacheable
;
1247 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1251 Worker function prints all MTRRs for debugging.
1253 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1255 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1257 @param MtrrSetting A buffer holding all MTRRs content.
1260 MtrrDebugPrintAllMtrrsWorker (
1261 IN MTRR_SETTINGS
*MtrrSetting
1265 MTRR_SETTINGS LocalMtrrs
;
1266 MTRR_SETTINGS
*Mtrrs
;
1269 UINTN VariableMtrrCount
;
1277 UINT64 NoRangeLimit
;
1280 UINTN PreviousMemoryType
;
1283 if (!IsMtrrSupported ()) {
1287 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1288 DEBUG((DEBUG_CACHE
, "=============\n"));
1290 if (MtrrSetting
!= NULL
) {
1291 Mtrrs
= MtrrSetting
;
1293 MtrrGetAllMtrrs (&LocalMtrrs
);
1294 Mtrrs
= &LocalMtrrs
;
1297 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1298 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1299 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1302 VariableMtrrCount
= GetVariableMtrrCount ();
1303 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1304 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1306 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1307 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1310 DEBUG((DEBUG_CACHE
, "\n"));
1311 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1312 DEBUG((DEBUG_CACHE
, "====================================\n"));
1315 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1316 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1317 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1318 for (Index1
= 0; Index1
< 8; Index1
++) {
1319 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1320 if (MemoryType
> CacheWriteBack
) {
1321 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1323 if (MemoryType
!= PreviousMemoryType
) {
1324 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1325 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1327 PreviousMemoryType
= MemoryType
;
1328 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1330 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1333 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1335 VariableMtrrCount
= GetVariableMtrrCount ();
1338 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1339 if (RegEax
>= 0x80000008) {
1340 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1341 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1344 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1346 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1347 if (MemoryType
> CacheWriteBack
) {
1348 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1351 if (MemoryType
!= PreviousMemoryType
) {
1352 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1353 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1355 PreviousMemoryType
= MemoryType
;
1356 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1359 RangeBase
= BASE_1MB
;
1360 NoRangeBase
= BASE_1MB
;
1362 NoRangeLimit
= Limit
;
1364 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1365 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1367 // If mask is not valid, then do not display range
1371 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1372 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1374 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1378 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1379 RangeBase
= MtrrBase
;
1381 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1382 RangeBase
= MtrrLimit
+ 1;
1384 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1385 RangeLimit
= MtrrBase
- 1;
1387 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1388 RangeLimit
= MtrrLimit
;
1391 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1392 NoRangeBase
= MtrrLimit
+ 1;
1394 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1395 NoRangeLimit
= MtrrBase
- 1;
1400 Base
= RangeLimit
+ 1;
1402 Base
= NoRangeLimit
+ 1;
1404 } while (Base
< Limit
);
1405 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1411 This function prints all MTRRs for debugging.
1415 MtrrDebugPrintAllMtrrs (
1419 MtrrDebugPrintAllMtrrsWorker (NULL
);
1424 Worker function attempts to set the attributes for a memory range.
1426 If MtrrSettings is not NULL, set the attributes into the input MTRR
1428 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1430 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1431 @param[in] BaseAddress The physical address that is the start
1432 address of a memory region.
1433 @param[in] Length The size in bytes of the memory region.
1434 @param[in] Attribute The bit mask of attributes to set for the
1437 @retval RETURN_SUCCESS The attributes were set for the memory
1439 @retval RETURN_INVALID_PARAMETER Length is zero.
1440 @retval RETURN_UNSUPPORTED The processor does not support one or
1441 more bytes of the memory resource range
1442 specified by BaseAddress and Length.
1443 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1444 for the memory resource range specified
1445 by BaseAddress and Length.
1446 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1447 range specified by BaseAddress and Length
1449 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1450 modify the attributes of the memory
1455 MtrrSetMemoryAttributeWorker (
1456 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1457 IN PHYSICAL_ADDRESS BaseAddress
,
1459 IN MTRR_MEMORY_CACHE_TYPE Attribute
1463 RETURN_STATUS Status
;
1470 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1472 UINT64 MtrrValidBitsMask
;
1473 UINT64 MtrrValidAddressMask
;
1474 BOOLEAN OverwriteExistingMtrr
;
1475 UINT32 FirmwareVariableMtrrCount
;
1476 MTRR_CONTEXT MtrrContext
;
1477 BOOLEAN MtrrContextValid
;
1478 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1479 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1480 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1481 UINT32 VariableMtrrCount
;
1482 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1483 BOOLEAN ProgramVariableSettings
;
1484 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1489 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1491 MtrrContextValid
= FALSE
;
1492 VariableMtrrCount
= 0;
1493 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1494 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1495 FixedSettingsValid
[Index
] = FALSE
;
1496 FixedSettingsModified
[Index
] = FALSE
;
1498 ProgramVariableSettings
= FALSE
;
1500 if (!IsMtrrSupported ()) {
1501 Status
= RETURN_UNSUPPORTED
;
1505 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1508 MemoryType
= (UINT64
)Attribute
;
1509 OverwriteExistingMtrr
= FALSE
;
1512 // Check for an invalid parameter
1515 Status
= RETURN_INVALID_PARAMETER
;
1520 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1521 (Length
& ~MtrrValidAddressMask
) != 0
1523 Status
= RETURN_UNSUPPORTED
;
1528 // Check if Fixed MTRR
1530 Status
= RETURN_SUCCESS
;
1531 if (BaseAddress
< BASE_1MB
) {
1532 MsrNum
= (UINT32
)-1;
1533 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1534 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1535 if (RETURN_ERROR (Status
)) {
1538 if (MtrrSetting
!= NULL
) {
1539 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1540 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1542 if (!FixedSettingsValid
[MsrNum
]) {
1543 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1544 FixedSettingsValid
[MsrNum
] = TRUE
;
1546 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1547 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1548 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1549 FixedSettingsModified
[MsrNum
] = TRUE
;
1556 // A Length of 0 can only make sense for fixed MTTR ranges.
1557 // Since we just handled the fixed MTRRs, we can skip the
1558 // variable MTRR section.
1565 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1566 // we can set the base to 0 to save variable MTRRs.
1568 if (BaseAddress
== BASE_1MB
) {
1574 // Read all variable MTRRs
1576 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1577 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1578 if (MtrrSetting
!= NULL
) {
1579 VariableSettings
= &MtrrSetting
->Variables
;
1581 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1582 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1583 ProgramVariableSettings
= TRUE
;
1584 VariableSettings
= &WorkingVariableSettings
;
1588 // Check for overlap
1590 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1592 FirmwareVariableMtrrCount
,
1594 MtrrValidAddressMask
,
1597 OverLap
= CheckMemoryAttributeOverlap (
1598 FirmwareVariableMtrrCount
,
1600 BaseAddress
+ Length
- 1,
1604 Status
= CombineMemoryAttribute (
1605 FirmwareVariableMtrrCount
,
1611 &OverwriteExistingMtrr
1613 if (RETURN_ERROR (Status
)) {
1619 // Combined successfully, invalidate the now-unused MTRRs
1621 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1622 Status
= RETURN_SUCCESS
;
1628 // The memory type is the same with the type specified by
1629 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1631 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1633 // Invalidate the now-unused MTRRs
1635 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1639 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1641 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1642 Status
= RETURN_OUT_OF_RESOURCES
;
1647 // Invalidate the now-unused MTRRs
1649 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1652 // Find first unused MTRR
1654 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1655 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1660 if (BaseAddress
!= 0) {
1663 // Calculate the alignment of the base address.
1665 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1667 if (Alignment
> Length
) {
1674 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1675 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1680 ProgramVariableMtrr (
1686 MtrrValidAddressMask
1688 BaseAddress
+= Alignment
;
1689 Length
-= Alignment
;
1700 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1705 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1706 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1711 ProgramVariableMtrr (
1717 MtrrValidAddressMask
1719 BaseAddress
+= Length
;
1720 TempQword
= Length
- TempQword
;
1721 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1728 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1729 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1734 Length
= Power2MaxMemory (TempQword
);
1736 BaseAddress
-= Length
;
1739 ProgramVariableMtrr (
1745 MtrrValidAddressMask
1749 BaseAddress
+= Length
;
1751 TempQword
-= Length
;
1753 } while (TempQword
> 0);
1758 // Write fixed MTRRs that have been modified
1760 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1761 if (FixedSettingsModified
[Index
]) {
1762 if (!MtrrContextValid
) {
1763 PreMtrrChange (&MtrrContext
);
1764 MtrrContextValid
= TRUE
;
1767 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1768 WorkingFixedSettings
.Mtrr
[Index
]
1774 // Write variable MTRRs
1776 if (ProgramVariableSettings
) {
1777 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1778 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1779 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1780 if (!MtrrContextValid
) {
1781 PreMtrrChange (&MtrrContext
);
1782 MtrrContextValid
= TRUE
;
1785 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1786 WorkingVariableSettings
.Mtrr
[Index
].Base
1789 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1790 WorkingVariableSettings
.Mtrr
[Index
].Mask
1795 if (MtrrContextValid
) {
1796 PostMtrrChange (&MtrrContext
);
1799 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1800 if (!RETURN_ERROR (Status
)) {
1801 if (MtrrSetting
!= NULL
) {
1802 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1804 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1811 This function attempts to set the attributes for a memory range.
1813 @param[in] BaseAddress The physical address that is the start
1814 address of a memory region.
1815 @param[in] Length The size in bytes of the memory region.
1816 @param[in] Attributes The bit mask of attributes to set for the
1819 @retval RETURN_SUCCESS The attributes were set for the memory
1821 @retval RETURN_INVALID_PARAMETER Length is zero.
1822 @retval RETURN_UNSUPPORTED The processor does not support one or
1823 more bytes of the memory resource range
1824 specified by BaseAddress and Length.
1825 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1826 for the memory resource range specified
1827 by BaseAddress and Length.
1828 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1829 range specified by BaseAddress and Length
1831 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1832 modify the attributes of the memory
1838 MtrrSetMemoryAttribute (
1839 IN PHYSICAL_ADDRESS BaseAddress
,
1841 IN MTRR_MEMORY_CACHE_TYPE Attribute
1844 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1845 return MtrrSetMemoryAttributeWorker (
1854 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1856 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1857 @param[in] BaseAddress The physical address that is the start address
1859 @param[in] Length The size in bytes of the memory region.
1860 @param[in] Attribute The bit mask of attributes to set for the
1863 @retval RETURN_SUCCESS The attributes were set for the memory region.
1864 @retval RETURN_INVALID_PARAMETER Length is zero.
1865 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1866 memory resource range specified by BaseAddress and Length.
1867 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1868 range specified by BaseAddress and Length.
1869 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1870 BaseAddress and Length cannot be modified.
1871 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1872 the memory resource range.
1877 MtrrSetMemoryAttributeInMtrrSettings (
1878 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1879 IN PHYSICAL_ADDRESS BaseAddress
,
1881 IN MTRR_MEMORY_CACHE_TYPE Attribute
1884 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1885 return MtrrSetMemoryAttributeWorker (
1894 Worker function setting variable MTRRs
1896 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1900 MtrrSetVariableMtrrWorker (
1901 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1905 UINT32 VariableMtrrCount
;
1907 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1908 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1910 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1912 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1913 VariableSettings
->Mtrr
[Index
].Base
1916 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1917 VariableSettings
->Mtrr
[Index
].Mask
1924 This function sets variable MTRRs
1926 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1928 @return The pointer of VariableSettings
1931 MTRR_VARIABLE_SETTINGS
*
1933 MtrrSetVariableMtrr (
1934 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1937 MTRR_CONTEXT MtrrContext
;
1939 if (!IsMtrrSupported ()) {
1940 return VariableSettings
;
1943 PreMtrrChange (&MtrrContext
);
1944 MtrrSetVariableMtrrWorker (VariableSettings
);
1945 PostMtrrChange (&MtrrContext
);
1946 MtrrDebugPrintAllMtrrs ();
1948 return VariableSettings
;
1952 Worker function setting fixed MTRRs
1954 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1958 MtrrSetFixedMtrrWorker (
1959 IN MTRR_FIXED_SETTINGS
*FixedSettings
1964 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1966 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1967 FixedSettings
->Mtrr
[Index
]
1974 This function sets fixed MTRRs
1976 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1978 @retval The pointer of FixedSettings
1981 MTRR_FIXED_SETTINGS
*
1984 IN MTRR_FIXED_SETTINGS
*FixedSettings
1987 MTRR_CONTEXT MtrrContext
;
1989 if (!IsMtrrSupported ()) {
1990 return FixedSettings
;
1993 PreMtrrChange (&MtrrContext
);
1994 MtrrSetFixedMtrrWorker (FixedSettings
);
1995 PostMtrrChange (&MtrrContext
);
1996 MtrrDebugPrintAllMtrrs ();
1998 return FixedSettings
;
2003 This function gets the content in all MTRRs (variable and fixed)
2005 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2007 @retval the pointer of MtrrSetting
2013 OUT MTRR_SETTINGS
*MtrrSetting
2016 if (!IsMtrrSupported ()) {
2023 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2026 // Get variable MTRRs
2028 MtrrGetVariableMtrrWorker (
2030 GetVariableMtrrCountWorker (),
2031 &MtrrSetting
->Variables
2035 // Get MTRR_DEF_TYPE value
2037 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2044 This function sets all MTRRs (variable and fixed)
2046 @param[in] MtrrSetting A buffer holding all MTRRs content.
2048 @retval The pointer of MtrrSetting
2054 IN MTRR_SETTINGS
*MtrrSetting
2057 MTRR_CONTEXT MtrrContext
;
2059 if (!IsMtrrSupported ()) {
2063 PreMtrrChange (&MtrrContext
);
2068 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2071 // Set variable MTRRs
2073 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2076 // Set MTRR_DEF_TYPE value
2078 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2080 PostMtrrChangeEnableCache (&MtrrContext
);
2082 MtrrDebugPrintAllMtrrs ();
2089 Checks if MTRR is supported.
2091 @retval TRUE MTRR is supported.
2092 @retval FALSE MTRR is not supported.
2105 // Check CPUID(1).EDX[12] for MTRR capability
2107 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
2108 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
2113 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2114 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2115 // exist, return false.
2117 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
2118 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {