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 - 2017, 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 <Register/Cpuid.h>
22 #include <Register/Msr.h>
24 #include <Library/MtrrLib.h>
25 #include <Library/BaseLib.h>
26 #include <Library/CpuLib.h>
27 #include <Library/BaseMemoryLib.h>
28 #include <Library/DebugLib.h>
30 #define OR_SEED 0x0101010101010101ull
31 #define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull
34 // Context to save and restore when MTRRs are programmed
38 BOOLEAN InterruptState
;
42 // This table defines the offset, base and length of the fixed MTRRs
44 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
46 MTRR_LIB_IA32_MTRR_FIX64K_00000
,
51 MTRR_LIB_IA32_MTRR_FIX16K_80000
,
56 MTRR_LIB_IA32_MTRR_FIX16K_A0000
,
61 MTRR_LIB_IA32_MTRR_FIX4K_C0000
,
66 MTRR_LIB_IA32_MTRR_FIX4K_C8000
,
71 MTRR_LIB_IA32_MTRR_FIX4K_D0000
,
76 MTRR_LIB_IA32_MTRR_FIX4K_D8000
,
81 MTRR_LIB_IA32_MTRR_FIX4K_E0000
,
86 MTRR_LIB_IA32_MTRR_FIX4K_E8000
,
91 MTRR_LIB_IA32_MTRR_FIX4K_F0000
,
96 MTRR_LIB_IA32_MTRR_FIX4K_F8000
,
103 // Lookup table used to print MTRRs
105 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
106 "UC", // CacheUncacheable
107 "WC", // CacheWriteCombining
110 "WT", // CacheWriteThrough
111 "WP", // CacheWriteProtected
112 "WB", // CacheWriteBack
117 Worker function returns the variable MTRR count for the CPU.
119 @return Variable MTRR count
123 GetVariableMtrrCountWorker (
127 MSR_IA32_MTRRCAP_REGISTER MtrrCap
;
129 MtrrCap
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRRCAP
);
130 ASSERT (MtrrCap
.Bits
.VCNT
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
131 return MtrrCap
.Bits
.VCNT
;
135 Returns the variable MTRR count for the CPU.
137 @return Variable MTRR count
142 GetVariableMtrrCount (
146 if (!IsMtrrSupported ()) {
149 return GetVariableMtrrCountWorker ();
153 Worker function returns the firmware usable variable MTRR count for the CPU.
155 @return Firmware usable variable MTRR count
159 GetFirmwareVariableMtrrCountWorker (
163 UINT32 VariableMtrrCount
;
164 UINT32 ReservedMtrrNumber
;
166 VariableMtrrCount
= GetVariableMtrrCountWorker ();
167 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
168 if (VariableMtrrCount
< ReservedMtrrNumber
) {
172 return VariableMtrrCount
- ReservedMtrrNumber
;
176 Returns the firmware usable variable MTRR count for the CPU.
178 @return Firmware usable variable MTRR count
183 GetFirmwareVariableMtrrCount (
187 if (!IsMtrrSupported ()) {
190 return GetFirmwareVariableMtrrCountWorker ();
194 Worker function returns the default MTRR cache type for the system.
196 If MtrrSetting is not NULL, returns the default MTRR cache type from input
197 MTRR settings buffer.
198 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
200 @param[in] MtrrSetting A buffer holding all MTRRs content.
202 @return The default MTRR cache type.
205 MTRR_MEMORY_CACHE_TYPE
206 MtrrGetDefaultMemoryTypeWorker (
207 IN MTRR_SETTINGS
*MtrrSetting
210 if (MtrrSetting
== NULL
) {
211 return (MTRR_MEMORY_CACHE_TYPE
) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
) & 0x7);
213 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
219 Returns the default MTRR cache type for the system.
221 @return The default MTRR cache type.
224 MTRR_MEMORY_CACHE_TYPE
226 MtrrGetDefaultMemoryType (
230 if (!IsMtrrSupported ()) {
231 return CacheUncacheable
;
233 return MtrrGetDefaultMemoryTypeWorker (NULL
);
237 Preparation before programming MTRR.
239 This function will do some preparation for programming MTRRs:
240 disable cache, invalid cache and disable MTRR caching functionality
242 @param[out] MtrrContext Pointer to context to save
246 MtrrLibPreMtrrChange (
247 OUT MTRR_CONTEXT
*MtrrContext
251 // Disable interrupts and save current interrupt state
253 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
256 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
261 // Save original CR4 value and clear PGE flag (Bit 7)
263 MtrrContext
->Cr4
= AsmReadCr4 ();
264 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
274 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
278 Cleaning up after programming MTRRs.
280 This function will do some clean up after programming MTRRs:
281 Flush all TLBs, re-enable caching, restore CR4.
283 @param[in] MtrrContext Pointer to context to restore
287 MtrrLibPostMtrrChangeEnableCache (
288 IN MTRR_CONTEXT
*MtrrContext
297 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
302 // Restore original CR4 value
304 AsmWriteCr4 (MtrrContext
->Cr4
);
307 // Restore original interrupt state
309 SetInterruptState (MtrrContext
->InterruptState
);
313 Cleaning up after programming MTRRs.
315 This function will do some clean up after programming MTRRs:
316 enable MTRR caching functionality, and enable cache
318 @param[in] MtrrContext Pointer to context to restore
322 MtrrLibPostMtrrChange (
323 IN MTRR_CONTEXT
*MtrrContext
329 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
331 MtrrLibPostMtrrChangeEnableCache (MtrrContext
);
335 Worker function gets the content in fixed MTRRs
337 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
339 @retval The pointer of FixedSettings
343 MtrrGetFixedMtrrWorker (
344 OUT MTRR_FIXED_SETTINGS
*FixedSettings
349 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
350 FixedSettings
->Mtrr
[Index
] =
351 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
354 return FixedSettings
;
359 This function gets the content in fixed MTRRs
361 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
363 @retval The pointer of FixedSettings
369 OUT MTRR_FIXED_SETTINGS
*FixedSettings
372 if (!IsMtrrSupported ()) {
373 return FixedSettings
;
376 return MtrrGetFixedMtrrWorker (FixedSettings
);
381 Worker function will get the raw value in variable MTRRs
383 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
384 MTRR settings buffer.
385 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
387 @param[in] MtrrSetting A buffer holding all MTRRs content.
388 @param[in] VariableMtrrCount Number of variable MTRRs.
389 @param[out] VariableSettings A buffer to hold variable MTRRs content.
391 @return The VariableSettings input pointer
394 MTRR_VARIABLE_SETTINGS
*
395 MtrrGetVariableMtrrWorker (
396 IN MTRR_SETTINGS
*MtrrSetting
,
397 IN UINT32 VariableMtrrCount
,
398 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
403 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
405 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
406 if (MtrrSetting
== NULL
) {
407 VariableSettings
->Mtrr
[Index
].Base
=
408 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1));
409 VariableSettings
->Mtrr
[Index
].Mask
=
410 AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1);
412 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
413 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
417 return VariableSettings
;
421 This function will get the raw value in variable MTRRs
423 @param[out] VariableSettings A buffer to hold variable MTRRs content.
425 @return The VariableSettings input pointer
428 MTRR_VARIABLE_SETTINGS
*
430 MtrrGetVariableMtrr (
431 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
434 if (!IsMtrrSupported ()) {
435 return VariableSettings
;
438 return MtrrGetVariableMtrrWorker (
440 GetVariableMtrrCountWorker (),
446 Programs fixed MTRRs registers.
448 @param[in] Type The memory type to set.
449 @param[in, out] Base The base address of memory range.
450 @param[in, out] Length The length of memory range.
451 @param[in, out] LastMsrNum On input, the last index of the fixed MTRR MSR to program.
452 On return, the current index of the fixed MTRR MSR to program.
453 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
454 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
456 @retval RETURN_SUCCESS The cache type was updated successfully
457 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
462 MtrrLibProgramFixedMtrr (
463 IN MTRR_MEMORY_CACHE_TYPE Type
,
465 IN OUT UINT64
*Length
,
466 IN OUT UINT32
*LastMsrNum
,
467 OUT UINT64
*ReturnClearMask
,
468 OUT UINT64
*ReturnOrMask
472 UINT32 LeftByteShift
;
473 UINT32 RightByteShift
;
479 // Find the fixed MTRR index to be programmed
481 for (MsrNum
= *LastMsrNum
+ 1; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
482 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
485 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
486 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
494 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
495 return RETURN_UNSUPPORTED
;
499 // Find the begin offset in fixed MTRR and calculate byte offset of left shift
501 LeftByteShift
= ((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
)
502 / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
504 if (LeftByteShift
>= 8) {
505 return RETURN_UNSUPPORTED
;
509 // Find the end offset in fixed MTRR and calculate byte offset of right shift
511 SubLength
= mMtrrLibFixedMtrrTable
[MsrNum
].Length
* (8 - LeftByteShift
);
512 if (*Length
>= SubLength
) {
515 RightByteShift
= 8 - LeftByteShift
-
516 (UINT32
)(*Length
) / mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
517 if ((LeftByteShift
>= 8) ||
518 (((UINT32
)(*Length
) % mMtrrLibFixedMtrrTable
[MsrNum
].Length
) != 0)
520 return RETURN_UNSUPPORTED
;
523 // Update SubLength by actual length
528 ClearMask
= CLEAR_SEED
;
529 OrMask
= MultU64x32 (OR_SEED
, (UINT32
) Type
);
531 if (LeftByteShift
!= 0) {
533 // Clear the low bits by LeftByteShift
535 ClearMask
&= LShiftU64 (ClearMask
, LeftByteShift
* 8);
536 OrMask
&= LShiftU64 (OrMask
, LeftByteShift
* 8);
539 if (RightByteShift
!= 0) {
541 // Clear the high bits by RightByteShift
543 ClearMask
&= RShiftU64 (ClearMask
, RightByteShift
* 8);
544 OrMask
&= RShiftU64 (OrMask
, RightByteShift
* 8);
547 *Length
-= SubLength
;
550 *LastMsrNum
= MsrNum
;
551 *ReturnClearMask
= ClearMask
;
552 *ReturnOrMask
= OrMask
;
554 return RETURN_SUCCESS
;
559 Worker function gets the attribute of variable MTRRs.
561 This function shadows the content of variable MTRRs into an
562 internal array: VariableMtrr.
564 @param[in] VariableSettings The variable MTRR values to shadow
565 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
566 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
567 @param[in] MtrrValidAddressMask The valid address mask for MTRR
568 @param[out] VariableMtrr The array to shadow variable MTRRs content
570 @return The return value of this parameter indicates the
571 number of MTRRs which has been used.
575 MtrrGetMemoryAttributeInVariableMtrrWorker (
576 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
577 IN UINTN FirmwareVariableMtrrCount
,
578 IN UINT64 MtrrValidBitsMask
,
579 IN UINT64 MtrrValidAddressMask
,
580 OUT VARIABLE_MTRR
*VariableMtrr
586 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
587 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
588 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
589 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
590 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
591 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
592 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
593 VariableMtrr
[Index
].Valid
= TRUE
;
594 VariableMtrr
[Index
].Used
= TRUE
;
603 Gets the attribute of variable MTRRs.
605 This function shadows the content of variable MTRRs into an
606 internal array: VariableMtrr.
608 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
609 @param[in] MtrrValidAddressMask The valid address mask for MTRR
610 @param[out] VariableMtrr The array to shadow variable MTRRs content
612 @return The return value of this parameter indicates the
613 number of MTRRs which has been used.
618 MtrrGetMemoryAttributeInVariableMtrr (
619 IN UINT64 MtrrValidBitsMask
,
620 IN UINT64 MtrrValidAddressMask
,
621 OUT VARIABLE_MTRR
*VariableMtrr
624 MTRR_VARIABLE_SETTINGS VariableSettings
;
626 if (!IsMtrrSupported ()) {
630 MtrrGetVariableMtrrWorker (
632 GetVariableMtrrCountWorker (),
636 return MtrrGetMemoryAttributeInVariableMtrrWorker (
638 GetFirmwareVariableMtrrCountWorker (),
640 MtrrValidAddressMask
,
647 Checks overlap between given memory range and MTRRs.
649 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
651 @param[in] Start The start address of memory range.
652 @param[in] End The end address of memory range.
653 @param[in] VariableMtrr The array to shadow variable MTRRs content
655 @retval TRUE Overlap exists.
656 @retval FALSE No overlap.
660 CheckMemoryAttributeOverlap (
661 IN UINTN FirmwareVariableMtrrCount
,
662 IN PHYSICAL_ADDRESS Start
,
663 IN PHYSICAL_ADDRESS End
,
664 IN VARIABLE_MTRR
*VariableMtrr
669 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
671 VariableMtrr
[Index
].Valid
&&
673 (Start
> (VariableMtrr
[Index
].BaseAddress
+
674 VariableMtrr
[Index
].Length
- 1)
676 (End
< VariableMtrr
[Index
].BaseAddress
)
688 Marks a variable MTRR as non-valid.
690 @param[in] Index The index of the array VariableMtrr to be invalidated
691 @param[in] VariableMtrr The array to shadow variable MTRRs content
692 @param[out] UsedMtrr The number of MTRRs which has already been used
696 InvalidateShadowMtrr (
698 IN VARIABLE_MTRR
*VariableMtrr
,
702 VariableMtrr
[Index
].Valid
= FALSE
;
703 *UsedMtrr
= *UsedMtrr
- 1;
708 Combines memory attributes.
710 If overlap exists between given memory range and MTRRs, try to combine them.
712 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
713 available to firmware.
714 @param[in] Attributes The memory type to set.
715 @param[in, out] Base The base address of memory range.
716 @param[in, out] Length The length of memory range.
717 @param[in] VariableMtrr The array to shadow variable MTRRs content
718 @param[in, out] UsedMtrr The number of MTRRs which has already been used
719 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
721 @retval EFI_SUCCESS Memory region successfully combined.
722 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
726 CombineMemoryAttribute (
727 IN UINT32 FirmwareVariableMtrrCount
,
728 IN UINT64 Attributes
,
730 IN OUT UINT64
*Length
,
731 IN VARIABLE_MTRR
*VariableMtrr
,
732 IN OUT UINT32
*UsedMtrr
,
733 OUT BOOLEAN
*OverwriteExistingMtrr
741 BOOLEAN CoveredByExistingMtrr
;
743 *OverwriteExistingMtrr
= FALSE
;
744 CoveredByExistingMtrr
= FALSE
;
745 EndAddress
= *Base
+*Length
- 1;
747 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
749 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
751 !VariableMtrr
[Index
].Valid
||
754 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
761 // Combine same attribute MTRR range
763 if (Attributes
== VariableMtrr
[Index
].Type
) {
765 // if the MTRR range contain the request range, set a flag, then continue to
766 // invalidate any MTRR of the same request range with higher priority cache type.
768 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
769 CoveredByExistingMtrr
= TRUE
;
773 // invalid this MTRR, and program the combine range
776 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
778 VariableMtrr
[Index
].BaseAddress
;
779 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
782 // Record the MTRR usage status in VariableMtrr array.
784 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
785 *Base
= CombineStart
;
786 *Length
= CombineEnd
- CombineStart
+ 1;
787 EndAddress
= CombineEnd
;
788 *OverwriteExistingMtrr
= TRUE
;
792 // The cache type is different, but the range is covered by one MTRR
794 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
795 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
801 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
802 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
803 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
804 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
805 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
806 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
808 *OverwriteExistingMtrr
= TRUE
;
812 // Other type memory overlap is invalid
814 return RETURN_ACCESS_DENIED
;
817 if (CoveredByExistingMtrr
) {
821 return RETURN_SUCCESS
;
826 Calculates the maximum value which is a power of 2, but less the MemoryLength.
828 @param[in] MemoryLength The number to pass in.
830 @return The maximum value which is align to power of 2 and less the MemoryLength
835 IN UINT64 MemoryLength
840 if (RShiftU64 (MemoryLength
, 32) != 0) {
842 (UINT64
) GetPowerOfTwo32 (
843 (UINT32
) RShiftU64 (MemoryLength
, 32)
848 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
856 Determines the MTRR numbers used to program a memory range.
858 This function first checks the alignment of the base address.
859 If the alignment of the base address <= Length, cover the memory range
860 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
861 Length -= alignment. Repeat the step until alignment > Length.
863 Then this function determines which direction of programming the variable
864 MTRRs for the remaining length will use fewer MTRRs.
866 @param[in] BaseAddress Length of Memory to program MTRR
867 @param[in] Length Length of Memory to program MTRR
868 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
870 @retval TRUE Positive direction is better.
871 FALSE Negative direction is better.
875 GetMtrrNumberAndDirection (
876 IN UINT64 BaseAddress
,
888 if (BaseAddress
!= 0) {
891 // Calculate the alignment of the base address.
893 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
895 if (Alignment
> Length
) {
900 BaseAddress
+= Alignment
;
914 TempQword
-= Power2MaxMemory (TempQword
);
916 } while (TempQword
!= 0);
918 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
921 TempQword
-= Power2MaxMemory (TempQword
);
923 } while (TempQword
!= 0);
925 if (Positive
<= Subtractive
) {
926 *MtrrNumber
+= Positive
;
929 *MtrrNumber
+= Subtractive
;
935 Invalid variable MTRRs according to the value in the shadow array.
937 This function programs MTRRs according to the values specified
940 @param[in, out] VariableSettings Variable MTRR settings
941 @param[in] VariableMtrrCount Number of variable MTRRs
942 @param[in, out] VariableMtrr Shadow of variable MTRR contents
947 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
948 IN UINTN VariableMtrrCount
,
949 IN OUT VARIABLE_MTRR
*VariableMtrr
954 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
955 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
956 VariableSettings
->Mtrr
[Index
].Base
= 0;
957 VariableSettings
->Mtrr
[Index
].Mask
= 0;
958 VariableMtrr
[Index
].Used
= FALSE
;
965 Programs variable MTRRs
967 This function programs variable MTRRs
969 @param[in, out] VariableSettings Variable MTRR settings.
970 @param[in] MtrrNumber Index of MTRR to program.
971 @param[in] BaseAddress Base address of memory region.
972 @param[in] Length Length of memory region.
973 @param[in] MemoryCacheType Memory type to set.
974 @param[in] MtrrValidAddressMask The valid address mask for MTRR
978 ProgramVariableMtrr (
979 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
981 IN PHYSICAL_ADDRESS BaseAddress
,
983 IN UINT64 MemoryCacheType
,
984 IN UINT64 MtrrValidAddressMask
990 // MTRR Physical Base
992 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
993 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
996 // MTRR Physical Mask
998 TempQword
= ~(Length
- 1);
999 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
1004 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
1006 If MtrrSetting is not NULL, gets the default memory attribute from input
1007 MTRR settings buffer.
1008 If MtrrSetting is NULL, gets the default memory attribute from MSR.
1010 @param[in] MtrrSetting A buffer holding all MTRRs content.
1011 @param[in] MtrrType MTRR memory type
1013 @return The enum item in MTRR_MEMORY_CACHE_TYPE
1016 MTRR_MEMORY_CACHE_TYPE
1017 GetMemoryCacheTypeFromMtrrType (
1018 IN MTRR_SETTINGS
*MtrrSetting
,
1023 case MTRR_CACHE_UNCACHEABLE
:
1024 return CacheUncacheable
;
1025 case MTRR_CACHE_WRITE_COMBINING
:
1026 return CacheWriteCombining
;
1027 case MTRR_CACHE_WRITE_THROUGH
:
1028 return CacheWriteThrough
;
1029 case MTRR_CACHE_WRITE_PROTECTED
:
1030 return CacheWriteProtected
;
1031 case MTRR_CACHE_WRITE_BACK
:
1032 return CacheWriteBack
;
1035 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1036 // no MTRR covers the range
1038 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1043 Initializes the valid bits mask and valid address mask for MTRRs.
1045 This function initializes the valid bits mask and valid address mask for MTRRs.
1047 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1048 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1052 MtrrLibInitializeMtrrMask (
1053 OUT UINT64
*MtrrValidBitsMask
,
1054 OUT UINT64
*MtrrValidAddressMask
1057 UINT32 MaxExtendedFunction
;
1058 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize
;
1061 AsmCpuid (CPUID_EXTENDED_FUNCTION
, &MaxExtendedFunction
, NULL
, NULL
, NULL
);
1063 if (MaxExtendedFunction
>= CPUID_VIR_PHY_ADDRESS_SIZE
) {
1064 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE
, &VirPhyAddressSize
.Uint32
, NULL
, NULL
, NULL
);
1066 VirPhyAddressSize
.Bits
.PhysicalAddressBits
= 36;
1069 *MtrrValidBitsMask
= LShiftU64 (1, VirPhyAddressSize
.Bits
.PhysicalAddressBits
) - 1;
1070 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1075 Determines the real attribute of a memory range.
1077 This function is to arbitrate the real attribute of the memory when
1078 there are 2 MTRRs covers the same memory range. For further details,
1079 please refer the IA32 Software Developer's Manual, Volume 3,
1082 @param[in] MtrrType1 The first kind of Memory type
1083 @param[in] MtrrType2 The second kind of memory type
1088 IN UINT64 MtrrType1
,
1094 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1095 switch (MtrrType1
) {
1096 case MTRR_CACHE_UNCACHEABLE
:
1097 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1099 case MTRR_CACHE_WRITE_COMBINING
:
1101 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1102 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1104 MtrrType
= MtrrType2
;
1107 case MTRR_CACHE_WRITE_THROUGH
:
1109 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1110 MtrrType2
==MTRR_CACHE_WRITE_BACK
1112 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1113 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1114 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1117 case MTRR_CACHE_WRITE_PROTECTED
:
1118 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1119 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1120 MtrrType
= MtrrType2
;
1123 case MTRR_CACHE_WRITE_BACK
:
1125 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1126 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1127 MtrrType2
== MTRR_CACHE_WRITE_BACK
1129 MtrrType
= MtrrType2
;
1132 case MTRR_CACHE_INVALID_TYPE
:
1133 MtrrType
= MtrrType2
;
1139 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1140 MtrrType
= MtrrType1
;
1146 Worker function will get the memory cache type of the specific address.
1148 If MtrrSetting is not NULL, gets the memory cache type from input
1149 MTRR settings buffer.
1150 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1152 @param[in] MtrrSetting A buffer holding all MTRRs content.
1153 @param[in] Address The specific address
1155 @return Memory cache type of the specific address
1158 MTRR_MEMORY_CACHE_TYPE
1159 MtrrGetMemoryAttributeByAddressWorker (
1160 IN MTRR_SETTINGS
*MtrrSetting
,
1161 IN PHYSICAL_ADDRESS Address
1168 UINT64 TempMtrrType
;
1169 MTRR_MEMORY_CACHE_TYPE CacheType
;
1170 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1171 UINT64 MtrrValidBitsMask
;
1172 UINT64 MtrrValidAddressMask
;
1173 UINTN VariableMtrrCount
;
1174 MTRR_VARIABLE_SETTINGS VariableSettings
;
1177 // Check if MTRR is enabled, if not, return UC as attribute
1179 if (MtrrSetting
== NULL
) {
1180 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1182 TempQword
= MtrrSetting
->MtrrDefType
;
1184 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1186 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1187 return CacheUncacheable
;
1191 // If address is less than 1M, then try to go through the fixed MTRR
1193 if (Address
< BASE_1MB
) {
1194 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1196 // Go through the fixed MTRR
1198 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1199 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1201 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1202 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1206 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1207 mMtrrLibFixedMtrrTable
[Index
].Length
;
1208 if (MtrrSetting
== NULL
) {
1209 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1211 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1213 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1214 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1219 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1221 MtrrGetVariableMtrrWorker (
1223 GetVariableMtrrCountWorker (),
1227 MtrrGetMemoryAttributeInVariableMtrrWorker (
1229 GetFirmwareVariableMtrrCountWorker (),
1231 MtrrValidAddressMask
,
1236 // Go through the variable MTRR
1238 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1239 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1241 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1242 if (VariableMtrr
[Index
].Valid
) {
1243 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1244 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1245 TempMtrrType
= VariableMtrr
[Index
].Type
;
1246 MtrrType
= MtrrLibPrecedence (MtrrType
, TempMtrrType
);
1250 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1257 This function will get the memory cache type of the specific address.
1259 This function is mainly for debug purpose.
1261 @param[in] Address The specific address
1263 @return Memory cache type of the specific address
1266 MTRR_MEMORY_CACHE_TYPE
1268 MtrrGetMemoryAttribute (
1269 IN PHYSICAL_ADDRESS Address
1272 if (!IsMtrrSupported ()) {
1273 return CacheUncacheable
;
1276 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1280 Worker function prints all MTRRs for debugging.
1282 If MtrrSetting is not NULL, print MTRR settings from input MTRR
1284 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1286 @param MtrrSetting A buffer holding all MTRRs content.
1289 MtrrDebugPrintAllMtrrsWorker (
1290 IN MTRR_SETTINGS
*MtrrSetting
1294 MTRR_SETTINGS LocalMtrrs
;
1295 MTRR_SETTINGS
*Mtrrs
;
1298 UINTN VariableMtrrCount
;
1306 UINT64 NoRangeLimit
;
1309 UINTN PreviousMemoryType
;
1312 if (!IsMtrrSupported ()) {
1316 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1317 DEBUG((DEBUG_CACHE
, "=============\n"));
1319 if (MtrrSetting
!= NULL
) {
1320 Mtrrs
= MtrrSetting
;
1322 MtrrGetAllMtrrs (&LocalMtrrs
);
1323 Mtrrs
= &LocalMtrrs
;
1326 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1327 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1328 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1331 VariableMtrrCount
= GetVariableMtrrCount ();
1332 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1333 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1335 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1336 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1339 DEBUG((DEBUG_CACHE
, "\n"));
1340 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1341 DEBUG((DEBUG_CACHE
, "====================================\n"));
1344 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1345 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1346 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1347 for (Index1
= 0; Index1
< 8; Index1
++) {
1348 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1349 if (MemoryType
> CacheWriteBack
) {
1350 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1352 if (MemoryType
!= PreviousMemoryType
) {
1353 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1354 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1356 PreviousMemoryType
= MemoryType
;
1357 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1359 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1362 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1364 VariableMtrrCount
= GetVariableMtrrCount ();
1367 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1368 if (RegEax
>= 0x80000008) {
1369 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1370 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1373 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1375 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1376 if (MemoryType
> CacheWriteBack
) {
1377 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1380 if (MemoryType
!= PreviousMemoryType
) {
1381 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1382 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1384 PreviousMemoryType
= MemoryType
;
1385 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1388 RangeBase
= BASE_1MB
;
1389 NoRangeBase
= BASE_1MB
;
1391 NoRangeLimit
= Limit
;
1393 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1394 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1396 // If mask is not valid, then do not display range
1400 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1401 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1403 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1407 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1408 RangeBase
= MtrrBase
;
1410 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1411 RangeBase
= MtrrLimit
+ 1;
1413 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1414 RangeLimit
= MtrrBase
- 1;
1416 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1417 RangeLimit
= MtrrLimit
;
1420 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1421 NoRangeBase
= MtrrLimit
+ 1;
1423 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1424 NoRangeLimit
= MtrrBase
- 1;
1429 Base
= RangeLimit
+ 1;
1431 Base
= NoRangeLimit
+ 1;
1433 } while (Base
< Limit
);
1434 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1440 This function prints all MTRRs for debugging.
1444 MtrrDebugPrintAllMtrrs (
1448 MtrrDebugPrintAllMtrrsWorker (NULL
);
1453 Worker function attempts to set the attributes for a memory range.
1455 If MtrrSettings is not NULL, set the attributes into the input MTRR
1457 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1459 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1460 @param[in] BaseAddress The physical address that is the start
1461 address of a memory region.
1462 @param[in] Length The size in bytes of the memory region.
1463 @param[in] Attribute The bit mask of attributes to set for the
1466 @retval RETURN_SUCCESS The attributes were set for the memory
1468 @retval RETURN_INVALID_PARAMETER Length is zero.
1469 @retval RETURN_UNSUPPORTED The processor does not support one or
1470 more bytes of the memory resource range
1471 specified by BaseAddress and Length.
1472 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1473 for the memory resource range specified
1474 by BaseAddress and Length.
1475 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1476 range specified by BaseAddress and Length
1478 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1479 modify the attributes of the memory
1484 MtrrSetMemoryAttributeWorker (
1485 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1486 IN PHYSICAL_ADDRESS BaseAddress
,
1488 IN MTRR_MEMORY_CACHE_TYPE Attribute
1492 RETURN_STATUS Status
;
1499 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1501 UINT64 MtrrValidBitsMask
;
1502 UINT64 MtrrValidAddressMask
;
1503 BOOLEAN OverwriteExistingMtrr
;
1504 UINT32 FirmwareVariableMtrrCount
;
1505 MTRR_CONTEXT MtrrContext
;
1506 BOOLEAN MtrrContextValid
;
1507 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1508 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1509 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1510 UINT32 VariableMtrrCount
;
1511 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1512 BOOLEAN ProgramVariableSettings
;
1513 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1518 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1520 MtrrContextValid
= FALSE
;
1521 VariableMtrrCount
= 0;
1522 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1523 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1524 FixedSettingsValid
[Index
] = FALSE
;
1525 FixedSettingsModified
[Index
] = FALSE
;
1527 ProgramVariableSettings
= FALSE
;
1529 if (!IsMtrrSupported ()) {
1530 Status
= RETURN_UNSUPPORTED
;
1534 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1537 MemoryType
= (UINT64
)Attribute
;
1538 OverwriteExistingMtrr
= FALSE
;
1541 // Check for an invalid parameter
1544 Status
= RETURN_INVALID_PARAMETER
;
1549 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1550 (Length
& ~MtrrValidAddressMask
) != 0
1552 Status
= RETURN_UNSUPPORTED
;
1557 // Check if Fixed MTRR
1559 Status
= RETURN_SUCCESS
;
1560 if (BaseAddress
< BASE_1MB
) {
1561 MsrNum
= (UINT32
)-1;
1562 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1563 Status
= MtrrLibProgramFixedMtrr (Attribute
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1564 if (RETURN_ERROR (Status
)) {
1567 if (MtrrSetting
!= NULL
) {
1568 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1569 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1571 if (!FixedSettingsValid
[MsrNum
]) {
1572 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1573 FixedSettingsValid
[MsrNum
] = TRUE
;
1575 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1576 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1577 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1578 FixedSettingsModified
[MsrNum
] = TRUE
;
1585 // A Length of 0 can only make sense for fixed MTTR ranges.
1586 // Since we just handled the fixed MTRRs, we can skip the
1587 // variable MTRR section.
1594 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1595 // we can set the base to 0 to save variable MTRRs.
1597 if (BaseAddress
== BASE_1MB
) {
1603 // Read all variable MTRRs
1605 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1606 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1607 if (MtrrSetting
!= NULL
) {
1608 VariableSettings
= &MtrrSetting
->Variables
;
1610 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1611 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1612 ProgramVariableSettings
= TRUE
;
1613 VariableSettings
= &WorkingVariableSettings
;
1617 // Check for overlap
1619 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1621 FirmwareVariableMtrrCount
,
1623 MtrrValidAddressMask
,
1626 OverLap
= CheckMemoryAttributeOverlap (
1627 FirmwareVariableMtrrCount
,
1629 BaseAddress
+ Length
- 1,
1633 Status
= CombineMemoryAttribute (
1634 FirmwareVariableMtrrCount
,
1640 &OverwriteExistingMtrr
1642 if (RETURN_ERROR (Status
)) {
1648 // Combined successfully, invalidate the now-unused MTRRs
1650 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1651 Status
= RETURN_SUCCESS
;
1657 // The memory type is the same with the type specified by
1658 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1660 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1662 // Invalidate the now-unused MTRRs
1664 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1668 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1670 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1671 Status
= RETURN_OUT_OF_RESOURCES
;
1676 // Invalidate the now-unused MTRRs
1678 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1681 // Find first unused MTRR
1683 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1684 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1689 if (BaseAddress
!= 0) {
1692 // Calculate the alignment of the base address.
1694 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1696 if (Alignment
> Length
) {
1703 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1704 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1709 ProgramVariableMtrr (
1715 MtrrValidAddressMask
1717 BaseAddress
+= Alignment
;
1718 Length
-= Alignment
;
1729 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1734 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1735 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1740 ProgramVariableMtrr (
1746 MtrrValidAddressMask
1748 BaseAddress
+= Length
;
1749 TempQword
= Length
- TempQword
;
1750 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1757 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1758 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1763 Length
= Power2MaxMemory (TempQword
);
1765 BaseAddress
-= Length
;
1768 ProgramVariableMtrr (
1774 MtrrValidAddressMask
1778 BaseAddress
+= Length
;
1780 TempQword
-= Length
;
1782 } while (TempQword
> 0);
1787 // Write fixed MTRRs that have been modified
1789 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1790 if (FixedSettingsModified
[Index
]) {
1791 if (!MtrrContextValid
) {
1792 MtrrLibPreMtrrChange (&MtrrContext
);
1793 MtrrContextValid
= TRUE
;
1796 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1797 WorkingFixedSettings
.Mtrr
[Index
]
1803 // Write variable MTRRs
1805 if (ProgramVariableSettings
) {
1806 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1807 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1808 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1809 if (!MtrrContextValid
) {
1810 MtrrLibPreMtrrChange (&MtrrContext
);
1811 MtrrContextValid
= TRUE
;
1814 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1815 WorkingVariableSettings
.Mtrr
[Index
].Base
1818 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1819 WorkingVariableSettings
.Mtrr
[Index
].Mask
1824 if (MtrrContextValid
) {
1825 MtrrLibPostMtrrChange (&MtrrContext
);
1828 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1829 if (!RETURN_ERROR (Status
)) {
1830 if (MtrrSetting
!= NULL
) {
1831 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1833 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1840 This function attempts to set the attributes for a memory range.
1842 @param[in] BaseAddress The physical address that is the start
1843 address of a memory region.
1844 @param[in] Length The size in bytes of the memory region.
1845 @param[in] Attributes The bit mask of attributes to set for the
1848 @retval RETURN_SUCCESS The attributes were set for the memory
1850 @retval RETURN_INVALID_PARAMETER Length is zero.
1851 @retval RETURN_UNSUPPORTED The processor does not support one or
1852 more bytes of the memory resource range
1853 specified by BaseAddress and Length.
1854 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1855 for the memory resource range specified
1856 by BaseAddress and Length.
1857 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1858 range specified by BaseAddress and Length
1860 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1861 modify the attributes of the memory
1867 MtrrSetMemoryAttribute (
1868 IN PHYSICAL_ADDRESS BaseAddress
,
1870 IN MTRR_MEMORY_CACHE_TYPE Attribute
1873 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1874 return MtrrSetMemoryAttributeWorker (
1883 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1885 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1886 @param[in] BaseAddress The physical address that is the start address
1888 @param[in] Length The size in bytes of the memory region.
1889 @param[in] Attribute The bit mask of attributes to set for the
1892 @retval RETURN_SUCCESS The attributes were set for the memory region.
1893 @retval RETURN_INVALID_PARAMETER Length is zero.
1894 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1895 memory resource range specified by BaseAddress and Length.
1896 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1897 range specified by BaseAddress and Length.
1898 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1899 BaseAddress and Length cannot be modified.
1900 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1901 the memory resource range.
1906 MtrrSetMemoryAttributeInMtrrSettings (
1907 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1908 IN PHYSICAL_ADDRESS BaseAddress
,
1910 IN MTRR_MEMORY_CACHE_TYPE Attribute
1913 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1914 return MtrrSetMemoryAttributeWorker (
1923 Worker function setting variable MTRRs
1925 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1929 MtrrSetVariableMtrrWorker (
1930 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1934 UINT32 VariableMtrrCount
;
1936 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1937 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1939 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1941 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1942 VariableSettings
->Mtrr
[Index
].Base
1945 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1946 VariableSettings
->Mtrr
[Index
].Mask
1953 This function sets variable MTRRs
1955 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1957 @return The pointer of VariableSettings
1960 MTRR_VARIABLE_SETTINGS
*
1962 MtrrSetVariableMtrr (
1963 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1966 MTRR_CONTEXT MtrrContext
;
1968 if (!IsMtrrSupported ()) {
1969 return VariableSettings
;
1972 MtrrLibPreMtrrChange (&MtrrContext
);
1973 MtrrSetVariableMtrrWorker (VariableSettings
);
1974 MtrrLibPostMtrrChange (&MtrrContext
);
1975 MtrrDebugPrintAllMtrrs ();
1977 return VariableSettings
;
1981 Worker function setting fixed MTRRs
1983 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1987 MtrrSetFixedMtrrWorker (
1988 IN MTRR_FIXED_SETTINGS
*FixedSettings
1993 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1995 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1996 FixedSettings
->Mtrr
[Index
]
2003 This function sets fixed MTRRs
2005 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
2007 @retval The pointer of FixedSettings
2010 MTRR_FIXED_SETTINGS
*
2013 IN MTRR_FIXED_SETTINGS
*FixedSettings
2016 MTRR_CONTEXT MtrrContext
;
2018 if (!IsMtrrSupported ()) {
2019 return FixedSettings
;
2022 MtrrLibPreMtrrChange (&MtrrContext
);
2023 MtrrSetFixedMtrrWorker (FixedSettings
);
2024 MtrrLibPostMtrrChange (&MtrrContext
);
2025 MtrrDebugPrintAllMtrrs ();
2027 return FixedSettings
;
2032 This function gets the content in all MTRRs (variable and fixed)
2034 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2036 @retval the pointer of MtrrSetting
2042 OUT MTRR_SETTINGS
*MtrrSetting
2045 if (!IsMtrrSupported ()) {
2052 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2055 // Get variable MTRRs
2057 MtrrGetVariableMtrrWorker (
2059 GetVariableMtrrCountWorker (),
2060 &MtrrSetting
->Variables
2064 // Get MTRR_DEF_TYPE value
2066 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2073 This function sets all MTRRs (variable and fixed)
2075 @param[in] MtrrSetting A buffer holding all MTRRs content.
2077 @retval The pointer of MtrrSetting
2083 IN MTRR_SETTINGS
*MtrrSetting
2086 MTRR_CONTEXT MtrrContext
;
2088 if (!IsMtrrSupported ()) {
2092 MtrrLibPreMtrrChange (&MtrrContext
);
2097 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2100 // Set variable MTRRs
2102 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2105 // Set MTRR_DEF_TYPE value
2107 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2109 MtrrLibPostMtrrChangeEnableCache (&MtrrContext
);
2116 Checks if MTRR is supported.
2118 @retval TRUE MTRR is supported.
2119 @retval FALSE MTRR is not supported.
2128 CPUID_VERSION_INFO_EDX Edx
;
2129 MSR_IA32_MTRRCAP_REGISTER MtrrCap
;
2132 // Check CPUID(1).EDX[12] for MTRR capability
2134 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &Edx
.Uint32
);
2135 if (Edx
.Bits
.MTRR
== 0) {
2140 // Check number of variable MTRRs and fixed MTRRs existence.
2141 // If number of variable MTRRs is zero, or fixed MTRRs do not
2142 // exist, return false.
2144 MtrrCap
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRRCAP
);
2145 if ((MtrrCap
.Bits
.VCNT
== 0) || (MtrrCap
.Bits
.FIX
== 0)) {