5 Most of services in this library instance are suggested to be invoked by BSP only,
6 except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.
8 Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
9 This program and the accompanying materials
10 are licensed and made available under the terms and conditions of the BSD License
11 which accompanies this distribution. The full text of the license may be found at
12 http://opensource.org/licenses/bsd-license.php
14 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
15 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
21 #include <Library/MtrrLib.h>
22 #include <Library/BaseLib.h>
23 #include <Library/CpuLib.h>
24 #include <Library/BaseMemoryLib.h>
25 #include <Library/DebugLib.h>
27 #define OR_SEED 0x0101010101010101ull
28 #define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull
31 // Context to save and restore when MTRRs are programmed
35 BOOLEAN InterruptState
;
39 // This table defines the offset, base and length of the fixed MTRRs
41 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
43 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
48 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
53 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
58 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
63 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
68 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
73 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
78 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
83 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
88 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
93 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
100 // Lookup table used to print MTRRs
102 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
103 "UC", // CacheUncacheable
104 "WC", // CacheWriteCombining
107 "WT", // CacheWriteThrough
108 "WP", // CacheWriteProtected
109 "WB", // CacheWriteBack
114 Worker function returns the variable MTRR count for the CPU.
116 @return Variable MTRR count
120 GetVariableMtrrCountWorker (
124 UINT32 VariableMtrrCount
;
126 VariableMtrrCount
= (UINT32
)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK
);
127 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
128 return VariableMtrrCount
;
132 Returns the variable MTRR count for the CPU.
134 @return Variable MTRR count
139 GetVariableMtrrCount (
143 if (!IsMtrrSupported ()) {
146 return GetVariableMtrrCountWorker ();
150 Worker function returns the firmware usable variable MTRR count for the CPU.
152 @return Firmware usable variable MTRR count
156 GetFirmwareVariableMtrrCountWorker (
160 UINT32 VariableMtrrCount
;
161 UINT32 ReservedMtrrNumber
;
163 VariableMtrrCount
= GetVariableMtrrCountWorker ();
164 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
165 if (VariableMtrrCount
< ReservedMtrrNumber
) {
169 return VariableMtrrCount
- ReservedMtrrNumber
;
173 Returns the firmware usable variable MTRR count for the CPU.
175 @return Firmware usable variable MTRR count
180 GetFirmwareVariableMtrrCount (
184 if (!IsMtrrSupported ()) {
187 return GetFirmwareVariableMtrrCountWorker ();
191 Worker function returns the default MTRR cache type for the system.
193 If MtrrSetting is not NULL, returns the default MTRR cache type from input
194 MTRR settings buffer.
195 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
197 @param[in] MtrrSetting A buffer holding all MTRRs content.
199 @return The default MTRR cache type.
202 MTRR_MEMORY_CACHE_TYPE
203 MtrrGetDefaultMemoryTypeWorker (
204 IN MTRR_SETTINGS
*MtrrSetting
207 if (MtrrSetting
== NULL
) {
208 return (MTRR_MEMORY_CACHE_TYPE
) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0x7);
210 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
216 Returns the default MTRR cache type for the system.
218 @return The default MTRR cache type.
221 MTRR_MEMORY_CACHE_TYPE
223 MtrrGetDefaultMemoryType (
227 if (!IsMtrrSupported ()) {
228 return CacheUncacheable
;
230 return MtrrGetDefaultMemoryTypeWorker (NULL
);
234 Preparation before programming MTRR.
236 This function will do some preparation for programming MTRRs:
237 disable cache, invalid cache and disable MTRR caching functionality
239 @param[out] MtrrContext Pointer to context to save
244 OUT MTRR_CONTEXT
*MtrrContext
248 // Disable interrupts and save current interrupt state
250 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
253 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
258 // Save original CR4 value and clear PGE flag (Bit 7)
260 MtrrContext
->Cr4
= AsmReadCr4 ();
261 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
271 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
275 Cleaning up after programming MTRRs.
277 This function will do some clean up after programming MTRRs:
278 Flush all TLBs, re-enable caching, restore CR4.
280 @param[in] MtrrContext Pointer to context to restore
284 PostMtrrChangeEnableCache (
285 IN MTRR_CONTEXT
*MtrrContext
294 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
299 // Restore original CR4 value
301 AsmWriteCr4 (MtrrContext
->Cr4
);
304 // Restore original interrupt state
306 SetInterruptState (MtrrContext
->InterruptState
);
310 Cleaning up after programming MTRRs.
312 This function will do some clean up after programming MTRRs:
313 enable MTRR caching functionality, and enable cache
315 @param[in] MtrrContext Pointer to context to restore
320 IN MTRR_CONTEXT
*MtrrContext
326 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
328 PostMtrrChangeEnableCache (MtrrContext
);
332 Worker function gets the content in fixed MTRRs
334 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
336 @retval The pointer of FixedSettings
340 MtrrGetFixedMtrrWorker (
341 OUT MTRR_FIXED_SETTINGS
*FixedSettings
346 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
347 FixedSettings
->Mtrr
[Index
] =
348 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
351 return FixedSettings
;
356 This function gets the content in fixed MTRRs
358 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
360 @retval The pointer of FixedSettings
366 OUT MTRR_FIXED_SETTINGS
*FixedSettings
369 if (!IsMtrrSupported ()) {
370 return FixedSettings
;
373 return MtrrGetFixedMtrrWorker (FixedSettings
);
378 Worker function will get the raw value in variable MTRRs
380 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
381 MTRR settings buffer.
382 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
384 @param[in] MtrrSetting A buffer holding all MTRRs content.
385 @param[in] VariableMtrrCount Number of variable MTRRs.
386 @param[out] VariableSettings A buffer to hold variable MTRRs content.
388 @return The VariableSettings input pointer
391 MTRR_VARIABLE_SETTINGS
*
392 MtrrGetVariableMtrrWorker (
393 IN MTRR_SETTINGS
*MtrrSetting
,
394 IN UINT32 VariableMtrrCount
,
395 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
400 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
402 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
403 if (MtrrSetting
== NULL
) {
404 VariableSettings
->Mtrr
[Index
].Base
=
405 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
406 VariableSettings
->Mtrr
[Index
].Mask
=
407 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
409 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
410 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
414 return VariableSettings
;
418 This function will get the raw value in variable MTRRs
420 @param[out] VariableSettings A buffer to hold variable MTRRs content.
422 @return The VariableSettings input pointer
425 MTRR_VARIABLE_SETTINGS
*
427 MtrrGetVariableMtrr (
428 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
431 if (!IsMtrrSupported ()) {
432 return VariableSettings
;
435 return MtrrGetVariableMtrrWorker (
437 GetVariableMtrrCountWorker (),
443 Programs fixed MTRRs registers.
445 @param[in] MemoryCacheType The memory type to set.
446 @param[in, out] Base The base address of memory range.
447 @param[in, out] Length The length of memory range.
448 @param[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.
449 On return, the current index of the fixed MTRR MSR to program.
450 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
451 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
453 @retval RETURN_SUCCESS The cache type was updated successfully
454 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
460 IN UINT64 MemoryCacheType
,
462 IN OUT UINT64
*Length
,
463 IN OUT UINT32
*LastMsrNum
,
464 OUT UINT64
*ReturnClearMask
,
465 OUT UINT64
*ReturnOrMask
469 UINT32 LeftByteShift
;
470 UINT32 RightByteShift
;
476 // Find the fixed MTRR index to be programmed
478 for (MsrNum
= *LastMsrNum
+ 1; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
479 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
482 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
483 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
491 if (MsrNum
>= MTRR_NUMBER_OF_FIXED_MTRR
) {
492 return RETURN_UNSUPPORTED
;
496 // Find the begin offset in fixed MTRR and calculate byte offset of left shift
498 LeftByteShift
= ((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
)
499 / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
501 if (LeftByteShift
>= 8) {
502 return RETURN_UNSUPPORTED
;
506 // Find the end offset in fixed MTRR and calculate byte offset of right shift
508 SubLength
= mMtrrLibFixedMtrrTable
[MsrNum
].Length
* (8 - LeftByteShift
);
509 if (*Length
>= SubLength
) {
512 RightByteShift
= 8 - LeftByteShift
-
513 (UINT32
)(*Length
) / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
514 if ((LeftByteShift
>= 8) ||
515 (((UINT32
)(*Length
) % mMtrrLibFixedMtrrTable
[MsrNum
].Length
) != 0)
517 return RETURN_UNSUPPORTED
;
520 // Update SubLength by actual length
525 ClearMask
= CLEAR_SEED
;
526 OrMask
= MultU64x32 (OR_SEED
, (UINT32
)MemoryCacheType
);
528 if (LeftByteShift
!= 0) {
530 // Clear the low bits by LeftByteShift
532 ClearMask
&= LShiftU64 (ClearMask
, LeftByteShift
* 8);
533 OrMask
&= LShiftU64 (OrMask
, LeftByteShift
* 8);
536 if (RightByteShift
!= 0) {
538 // Clear the high bits by RightByteShift
540 ClearMask
&= RShiftU64 (ClearMask
, RightByteShift
* 8);
541 OrMask
&= RShiftU64 (OrMask
, RightByteShift
* 8);
544 *Length
-= SubLength
;
547 *LastMsrNum
= MsrNum
;
548 *ReturnClearMask
= ClearMask
;
549 *ReturnOrMask
= OrMask
;
551 return RETURN_SUCCESS
;
556 Worker function gets the attribute of variable MTRRs.
558 This function shadows the content of variable MTRRs into an
559 internal array: VariableMtrr.
561 @param[in] VariableSettings The variable MTRR values to shadow
562 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
563 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
564 @param[in] MtrrValidAddressMask The valid address mask for MTRR
565 @param[out] VariableMtrr The array to shadow variable MTRRs content
567 @return The return value of this parameter indicates the
568 number of MTRRs which has been used.
572 MtrrGetMemoryAttributeInVariableMtrrWorker (
573 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
574 IN UINTN FirmwareVariableMtrrCount
,
575 IN UINT64 MtrrValidBitsMask
,
576 IN UINT64 MtrrValidAddressMask
,
577 OUT VARIABLE_MTRR
*VariableMtrr
583 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
584 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
585 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
586 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
587 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
588 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
589 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
590 VariableMtrr
[Index
].Valid
= TRUE
;
591 VariableMtrr
[Index
].Used
= TRUE
;
600 Gets the attribute of variable MTRRs.
602 This function shadows the content of variable MTRRs into an
603 internal array: VariableMtrr.
605 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
606 @param[in] MtrrValidAddressMask The valid address mask for MTRR
607 @param[out] VariableMtrr The array to shadow variable MTRRs content
609 @return The return value of this parameter indicates the
610 number of MTRRs which has been used.
615 MtrrGetMemoryAttributeInVariableMtrr (
616 IN UINT64 MtrrValidBitsMask
,
617 IN UINT64 MtrrValidAddressMask
,
618 OUT VARIABLE_MTRR
*VariableMtrr
621 MTRR_VARIABLE_SETTINGS VariableSettings
;
623 if (!IsMtrrSupported ()) {
627 MtrrGetVariableMtrrWorker (
629 GetVariableMtrrCountWorker (),
633 return MtrrGetMemoryAttributeInVariableMtrrWorker (
635 GetFirmwareVariableMtrrCountWorker (),
637 MtrrValidAddressMask
,
644 Checks overlap between given memory range and MTRRs.
646 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
648 @param[in] Start The start address of memory range.
649 @param[in] End The end address of memory range.
650 @param[in] VariableMtrr The array to shadow variable MTRRs content
652 @retval TRUE Overlap exists.
653 @retval FALSE No overlap.
657 CheckMemoryAttributeOverlap (
658 IN UINTN FirmwareVariableMtrrCount
,
659 IN PHYSICAL_ADDRESS Start
,
660 IN PHYSICAL_ADDRESS End
,
661 IN VARIABLE_MTRR
*VariableMtrr
666 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
668 VariableMtrr
[Index
].Valid
&&
670 (Start
> (VariableMtrr
[Index
].BaseAddress
+
671 VariableMtrr
[Index
].Length
- 1)
673 (End
< VariableMtrr
[Index
].BaseAddress
)
685 Marks a variable MTRR as non-valid.
687 @param[in] Index The index of the array VariableMtrr to be invalidated
688 @param[in] VariableMtrr The array to shadow variable MTRRs content
689 @param[out] UsedMtrr The number of MTRRs which has already been used
693 InvalidateShadowMtrr (
695 IN VARIABLE_MTRR
*VariableMtrr
,
699 VariableMtrr
[Index
].Valid
= FALSE
;
700 *UsedMtrr
= *UsedMtrr
- 1;
705 Combines memory attributes.
707 If overlap exists between given memory range and MTRRs, try to combine them.
709 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
710 available to firmware.
711 @param[in] Attributes The memory type to set.
712 @param[in, out] Base The base address of memory range.
713 @param[in, out] Length The length of memory range.
714 @param[in] VariableMtrr The array to shadow variable MTRRs content
715 @param[in, out] UsedMtrr The number of MTRRs which has already been used
716 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
718 @retval EFI_SUCCESS Memory region successfully combined.
719 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
723 CombineMemoryAttribute (
724 IN UINT32 FirmwareVariableMtrrCount
,
725 IN UINT64 Attributes
,
727 IN OUT UINT64
*Length
,
728 IN VARIABLE_MTRR
*VariableMtrr
,
729 IN OUT UINT32
*UsedMtrr
,
730 OUT BOOLEAN
*OverwriteExistingMtrr
738 BOOLEAN CoveredByExistingMtrr
;
740 *OverwriteExistingMtrr
= FALSE
;
741 CoveredByExistingMtrr
= FALSE
;
742 EndAddress
= *Base
+*Length
- 1;
744 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
746 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
748 !VariableMtrr
[Index
].Valid
||
751 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
758 // Combine same attribute MTRR range
760 if (Attributes
== VariableMtrr
[Index
].Type
) {
762 // if the MTRR range contain the request range, set a flag, then continue to
763 // invalidate any MTRR of the same request range with higher priority cache type.
765 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
766 CoveredByExistingMtrr
= TRUE
;
770 // invalid this MTRR, and program the combine range
773 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
775 VariableMtrr
[Index
].BaseAddress
;
776 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
779 // Record the MTRR usage status in VariableMtrr array.
781 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
782 *Base
= CombineStart
;
783 *Length
= CombineEnd
- CombineStart
+ 1;
784 EndAddress
= CombineEnd
;
785 *OverwriteExistingMtrr
= TRUE
;
789 // The cache type is different, but the range is convered by one MTRR
791 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
792 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
798 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
799 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
800 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
801 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
802 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
803 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
805 *OverwriteExistingMtrr
= TRUE
;
809 // Other type memory overlap is invalid
811 return RETURN_ACCESS_DENIED
;
814 if (CoveredByExistingMtrr
) {
818 return RETURN_SUCCESS
;
823 Calculates the maximum value which is a power of 2, but less the MemoryLength.
825 @param[in] MemoryLength The number to pass in.
827 @return The maximum value which is align to power of 2 and less the MemoryLength
832 IN UINT64 MemoryLength
837 if (RShiftU64 (MemoryLength
, 32) != 0) {
839 (UINT64
) GetPowerOfTwo32 (
840 (UINT32
) RShiftU64 (MemoryLength
, 32)
845 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
853 Determines the MTRR numbers used to program a memory range.
855 This function first checks the alignment of the base address.
856 If the alignment of the base address <= Length, cover the memory range
857 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
858 Length -= alignment. Repeat the step until alignment > Length.
860 Then this function determines which direction of programming the variable
861 MTRRs for the remaining length will use fewer MTRRs.
863 @param[in] BaseAddress Length of Memory to program MTRR
864 @param[in] Length Length of Memory to program MTRR
865 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
867 @retval TRUE Positive direction is better.
868 FALSE Negative direction is better.
872 GetMtrrNumberAndDirection (
873 IN UINT64 BaseAddress
,
885 if (BaseAddress
!= 0) {
888 // Calculate the alignment of the base address.
890 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
892 if (Alignment
> Length
) {
897 BaseAddress
+= Alignment
;
911 TempQword
-= Power2MaxMemory (TempQword
);
913 } while (TempQword
!= 0);
915 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
918 TempQword
-= Power2MaxMemory (TempQword
);
920 } while (TempQword
!= 0);
922 if (Positive
<= Subtractive
) {
923 *MtrrNumber
+= Positive
;
926 *MtrrNumber
+= Subtractive
;
932 Invalid variable MTRRs according to the value in the shadow array.
934 This function programs MTRRs according to the values specified
937 @param[in, out] VariableSettings Variable MTRR settings
938 @param[in] VariableMtrrCount Number of variable MTRRs
939 @param[in, out] VariableMtrr Shadow of variable MTRR contents
944 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
945 IN UINTN VariableMtrrCount
,
946 IN OUT VARIABLE_MTRR
*VariableMtrr
951 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
952 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
953 VariableSettings
->Mtrr
[Index
].Base
= 0;
954 VariableSettings
->Mtrr
[Index
].Mask
= 0;
955 VariableMtrr
[Index
].Used
= FALSE
;
962 Programs variable MTRRs
964 This function programs variable MTRRs
966 @param[in, out] VariableSettings Variable MTRR settings.
967 @param[in] MtrrNumber Index of MTRR to program.
968 @param[in] BaseAddress Base address of memory region.
969 @param[in] Length Length of memory region.
970 @param[in] MemoryCacheType Memory type to set.
971 @param[in] MtrrValidAddressMask The valid address mask for MTRR
975 ProgramVariableMtrr (
976 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
978 IN PHYSICAL_ADDRESS BaseAddress
,
980 IN UINT64 MemoryCacheType
,
981 IN UINT64 MtrrValidAddressMask
987 // MTRR Physical Base
989 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
990 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
993 // MTRR Physical Mask
995 TempQword
= ~(Length
- 1);
996 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
1001 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
1003 If MtrrSetting is not NULL, gets the default memory attribute from input
1004 MTRR settings buffer.
1005 If MtrrSetting is NULL, gets the default memory attribute from MSR.
1007 @param[in] MtrrSetting A buffer holding all MTRRs content.
1008 @param[in] MtrrType MTRR memory type
1010 @return The enum item in MTRR_MEMORY_CACHE_TYPE
1013 MTRR_MEMORY_CACHE_TYPE
1014 GetMemoryCacheTypeFromMtrrType (
1015 IN MTRR_SETTINGS
*MtrrSetting
,
1020 case MTRR_CACHE_UNCACHEABLE
:
1021 return CacheUncacheable
;
1022 case MTRR_CACHE_WRITE_COMBINING
:
1023 return CacheWriteCombining
;
1024 case MTRR_CACHE_WRITE_THROUGH
:
1025 return CacheWriteThrough
;
1026 case MTRR_CACHE_WRITE_PROTECTED
:
1027 return CacheWriteProtected
;
1028 case MTRR_CACHE_WRITE_BACK
:
1029 return CacheWriteBack
;
1032 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1033 // no MTRR covers the range
1035 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1040 Initializes the valid bits mask and valid address mask for MTRRs.
1042 This function initializes the valid bits mask and valid address mask for MTRRs.
1044 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1045 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1049 MtrrLibInitializeMtrrMask (
1050 OUT UINT64
*MtrrValidBitsMask
,
1051 OUT UINT64
*MtrrValidAddressMask
1055 UINT8 PhysicalAddressBits
;
1057 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1059 if (RegEax
>= 0x80000008) {
1060 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1062 PhysicalAddressBits
= (UINT8
) RegEax
;
1064 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1065 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1067 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1068 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1074 Determines the real attribute of a memory range.
1076 This function is to arbitrate the real attribute of the memory when
1077 there are 2 MTRRs covers the same memory range. For further details,
1078 please refer the IA32 Software Developer's Manual, Volume 3,
1081 @param[in] MtrrType1 The first kind of Memory type
1082 @param[in] MtrrType2 The second kind of memory type
1087 IN UINT64 MtrrType1
,
1093 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1094 switch (MtrrType1
) {
1095 case MTRR_CACHE_UNCACHEABLE
:
1096 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1098 case MTRR_CACHE_WRITE_COMBINING
:
1100 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1101 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1103 MtrrType
= MtrrType2
;
1106 case MTRR_CACHE_WRITE_THROUGH
:
1108 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1109 MtrrType2
==MTRR_CACHE_WRITE_BACK
1111 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1112 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1113 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1116 case MTRR_CACHE_WRITE_PROTECTED
:
1117 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1118 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1119 MtrrType
= MtrrType2
;
1122 case MTRR_CACHE_WRITE_BACK
:
1124 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1125 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1126 MtrrType2
== MTRR_CACHE_WRITE_BACK
1128 MtrrType
= MtrrType2
;
1131 case MTRR_CACHE_INVALID_TYPE
:
1132 MtrrType
= MtrrType2
;
1138 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1139 MtrrType
= MtrrType1
;
1145 Worker function will get the memory cache type of the specific address.
1147 If MtrrSetting is not NULL, gets the memory cache type from input
1148 MTRR settings buffer.
1149 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1151 @param[in] MtrrSetting A buffer holding all MTRRs content.
1152 @param[in] Address The specific address
1154 @return Memory cache type of the specific address
1157 MTRR_MEMORY_CACHE_TYPE
1158 MtrrGetMemoryAttributeByAddressWorker (
1159 IN MTRR_SETTINGS
*MtrrSetting
,
1160 IN PHYSICAL_ADDRESS Address
1167 UINT64 TempMtrrType
;
1168 MTRR_MEMORY_CACHE_TYPE CacheType
;
1169 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1170 UINT64 MtrrValidBitsMask
;
1171 UINT64 MtrrValidAddressMask
;
1172 UINTN VariableMtrrCount
;
1173 MTRR_VARIABLE_SETTINGS VariableSettings
;
1176 // Check if MTRR is enabled, if not, return UC as attribute
1178 if (MtrrSetting
== NULL
) {
1179 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1181 TempQword
= MtrrSetting
->MtrrDefType
;
1183 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1185 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1186 return CacheUncacheable
;
1190 // If address is less than 1M, then try to go through the fixed MTRR
1192 if (Address
< BASE_1MB
) {
1193 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1195 // Go through the fixed MTRR
1197 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1198 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1200 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1201 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1205 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1206 mMtrrLibFixedMtrrTable
[Index
].Length
;
1207 if (MtrrSetting
== NULL
) {
1208 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1210 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1212 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1213 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1218 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1220 MtrrGetVariableMtrrWorker (
1222 GetVariableMtrrCountWorker (),
1226 MtrrGetMemoryAttributeInVariableMtrrWorker (
1228 GetFirmwareVariableMtrrCountWorker (),
1230 MtrrValidAddressMask
,
1235 // Go through the variable MTRR
1237 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1238 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1240 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1241 if (VariableMtrr
[Index
].Valid
) {
1242 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1243 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1244 TempMtrrType
= VariableMtrr
[Index
].Type
;
1245 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1249 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1256 This function will get the memory cache type of the specific address.
1258 This function is mainly for debug purpose.
1260 @param[in] Address The specific address
1262 @return Memory cache type of the specific address
1265 MTRR_MEMORY_CACHE_TYPE
1267 MtrrGetMemoryAttribute (
1268 IN PHYSICAL_ADDRESS Address
1271 if (!IsMtrrSupported ()) {
1272 return CacheUncacheable
;
1275 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1279 Worker function prints all MTRRs for debugging.
1281 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1283 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1285 @param MtrrSetting A buffer holding all MTRRs content.
1288 MtrrDebugPrintAllMtrrsWorker (
1289 IN MTRR_SETTINGS
*MtrrSetting
1293 MTRR_SETTINGS LocalMtrrs
;
1294 MTRR_SETTINGS
*Mtrrs
;
1297 UINTN VariableMtrrCount
;
1305 UINT64 NoRangeLimit
;
1308 UINTN PreviousMemoryType
;
1311 if (!IsMtrrSupported ()) {
1315 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1316 DEBUG((DEBUG_CACHE
, "=============\n"));
1318 if (MtrrSetting
!= NULL
) {
1319 Mtrrs
= MtrrSetting
;
1321 MtrrGetAllMtrrs (&LocalMtrrs
);
1322 Mtrrs
= &LocalMtrrs
;
1325 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1326 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1327 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1330 VariableMtrrCount
= GetVariableMtrrCount ();
1331 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1332 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1334 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1335 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1338 DEBUG((DEBUG_CACHE
, "\n"));
1339 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1340 DEBUG((DEBUG_CACHE
, "====================================\n"));
1343 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1344 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1345 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1346 for (Index1
= 0; Index1
< 8; Index1
++) {
1347 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1348 if (MemoryType
> CacheWriteBack
) {
1349 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
));
1358 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1361 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1363 VariableMtrrCount
= GetVariableMtrrCount ();
1366 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1367 if (RegEax
>= 0x80000008) {
1368 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1369 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1372 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1374 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1375 if (MemoryType
> CacheWriteBack
) {
1376 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1379 if (MemoryType
!= PreviousMemoryType
) {
1380 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1381 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1383 PreviousMemoryType
= MemoryType
;
1384 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1387 RangeBase
= BASE_1MB
;
1388 NoRangeBase
= BASE_1MB
;
1390 NoRangeLimit
= Limit
;
1392 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1393 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1395 // If mask is not valid, then do not display range
1399 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1400 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1402 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1406 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1407 RangeBase
= MtrrBase
;
1409 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1410 RangeBase
= MtrrLimit
+ 1;
1412 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1413 RangeLimit
= MtrrBase
- 1;
1415 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1416 RangeLimit
= MtrrLimit
;
1419 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1420 NoRangeBase
= MtrrLimit
+ 1;
1422 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1423 NoRangeLimit
= MtrrBase
- 1;
1428 Base
= RangeLimit
+ 1;
1430 Base
= NoRangeLimit
+ 1;
1432 } while (Base
< Limit
);
1433 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1439 This function prints all MTRRs for debugging.
1443 MtrrDebugPrintAllMtrrs (
1447 MtrrDebugPrintAllMtrrsWorker (NULL
);
1452 Worker function attempts to set the attributes for a memory range.
1454 If MtrrSettings is not NULL, set the attributes into the input MTRR
1456 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1458 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1459 @param[in] BaseAddress The physical address that is the start
1460 address of a memory region.
1461 @param[in] Length The size in bytes of the memory region.
1462 @param[in] Attribute The bit mask of attributes to set for the
1465 @retval RETURN_SUCCESS The attributes were set for the memory
1467 @retval RETURN_INVALID_PARAMETER Length is zero.
1468 @retval RETURN_UNSUPPORTED The processor does not support one or
1469 more bytes of the memory resource range
1470 specified by BaseAddress and Length.
1471 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1472 for the memory resource range specified
1473 by BaseAddress and Length.
1474 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1475 range specified by BaseAddress and Length
1477 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1478 modify the attributes of the memory
1483 MtrrSetMemoryAttributeWorker (
1484 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1485 IN PHYSICAL_ADDRESS BaseAddress
,
1487 IN MTRR_MEMORY_CACHE_TYPE Attribute
1491 RETURN_STATUS Status
;
1498 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1500 UINT64 MtrrValidBitsMask
;
1501 UINT64 MtrrValidAddressMask
;
1502 BOOLEAN OverwriteExistingMtrr
;
1503 UINT32 FirmwareVariableMtrrCount
;
1504 MTRR_CONTEXT MtrrContext
;
1505 BOOLEAN MtrrContextValid
;
1506 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1507 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1508 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1509 UINT32 VariableMtrrCount
;
1510 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1511 BOOLEAN ProgramVariableSettings
;
1512 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1517 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1519 MtrrContextValid
= FALSE
;
1520 VariableMtrrCount
= 0;
1521 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1522 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1523 FixedSettingsValid
[Index
] = FALSE
;
1524 FixedSettingsModified
[Index
] = FALSE
;
1526 ProgramVariableSettings
= FALSE
;
1528 if (!IsMtrrSupported ()) {
1529 Status
= RETURN_UNSUPPORTED
;
1533 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1536 MemoryType
= (UINT64
)Attribute
;
1537 OverwriteExistingMtrr
= FALSE
;
1540 // Check for an invalid parameter
1543 Status
= RETURN_INVALID_PARAMETER
;
1548 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1549 (Length
& ~MtrrValidAddressMask
) != 0
1551 Status
= RETURN_UNSUPPORTED
;
1556 // Check if Fixed MTRR
1558 Status
= RETURN_SUCCESS
;
1559 if (BaseAddress
< BASE_1MB
) {
1560 MsrNum
= (UINT32
)-1;
1561 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1562 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1563 if (RETURN_ERROR (Status
)) {
1566 if (MtrrSetting
!= NULL
) {
1567 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1568 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1570 if (!FixedSettingsValid
[MsrNum
]) {
1571 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1572 FixedSettingsValid
[MsrNum
] = TRUE
;
1574 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1575 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1576 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1577 FixedSettingsModified
[MsrNum
] = TRUE
;
1584 // A Length of 0 can only make sense for fixed MTTR ranges.
1585 // Since we just handled the fixed MTRRs, we can skip the
1586 // variable MTRR section.
1593 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1594 // we can set the base to 0 to save variable MTRRs.
1596 if (BaseAddress
== BASE_1MB
) {
1602 // Read all variable MTRRs
1604 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1605 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1606 if (MtrrSetting
!= NULL
) {
1607 VariableSettings
= &MtrrSetting
->Variables
;
1609 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1610 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1611 ProgramVariableSettings
= TRUE
;
1612 VariableSettings
= &WorkingVariableSettings
;
1616 // Check for overlap
1618 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1620 FirmwareVariableMtrrCount
,
1622 MtrrValidAddressMask
,
1625 OverLap
= CheckMemoryAttributeOverlap (
1626 FirmwareVariableMtrrCount
,
1628 BaseAddress
+ Length
- 1,
1632 Status
= CombineMemoryAttribute (
1633 FirmwareVariableMtrrCount
,
1639 &OverwriteExistingMtrr
1641 if (RETURN_ERROR (Status
)) {
1647 // Combined successfully, invalidate the now-unused MTRRs
1649 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1650 Status
= RETURN_SUCCESS
;
1656 // The memory type is the same with the type specified by
1657 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1659 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1661 // Invalidate the now-unused MTRRs
1663 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1667 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1669 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1670 Status
= RETURN_OUT_OF_RESOURCES
;
1675 // Invalidate the now-unused MTRRs
1677 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1680 // Find first unused MTRR
1682 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1683 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1688 if (BaseAddress
!= 0) {
1691 // Calculate the alignment of the base address.
1693 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1695 if (Alignment
> Length
) {
1702 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1703 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1708 ProgramVariableMtrr (
1714 MtrrValidAddressMask
1716 BaseAddress
+= Alignment
;
1717 Length
-= Alignment
;
1728 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1733 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1734 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1739 ProgramVariableMtrr (
1745 MtrrValidAddressMask
1747 BaseAddress
+= Length
;
1748 TempQword
= Length
- TempQword
;
1749 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1756 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1757 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1762 Length
= Power2MaxMemory (TempQword
);
1764 BaseAddress
-= Length
;
1767 ProgramVariableMtrr (
1773 MtrrValidAddressMask
1777 BaseAddress
+= Length
;
1779 TempQword
-= Length
;
1781 } while (TempQword
> 0);
1786 // Write fixed MTRRs that have been modified
1788 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1789 if (FixedSettingsModified
[Index
]) {
1790 if (!MtrrContextValid
) {
1791 PreMtrrChange (&MtrrContext
);
1792 MtrrContextValid
= TRUE
;
1795 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1796 WorkingFixedSettings
.Mtrr
[Index
]
1802 // Write variable MTRRs
1804 if (ProgramVariableSettings
) {
1805 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1806 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1807 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1808 if (!MtrrContextValid
) {
1809 PreMtrrChange (&MtrrContext
);
1810 MtrrContextValid
= TRUE
;
1813 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1814 WorkingVariableSettings
.Mtrr
[Index
].Base
1817 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1818 WorkingVariableSettings
.Mtrr
[Index
].Mask
1823 if (MtrrContextValid
) {
1824 PostMtrrChange (&MtrrContext
);
1827 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1828 if (!RETURN_ERROR (Status
)) {
1829 if (MtrrSetting
!= NULL
) {
1830 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1832 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1839 This function attempts to set the attributes for a memory range.
1841 @param[in] BaseAddress The physical address that is the start
1842 address of a memory region.
1843 @param[in] Length The size in bytes of the memory region.
1844 @param[in] Attributes The bit mask of attributes to set for the
1847 @retval RETURN_SUCCESS The attributes were set for the memory
1849 @retval RETURN_INVALID_PARAMETER Length is zero.
1850 @retval RETURN_UNSUPPORTED The processor does not support one or
1851 more bytes of the memory resource range
1852 specified by BaseAddress and Length.
1853 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1854 for the memory resource range specified
1855 by BaseAddress and Length.
1856 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1857 range specified by BaseAddress and Length
1859 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1860 modify the attributes of the memory
1866 MtrrSetMemoryAttribute (
1867 IN PHYSICAL_ADDRESS BaseAddress
,
1869 IN MTRR_MEMORY_CACHE_TYPE Attribute
1872 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1873 return MtrrSetMemoryAttributeWorker (
1882 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1884 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1885 @param[in] BaseAddress The physical address that is the start address
1887 @param[in] Length The size in bytes of the memory region.
1888 @param[in] Attribute The bit mask of attributes to set for the
1891 @retval RETURN_SUCCESS The attributes were set for the memory region.
1892 @retval RETURN_INVALID_PARAMETER Length is zero.
1893 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1894 memory resource range specified by BaseAddress and Length.
1895 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1896 range specified by BaseAddress and Length.
1897 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1898 BaseAddress and Length cannot be modified.
1899 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1900 the memory resource range.
1905 MtrrSetMemoryAttributeInMtrrSettings (
1906 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1907 IN PHYSICAL_ADDRESS BaseAddress
,
1909 IN MTRR_MEMORY_CACHE_TYPE Attribute
1912 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1913 return MtrrSetMemoryAttributeWorker (
1922 Worker function setting variable MTRRs
1924 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1928 MtrrSetVariableMtrrWorker (
1929 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1933 UINT32 VariableMtrrCount
;
1935 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1936 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1938 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1940 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1941 VariableSettings
->Mtrr
[Index
].Base
1944 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1945 VariableSettings
->Mtrr
[Index
].Mask
1952 This function sets variable MTRRs
1954 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1956 @return The pointer of VariableSettings
1959 MTRR_VARIABLE_SETTINGS
*
1961 MtrrSetVariableMtrr (
1962 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1965 MTRR_CONTEXT MtrrContext
;
1967 if (!IsMtrrSupported ()) {
1968 return VariableSettings
;
1971 PreMtrrChange (&MtrrContext
);
1972 MtrrSetVariableMtrrWorker (VariableSettings
);
1973 PostMtrrChange (&MtrrContext
);
1974 MtrrDebugPrintAllMtrrs ();
1976 return VariableSettings
;
1980 Worker function setting fixed MTRRs
1982 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1986 MtrrSetFixedMtrrWorker (
1987 IN MTRR_FIXED_SETTINGS
*FixedSettings
1992 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1994 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1995 FixedSettings
->Mtrr
[Index
]
2002 This function sets fixed MTRRs
2004 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
2006 @retval The pointer of FixedSettings
2009 MTRR_FIXED_SETTINGS
*
2012 IN MTRR_FIXED_SETTINGS
*FixedSettings
2015 MTRR_CONTEXT MtrrContext
;
2017 if (!IsMtrrSupported ()) {
2018 return FixedSettings
;
2021 PreMtrrChange (&MtrrContext
);
2022 MtrrSetFixedMtrrWorker (FixedSettings
);
2023 PostMtrrChange (&MtrrContext
);
2024 MtrrDebugPrintAllMtrrs ();
2026 return FixedSettings
;
2031 This function gets the content in all MTRRs (variable and fixed)
2033 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2035 @retval the pointer of MtrrSetting
2041 OUT MTRR_SETTINGS
*MtrrSetting
2044 if (!IsMtrrSupported ()) {
2051 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2054 // Get variable MTRRs
2056 MtrrGetVariableMtrrWorker (
2058 GetVariableMtrrCountWorker (),
2059 &MtrrSetting
->Variables
2063 // Get MTRR_DEF_TYPE value
2065 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2072 This function sets all MTRRs (variable and fixed)
2074 @param[in] MtrrSetting A buffer holding all MTRRs content.
2076 @retval The pointer of MtrrSetting
2082 IN MTRR_SETTINGS
*MtrrSetting
2085 MTRR_CONTEXT MtrrContext
;
2087 if (!IsMtrrSupported ()) {
2091 PreMtrrChange (&MtrrContext
);
2096 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2099 // Set variable MTRRs
2101 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2104 // Set MTRR_DEF_TYPE value
2106 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2108 PostMtrrChangeEnableCache (&MtrrContext
);
2115 Checks if MTRR is supported.
2117 @retval TRUE MTRR is supported.
2118 @retval FALSE MTRR is not supported.
2131 // Check CPUID(1).EDX[12] for MTRR capability
2133 AsmCpuid (1, NULL
, NULL
, NULL
, &RegEdx
);
2134 if (BitFieldRead32 (RegEdx
, 12, 12) == 0) {
2139 // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for
2140 // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not
2141 // exist, return false.
2143 MtrrCap
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP
);
2144 if ((BitFieldRead64 (MtrrCap
, 0, 7) == 0) || (BitFieldRead64 (MtrrCap
, 8, 8) == 0)) {