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>
23 #define OR_SEED 0x01010101
24 #define CLEAR_SEED 0xFFFFFFFF
27 // Context to save and restore when MTRRs are programmed
31 BOOLEAN InterruptState
;
35 // This table defines the offset, base and length of the fixed MTRRs
37 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
39 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
44 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
49 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
54 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
59 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
64 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
69 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
74 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
79 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
84 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
89 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
96 // Lookup table used to print MTRRs
98 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
99 "UC", // CacheUncacheable
100 "WC", // CacheWriteCombining
103 "WT", // CacheWriteThrough
104 "WP", // CacheWriteProtected
105 "WB", // CacheWriteBack
110 Worker function returns the variable MTRR count for the CPU.
112 @return Variable MTRR count
116 GetVariableMtrrCountWorker (
120 UINT32 VariableMtrrCount
;
122 VariableMtrrCount
= (UINT32
)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK
);
123 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
124 return VariableMtrrCount
;
128 Returns the variable MTRR count for the CPU.
130 @return Variable MTRR count
135 GetVariableMtrrCount (
139 if (!IsMtrrSupported ()) {
142 return GetVariableMtrrCountWorker ();
146 Worker function returns the firmware usable variable MTRR count for the CPU.
148 @return Firmware usable variable MTRR count
152 GetFirmwareVariableMtrrCountWorker (
156 UINT32 VariableMtrrCount
;
157 UINT32 ReservedMtrrNumber
;
159 VariableMtrrCount
= GetVariableMtrrCountWorker ();
160 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
161 if (VariableMtrrCount
< ReservedMtrrNumber
) {
165 return VariableMtrrCount
- ReservedMtrrNumber
;
169 Returns the firmware usable variable MTRR count for the CPU.
171 @return Firmware usable variable MTRR count
176 GetFirmwareVariableMtrrCount (
180 if (!IsMtrrSupported ()) {
183 return GetFirmwareVariableMtrrCountWorker ();
187 Worker function returns the default MTRR cache type for the system.
189 If MtrrSetting is not NULL, returns the default MTRR cache type from input
190 MTRR settings buffer.
191 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
193 @param[in] MtrrSetting A buffer holding all MTRRs content.
195 @return The default MTRR cache type.
198 MTRR_MEMORY_CACHE_TYPE
199 MtrrGetDefaultMemoryTypeWorker (
200 IN MTRR_SETTINGS
*MtrrSetting
203 if (MtrrSetting
== NULL
) {
204 return (MTRR_MEMORY_CACHE_TYPE
) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0x7);
206 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
212 Returns the default MTRR cache type for the system.
214 @return The default MTRR cache type.
217 MTRR_MEMORY_CACHE_TYPE
219 MtrrGetDefaultMemoryType (
223 if (!IsMtrrSupported ()) {
224 return CacheUncacheable
;
226 return MtrrGetDefaultMemoryTypeWorker (NULL
);
230 Preparation before programming MTRR.
232 This function will do some preparation for programming MTRRs:
233 disable cache, invalid cache and disable MTRR caching functionality
235 @param[out] MtrrContext Pointer to context to save
240 OUT MTRR_CONTEXT
*MtrrContext
244 // Disable interrupts and save current interrupt state
246 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
249 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
254 // Save original CR4 value and clear PGE flag (Bit 7)
256 MtrrContext
->Cr4
= AsmReadCr4 ();
257 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
267 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
271 Cleaning up after programming MTRRs.
273 This function will do some clean up after programming MTRRs:
274 Flush all TLBs, re-enable caching, restore CR4.
276 @param[in] MtrrContext Pointer to context to restore
280 PostMtrrChangeEnableCache (
281 IN MTRR_CONTEXT
*MtrrContext
290 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
295 // Restore original CR4 value
297 AsmWriteCr4 (MtrrContext
->Cr4
);
300 // Restore original interrupt state
302 SetInterruptState (MtrrContext
->InterruptState
);
306 Cleaning up after programming MTRRs.
308 This function will do some clean up after programming MTRRs:
309 enable MTRR caching functionality, and enable cache
311 @param[in] MtrrContext Pointer to context to restore
316 IN MTRR_CONTEXT
*MtrrContext
322 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
324 PostMtrrChangeEnableCache (MtrrContext
);
328 Worker function gets the content in fixed MTRRs
330 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
332 @retval The pointer of FixedSettings
336 MtrrGetFixedMtrrWorker (
337 OUT MTRR_FIXED_SETTINGS
*FixedSettings
342 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
343 FixedSettings
->Mtrr
[Index
] =
344 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
347 return FixedSettings
;
352 This function gets the content in fixed MTRRs
354 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
356 @retval The pointer of FixedSettings
362 OUT MTRR_FIXED_SETTINGS
*FixedSettings
365 if (!IsMtrrSupported ()) {
366 return FixedSettings
;
369 return MtrrGetFixedMtrrWorker (FixedSettings
);
374 Worker function will get the raw value in variable MTRRs
376 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
377 MTRR settings buffer.
378 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
380 @param[in] MtrrSetting A buffer holding all MTRRs content.
381 @param[in] VariableMtrrCount Number of variable MTRRs.
382 @param[out] VariableSettings A buffer to hold variable MTRRs content.
384 @return The VariableSettings input pointer
387 MTRR_VARIABLE_SETTINGS
*
388 MtrrGetVariableMtrrWorker (
389 IN MTRR_SETTINGS
*MtrrSetting
,
390 IN UINT32 VariableMtrrCount
,
391 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
396 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
398 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
399 if (MtrrSetting
== NULL
) {
400 VariableSettings
->Mtrr
[Index
].Base
=
401 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
402 VariableSettings
->Mtrr
[Index
].Mask
=
403 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
405 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
406 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
410 return VariableSettings
;
414 This function will get the raw value in variable MTRRs
416 @param[out] VariableSettings A buffer to hold variable MTRRs content.
418 @return The VariableSettings input pointer
421 MTRR_VARIABLE_SETTINGS
*
423 MtrrGetVariableMtrr (
424 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
427 if (!IsMtrrSupported ()) {
428 return VariableSettings
;
431 return MtrrGetVariableMtrrWorker (
433 GetVariableMtrrCountWorker (),
439 Programs fixed MTRRs registers.
441 @param[in] MemoryCacheType The memory type to set.
442 @param[in, out] Base The base address of memory range.
443 @param[in, out] Length The length of memory range.
444 @param[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.
445 On return, the current index of the fixed MTRR MSR to program.
446 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
447 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
449 @retval RETURN_SUCCESS The cache type was updated successfully
450 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
456 IN UINT64 MemoryCacheType
,
458 IN OUT UINT64
*Length
,
459 IN OUT UINT32
*LastMsrNum
,
460 OUT UINT64
*ReturnClearMask
,
461 OUT UINT64
*ReturnOrMask
470 *(UINT64
*)OrMask
= 0;
471 *(UINT64
*)ClearMask
= 0;
473 for (MsrNum
= *LastMsrNum
+ 1; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
474 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
477 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
478 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
486 if (MsrNum
>= MTRR_NUMBER_OF_FIXED_MTRR
) {
487 return RETURN_UNSUPPORTED
;
491 // We found the fixed MTRR to be programmed
493 ByteShift
= ((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
)
494 / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
496 if (ByteShift
>= 8) {
497 return RETURN_UNSUPPORTED
;
501 OrMask
[0] = OR_SEED
* (UINT32
)MemoryCacheType
;
502 ClearMask
[0] = CLEAR_SEED
;
503 OrMask
[1] = (OR_SEED
* (UINT32
)MemoryCacheType
) >> ((4 - ByteShift
) * 8);
504 ClearMask
[1] = CLEAR_SEED
>> ((4 - ByteShift
) * 8);
506 OrMask
[0] = (OR_SEED
* (UINT32
)MemoryCacheType
) >> ((8 - ByteShift
) * 8);
507 ClearMask
[0] = CLEAR_SEED
>> ((8 - ByteShift
) * 8);
510 SubLength
= mMtrrLibFixedMtrrTable
[MsrNum
].Length
* (8 - ByteShift
);
511 if (*Length
< SubLength
) {
512 return RETURN_UNSUPPORTED
;
515 *Length
-= SubLength
;
518 *LastMsrNum
= MsrNum
;
519 *ReturnClearMask
= *(UINT64
*)ClearMask
;
520 *ReturnOrMask
= *(UINT64
*)OrMask
;
522 return RETURN_SUCCESS
;
527 Worker function gets the attribute of variable MTRRs.
529 This function shadows the content of variable MTRRs into an
530 internal array: VariableMtrr.
532 @param[in] VariableSettings The variable MTRR values to shadow
533 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
534 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
535 @param[in] MtrrValidAddressMask The valid address mask for MTRR
536 @param[out] VariableMtrr The array to shadow variable MTRRs content
538 @return The return value of this parameter indicates the
539 number of MTRRs which has been used.
543 MtrrGetMemoryAttributeInVariableMtrrWorker (
544 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
545 IN UINTN FirmwareVariableMtrrCount
,
546 IN UINT64 MtrrValidBitsMask
,
547 IN UINT64 MtrrValidAddressMask
,
548 OUT VARIABLE_MTRR
*VariableMtrr
554 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
555 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
556 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
557 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
558 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
559 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
560 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
561 VariableMtrr
[Index
].Valid
= TRUE
;
562 VariableMtrr
[Index
].Used
= TRUE
;
571 Gets the attribute of variable MTRRs.
573 This function shadows the content of variable MTRRs into an
574 internal array: VariableMtrr.
576 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
577 @param[in] MtrrValidAddressMask The valid address mask for MTRR
578 @param[out] VariableMtrr The array to shadow variable MTRRs content
580 @return The return value of this paramter indicates the
581 number of MTRRs which has been used.
586 MtrrGetMemoryAttributeInVariableMtrr (
587 IN UINT64 MtrrValidBitsMask
,
588 IN UINT64 MtrrValidAddressMask
,
589 OUT VARIABLE_MTRR
*VariableMtrr
592 MTRR_VARIABLE_SETTINGS VariableSettings
;
594 if (!IsMtrrSupported ()) {
598 MtrrGetVariableMtrrWorker (
600 GetVariableMtrrCountWorker (),
604 return MtrrGetMemoryAttributeInVariableMtrrWorker (
606 GetFirmwareVariableMtrrCountWorker (),
608 MtrrValidAddressMask
,
615 Checks overlap between given memory range and MTRRs.
617 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
619 @param[in] Start The start address of memory range.
620 @param[in] End The end address of memory range.
621 @param[in] VariableMtrr The array to shadow variable MTRRs content
623 @retval TRUE Overlap exists.
624 @retval FALSE No overlap.
628 CheckMemoryAttributeOverlap (
629 IN UINTN FirmwareVariableMtrrCount
,
630 IN PHYSICAL_ADDRESS Start
,
631 IN PHYSICAL_ADDRESS End
,
632 IN VARIABLE_MTRR
*VariableMtrr
637 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
639 VariableMtrr
[Index
].Valid
&&
641 (Start
> (VariableMtrr
[Index
].BaseAddress
+
642 VariableMtrr
[Index
].Length
- 1)
644 (End
< VariableMtrr
[Index
].BaseAddress
)
656 Marks a variable MTRR as non-valid.
658 @param[in] Index The index of the array VariableMtrr to be invalidated
659 @param[in] VariableMtrr The array to shadow variable MTRRs content
660 @param[out] UsedMtrr The number of MTRRs which has already been used
664 InvalidateShadowMtrr (
666 IN VARIABLE_MTRR
*VariableMtrr
,
670 VariableMtrr
[Index
].Valid
= FALSE
;
671 *UsedMtrr
= *UsedMtrr
- 1;
676 Combines memory attributes.
678 If overlap exists between given memory range and MTRRs, try to combine them.
680 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
681 available to firmware.
682 @param[in] Attributes The memory type to set.
683 @param[in, out] Base The base address of memory range.
684 @param[in, out] Length The length of memory range.
685 @param[in] VariableMtrr The array to shadow variable MTRRs content
686 @param[in, out] UsedMtrr The number of MTRRs which has already been used
687 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
689 @retval EFI_SUCCESS Memory region successfully combined.
690 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
694 CombineMemoryAttribute (
695 IN UINT32 FirmwareVariableMtrrCount
,
696 IN UINT64 Attributes
,
698 IN OUT UINT64
*Length
,
699 IN VARIABLE_MTRR
*VariableMtrr
,
700 IN OUT UINT32
*UsedMtrr
,
701 OUT BOOLEAN
*OverwriteExistingMtrr
709 BOOLEAN CoveredByExistingMtrr
;
711 *OverwriteExistingMtrr
= FALSE
;
712 CoveredByExistingMtrr
= FALSE
;
713 EndAddress
= *Base
+*Length
- 1;
715 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
717 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
719 !VariableMtrr
[Index
].Valid
||
722 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
729 // Combine same attribute MTRR range
731 if (Attributes
== VariableMtrr
[Index
].Type
) {
733 // if the MTRR range contain the request range, set a flag, then continue to
734 // invalidate any MTRR of the same request range with higher priority cache type.
736 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
737 CoveredByExistingMtrr
= TRUE
;
741 // invalid this MTRR, and program the combine range
744 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
746 VariableMtrr
[Index
].BaseAddress
;
747 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
750 // Record the MTRR usage status in VariableMtrr array.
752 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
753 *Base
= CombineStart
;
754 *Length
= CombineEnd
- CombineStart
+ 1;
755 EndAddress
= CombineEnd
;
756 *OverwriteExistingMtrr
= TRUE
;
760 // The cache type is different, but the range is convered by one MTRR
762 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
763 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
769 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
770 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
771 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
772 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
773 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
774 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
776 *OverwriteExistingMtrr
= TRUE
;
780 // Other type memory overlap is invalid
782 return RETURN_ACCESS_DENIED
;
785 if (CoveredByExistingMtrr
) {
789 return RETURN_SUCCESS
;
794 Calculates the maximum value which is a power of 2, but less the MemoryLength.
796 @param[in] MemoryLength The number to pass in.
798 @return The maximum value which is align to power of 2 and less the MemoryLength
803 IN UINT64 MemoryLength
808 if (RShiftU64 (MemoryLength
, 32) != 0) {
810 (UINT64
) GetPowerOfTwo32 (
811 (UINT32
) RShiftU64 (MemoryLength
, 32)
816 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
824 Determines the MTRR numbers used to program a memory range.
826 This function first checks the alignment of the base address.
827 If the alignment of the base address <= Length, cover the memory range
828 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
829 Length -= alignment. Repeat the step until alignment > Length.
831 Then this function determines which direction of programming the variable
832 MTRRs for the remaining length will use fewer MTRRs.
834 @param[in] BaseAddress Length of Memory to program MTRR
835 @param[in] Length Length of Memory to program MTRR
836 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
838 @retval TRUE Positive direction is better.
839 FALSE Negative direction is better.
843 GetMtrrNumberAndDirection (
844 IN UINT64 BaseAddress
,
856 if (BaseAddress
!= 0) {
859 // Calculate the alignment of the base address.
861 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
863 if (Alignment
> Length
) {
868 BaseAddress
+= Alignment
;
882 TempQword
-= Power2MaxMemory (TempQword
);
884 } while (TempQword
!= 0);
886 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
889 TempQword
-= Power2MaxMemory (TempQword
);
891 } while (TempQword
!= 0);
893 if (Positive
<= Subtractive
) {
894 *MtrrNumber
+= Positive
;
897 *MtrrNumber
+= Subtractive
;
903 Invalid variable MTRRs according to the value in the shadow array.
905 This function programs MTRRs according to the values specified
908 @param[in, out] VariableSettings Variable MTRR settings
909 @param[in] VariableMtrrCount Number of variable MTRRs
910 @param[in, out] VariableMtrr Shadow of variable MTRR contents
915 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
916 IN UINTN VariableMtrrCount
,
917 IN OUT VARIABLE_MTRR
*VariableMtrr
922 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
923 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
924 VariableSettings
->Mtrr
[Index
].Base
= 0;
925 VariableSettings
->Mtrr
[Index
].Mask
= 0;
926 VariableMtrr
[Index
].Used
= FALSE
;
933 Programs variable MTRRs
935 This function programs variable MTRRs
937 @param[in, out] VariableSettings Variable MTRR settings.
938 @param[in] MtrrNumber Index of MTRR to program.
939 @param[in] BaseAddress Base address of memory region.
940 @param[in] Length Length of memory region.
941 @param[in] MemoryCacheType Memory type to set.
942 @param[in] MtrrValidAddressMask The valid address mask for MTRR
946 ProgramVariableMtrr (
947 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
949 IN PHYSICAL_ADDRESS BaseAddress
,
951 IN UINT64 MemoryCacheType
,
952 IN UINT64 MtrrValidAddressMask
958 // MTRR Physical Base
960 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
961 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
964 // MTRR Physical Mask
966 TempQword
= ~(Length
- 1);
967 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
972 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
974 If MtrrSetting is not NULL, gets the default memory attribute from input
975 MTRR settings buffer.
976 If MtrrSetting is NULL, gets the default memory attribute from MSR.
978 @param[in] MtrrSetting A buffer holding all MTRRs content.
979 @param[in] MtrrType MTRR memory type
981 @return The enum item in MTRR_MEMORY_CACHE_TYPE
984 MTRR_MEMORY_CACHE_TYPE
985 GetMemoryCacheTypeFromMtrrType (
986 IN MTRR_SETTINGS
*MtrrSetting
,
991 case MTRR_CACHE_UNCACHEABLE
:
992 return CacheUncacheable
;
993 case MTRR_CACHE_WRITE_COMBINING
:
994 return CacheWriteCombining
;
995 case MTRR_CACHE_WRITE_THROUGH
:
996 return CacheWriteThrough
;
997 case MTRR_CACHE_WRITE_PROTECTED
:
998 return CacheWriteProtected
;
999 case MTRR_CACHE_WRITE_BACK
:
1000 return CacheWriteBack
;
1003 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1004 // no MTRR covers the range
1006 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1011 Initializes the valid bits mask and valid address mask for MTRRs.
1013 This function initializes the valid bits mask and valid address mask for MTRRs.
1015 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1016 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1020 MtrrLibInitializeMtrrMask (
1021 OUT UINT64
*MtrrValidBitsMask
,
1022 OUT UINT64
*MtrrValidAddressMask
1026 UINT8 PhysicalAddressBits
;
1028 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1030 if (RegEax
>= 0x80000008) {
1031 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1033 PhysicalAddressBits
= (UINT8
) RegEax
;
1035 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1036 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1038 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1039 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1045 Determines the real attribute of a memory range.
1047 This function is to arbitrate the real attribute of the memory when
1048 there are 2 MTRRs covers the same memory range. For further details,
1049 please refer the IA32 Software Developer's Manual, Volume 3,
1052 @param[in] MtrrType1 The first kind of Memory type
1053 @param[in] MtrrType2 The second kind of memory type
1058 IN UINT64 MtrrType1
,
1064 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1065 switch (MtrrType1
) {
1066 case MTRR_CACHE_UNCACHEABLE
:
1067 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1069 case MTRR_CACHE_WRITE_COMBINING
:
1071 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1072 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1074 MtrrType
= MtrrType2
;
1077 case MTRR_CACHE_WRITE_THROUGH
:
1079 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1080 MtrrType2
==MTRR_CACHE_WRITE_BACK
1082 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1083 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1084 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1087 case MTRR_CACHE_WRITE_PROTECTED
:
1088 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1089 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1090 MtrrType
= MtrrType2
;
1093 case MTRR_CACHE_WRITE_BACK
:
1095 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1096 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1097 MtrrType2
== MTRR_CACHE_WRITE_BACK
1099 MtrrType
= MtrrType2
;
1102 case MTRR_CACHE_INVALID_TYPE
:
1103 MtrrType
= MtrrType2
;
1109 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1110 MtrrType
= MtrrType1
;
1116 Worker function will get the memory cache type of the specific address.
1118 If MtrrSetting is not NULL, gets the memory cache type from input
1119 MTRR settings buffer.
1120 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1122 @param[in] MtrrSetting A buffer holding all MTRRs content.
1123 @param[in] Address The specific address
1125 @return Memory cache type of the specific address
1128 MTRR_MEMORY_CACHE_TYPE
1129 MtrrGetMemoryAttributeByAddressWorker (
1130 IN MTRR_SETTINGS
*MtrrSetting
,
1131 IN PHYSICAL_ADDRESS Address
1138 UINT64 TempMtrrType
;
1139 MTRR_MEMORY_CACHE_TYPE CacheType
;
1140 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1141 UINT64 MtrrValidBitsMask
;
1142 UINT64 MtrrValidAddressMask
;
1143 UINTN VariableMtrrCount
;
1144 MTRR_VARIABLE_SETTINGS VariableSettings
;
1147 // Check if MTRR is enabled, if not, return UC as attribute
1149 if (MtrrSetting
== NULL
) {
1150 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1152 TempQword
= MtrrSetting
->MtrrDefType
;
1154 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1156 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1157 return CacheUncacheable
;
1161 // If address is less than 1M, then try to go through the fixed MTRR
1163 if (Address
< BASE_1MB
) {
1164 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1166 // Go through the fixed MTRR
1168 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1169 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1171 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1172 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1176 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1177 mMtrrLibFixedMtrrTable
[Index
].Length
;
1178 if (MtrrSetting
== NULL
) {
1179 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1181 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1183 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1184 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1189 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1191 MtrrGetVariableMtrrWorker (
1193 GetVariableMtrrCountWorker (),
1197 MtrrGetMemoryAttributeInVariableMtrrWorker (
1199 GetFirmwareVariableMtrrCountWorker (),
1201 MtrrValidAddressMask
,
1206 // Go through the variable MTRR
1208 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1209 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1211 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1212 if (VariableMtrr
[Index
].Valid
) {
1213 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1214 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1215 TempMtrrType
= VariableMtrr
[Index
].Type
;
1216 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1220 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1227 This function will get the memory cache type of the specific address.
1229 This function is mainly for debug purpose.
1231 @param[in] Address The specific address
1233 @return Memory cache type of the specific address
1236 MTRR_MEMORY_CACHE_TYPE
1238 MtrrGetMemoryAttribute (
1239 IN PHYSICAL_ADDRESS Address
1242 if (!IsMtrrSupported ()) {
1243 return CacheUncacheable
;
1246 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1250 Worker function prints all MTRRs for debugging.
1252 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1254 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1256 @param MtrrSetting A buffer holding all MTRRs content.
1259 MtrrDebugPrintAllMtrrsWorker (
1260 IN MTRR_SETTINGS
*MtrrSetting
1264 MTRR_SETTINGS LocalMtrrs
;
1265 MTRR_SETTINGS
*Mtrrs
;
1268 UINTN VariableMtrrCount
;
1276 UINT64 NoRangeLimit
;
1279 UINTN PreviousMemoryType
;
1282 if (!IsMtrrSupported ()) {
1286 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1287 DEBUG((DEBUG_CACHE
, "=============\n"));
1289 if (MtrrSetting
!= NULL
) {
1290 Mtrrs
= MtrrSetting
;
1292 MtrrGetAllMtrrs (&LocalMtrrs
);
1293 Mtrrs
= &LocalMtrrs
;
1296 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1297 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1298 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1301 VariableMtrrCount
= GetVariableMtrrCount ();
1302 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1303 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1305 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1306 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1309 DEBUG((DEBUG_CACHE
, "\n"));
1310 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1311 DEBUG((DEBUG_CACHE
, "====================================\n"));
1314 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1315 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1316 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1317 for (Index1
= 0; Index1
< 8; Index1
++) {
1318 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1319 if (MemoryType
> CacheWriteBack
) {
1320 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1322 if (MemoryType
!= PreviousMemoryType
) {
1323 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1324 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1326 PreviousMemoryType
= MemoryType
;
1327 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1329 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1332 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1334 VariableMtrrCount
= GetVariableMtrrCount ();
1337 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1338 if (RegEax
>= 0x80000008) {
1339 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1340 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1343 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1345 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1346 if (MemoryType
> CacheWriteBack
) {
1347 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1350 if (MemoryType
!= PreviousMemoryType
) {
1351 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1352 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1354 PreviousMemoryType
= MemoryType
;
1355 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1358 RangeBase
= BASE_1MB
;
1359 NoRangeBase
= BASE_1MB
;
1361 NoRangeLimit
= Limit
;
1363 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1364 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1366 // If mask is not valid, then do not display range
1370 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1371 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1373 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1377 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1378 RangeBase
= MtrrBase
;
1380 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1381 RangeBase
= MtrrLimit
+ 1;
1383 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1384 RangeLimit
= MtrrBase
- 1;
1386 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1387 RangeLimit
= MtrrLimit
;
1390 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1391 NoRangeBase
= MtrrLimit
+ 1;
1393 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1394 NoRangeLimit
= MtrrBase
- 1;
1399 Base
= RangeLimit
+ 1;
1401 Base
= NoRangeLimit
+ 1;
1403 } while (Base
< Limit
);
1404 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1410 This function prints all MTRRs for debugging.
1414 MtrrDebugPrintAllMtrrs (
1418 MtrrDebugPrintAllMtrrsWorker (NULL
);
1423 Worker function attempts to set the attributes for a memory range.
1425 If MtrrSettings is not NULL, set the attributes into the input MTRR
1427 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1429 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1430 @param[in] BaseAddress The physical address that is the start
1431 address of a memory region.
1432 @param[in] Length The size in bytes of the memory region.
1433 @param[in] Attribute The bit mask of attributes to set for the
1436 @retval RETURN_SUCCESS The attributes were set for the memory
1438 @retval RETURN_INVALID_PARAMETER Length is zero.
1439 @retval RETURN_UNSUPPORTED The processor does not support one or
1440 more bytes of the memory resource range
1441 specified by BaseAddress and Length.
1442 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1443 for the memory resource range specified
1444 by BaseAddress and Length.
1445 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1446 range specified by BaseAddress and Length
1448 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1449 modify the attributes of the memory
1454 MtrrSetMemoryAttributeWorker (
1455 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1456 IN PHYSICAL_ADDRESS BaseAddress
,
1458 IN MTRR_MEMORY_CACHE_TYPE Attribute
1462 RETURN_STATUS Status
;
1469 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1471 UINT64 MtrrValidBitsMask
;
1472 UINT64 MtrrValidAddressMask
;
1473 BOOLEAN OverwriteExistingMtrr
;
1474 UINT32 FirmwareVariableMtrrCount
;
1475 MTRR_CONTEXT MtrrContext
;
1476 BOOLEAN MtrrContextValid
;
1477 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1478 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1479 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1480 UINT32 VariableMtrrCount
;
1481 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1482 BOOLEAN ProgramVariableSettings
;
1483 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1488 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1490 MtrrContextValid
= FALSE
;
1491 VariableMtrrCount
= 0;
1492 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1493 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1494 FixedSettingsValid
[Index
] = FALSE
;
1495 FixedSettingsModified
[Index
] = FALSE
;
1497 ProgramVariableSettings
= FALSE
;
1499 if (!IsMtrrSupported ()) {
1500 Status
= RETURN_UNSUPPORTED
;
1504 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1507 MemoryType
= (UINT64
)Attribute
;
1508 OverwriteExistingMtrr
= FALSE
;
1511 // Check for an invalid parameter
1514 Status
= RETURN_INVALID_PARAMETER
;
1519 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1520 (Length
& ~MtrrValidAddressMask
) != 0
1522 Status
= RETURN_UNSUPPORTED
;
1527 // Check if Fixed MTRR
1529 Status
= RETURN_SUCCESS
;
1530 if (BaseAddress
< BASE_1MB
) {
1531 MsrNum
= (UINT32
)-1;
1532 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1533 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1534 if (RETURN_ERROR (Status
)) {
1537 if (MtrrSetting
!= NULL
) {
1538 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1539 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1541 if (!FixedSettingsValid
[MsrNum
]) {
1542 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1543 FixedSettingsValid
[MsrNum
] = TRUE
;
1545 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1546 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1547 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1548 FixedSettingsModified
[MsrNum
] = TRUE
;
1555 // A Length of 0 can only make sense for fixed MTTR ranges.
1556 // Since we just handled the fixed MTRRs, we can skip the
1557 // variable MTRR section.
1564 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1565 // we can set the base to 0 to save variable MTRRs.
1567 if (BaseAddress
== BASE_1MB
) {
1573 // Read all variable MTRRs
1575 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1576 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1577 if (MtrrSetting
!= NULL
) {
1578 VariableSettings
= &MtrrSetting
->Variables
;
1580 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1581 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1582 ProgramVariableSettings
= TRUE
;
1583 VariableSettings
= &WorkingVariableSettings
;
1587 // Check for overlap
1589 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1591 FirmwareVariableMtrrCount
,
1593 MtrrValidAddressMask
,
1596 OverLap
= CheckMemoryAttributeOverlap (
1597 FirmwareVariableMtrrCount
,
1599 BaseAddress
+ Length
- 1,
1603 Status
= CombineMemoryAttribute (
1604 FirmwareVariableMtrrCount
,
1610 &OverwriteExistingMtrr
1612 if (RETURN_ERROR (Status
)) {
1618 // Combined successfully, invalidate the now-unused MTRRs
1620 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1621 Status
= RETURN_SUCCESS
;
1627 // The memory type is the same with the type specified by
1628 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1630 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1632 // Invalidate the now-unused MTRRs
1634 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1638 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1640 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1641 Status
= RETURN_OUT_OF_RESOURCES
;
1646 // Invalidate the now-unused MTRRs
1648 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1651 // Find first unused MTRR
1653 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1654 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1659 if (BaseAddress
!= 0) {
1662 // Calculate the alignment of the base address.
1664 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1666 if (Alignment
> Length
) {
1673 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1674 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1679 ProgramVariableMtrr (
1685 MtrrValidAddressMask
1687 BaseAddress
+= Alignment
;
1688 Length
-= Alignment
;
1699 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1704 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1705 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1710 ProgramVariableMtrr (
1716 MtrrValidAddressMask
1718 BaseAddress
+= Length
;
1719 TempQword
= Length
- TempQword
;
1720 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1727 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1728 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1733 Length
= Power2MaxMemory (TempQword
);
1735 BaseAddress
-= Length
;
1738 ProgramVariableMtrr (
1744 MtrrValidAddressMask
1748 BaseAddress
+= Length
;
1750 TempQword
-= Length
;
1752 } while (TempQword
> 0);
1757 // Write fixed MTRRs that have been modified
1759 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1760 if (FixedSettingsModified
[Index
]) {
1761 if (!MtrrContextValid
) {
1762 PreMtrrChange (&MtrrContext
);
1763 MtrrContextValid
= TRUE
;
1766 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1767 WorkingFixedSettings
.Mtrr
[Index
]
1773 // Write variable MTRRs
1775 if (ProgramVariableSettings
) {
1776 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1777 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1778 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1779 if (!MtrrContextValid
) {
1780 PreMtrrChange (&MtrrContext
);
1781 MtrrContextValid
= TRUE
;
1784 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1785 WorkingVariableSettings
.Mtrr
[Index
].Base
1788 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1789 WorkingVariableSettings
.Mtrr
[Index
].Mask
1794 if (MtrrContextValid
) {
1795 PostMtrrChange (&MtrrContext
);
1798 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1799 if (!RETURN_ERROR (Status
)) {
1800 if (MtrrSetting
!= NULL
) {
1801 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1803 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1810 This function attempts to set the attributes for a memory range.
1812 @param[in] BaseAddress The physical address that is the start
1813 address of a memory region.
1814 @param[in] Length The size in bytes of the memory region.
1815 @param[in] Attributes The bit mask of attributes to set for the
1818 @retval RETURN_SUCCESS The attributes were set for the memory
1820 @retval RETURN_INVALID_PARAMETER Length is zero.
1821 @retval RETURN_UNSUPPORTED The processor does not support one or
1822 more bytes of the memory resource range
1823 specified by BaseAddress and Length.
1824 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1825 for the memory resource range specified
1826 by BaseAddress and Length.
1827 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1828 range specified by BaseAddress and Length
1830 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1831 modify the attributes of the memory
1837 MtrrSetMemoryAttribute (
1838 IN PHYSICAL_ADDRESS BaseAddress
,
1840 IN MTRR_MEMORY_CACHE_TYPE Attribute
1843 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1844 return MtrrSetMemoryAttributeWorker (
1853 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1855 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1856 @param[in] BaseAddress The physical address that is the start address
1858 @param[in] Length The size in bytes of the memory region.
1859 @param[in] Attribute The bit mask of attributes to set for the
1862 @retval RETURN_SUCCESS The attributes were set for the memory region.
1863 @retval RETURN_INVALID_PARAMETER Length is zero.
1864 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1865 memory resource range specified by BaseAddress and Length.
1866 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1867 range specified by BaseAddress and Length.
1868 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1869 BaseAddress and Length cannot be modified.
1870 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1871 the memory resource range.
1876 MtrrSetMemoryAttributeInMtrrSettings (
1877 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1878 IN PHYSICAL_ADDRESS BaseAddress
,
1880 IN MTRR_MEMORY_CACHE_TYPE Attribute
1883 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1884 return MtrrSetMemoryAttributeWorker (
1893 Worker function setting variable MTRRs
1895 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1899 MtrrSetVariableMtrrWorker (
1900 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1904 UINT32 VariableMtrrCount
;
1906 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1907 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1909 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1911 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1912 VariableSettings
->Mtrr
[Index
].Base
1915 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1916 VariableSettings
->Mtrr
[Index
].Mask
1923 This function sets variable MTRRs
1925 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1927 @return The pointer of VariableSettings
1930 MTRR_VARIABLE_SETTINGS
*
1932 MtrrSetVariableMtrr (
1933 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1936 MTRR_CONTEXT MtrrContext
;
1938 if (!IsMtrrSupported ()) {
1939 return VariableSettings
;
1942 PreMtrrChange (&MtrrContext
);
1943 MtrrSetVariableMtrrWorker (VariableSettings
);
1944 PostMtrrChange (&MtrrContext
);
1945 MtrrDebugPrintAllMtrrs ();
1947 return VariableSettings
;
1951 Worker function setting fixed MTRRs
1953 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1957 MtrrSetFixedMtrrWorker (
1958 IN MTRR_FIXED_SETTINGS
*FixedSettings
1963 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1965 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1966 FixedSettings
->Mtrr
[Index
]
1973 This function sets fixed MTRRs
1975 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1977 @retval The pointer of FixedSettings
1980 MTRR_FIXED_SETTINGS
*
1983 IN MTRR_FIXED_SETTINGS
*FixedSettings
1986 MTRR_CONTEXT MtrrContext
;
1988 if (!IsMtrrSupported ()) {
1989 return FixedSettings
;
1992 PreMtrrChange (&MtrrContext
);
1993 MtrrSetFixedMtrrWorker (FixedSettings
);
1994 PostMtrrChange (&MtrrContext
);
1995 MtrrDebugPrintAllMtrrs ();
1997 return FixedSettings
;
2002 This function gets the content in all MTRRs (variable and fixed)
2004 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2006 @retval the pointer of MtrrSetting
2012 OUT MTRR_SETTINGS
*MtrrSetting
2015 if (!IsMtrrSupported ()) {
2022 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2025 // Get variable MTRRs
2027 MtrrGetVariableMtrrWorker (
2029 GetVariableMtrrCountWorker (),
2030 &MtrrSetting
->Variables
2034 // Get MTRR_DEF_TYPE value
2036 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2043 This function sets all MTRRs (variable and fixed)
2045 @param[in] MtrrSetting A buffer holding all MTRRs content.
2047 @retval The pointer of MtrrSetting
2053 IN MTRR_SETTINGS
*MtrrSetting
2056 MTRR_CONTEXT MtrrContext
;
2058 if (!IsMtrrSupported ()) {
2062 PreMtrrChange (&MtrrContext
);
2067 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2070 // Set variable MTRRs
2072 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2075 // Set MTRR_DEF_TYPE value
2077 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2079 PostMtrrChangeEnableCache (&MtrrContext
);
2081 MtrrDebugPrintAllMtrrs ();
2088 Checks if MTRR is supported.
2090 @retval TRUE MTRR is supported.
2091 @retval FALSE MTRR is not supported.
2104 // Check CPUID(1).EDX[12] for MTRR capability
2106 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
2107 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
2112 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2113 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2114 // exist, return false.
2116 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
2117 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {