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
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 PostMtrrChangeEnableCache (
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
323 IN MTRR_CONTEXT
*MtrrContext
329 AsmMsrBitFieldWrite64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
331 PostMtrrChangeEnableCache (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] MemoryCacheType 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
463 IN UINT64 MemoryCacheType
,
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
)MemoryCacheType
);
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
1058 UINT8 PhysicalAddressBits
;
1060 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1062 if (RegEax
>= 0x80000008) {
1063 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1065 PhysicalAddressBits
= (UINT8
) RegEax
;
1067 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1068 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1070 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1071 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1077 Determines the real attribute of a memory range.
1079 This function is to arbitrate the real attribute of the memory when
1080 there are 2 MTRRs covers the same memory range. For further details,
1081 please refer the IA32 Software Developer's Manual, Volume 3,
1084 @param[in] MtrrType1 The first kind of Memory type
1085 @param[in] MtrrType2 The second kind of memory type
1090 IN UINT64 MtrrType1
,
1096 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1097 switch (MtrrType1
) {
1098 case MTRR_CACHE_UNCACHEABLE
:
1099 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1101 case MTRR_CACHE_WRITE_COMBINING
:
1103 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1104 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1106 MtrrType
= MtrrType2
;
1109 case MTRR_CACHE_WRITE_THROUGH
:
1111 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1112 MtrrType2
==MTRR_CACHE_WRITE_BACK
1114 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1115 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1116 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1119 case MTRR_CACHE_WRITE_PROTECTED
:
1120 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1121 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1122 MtrrType
= MtrrType2
;
1125 case MTRR_CACHE_WRITE_BACK
:
1127 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1128 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1129 MtrrType2
== MTRR_CACHE_WRITE_BACK
1131 MtrrType
= MtrrType2
;
1134 case MTRR_CACHE_INVALID_TYPE
:
1135 MtrrType
= MtrrType2
;
1141 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1142 MtrrType
= MtrrType1
;
1148 Worker function will get the memory cache type of the specific address.
1150 If MtrrSetting is not NULL, gets the memory cache type from input
1151 MTRR settings buffer.
1152 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1154 @param[in] MtrrSetting A buffer holding all MTRRs content.
1155 @param[in] Address The specific address
1157 @return Memory cache type of the specific address
1160 MTRR_MEMORY_CACHE_TYPE
1161 MtrrGetMemoryAttributeByAddressWorker (
1162 IN MTRR_SETTINGS
*MtrrSetting
,
1163 IN PHYSICAL_ADDRESS Address
1170 UINT64 TempMtrrType
;
1171 MTRR_MEMORY_CACHE_TYPE CacheType
;
1172 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1173 UINT64 MtrrValidBitsMask
;
1174 UINT64 MtrrValidAddressMask
;
1175 UINTN VariableMtrrCount
;
1176 MTRR_VARIABLE_SETTINGS VariableSettings
;
1179 // Check if MTRR is enabled, if not, return UC as attribute
1181 if (MtrrSetting
== NULL
) {
1182 TempQword
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
1184 TempQword
= MtrrSetting
->MtrrDefType
;
1186 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1188 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1189 return CacheUncacheable
;
1193 // If address is less than 1M, then try to go through the fixed MTRR
1195 if (Address
< BASE_1MB
) {
1196 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1198 // Go through the fixed MTRR
1200 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1201 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1203 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1204 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1208 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1209 mMtrrLibFixedMtrrTable
[Index
].Length
;
1210 if (MtrrSetting
== NULL
) {
1211 TempQword
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1213 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1215 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1216 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1221 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1223 MtrrGetVariableMtrrWorker (
1225 GetVariableMtrrCountWorker (),
1229 MtrrGetMemoryAttributeInVariableMtrrWorker (
1231 GetFirmwareVariableMtrrCountWorker (),
1233 MtrrValidAddressMask
,
1238 // Go through the variable MTRR
1240 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1241 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1243 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1244 if (VariableMtrr
[Index
].Valid
) {
1245 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1246 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1247 TempMtrrType
= VariableMtrr
[Index
].Type
;
1248 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1252 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1259 This function will get the memory cache type of the specific address.
1261 This function is mainly for debug purpose.
1263 @param[in] Address The specific address
1265 @return Memory cache type of the specific address
1268 MTRR_MEMORY_CACHE_TYPE
1270 MtrrGetMemoryAttribute (
1271 IN PHYSICAL_ADDRESS Address
1274 if (!IsMtrrSupported ()) {
1275 return CacheUncacheable
;
1278 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1282 Worker function prints all MTRRs for debugging.
1284 If MtrrSetting is not NULL, print MTRR settings from input MTRR
1286 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1288 @param MtrrSetting A buffer holding all MTRRs content.
1291 MtrrDebugPrintAllMtrrsWorker (
1292 IN MTRR_SETTINGS
*MtrrSetting
1296 MTRR_SETTINGS LocalMtrrs
;
1297 MTRR_SETTINGS
*Mtrrs
;
1300 UINTN VariableMtrrCount
;
1308 UINT64 NoRangeLimit
;
1311 UINTN PreviousMemoryType
;
1314 if (!IsMtrrSupported ()) {
1318 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1319 DEBUG((DEBUG_CACHE
, "=============\n"));
1321 if (MtrrSetting
!= NULL
) {
1322 Mtrrs
= MtrrSetting
;
1324 MtrrGetAllMtrrs (&LocalMtrrs
);
1325 Mtrrs
= &LocalMtrrs
;
1328 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1329 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1330 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1333 VariableMtrrCount
= GetVariableMtrrCount ();
1334 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1335 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1337 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1338 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1341 DEBUG((DEBUG_CACHE
, "\n"));
1342 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1343 DEBUG((DEBUG_CACHE
, "====================================\n"));
1346 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1347 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1348 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1349 for (Index1
= 0; Index1
< 8; Index1
++) {
1350 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1351 if (MemoryType
> CacheWriteBack
) {
1352 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1354 if (MemoryType
!= PreviousMemoryType
) {
1355 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1356 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1358 PreviousMemoryType
= MemoryType
;
1359 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1361 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1364 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1366 VariableMtrrCount
= GetVariableMtrrCount ();
1369 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1370 if (RegEax
>= 0x80000008) {
1371 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1372 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1375 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1377 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1378 if (MemoryType
> CacheWriteBack
) {
1379 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1382 if (MemoryType
!= PreviousMemoryType
) {
1383 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1384 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1386 PreviousMemoryType
= MemoryType
;
1387 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1390 RangeBase
= BASE_1MB
;
1391 NoRangeBase
= BASE_1MB
;
1393 NoRangeLimit
= Limit
;
1395 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1396 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1398 // If mask is not valid, then do not display range
1402 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1403 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1405 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1409 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1410 RangeBase
= MtrrBase
;
1412 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1413 RangeBase
= MtrrLimit
+ 1;
1415 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1416 RangeLimit
= MtrrBase
- 1;
1418 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1419 RangeLimit
= MtrrLimit
;
1422 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1423 NoRangeBase
= MtrrLimit
+ 1;
1425 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1426 NoRangeLimit
= MtrrBase
- 1;
1431 Base
= RangeLimit
+ 1;
1433 Base
= NoRangeLimit
+ 1;
1435 } while (Base
< Limit
);
1436 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1442 This function prints all MTRRs for debugging.
1446 MtrrDebugPrintAllMtrrs (
1450 MtrrDebugPrintAllMtrrsWorker (NULL
);
1455 Worker function attempts to set the attributes for a memory range.
1457 If MtrrSettings is not NULL, set the attributes into the input MTRR
1459 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1461 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1462 @param[in] BaseAddress The physical address that is the start
1463 address of a memory region.
1464 @param[in] Length The size in bytes of the memory region.
1465 @param[in] Attribute The bit mask of attributes to set for the
1468 @retval RETURN_SUCCESS The attributes were set for the memory
1470 @retval RETURN_INVALID_PARAMETER Length is zero.
1471 @retval RETURN_UNSUPPORTED The processor does not support one or
1472 more bytes of the memory resource range
1473 specified by BaseAddress and Length.
1474 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1475 for the memory resource range specified
1476 by BaseAddress and Length.
1477 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1478 range specified by BaseAddress and Length
1480 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1481 modify the attributes of the memory
1486 MtrrSetMemoryAttributeWorker (
1487 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1488 IN PHYSICAL_ADDRESS BaseAddress
,
1490 IN MTRR_MEMORY_CACHE_TYPE Attribute
1494 RETURN_STATUS Status
;
1501 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1503 UINT64 MtrrValidBitsMask
;
1504 UINT64 MtrrValidAddressMask
;
1505 BOOLEAN OverwriteExistingMtrr
;
1506 UINT32 FirmwareVariableMtrrCount
;
1507 MTRR_CONTEXT MtrrContext
;
1508 BOOLEAN MtrrContextValid
;
1509 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1510 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1511 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1512 UINT32 VariableMtrrCount
;
1513 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1514 BOOLEAN ProgramVariableSettings
;
1515 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1520 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1522 MtrrContextValid
= FALSE
;
1523 VariableMtrrCount
= 0;
1524 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1525 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1526 FixedSettingsValid
[Index
] = FALSE
;
1527 FixedSettingsModified
[Index
] = FALSE
;
1529 ProgramVariableSettings
= FALSE
;
1531 if (!IsMtrrSupported ()) {
1532 Status
= RETURN_UNSUPPORTED
;
1536 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1539 MemoryType
= (UINT64
)Attribute
;
1540 OverwriteExistingMtrr
= FALSE
;
1543 // Check for an invalid parameter
1546 Status
= RETURN_INVALID_PARAMETER
;
1551 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1552 (Length
& ~MtrrValidAddressMask
) != 0
1554 Status
= RETURN_UNSUPPORTED
;
1559 // Check if Fixed MTRR
1561 Status
= RETURN_SUCCESS
;
1562 if (BaseAddress
< BASE_1MB
) {
1563 MsrNum
= (UINT32
)-1;
1564 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1565 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1566 if (RETURN_ERROR (Status
)) {
1569 if (MtrrSetting
!= NULL
) {
1570 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1571 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1573 if (!FixedSettingsValid
[MsrNum
]) {
1574 WorkingFixedSettings
.Mtrr
[MsrNum
] = AsmReadMsr64 (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1575 FixedSettingsValid
[MsrNum
] = TRUE
;
1577 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1578 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1579 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1580 FixedSettingsModified
[MsrNum
] = TRUE
;
1587 // A Length of 0 can only make sense for fixed MTTR ranges.
1588 // Since we just handled the fixed MTRRs, we can skip the
1589 // variable MTRR section.
1596 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1597 // we can set the base to 0 to save variable MTRRs.
1599 if (BaseAddress
== BASE_1MB
) {
1605 // Read all variable MTRRs
1607 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1608 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1609 if (MtrrSetting
!= NULL
) {
1610 VariableSettings
= &MtrrSetting
->Variables
;
1612 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1613 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1614 ProgramVariableSettings
= TRUE
;
1615 VariableSettings
= &WorkingVariableSettings
;
1619 // Check for overlap
1621 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1623 FirmwareVariableMtrrCount
,
1625 MtrrValidAddressMask
,
1628 OverLap
= CheckMemoryAttributeOverlap (
1629 FirmwareVariableMtrrCount
,
1631 BaseAddress
+ Length
- 1,
1635 Status
= CombineMemoryAttribute (
1636 FirmwareVariableMtrrCount
,
1642 &OverwriteExistingMtrr
1644 if (RETURN_ERROR (Status
)) {
1650 // Combined successfully, invalidate the now-unused MTRRs
1652 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1653 Status
= RETURN_SUCCESS
;
1659 // The memory type is the same with the type specified by
1660 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1662 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryTypeWorker (MtrrSetting
))) {
1664 // Invalidate the now-unused MTRRs
1666 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1670 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1672 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1673 Status
= RETURN_OUT_OF_RESOURCES
;
1678 // Invalidate the now-unused MTRRs
1680 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1683 // Find first unused MTRR
1685 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1686 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1691 if (BaseAddress
!= 0) {
1694 // Calculate the alignment of the base address.
1696 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1698 if (Alignment
> Length
) {
1705 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1706 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1711 ProgramVariableMtrr (
1717 MtrrValidAddressMask
1719 BaseAddress
+= Alignment
;
1720 Length
-= Alignment
;
1731 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1736 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1737 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1742 ProgramVariableMtrr (
1748 MtrrValidAddressMask
1750 BaseAddress
+= Length
;
1751 TempQword
= Length
- TempQword
;
1752 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1759 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1760 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1765 Length
= Power2MaxMemory (TempQword
);
1767 BaseAddress
-= Length
;
1770 ProgramVariableMtrr (
1776 MtrrValidAddressMask
1780 BaseAddress
+= Length
;
1782 TempQword
-= Length
;
1784 } while (TempQword
> 0);
1789 // Write fixed MTRRs that have been modified
1791 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1792 if (FixedSettingsModified
[Index
]) {
1793 if (!MtrrContextValid
) {
1794 PreMtrrChange (&MtrrContext
);
1795 MtrrContextValid
= TRUE
;
1798 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1799 WorkingFixedSettings
.Mtrr
[Index
]
1805 // Write variable MTRRs
1807 if (ProgramVariableSettings
) {
1808 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1809 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1810 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1811 if (!MtrrContextValid
) {
1812 PreMtrrChange (&MtrrContext
);
1813 MtrrContextValid
= TRUE
;
1816 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1817 WorkingVariableSettings
.Mtrr
[Index
].Base
1820 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1821 WorkingVariableSettings
.Mtrr
[Index
].Mask
1826 if (MtrrContextValid
) {
1827 PostMtrrChange (&MtrrContext
);
1830 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1831 if (!RETURN_ERROR (Status
)) {
1832 if (MtrrSetting
!= NULL
) {
1833 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1835 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1842 This function attempts to set the attributes for a memory range.
1844 @param[in] BaseAddress The physical address that is the start
1845 address of a memory region.
1846 @param[in] Length The size in bytes of the memory region.
1847 @param[in] Attributes The bit mask of attributes to set for the
1850 @retval RETURN_SUCCESS The attributes were set for the memory
1852 @retval RETURN_INVALID_PARAMETER Length is zero.
1853 @retval RETURN_UNSUPPORTED The processor does not support one or
1854 more bytes of the memory resource range
1855 specified by BaseAddress and Length.
1856 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1857 for the memory resource range specified
1858 by BaseAddress and Length.
1859 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1860 range specified by BaseAddress and Length
1862 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1863 modify the attributes of the memory
1869 MtrrSetMemoryAttribute (
1870 IN PHYSICAL_ADDRESS BaseAddress
,
1872 IN MTRR_MEMORY_CACHE_TYPE Attribute
1875 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1876 return MtrrSetMemoryAttributeWorker (
1885 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1887 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1888 @param[in] BaseAddress The physical address that is the start address
1890 @param[in] Length The size in bytes of the memory region.
1891 @param[in] Attribute The bit mask of attributes to set for the
1894 @retval RETURN_SUCCESS The attributes were set for the memory region.
1895 @retval RETURN_INVALID_PARAMETER Length is zero.
1896 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1897 memory resource range specified by BaseAddress and Length.
1898 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1899 range specified by BaseAddress and Length.
1900 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1901 BaseAddress and Length cannot be modified.
1902 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1903 the memory resource range.
1908 MtrrSetMemoryAttributeInMtrrSettings (
1909 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1910 IN PHYSICAL_ADDRESS BaseAddress
,
1912 IN MTRR_MEMORY_CACHE_TYPE Attribute
1915 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1916 return MtrrSetMemoryAttributeWorker (
1925 Worker function setting variable MTRRs
1927 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1931 MtrrSetVariableMtrrWorker (
1932 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1936 UINT32 VariableMtrrCount
;
1938 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1939 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1941 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1943 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1),
1944 VariableSettings
->Mtrr
[Index
].Base
1947 MTRR_LIB_IA32_VARIABLE_MTRR_BASE
+ (Index
<< 1) + 1,
1948 VariableSettings
->Mtrr
[Index
].Mask
1955 This function sets variable MTRRs
1957 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1959 @return The pointer of VariableSettings
1962 MTRR_VARIABLE_SETTINGS
*
1964 MtrrSetVariableMtrr (
1965 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1968 MTRR_CONTEXT MtrrContext
;
1970 if (!IsMtrrSupported ()) {
1971 return VariableSettings
;
1974 PreMtrrChange (&MtrrContext
);
1975 MtrrSetVariableMtrrWorker (VariableSettings
);
1976 PostMtrrChange (&MtrrContext
);
1977 MtrrDebugPrintAllMtrrs ();
1979 return VariableSettings
;
1983 Worker function setting fixed MTRRs
1985 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1989 MtrrSetFixedMtrrWorker (
1990 IN MTRR_FIXED_SETTINGS
*FixedSettings
1995 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1997 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1998 FixedSettings
->Mtrr
[Index
]
2005 This function sets fixed MTRRs
2007 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
2009 @retval The pointer of FixedSettings
2012 MTRR_FIXED_SETTINGS
*
2015 IN MTRR_FIXED_SETTINGS
*FixedSettings
2018 MTRR_CONTEXT MtrrContext
;
2020 if (!IsMtrrSupported ()) {
2021 return FixedSettings
;
2024 PreMtrrChange (&MtrrContext
);
2025 MtrrSetFixedMtrrWorker (FixedSettings
);
2026 PostMtrrChange (&MtrrContext
);
2027 MtrrDebugPrintAllMtrrs ();
2029 return FixedSettings
;
2034 This function gets the content in all MTRRs (variable and fixed)
2036 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2038 @retval the pointer of MtrrSetting
2044 OUT MTRR_SETTINGS
*MtrrSetting
2047 if (!IsMtrrSupported ()) {
2054 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2057 // Get variable MTRRs
2059 MtrrGetVariableMtrrWorker (
2061 GetVariableMtrrCountWorker (),
2062 &MtrrSetting
->Variables
2066 // Get MTRR_DEF_TYPE value
2068 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
);
2075 This function sets all MTRRs (variable and fixed)
2077 @param[in] MtrrSetting A buffer holding all MTRRs content.
2079 @retval The pointer of MtrrSetting
2085 IN MTRR_SETTINGS
*MtrrSetting
2088 MTRR_CONTEXT MtrrContext
;
2090 if (!IsMtrrSupported ()) {
2094 PreMtrrChange (&MtrrContext
);
2099 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2102 // Set variable MTRRs
2104 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2107 // Set MTRR_DEF_TYPE value
2109 AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2111 PostMtrrChangeEnableCache (&MtrrContext
);
2118 Checks if MTRR is supported.
2120 @retval TRUE MTRR is supported.
2121 @retval FALSE MTRR is not supported.
2130 CPUID_VERSION_INFO_EDX Edx
;
2131 MSR_IA32_MTRRCAP_REGISTER MtrrCap
;
2134 // Check CPUID(1).EDX[12] for MTRR capability
2136 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &Edx
.Uint32
);
2137 if (Edx
.Bits
.MTRR
== 0) {
2142 // Check number of variable MTRRs and fixed MTRRs existence.
2143 // If number of variable MTRRs is zero, or fixed MTRRs do not
2144 // exist, return false.
2146 MtrrCap
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRRCAP
);
2147 if ((MtrrCap
.Bits
.VCNT
== 0) || (MtrrCap
.Bits
.FIX
== 0)) {