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 - 2018, 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.
20 #include <Register/Cpuid.h>
21 #include <Register/Msr.h>
23 #include <Library/MtrrLib.h>
24 #include <Library/BaseLib.h>
25 #include <Library/CpuLib.h>
26 #include <Library/BaseMemoryLib.h>
27 #include <Library/DebugLib.h>
29 #define OR_SEED 0x0101010101010101ull
30 #define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull
31 #define MAX_WEIGHT MAX_UINT8
32 #define SCRATCH_BUFFER_SIZE (4 * SIZE_4KB)
33 #define MTRR_LIB_ASSERT_ALIGNED(B, L) ASSERT ((B & ~(L - 1)) == B);
35 #define M(x,y) ((x) * VertexCount + (y))
36 #define O(x,y) ((y) * VertexCount + (x))
39 // Context to save and restore when MTRRs are programmed
43 BOOLEAN InterruptState
;
50 MTRR_MEMORY_CACHE_TYPE Type
: 7;
53 // Temprary use for calculating the best MTRR settings.
61 // This table defines the offset, base and length of the fixed MTRRs
63 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
65 MSR_IA32_MTRR_FIX64K_00000
,
70 MSR_IA32_MTRR_FIX16K_80000
,
75 MSR_IA32_MTRR_FIX16K_A0000
,
80 MSR_IA32_MTRR_FIX4K_C0000
,
85 MSR_IA32_MTRR_FIX4K_C8000
,
90 MSR_IA32_MTRR_FIX4K_D0000
,
95 MSR_IA32_MTRR_FIX4K_D8000
,
100 MSR_IA32_MTRR_FIX4K_E0000
,
105 MSR_IA32_MTRR_FIX4K_E8000
,
110 MSR_IA32_MTRR_FIX4K_F0000
,
115 MSR_IA32_MTRR_FIX4K_F8000
,
122 // Lookup table used to print MTRRs
124 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
125 "UC", // CacheUncacheable
126 "WC", // CacheWriteCombining
129 "WT", // CacheWriteThrough
130 "WP", // CacheWriteProtected
131 "WB", // CacheWriteBack
137 Worker function prints all MTRRs for debugging.
139 If MtrrSetting is not NULL, print MTRR settings from input MTRR
141 If MtrrSetting is NULL, print MTRR settings from MTRRs.
143 @param MtrrSetting A buffer holding all MTRRs content.
146 MtrrDebugPrintAllMtrrsWorker (
147 IN MTRR_SETTINGS
*MtrrSetting
151 Worker function returns the variable MTRR count for the CPU.
153 @return Variable MTRR count
157 GetVariableMtrrCountWorker (
161 MSR_IA32_MTRRCAP_REGISTER MtrrCap
;
163 MtrrCap
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRRCAP
);
164 ASSERT (MtrrCap
.Bits
.VCNT
<= ARRAY_SIZE (((MTRR_VARIABLE_SETTINGS
*) 0)->Mtrr
));
165 return MtrrCap
.Bits
.VCNT
;
169 Returns the variable MTRR count for the CPU.
171 @return Variable MTRR count
176 GetVariableMtrrCount (
180 if (!IsMtrrSupported ()) {
183 return GetVariableMtrrCountWorker ();
187 Worker function returns the firmware usable variable MTRR count for the CPU.
189 @return Firmware usable variable MTRR count
193 GetFirmwareVariableMtrrCountWorker (
197 UINT32 VariableMtrrCount
;
198 UINT32 ReservedMtrrNumber
;
200 VariableMtrrCount
= GetVariableMtrrCountWorker ();
201 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
202 if (VariableMtrrCount
< ReservedMtrrNumber
) {
206 return VariableMtrrCount
- ReservedMtrrNumber
;
210 Returns the firmware usable variable MTRR count for the CPU.
212 @return Firmware usable variable MTRR count
217 GetFirmwareVariableMtrrCount (
221 if (!IsMtrrSupported ()) {
224 return GetFirmwareVariableMtrrCountWorker ();
228 Worker function returns the default MTRR cache type for the system.
230 If MtrrSetting is not NULL, returns the default MTRR cache type from input
231 MTRR settings buffer.
232 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
234 @param[in] MtrrSetting A buffer holding all MTRRs content.
236 @return The default MTRR cache type.
239 MTRR_MEMORY_CACHE_TYPE
240 MtrrGetDefaultMemoryTypeWorker (
241 IN MTRR_SETTINGS
*MtrrSetting
244 MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType
;
246 if (MtrrSetting
== NULL
) {
247 DefType
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE
);
249 DefType
.Uint64
= MtrrSetting
->MtrrDefType
;
252 return (MTRR_MEMORY_CACHE_TYPE
) DefType
.Bits
.Type
;
257 Returns the default MTRR cache type for the system.
259 @return The default MTRR cache type.
262 MTRR_MEMORY_CACHE_TYPE
264 MtrrGetDefaultMemoryType (
268 if (!IsMtrrSupported ()) {
269 return CacheUncacheable
;
271 return MtrrGetDefaultMemoryTypeWorker (NULL
);
275 Preparation before programming MTRR.
277 This function will do some preparation for programming MTRRs:
278 disable cache, invalid cache and disable MTRR caching functionality
280 @param[out] MtrrContext Pointer to context to save
284 MtrrLibPreMtrrChange (
285 OUT MTRR_CONTEXT
*MtrrContext
288 MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType
;
290 // Disable interrupts and save current interrupt state
292 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
295 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
300 // Save original CR4 value and clear PGE flag (Bit 7)
302 MtrrContext
->Cr4
= AsmReadCr4 ();
303 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
313 DefType
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE
);
315 AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE
, DefType
.Uint64
);
319 Cleaning up after programming MTRRs.
321 This function will do some clean up after programming MTRRs:
322 Flush all TLBs, re-enable caching, restore CR4.
324 @param[in] MtrrContext Pointer to context to restore
328 MtrrLibPostMtrrChangeEnableCache (
329 IN MTRR_CONTEXT
*MtrrContext
338 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
343 // Restore original CR4 value
345 AsmWriteCr4 (MtrrContext
->Cr4
);
348 // Restore original interrupt state
350 SetInterruptState (MtrrContext
->InterruptState
);
354 Cleaning up after programming MTRRs.
356 This function will do some clean up after programming MTRRs:
357 enable MTRR caching functionality, and enable cache
359 @param[in] MtrrContext Pointer to context to restore
363 MtrrLibPostMtrrChange (
364 IN MTRR_CONTEXT
*MtrrContext
367 MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType
;
371 DefType
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE
);
374 AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE
, DefType
.Uint64
);
376 MtrrLibPostMtrrChangeEnableCache (MtrrContext
);
380 Worker function gets the content in fixed MTRRs
382 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
384 @retval The pointer of FixedSettings
388 MtrrGetFixedMtrrWorker (
389 OUT MTRR_FIXED_SETTINGS
*FixedSettings
394 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
395 FixedSettings
->Mtrr
[Index
] =
396 AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
399 return FixedSettings
;
404 This function gets the content in fixed MTRRs
406 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
408 @retval The pointer of FixedSettings
414 OUT MTRR_FIXED_SETTINGS
*FixedSettings
417 if (!IsMtrrSupported ()) {
418 return FixedSettings
;
421 return MtrrGetFixedMtrrWorker (FixedSettings
);
426 Worker function will get the raw value in variable MTRRs
428 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
429 MTRR settings buffer.
430 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
432 @param[in] MtrrSetting A buffer holding all MTRRs content.
433 @param[in] VariableMtrrCount Number of variable MTRRs.
434 @param[out] VariableSettings A buffer to hold variable MTRRs content.
436 @return The VariableSettings input pointer
439 MTRR_VARIABLE_SETTINGS
*
440 MtrrGetVariableMtrrWorker (
441 IN MTRR_SETTINGS
*MtrrSetting
,
442 IN UINT32 VariableMtrrCount
,
443 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
448 ASSERT (VariableMtrrCount
<= ARRAY_SIZE (VariableSettings
->Mtrr
));
450 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
451 if (MtrrSetting
== NULL
) {
452 VariableSettings
->Mtrr
[Index
].Mask
= AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0
+ (Index
<< 1));
454 // Skip to read the Base MSR when the Mask.V is not set.
456 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER
*)&VariableSettings
->Mtrr
[Index
].Mask
)->Bits
.V
!= 0) {
457 VariableSettings
->Mtrr
[Index
].Base
= AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0
+ (Index
<< 1));
460 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
461 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
465 return VariableSettings
;
469 This function will get the raw value in variable MTRRs
471 @param[out] VariableSettings A buffer to hold variable MTRRs content.
473 @return The VariableSettings input pointer
476 MTRR_VARIABLE_SETTINGS
*
478 MtrrGetVariableMtrr (
479 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
482 if (!IsMtrrSupported ()) {
483 return VariableSettings
;
486 return MtrrGetVariableMtrrWorker (
488 GetVariableMtrrCountWorker (),
494 Programs fixed MTRRs registers.
496 @param[in] Type The memory type to set.
497 @param[in, out] Base The base address of memory range.
498 @param[in, out] Length The length of memory range.
499 @param[in, out] LastMsrIndex On input, the last index of the fixed MTRR MSR to program.
500 On return, the current index of the fixed MTRR MSR to program.
501 @param[out] ClearMask The bits to clear in the fixed MTRR MSR.
502 @param[out] OrMask The bits to set in the fixed MTRR MSR.
504 @retval RETURN_SUCCESS The cache type was updated successfully
505 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
510 MtrrLibProgramFixedMtrr (
511 IN MTRR_MEMORY_CACHE_TYPE Type
,
513 IN OUT UINT64
*Length
,
514 IN OUT UINT32
*LastMsrIndex
,
515 OUT UINT64
*ClearMask
,
520 UINT32 LeftByteShift
;
521 UINT32 RightByteShift
;
525 // Find the fixed MTRR index to be programmed
527 for (MsrIndex
= *LastMsrIndex
+ 1; MsrIndex
< ARRAY_SIZE (mMtrrLibFixedMtrrTable
); MsrIndex
++) {
528 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrIndex
].BaseAddress
) &&
531 mMtrrLibFixedMtrrTable
[MsrIndex
].BaseAddress
+
532 (8 * mMtrrLibFixedMtrrTable
[MsrIndex
].Length
)
540 ASSERT (MsrIndex
!= ARRAY_SIZE (mMtrrLibFixedMtrrTable
));
543 // Find the begin offset in fixed MTRR and calculate byte offset of left shift
545 if ((((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrIndex
].BaseAddress
) % mMtrrLibFixedMtrrTable
[MsrIndex
].Length
) != 0) {
547 // Base address should be aligned to the begin of a certain Fixed MTRR range.
549 return RETURN_UNSUPPORTED
;
551 LeftByteShift
= ((UINT32
)*Base
- mMtrrLibFixedMtrrTable
[MsrIndex
].BaseAddress
) / mMtrrLibFixedMtrrTable
[MsrIndex
].Length
;
552 ASSERT (LeftByteShift
< 8);
555 // Find the end offset in fixed MTRR and calculate byte offset of right shift
557 SubLength
= mMtrrLibFixedMtrrTable
[MsrIndex
].Length
* (8 - LeftByteShift
);
558 if (*Length
>= SubLength
) {
561 if (((UINT32
)(*Length
) % mMtrrLibFixedMtrrTable
[MsrIndex
].Length
) != 0) {
563 // Length should be aligned to the end of a certain Fixed MTRR range.
565 return RETURN_UNSUPPORTED
;
567 RightByteShift
= 8 - LeftByteShift
- (UINT32
)(*Length
) / mMtrrLibFixedMtrrTable
[MsrIndex
].Length
;
569 // Update SubLength by actual length
574 *ClearMask
= CLEAR_SEED
;
575 *OrMask
= MultU64x32 (OR_SEED
, (UINT32
) Type
);
577 if (LeftByteShift
!= 0) {
579 // Clear the low bits by LeftByteShift
581 *ClearMask
&= LShiftU64 (*ClearMask
, LeftByteShift
* 8);
582 *OrMask
&= LShiftU64 (*OrMask
, LeftByteShift
* 8);
585 if (RightByteShift
!= 0) {
587 // Clear the high bits by RightByteShift
589 *ClearMask
&= RShiftU64 (*ClearMask
, RightByteShift
* 8);
590 *OrMask
&= RShiftU64 (*OrMask
, RightByteShift
* 8);
593 *Length
-= SubLength
;
596 *LastMsrIndex
= MsrIndex
;
598 return RETURN_SUCCESS
;
603 Worker function gets the attribute of variable MTRRs.
605 This function shadows the content of variable MTRRs into an
606 internal array: VariableMtrr.
608 @param[in] VariableSettings The variable MTRR values to shadow
609 @param[in] VariableMtrrCount The number of variable MTRRs
610 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
611 @param[in] MtrrValidAddressMask The valid address mask for MTRR
612 @param[out] VariableMtrr The array to shadow variable MTRRs content
614 @return Number of MTRRs which has been used.
618 MtrrGetMemoryAttributeInVariableMtrrWorker (
619 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
620 IN UINTN VariableMtrrCount
,
621 IN UINT64 MtrrValidBitsMask
,
622 IN UINT64 MtrrValidAddressMask
,
623 OUT VARIABLE_MTRR
*VariableMtrr
629 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * ARRAY_SIZE (VariableSettings
->Mtrr
));
630 for (Index
= 0, UsedMtrr
= 0; Index
< VariableMtrrCount
; Index
++) {
631 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &VariableSettings
->Mtrr
[Index
].Mask
)->Bits
.V
!= 0) {
632 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
633 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
634 VariableMtrr
[Index
].Length
=
635 ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
636 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
637 VariableMtrr
[Index
].Valid
= TRUE
;
638 VariableMtrr
[Index
].Used
= TRUE
;
646 Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array.
647 One MTRR_MEMORY_RANGE element is created for each MTRR setting.
648 The routine doesn't remove the overlap or combine the near-by region.
650 @param[in] VariableSettings The variable MTRR values to shadow
651 @param[in] VariableMtrrCount The number of variable MTRRs
652 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
653 @param[in] MtrrValidAddressMask The valid address mask for MTRR
654 @param[out] VariableMtrr The array to shadow variable MTRRs content
656 @return Number of MTRRs which has been used.
660 MtrrLibGetRawVariableRanges (
661 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
662 IN UINTN VariableMtrrCount
,
663 IN UINT64 MtrrValidBitsMask
,
664 IN UINT64 MtrrValidAddressMask
,
665 OUT MTRR_MEMORY_RANGE
*VariableMtrr
671 ZeroMem (VariableMtrr
, sizeof (MTRR_MEMORY_RANGE
) * ARRAY_SIZE (VariableSettings
->Mtrr
));
672 for (Index
= 0, UsedMtrr
= 0; Index
< VariableMtrrCount
; Index
++) {
673 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER
*) &VariableSettings
->Mtrr
[Index
].Mask
)->Bits
.V
!= 0) {
674 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
675 VariableMtrr
[Index
].Length
=
676 ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
677 VariableMtrr
[Index
].Type
= (MTRR_MEMORY_CACHE_TYPE
)(VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
685 Gets the attribute of variable MTRRs.
687 This function shadows the content of variable MTRRs into an
688 internal array: VariableMtrr.
690 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
691 @param[in] MtrrValidAddressMask The valid address mask for MTRR
692 @param[out] VariableMtrr The array to shadow variable MTRRs content
694 @return The return value of this parameter indicates the
695 number of MTRRs which has been used.
700 MtrrGetMemoryAttributeInVariableMtrr (
701 IN UINT64 MtrrValidBitsMask
,
702 IN UINT64 MtrrValidAddressMask
,
703 OUT VARIABLE_MTRR
*VariableMtrr
706 MTRR_VARIABLE_SETTINGS VariableSettings
;
708 if (!IsMtrrSupported ()) {
712 MtrrGetVariableMtrrWorker (
714 GetVariableMtrrCountWorker (),
718 return MtrrGetMemoryAttributeInVariableMtrrWorker (
720 GetFirmwareVariableMtrrCountWorker (),
722 MtrrValidAddressMask
,
728 Return the biggest alignment (lowest set bit) of address.
729 The function is equivalent to: 1 << LowBitSet64 (Address).
731 @param Address The address to return the alignment.
732 @param Alignment0 The alignment to return when Address is 0.
734 @return The least alignment of the Address.
737 MtrrLibBiggestAlignment (
746 return Address
& ((~Address
) + 1);
750 Return whether the left MTRR type precedes the right MTRR type.
752 The MTRR type precedence rules are:
753 1. UC precedes any other type
755 For further details, please refer the IA32 Software Developer's Manual,
756 Volume 3, Section "MTRR Precedences".
758 @param Left The left MTRR type.
759 @param Right The right MTRR type.
761 @retval TRUE Left precedes Right.
762 @retval FALSE Left doesn't precede Right.
765 MtrrLibTypeLeftPrecedeRight (
766 IN MTRR_MEMORY_CACHE_TYPE Left
,
767 IN MTRR_MEMORY_CACHE_TYPE Right
770 return (BOOLEAN
) (Left
== CacheUncacheable
|| (Left
== CacheWriteThrough
&& Right
== CacheWriteBack
));
774 Initializes the valid bits mask and valid address mask for MTRRs.
776 This function initializes the valid bits mask and valid address mask for MTRRs.
778 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
779 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
783 MtrrLibInitializeMtrrMask (
784 OUT UINT64
*MtrrValidBitsMask
,
785 OUT UINT64
*MtrrValidAddressMask
788 UINT32 MaxExtendedFunction
;
789 CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize
;
792 AsmCpuid (CPUID_EXTENDED_FUNCTION
, &MaxExtendedFunction
, NULL
, NULL
, NULL
);
794 if (MaxExtendedFunction
>= CPUID_VIR_PHY_ADDRESS_SIZE
) {
795 AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE
, &VirPhyAddressSize
.Uint32
, NULL
, NULL
, NULL
);
797 VirPhyAddressSize
.Bits
.PhysicalAddressBits
= 36;
800 *MtrrValidBitsMask
= LShiftU64 (1, VirPhyAddressSize
.Bits
.PhysicalAddressBits
) - 1;
801 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
806 Determines the real attribute of a memory range.
808 This function is to arbitrate the real attribute of the memory when
809 there are 2 MTRRs covers the same memory range. For further details,
810 please refer the IA32 Software Developer's Manual, Volume 3,
811 Section "MTRR Precedences".
813 @param[in] MtrrType1 The first kind of Memory type
814 @param[in] MtrrType2 The second kind of memory type
817 MTRR_MEMORY_CACHE_TYPE
819 IN MTRR_MEMORY_CACHE_TYPE MtrrType1
,
820 IN MTRR_MEMORY_CACHE_TYPE MtrrType2
823 if (MtrrType1
== MtrrType2
) {
828 MtrrLibTypeLeftPrecedeRight (MtrrType1
, MtrrType2
) ||
829 MtrrLibTypeLeftPrecedeRight (MtrrType2
, MtrrType1
)
832 if (MtrrLibTypeLeftPrecedeRight (MtrrType1
, MtrrType2
)) {
840 Worker function will get the memory cache type of the specific address.
842 If MtrrSetting is not NULL, gets the memory cache type from input
843 MTRR settings buffer.
844 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
846 @param[in] MtrrSetting A buffer holding all MTRRs content.
847 @param[in] Address The specific address
849 @return Memory cache type of the specific address
852 MTRR_MEMORY_CACHE_TYPE
853 MtrrGetMemoryAttributeByAddressWorker (
854 IN MTRR_SETTINGS
*MtrrSetting
,
855 IN PHYSICAL_ADDRESS Address
858 MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType
;
862 MTRR_MEMORY_CACHE_TYPE MtrrType
;
863 MTRR_MEMORY_RANGE VariableMtrr
[ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
)];
864 UINT64 MtrrValidBitsMask
;
865 UINT64 MtrrValidAddressMask
;
866 UINT32 VariableMtrrCount
;
867 MTRR_VARIABLE_SETTINGS VariableSettings
;
870 // Check if MTRR is enabled, if not, return UC as attribute
872 if (MtrrSetting
== NULL
) {
873 DefType
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE
);
875 DefType
.Uint64
= MtrrSetting
->MtrrDefType
;
878 if (DefType
.Bits
.E
== 0) {
879 return CacheUncacheable
;
883 // If address is less than 1M, then try to go through the fixed MTRR
885 if (Address
< BASE_1MB
) {
886 if (DefType
.Bits
.FE
!= 0) {
888 // Go through the fixed MTRR
890 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
891 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
892 Address
< mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
893 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)) {
895 ((UINTN
) Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
896 mMtrrLibFixedMtrrTable
[Index
].Length
;
897 if (MtrrSetting
== NULL
) {
898 FixedMtrr
= AsmReadMsr64 (mMtrrLibFixedMtrrTable
[Index
].Msr
);
900 FixedMtrr
= MtrrSetting
->Fixed
.Mtrr
[Index
];
902 return (MTRR_MEMORY_CACHE_TYPE
) (RShiftU64 (FixedMtrr
, SubIndex
* 8) & 0xFF);
908 VariableMtrrCount
= GetVariableMtrrCountWorker ();
909 ASSERT (VariableMtrrCount
<= ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
));
910 MtrrGetVariableMtrrWorker (MtrrSetting
, VariableMtrrCount
, &VariableSettings
);
912 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
913 MtrrLibGetRawVariableRanges (
917 MtrrValidAddressMask
,
922 // Go through the variable MTRR
924 MtrrType
= CacheInvalid
;
925 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
926 if (VariableMtrr
[Index
].Length
!= 0) {
927 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
928 Address
< VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
) {
929 if (MtrrType
== CacheInvalid
) {
930 MtrrType
= (MTRR_MEMORY_CACHE_TYPE
) VariableMtrr
[Index
].Type
;
932 MtrrType
= MtrrLibPrecedence (MtrrType
, (MTRR_MEMORY_CACHE_TYPE
) VariableMtrr
[Index
].Type
);
939 // If there is no MTRR which covers the Address, use the default MTRR type.
941 if (MtrrType
== CacheInvalid
) {
942 MtrrType
= (MTRR_MEMORY_CACHE_TYPE
) DefType
.Bits
.Type
;
950 This function will get the memory cache type of the specific address.
952 This function is mainly for debug purpose.
954 @param[in] Address The specific address
956 @return Memory cache type of the specific address
959 MTRR_MEMORY_CACHE_TYPE
961 MtrrGetMemoryAttribute (
962 IN PHYSICAL_ADDRESS Address
965 if (!IsMtrrSupported ()) {
966 return CacheUncacheable
;
969 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
973 Update the Ranges array to change the specified range identified by
974 BaseAddress and Length to Type.
976 @param Ranges Array holding memory type settings for all memory regions.
977 @param Capacity The maximum count of memory ranges the array can hold.
978 @param Count Return the new memory range count in the array.
979 @param BaseAddress The base address of the memory range to change type.
980 @param Length The length of the memory range to change type.
981 @param Type The new type of the specified memory range.
983 @retval RETURN_SUCCESS The type of the specified memory range is
984 changed successfully.
985 @retval RETURN_ALREADY_STARTED The type of the specified memory range equals
987 @retval RETURN_OUT_OF_RESOURCES The new type set causes the count of memory
988 range exceeds capacity.
991 MtrrLibSetMemoryType (
992 IN MTRR_MEMORY_RANGE
*Ranges
,
995 IN UINT64 BaseAddress
,
997 IN MTRR_MEMORY_CACHE_TYPE Type
1010 Limit
= BaseAddress
+ Length
;
1011 StartIndex
= *Count
;
1013 for (Index
= 0; Index
< *Count
; Index
++) {
1014 if ((StartIndex
== *Count
) &&
1015 (Ranges
[Index
].BaseAddress
<= BaseAddress
) &&
1016 (BaseAddress
< Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
)) {
1018 LengthLeft
= BaseAddress
- Ranges
[Index
].BaseAddress
;
1021 if ((EndIndex
== *Count
) &&
1022 (Ranges
[Index
].BaseAddress
< Limit
) &&
1023 (Limit
<= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
)) {
1025 LengthRight
= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
- Limit
;
1030 ASSERT (StartIndex
!= *Count
&& EndIndex
!= *Count
);
1031 if (StartIndex
== EndIndex
&& Ranges
[StartIndex
].Type
== Type
) {
1032 return RETURN_ALREADY_STARTED
;
1036 // The type change may cause merging with previous range or next range.
1037 // Update the StartIndex, EndIndex, BaseAddress, Length so that following
1038 // logic doesn't need to consider merging.
1040 if (StartIndex
!= 0) {
1041 if (LengthLeft
== 0 && Ranges
[StartIndex
- 1].Type
== Type
) {
1043 Length
+= Ranges
[StartIndex
].Length
;
1044 BaseAddress
-= Ranges
[StartIndex
].Length
;
1047 if (EndIndex
!= (*Count
) - 1) {
1048 if (LengthRight
== 0 && Ranges
[EndIndex
+ 1].Type
== Type
) {
1050 Length
+= Ranges
[EndIndex
].Length
;
1055 // |- 0 -|- 1 -|- 2 -|- 3 -| StartIndex EndIndex DeltaCount Count (Count = 4)
1056 // |++++++++++++++++++| 0 3 1=3-0-2 3
1057 // |+++++++| 0 1 -1=1-0-2 5
1058 // |+| 0 0 -2=0-0-2 6
1059 // |+++| 0 0 -1=0-0-2+1 5
1062 DeltaCount
= EndIndex
- StartIndex
- 2;
1063 if (LengthLeft
== 0) {
1066 if (LengthRight
== 0) {
1069 if (*Count
- DeltaCount
> Capacity
) {
1070 return RETURN_OUT_OF_RESOURCES
;
1074 // Reserve (-DeltaCount) space
1076 CopyMem (&Ranges
[EndIndex
+ 1 - DeltaCount
], &Ranges
[EndIndex
+ 1], (*Count
- EndIndex
- 1) * sizeof (Ranges
[0]));
1077 *Count
-= DeltaCount
;
1079 if (LengthLeft
!= 0) {
1080 Ranges
[StartIndex
].Length
= LengthLeft
;
1083 if (LengthRight
!= 0) {
1084 Ranges
[EndIndex
- DeltaCount
].BaseAddress
= BaseAddress
+ Length
;
1085 Ranges
[EndIndex
- DeltaCount
].Length
= LengthRight
;
1086 Ranges
[EndIndex
- DeltaCount
].Type
= Ranges
[EndIndex
].Type
;
1088 Ranges
[StartIndex
].BaseAddress
= BaseAddress
;
1089 Ranges
[StartIndex
].Length
= Length
;
1090 Ranges
[StartIndex
].Type
= Type
;
1091 return RETURN_SUCCESS
;
1095 Return the number of memory types in range [BaseAddress, BaseAddress + Length).
1097 @param Ranges Array holding memory type settings for all memory regions.
1098 @param RangeCount The count of memory ranges the array holds.
1099 @param BaseAddress Base address.
1100 @param Length Length.
1101 @param Types Return bit mask to indicate all memory types in the specified range.
1103 @retval Number of memory types.
1106 MtrrLibGetNumberOfTypes (
1107 IN CONST MTRR_MEMORY_RANGE
*Ranges
,
1108 IN UINTN RangeCount
,
1109 IN UINT64 BaseAddress
,
1111 IN OUT UINT8
*Types OPTIONAL
1120 for (Index
= 0; Index
< RangeCount
; Index
++) {
1121 if ((Ranges
[Index
].BaseAddress
<= BaseAddress
) &&
1122 (BaseAddress
< Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
)
1124 if ((LocalTypes
& (1 << Ranges
[Index
].Type
)) == 0) {
1125 LocalTypes
|= (UINT8
)(1 << Ranges
[Index
].Type
);
1129 if (BaseAddress
+ Length
> Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
) {
1130 Length
-= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
- BaseAddress
;
1131 BaseAddress
= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
;
1138 if (Types
!= NULL
) {
1139 *Types
= LocalTypes
;
1145 Calculate the least MTRR number from vertex Start to Stop and update
1146 the Previous of all vertices from Start to Stop is updated to reflect
1147 how the memory range is covered by MTRR.
1149 @param VertexCount The count of vertices in the graph.
1150 @param Vertices Array holding all vertices.
1151 @param Weight 2-dimention array holding weights between vertices.
1152 @param Start Start vertex.
1153 @param Stop Stop vertex.
1154 @param IncludeOptional TRUE to count the optional weight.
1157 MtrrLibCalculateLeastMtrrs (
1158 IN UINT16 VertexCount
,
1159 IN MTRR_LIB_ADDRESS
*Vertices
,
1160 IN OUT CONST UINT8
*Weight
,
1163 IN BOOLEAN IncludeOptional
1172 for (Index
= Start
; Index
<= Stop
; Index
++) {
1173 Vertices
[Index
].Visited
= FALSE
;
1174 Vertices
[Index
].Previous
= VertexCount
;
1175 Mandatory
= Weight
[M(Start
,Index
)];
1176 Vertices
[Index
].Weight
= Mandatory
;
1177 if (Mandatory
!= MAX_WEIGHT
) {
1178 Optional
= IncludeOptional
? Weight
[O(Start
, Index
)] : 0;
1179 Vertices
[Index
].Weight
+= Optional
;
1180 ASSERT (Vertices
[Index
].Weight
>= Optional
);
1186 while (!Vertices
[Stop
].Visited
) {
1188 // Update the weight from the shortest vertex to other unvisited vertices
1190 for (Index
= Start
+ 1; Index
<= Stop
; Index
++) {
1191 if (!Vertices
[Index
].Visited
) {
1192 Mandatory
= Weight
[M(MinI
, Index
)];
1193 if (Mandatory
!= MAX_WEIGHT
) {
1194 Optional
= IncludeOptional
? Weight
[O(MinI
, Index
)] : 0;
1195 if (MinWeight
+ Mandatory
+ Optional
<= Vertices
[Index
].Weight
) {
1196 Vertices
[Index
].Weight
= MinWeight
+ Mandatory
+ Optional
;
1197 Vertices
[Index
].Previous
= MinI
; // Previous is Start based.
1204 // Find the shortest vertex from Start
1207 MinWeight
= MAX_WEIGHT
;
1208 for (Index
= Start
+ 1; Index
<= Stop
; Index
++) {
1209 if (!Vertices
[Index
].Visited
&& MinWeight
> Vertices
[Index
].Weight
) {
1211 MinWeight
= Vertices
[Index
].Weight
;
1216 // Mark the shortest vertex from Start as visited
1218 Vertices
[MinI
].Visited
= TRUE
;
1223 Append the MTRR setting to MTRR setting array.
1225 @param Mtrrs Array holding all MTRR settings.
1226 @param MtrrCapacity Capacity of the MTRR array.
1227 @param MtrrCount The count of MTRR settings in array.
1228 @param BaseAddress Base address.
1229 @param Length Length.
1230 @param Type Memory type.
1232 @retval RETURN_SUCCESS MTRR setting is appended to array.
1233 @retval RETURN_OUT_OF_RESOURCES Array is full.
1236 MtrrLibAppendVariableMtrr (
1237 IN OUT MTRR_MEMORY_RANGE
*Mtrrs
,
1238 IN UINT32 MtrrCapacity
,
1239 IN OUT UINT32
*MtrrCount
,
1240 IN UINT64 BaseAddress
,
1242 IN MTRR_MEMORY_CACHE_TYPE Type
1245 if (*MtrrCount
== MtrrCapacity
) {
1246 return RETURN_OUT_OF_RESOURCES
;
1249 Mtrrs
[*MtrrCount
].BaseAddress
= BaseAddress
;
1250 Mtrrs
[*MtrrCount
].Length
= Length
;
1251 Mtrrs
[*MtrrCount
].Type
= Type
;
1253 return RETURN_SUCCESS
;
1257 Return the memory type that has the least precedence.
1259 @param TypeBits Bit mask of memory type.
1261 @retval Memory type that has the least precedence.
1263 MTRR_MEMORY_CACHE_TYPE
1270 ASSERT (TypeBits
!= 0);
1271 for (Type
= 7; (INT8
)TypeBits
> 0; Type
--, TypeBits
<<= 1);
1272 return (MTRR_MEMORY_CACHE_TYPE
)Type
;
1276 Return TRUE when the Operand is exactly power of 2.
1278 @retval TRUE Operand is exactly power of 2.
1279 @retval FALSE Operand is not power of 2.
1282 MtrrLibIsPowerOfTwo (
1286 ASSERT (Operand
!= 0);
1287 return (BOOLEAN
) ((Operand
& (Operand
- 1)) == 0);
1291 Calculate the subtractive path from vertex Start to Stop.
1293 @param DefaultType Default memory type.
1294 @param A0 Alignment to use when base address is 0.
1295 @param Ranges Array holding memory type settings for all memory regions.
1296 @param RangeCount The count of memory ranges the array holds.
1297 @param VertexCount The count of vertices in the graph.
1298 @param Vertices Array holding all vertices.
1299 @param Weight 2-dimention array holding weights between vertices.
1300 @param Start Start vertex.
1301 @param Stop Stop vertex.
1302 @param Types Type bit mask of memory range from Start to Stop.
1303 @param TypeCount Number of different memory types from Start to Stop.
1304 @param Mtrrs Array holding all MTRR settings.
1305 @param MtrrCapacity Capacity of the MTRR array.
1306 @param MtrrCount The count of MTRR settings in array.
1308 @retval RETURN_SUCCESS The subtractive path is calculated successfully.
1309 @retval RETURN_OUT_OF_RESOURCES The MTRR setting array is full.
1313 MtrrLibCalculateSubtractivePath (
1314 IN MTRR_MEMORY_CACHE_TYPE DefaultType
,
1316 IN CONST MTRR_MEMORY_RANGE
*Ranges
,
1317 IN UINTN RangeCount
,
1318 IN UINT16 VertexCount
,
1319 IN MTRR_LIB_ADDRESS
*Vertices
,
1320 IN OUT UINT8
*Weight
,
1325 IN OUT MTRR_MEMORY_RANGE
*Mtrrs
, OPTIONAL
1326 IN UINT32 MtrrCapacity
, OPTIONAL
1327 IN OUT UINT32
*MtrrCount OPTIONAL
1330 RETURN_STATUS Status
;
1333 UINT8 PrecedentTypes
;
1342 MTRR_MEMORY_CACHE_TYPE LowestType
;
1343 MTRR_MEMORY_CACHE_TYPE LowestPrecedentType
;
1345 Base
= Vertices
[Start
].Address
;
1346 Length
= Vertices
[Stop
].Address
- Base
;
1348 LowestType
= MtrrLibLowestType (Types
);
1351 // Clear the lowest type (highest bit) to get the precedent types
1353 PrecedentTypes
= ~(1 << LowestType
) & Types
;
1354 LowestPrecedentType
= MtrrLibLowestType (PrecedentTypes
);
1356 if (Mtrrs
== NULL
) {
1357 Weight
[M(Start
, Stop
)] = ((LowestType
== DefaultType
) ? 0 : 1);
1358 Weight
[O(Start
, Stop
)] = ((LowestType
== DefaultType
) ? 1 : 0);
1361 // Add all high level ranges
1364 for (Index
= 0; Index
< RangeCount
; Index
++) {
1368 if ((Base
< Ranges
[Index
].BaseAddress
) || (Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
<= Base
)) {
1373 // Base is in the Range[Index]
1375 if (Base
+ Length
> Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
) {
1376 SubLength
= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
- Base
;
1380 if (((1 << Ranges
[Index
].Type
) & PrecedentTypes
) != 0) {
1382 // Meet a range whose types take precedence.
1383 // Update the [HBase, HBase + HLength) to include the range,
1384 // [HBase, HBase + HLength) may contain sub ranges with 2 different types, and both take precedence.
1386 if (HBase
== MAX_UINT64
) {
1389 HLength
+= SubLength
;
1393 Length
-= SubLength
;
1399 if ((Ranges
[Index
].Type
== LowestType
) || (Length
== 0)) { // meet low type or end
1402 // Add the MTRRs for each high priority type range
1403 // the range[HBase, HBase + HLength) contains only two types.
1404 // We might use positive or subtractive, depending on which way uses less MTRR
1406 for (SubStart
= Start
; SubStart
<= Stop
; SubStart
++) {
1407 if (Vertices
[SubStart
].Address
== HBase
) {
1412 for (SubStop
= SubStart
; SubStop
<= Stop
; SubStop
++) {
1413 if (Vertices
[SubStop
].Address
== HBase
+ HLength
) {
1417 ASSERT (Vertices
[SubStart
].Address
== HBase
);
1418 ASSERT (Vertices
[SubStop
].Address
== HBase
+ HLength
);
1420 if ((TypeCount
== 2) || (SubStart
== SubStop
- 1)) {
1422 // add subtractive MTRRs for [HBase, HBase + HLength)
1423 // [HBase, HBase + HLength) contains only one type.
1424 // while - loop is to split the range to MTRR - compliant aligned range.
1426 if (Mtrrs
== NULL
) {
1427 Weight
[M (Start
, Stop
)] += (UINT8
)(SubStop
- SubStart
);
1429 while (SubStart
!= SubStop
) {
1430 Status
= MtrrLibAppendVariableMtrr (
1431 Mtrrs
, MtrrCapacity
, MtrrCount
,
1432 Vertices
[SubStart
].Address
, Vertices
[SubStart
].Length
, Vertices
[SubStart
].Type
1434 if (RETURN_ERROR (Status
)) {
1441 ASSERT (TypeCount
== 3);
1442 MtrrLibCalculateLeastMtrrs (VertexCount
, Vertices
, Weight
, SubStart
, SubStop
, TRUE
);
1444 if (Mtrrs
== NULL
) {
1445 Weight
[M (Start
, Stop
)] += Vertices
[SubStop
].Weight
;
1447 // When we need to collect the optimal path from SubStart to SubStop
1448 while (SubStop
!= SubStart
) {
1450 Pre
= Vertices
[Cur
].Previous
;
1453 if (Weight
[M (Pre
, Cur
)] + Weight
[O (Pre
, Cur
)] != 0) {
1454 Status
= MtrrLibAppendVariableMtrr (
1455 Mtrrs
, MtrrCapacity
, MtrrCount
,
1456 Vertices
[Pre
].Address
, Vertices
[Cur
].Address
- Vertices
[Pre
].Address
,
1457 (Pre
!= Cur
- 1) ? LowestPrecedentType
: Vertices
[Pre
].Type
1459 if (RETURN_ERROR (Status
)) {
1463 if (Pre
!= Cur
- 1) {
1464 Status
= MtrrLibCalculateSubtractivePath (
1467 VertexCount
, Vertices
, Weight
,
1468 Pre
, Cur
, PrecedentTypes
, 2,
1469 Mtrrs
, MtrrCapacity
, MtrrCount
1471 if (RETURN_ERROR (Status
)) {
1480 // Reset HBase, HLength
1486 return RETURN_SUCCESS
;
1490 Calculate MTRR settings to cover the specified memory ranges.
1492 @param DefaultType Default memory type.
1493 @param A0 Alignment to use when base address is 0.
1494 @param Ranges Memory range array holding the memory type
1495 settings for all memory address.
1496 @param RangeCount Count of memory ranges.
1497 @param Scratch A temporary scratch buffer that is used to perform the calculation.
1498 This is an optional parameter that may be NULL.
1499 @param ScratchSize Pointer to the size in bytes of the scratch buffer.
1500 It may be updated to the actual required size when the calculation
1501 needs more scratch buffer.
1502 @param Mtrrs Array holding all MTRR settings.
1503 @param MtrrCapacity Capacity of the MTRR array.
1504 @param MtrrCount The count of MTRR settings in array.
1506 @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.
1507 @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.
1508 @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
1511 MtrrLibCalculateMtrrs (
1512 IN MTRR_MEMORY_CACHE_TYPE DefaultType
,
1514 IN CONST MTRR_MEMORY_RANGE
*Ranges
,
1515 IN UINTN RangeCount
,
1517 IN OUT UINTN
*ScratchSize
,
1518 IN OUT MTRR_MEMORY_RANGE
*Mtrrs
,
1519 IN UINT32 MtrrCapacity
,
1520 IN OUT UINT32
*MtrrCount
1530 MTRR_LIB_ADDRESS
*Vertices
;
1534 UINTN RequiredScratchSize
;
1539 RETURN_STATUS Status
;
1541 Base0
= Ranges
[0].BaseAddress
;
1542 Base1
= Ranges
[RangeCount
- 1].BaseAddress
+ Ranges
[RangeCount
- 1].Length
;
1543 MTRR_LIB_ASSERT_ALIGNED (Base0
, Base1
- Base0
);
1546 // Count the number of vertices.
1548 Vertices
= (MTRR_LIB_ADDRESS
*)Scratch
;
1549 for (VertexIndex
= 0, Index
= 0; Index
< RangeCount
; Index
++) {
1550 Base
= Ranges
[Index
].BaseAddress
;
1551 Length
= Ranges
[Index
].Length
;
1552 while (Length
!= 0) {
1553 Alignment
= MtrrLibBiggestAlignment (Base
, A0
);
1554 SubLength
= Alignment
;
1555 if (SubLength
> Length
) {
1556 SubLength
= GetPowerOfTwo64 (Length
);
1558 if (VertexIndex
< *ScratchSize
/ sizeof (*Vertices
)) {
1559 Vertices
[VertexIndex
].Address
= Base
;
1560 Vertices
[VertexIndex
].Alignment
= Alignment
;
1561 Vertices
[VertexIndex
].Type
= Ranges
[Index
].Type
;
1562 Vertices
[VertexIndex
].Length
= SubLength
;
1565 Length
-= SubLength
;
1570 // Vertices[VertexIndex] = Base1, so whole vertex count is (VertexIndex + 1).
1572 VertexCount
= VertexIndex
+ 1;
1574 DEBUG_CACHE
, " Count of vertices (%016llx - %016llx) = %d\n",
1575 Ranges
[0].BaseAddress
, Ranges
[RangeCount
- 1].BaseAddress
+ Ranges
[RangeCount
- 1].Length
, VertexCount
1577 ASSERT (VertexCount
< MAX_UINT16
);
1579 RequiredScratchSize
= VertexCount
* sizeof (*Vertices
) + VertexCount
* VertexCount
* sizeof (*Weight
);
1580 if (*ScratchSize
< RequiredScratchSize
) {
1581 *ScratchSize
= RequiredScratchSize
;
1582 return RETURN_BUFFER_TOO_SMALL
;
1584 Vertices
[VertexCount
- 1].Address
= Base1
;
1586 Weight
= (UINT8
*) &Vertices
[VertexCount
];
1587 for (VertexIndex
= 0; VertexIndex
< VertexCount
; VertexIndex
++) {
1589 // Set optional weight between vertices and self->self to 0
1591 SetMem (&Weight
[M(VertexIndex
, 0)], VertexIndex
+ 1, 0);
1593 // Set mandatory weight between vertices to MAX_WEIGHT
1595 SetMem (&Weight
[M (VertexIndex
, VertexIndex
+ 1)], VertexCount
- VertexIndex
- 1, MAX_WEIGHT
);
1597 // Final result looks like:
1605 // Set mandatory weight and optional weight for adjacent vertices
1607 for (VertexIndex
= 0; VertexIndex
< VertexCount
- 1; VertexIndex
++) {
1608 if (Vertices
[VertexIndex
].Type
!= DefaultType
) {
1609 Weight
[M (VertexIndex
, VertexIndex
+ 1)] = 1;
1610 Weight
[O (VertexIndex
, VertexIndex
+ 1)] = 0;
1612 Weight
[M (VertexIndex
, VertexIndex
+ 1)] = 0;
1613 Weight
[O (VertexIndex
, VertexIndex
+ 1)] = 1;
1617 for (TypeCount
= 2; TypeCount
<= 3; TypeCount
++) {
1618 for (Start
= 0; Start
< VertexCount
; Start
++) {
1619 for (Stop
= Start
+ 2; Stop
< VertexCount
; Stop
++) {
1620 ASSERT (Vertices
[Stop
].Address
> Vertices
[Start
].Address
);
1621 Length
= Vertices
[Stop
].Address
- Vertices
[Start
].Address
;
1622 if (Length
> Vertices
[Start
].Alignment
) {
1624 // Pickup a new Start when [Start, Stop) cannot be described by one MTRR.
1628 if ((Weight
[M(Start
, Stop
)] == MAX_WEIGHT
) && MtrrLibIsPowerOfTwo (Length
)) {
1629 if (MtrrLibGetNumberOfTypes (
1630 Ranges
, RangeCount
, Vertices
[Start
].Address
, Vertices
[Stop
].Address
- Vertices
[Start
].Address
, &Type
1633 // Update the Weight[Start, Stop] using subtractive path.
1635 MtrrLibCalculateSubtractivePath (
1638 (UINT16
)VertexCount
, Vertices
, Weight
,
1639 Start
, Stop
, Type
, TypeCount
,
1642 } else if (TypeCount
== 2) {
1644 // Pick up a new Start when we expect 2-type range, but 3-type range is met.
1645 // Because no matter how Stop is increased, we always meet 3-type range.
1654 Status
= RETURN_SUCCESS
;
1655 MtrrLibCalculateLeastMtrrs ((UINT16
) VertexCount
, Vertices
, Weight
, 0, (UINT16
) VertexCount
- 1, FALSE
);
1656 Stop
= (UINT16
) VertexCount
- 1;
1658 Start
= Vertices
[Stop
].Previous
;
1659 TypeCount
= MAX_UINT8
;
1661 if (Weight
[M(Start
, Stop
)] != 0) {
1662 TypeCount
= MtrrLibGetNumberOfTypes (Ranges
, RangeCount
, Vertices
[Start
].Address
, Vertices
[Stop
].Address
- Vertices
[Start
].Address
, &Type
);
1663 Status
= MtrrLibAppendVariableMtrr (
1664 Mtrrs
, MtrrCapacity
, MtrrCount
,
1665 Vertices
[Start
].Address
, Vertices
[Stop
].Address
- Vertices
[Start
].Address
,
1666 MtrrLibLowestType (Type
)
1668 if (RETURN_ERROR (Status
)) {
1673 if (Start
!= Stop
- 1) {
1675 // substractive path
1677 if (TypeCount
== MAX_UINT8
) {
1678 TypeCount
= MtrrLibGetNumberOfTypes (
1679 Ranges
, RangeCount
, Vertices
[Start
].Address
, Vertices
[Stop
].Address
- Vertices
[Start
].Address
, &Type
1682 Status
= MtrrLibCalculateSubtractivePath (
1685 (UINT16
) VertexCount
, Vertices
, Weight
, Start
, Stop
,
1687 Mtrrs
, MtrrCapacity
, MtrrCount
1689 if (RETURN_ERROR (Status
)) {
1700 Apply the fixed MTRR settings to memory range array.
1702 @param Fixed The fixed MTRR settings.
1703 @param Ranges Return the memory range array holding memory type
1704 settings for all memory address.
1705 @param RangeCapacity The capacity of memory range array.
1706 @param RangeCount Return the count of memory range.
1708 @retval RETURN_SUCCESS The memory range array is returned successfully.
1709 @retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
1712 MtrrLibApplyFixedMtrrs (
1713 IN MTRR_FIXED_SETTINGS
*Fixed
,
1714 IN OUT MTRR_MEMORY_RANGE
*Ranges
,
1715 IN UINTN RangeCapacity
,
1716 IN OUT UINTN
*RangeCount
1719 RETURN_STATUS Status
;
1722 MTRR_MEMORY_CACHE_TYPE MemoryType
;
1726 for (MsrIndex
= 0; MsrIndex
< ARRAY_SIZE (mMtrrLibFixedMtrrTable
); MsrIndex
++) {
1727 ASSERT (Base
== mMtrrLibFixedMtrrTable
[MsrIndex
].BaseAddress
);
1728 for (Index
= 0; Index
< sizeof (UINT64
); Index
++) {
1729 MemoryType
= (MTRR_MEMORY_CACHE_TYPE
)((UINT8
*)(&Fixed
->Mtrr
[MsrIndex
]))[Index
];
1730 Status
= MtrrLibSetMemoryType (
1731 Ranges
, RangeCapacity
, RangeCount
, Base
, mMtrrLibFixedMtrrTable
[MsrIndex
].Length
, MemoryType
1733 if (Status
== RETURN_OUT_OF_RESOURCES
) {
1736 Base
+= mMtrrLibFixedMtrrTable
[MsrIndex
].Length
;
1739 ASSERT (Base
== BASE_1MB
);
1740 return RETURN_SUCCESS
;
1744 Apply the variable MTRR settings to memory range array.
1746 @param VariableMtrr The variable MTRR array.
1747 @param VariableMtrrCount The count of variable MTRRs.
1748 @param Ranges Return the memory range array with new MTRR settings applied.
1749 @param RangeCapacity The capacity of memory range array.
1750 @param RangeCount Return the count of memory range.
1752 @retval RETURN_SUCCESS The memory range array is returned successfully.
1753 @retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
1756 MtrrLibApplyVariableMtrrs (
1757 IN CONST MTRR_MEMORY_RANGE
*VariableMtrr
,
1758 IN UINT32 VariableMtrrCount
,
1759 IN OUT MTRR_MEMORY_RANGE
*Ranges
,
1760 IN UINTN RangeCapacity
,
1761 IN OUT UINTN
*RangeCount
1764 RETURN_STATUS Status
;
1770 // UC > * (except WB, UC) > WB
1776 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1777 if ((VariableMtrr
[Index
].Length
!= 0) && (VariableMtrr
[Index
].Type
== CacheWriteBack
)) {
1778 Status
= MtrrLibSetMemoryType (
1779 Ranges
, RangeCapacity
, RangeCount
,
1780 VariableMtrr
[Index
].BaseAddress
, VariableMtrr
[Index
].Length
, VariableMtrr
[Index
].Type
1782 if (Status
== RETURN_OUT_OF_RESOURCES
) {
1789 // 2. Set other types than WB or UC
1791 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1792 if ((VariableMtrr
[Index
].Length
!= 0) &&
1793 (VariableMtrr
[Index
].Type
!= CacheWriteBack
) && (VariableMtrr
[Index
].Type
!= CacheUncacheable
)) {
1794 Status
= MtrrLibSetMemoryType (
1795 Ranges
, RangeCapacity
, RangeCount
,
1796 VariableMtrr
[Index
].BaseAddress
, VariableMtrr
[Index
].Length
, VariableMtrr
[Index
].Type
1798 if (Status
== RETURN_OUT_OF_RESOURCES
) {
1807 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1808 if (VariableMtrr
[Index
].Length
!= 0 && VariableMtrr
[Index
].Type
== CacheUncacheable
) {
1809 Status
= MtrrLibSetMemoryType (
1810 Ranges
, RangeCapacity
, RangeCount
,
1811 VariableMtrr
[Index
].BaseAddress
, VariableMtrr
[Index
].Length
, VariableMtrr
[Index
].Type
1813 if (Status
== RETURN_OUT_OF_RESOURCES
) {
1818 return RETURN_SUCCESS
;
1822 Return the memory type bit mask that's compatible to first type in the Ranges.
1824 @param Ranges Memory range array holding the memory type
1825 settings for all memory address.
1826 @param RangeCount Count of memory ranges.
1828 @return Compatible memory type bit mask.
1831 MtrrLibGetCompatibleTypes (
1832 IN CONST MTRR_MEMORY_RANGE
*Ranges
,
1836 ASSERT (RangeCount
!= 0);
1838 switch (Ranges
[0].Type
) {
1839 case CacheWriteBack
:
1840 case CacheWriteThrough
:
1841 return (1 << CacheWriteBack
) | (1 << CacheWriteThrough
) | (1 << CacheUncacheable
);
1844 case CacheWriteCombining
:
1845 case CacheWriteProtected
:
1846 return (1 << Ranges
[0].Type
) | (1 << CacheUncacheable
);
1849 case CacheUncacheable
:
1850 if (RangeCount
== 1) {
1851 return (1 << CacheUncacheable
);
1853 return MtrrLibGetCompatibleTypes (&Ranges
[1], RangeCount
- 1);
1865 Overwrite the destination MTRR settings with the source MTRR settings.
1866 This routine is to make sure the modification to destination MTRR settings
1867 is as small as possible.
1869 @param DstMtrrs Destination MTRR settings.
1870 @param DstMtrrCount Count of destination MTRR settings.
1871 @param SrcMtrrs Source MTRR settings.
1872 @param SrcMtrrCount Count of source MTRR settings.
1873 @param Modified Flag array to indicate which destination MTRR setting is modified.
1876 MtrrLibMergeVariableMtrr (
1877 MTRR_MEMORY_RANGE
*DstMtrrs
,
1878 UINT32 DstMtrrCount
,
1879 MTRR_MEMORY_RANGE
*SrcMtrrs
,
1880 UINT32 SrcMtrrCount
,
1887 ASSERT (SrcMtrrCount
<= DstMtrrCount
);
1889 for (DstIndex
= 0; DstIndex
< DstMtrrCount
; DstIndex
++) {
1890 Modified
[DstIndex
] = FALSE
;
1892 if (DstMtrrs
[DstIndex
].Length
== 0) {
1895 for (SrcIndex
= 0; SrcIndex
< SrcMtrrCount
; SrcIndex
++) {
1896 if (DstMtrrs
[DstIndex
].BaseAddress
== SrcMtrrs
[SrcIndex
].BaseAddress
&&
1897 DstMtrrs
[DstIndex
].Length
== SrcMtrrs
[SrcIndex
].Length
&&
1898 DstMtrrs
[DstIndex
].Type
== SrcMtrrs
[SrcIndex
].Type
) {
1903 if (SrcIndex
== SrcMtrrCount
) {
1905 // Remove the one from DstMtrrs which is not in SrcMtrrs
1907 DstMtrrs
[DstIndex
].Length
= 0;
1908 Modified
[DstIndex
] = TRUE
;
1911 // Remove the one from SrcMtrrs which is also in DstMtrrs
1913 SrcMtrrs
[SrcIndex
].Length
= 0;
1918 // Now valid MTRR only exists in either DstMtrrs or SrcMtrrs.
1919 // Merge MTRRs from SrcMtrrs to DstMtrrs
1922 for (SrcIndex
= 0; SrcIndex
< SrcMtrrCount
; SrcIndex
++) {
1923 if (SrcMtrrs
[SrcIndex
].Length
!= 0) {
1926 // Find the empty slot in DstMtrrs
1928 while (DstIndex
< DstMtrrCount
) {
1929 if (DstMtrrs
[DstIndex
].Length
== 0) {
1934 ASSERT (DstIndex
< DstMtrrCount
);
1935 CopyMem (&DstMtrrs
[DstIndex
], &SrcMtrrs
[SrcIndex
], sizeof (SrcMtrrs
[0]));
1936 Modified
[DstIndex
] = TRUE
;
1942 Calculate the variable MTRR settings for all memory ranges.
1944 @param DefaultType Default memory type.
1945 @param A0 Alignment to use when base address is 0.
1946 @param Ranges Memory range array holding the memory type
1947 settings for all memory address.
1948 @param RangeCount Count of memory ranges.
1949 @param Scratch Scratch buffer to be used in MTRR calculation.
1950 @param ScratchSize Pointer to the size of scratch buffer.
1951 @param VariableMtrr Array holding all MTRR settings.
1952 @param VariableMtrrCapacity Capacity of the MTRR array.
1953 @param VariableMtrrCount The count of MTRR settings in array.
1955 @retval RETURN_SUCCESS Variable MTRRs are allocated successfully.
1956 @retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.
1957 @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
1958 The required scratch buffer size is returned through ScratchSize.
1961 MtrrLibSetMemoryRanges (
1962 IN MTRR_MEMORY_CACHE_TYPE DefaultType
,
1964 IN MTRR_MEMORY_RANGE
*Ranges
,
1965 IN UINTN RangeCount
,
1967 IN OUT UINTN
*ScratchSize
,
1968 OUT MTRR_MEMORY_RANGE
*VariableMtrr
,
1969 IN UINT32 VariableMtrrCapacity
,
1970 OUT UINT32
*VariableMtrrCount
1973 RETURN_STATUS Status
;
1978 UINT8 CompatibleTypes
;
1981 UINTN ActualScratchSize
;
1982 UINTN BiggestScratchSize
;
1984 *VariableMtrrCount
= 0;
1987 // Since the whole ranges need multiple calls of MtrrLibCalculateMtrrs().
1988 // Each call needs different scratch buffer size.
1989 // When the provided scratch buffer size is not sufficient in any call,
1990 // set the GetActualScratchSize to TRUE, and following calls will only
1991 // calculate the actual scratch size for the caller.
1993 BiggestScratchSize
= 0;
1995 for (Index
= 0; Index
< RangeCount
;) {
1996 Base0
= Ranges
[Index
].BaseAddress
;
1999 // Full step is optimal
2001 while (Index
< RangeCount
) {
2002 ASSERT (Ranges
[Index
].BaseAddress
== Base0
);
2003 Alignment
= MtrrLibBiggestAlignment (Base0
, A0
);
2004 while (Base0
+ Alignment
<= Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
) {
2005 if ((BiggestScratchSize
<= *ScratchSize
) && (Ranges
[Index
].Type
!= DefaultType
)) {
2006 Status
= MtrrLibAppendVariableMtrr (
2007 VariableMtrr
, VariableMtrrCapacity
, VariableMtrrCount
,
2008 Base0
, Alignment
, Ranges
[Index
].Type
2010 if (RETURN_ERROR (Status
)) {
2015 Alignment
= MtrrLibBiggestAlignment (Base0
, A0
);
2019 // Remove the above range from Ranges[Index]
2021 Ranges
[Index
].Length
-= Base0
- Ranges
[Index
].BaseAddress
;
2022 Ranges
[Index
].BaseAddress
= Base0
;
2023 if (Ranges
[Index
].Length
!= 0) {
2030 if (Index
== RangeCount
) {
2035 // Find continous ranges [Base0, Base1) which could be combined by MTRR.
2036 // Per SDM, the compatible types between[B0, B1) are:
2041 CompatibleTypes
= MtrrLibGetCompatibleTypes (&Ranges
[Index
], RangeCount
- Index
);
2043 End
= Index
; // End points to last one that matches the CompatibleTypes.
2044 while (End
+ 1 < RangeCount
) {
2045 if (((1 << Ranges
[End
+ 1].Type
) & CompatibleTypes
) == 0) {
2050 Alignment
= MtrrLibBiggestAlignment (Base0
, A0
);
2051 Length
= GetPowerOfTwo64 (Ranges
[End
].BaseAddress
+ Ranges
[End
].Length
- Base0
);
2052 Base1
= Base0
+ MIN (Alignment
, Length
);
2055 // Base1 may not in Ranges[End]. Update End to the range Base1 belongs to.
2058 while (End
+ 1 < RangeCount
) {
2059 if (Base1
<= Ranges
[End
+ 1].BaseAddress
) {
2065 Length
= Ranges
[End
].Length
;
2066 Ranges
[End
].Length
= Base1
- Ranges
[End
].BaseAddress
;
2067 ActualScratchSize
= *ScratchSize
;
2068 Status
= MtrrLibCalculateMtrrs (
2070 &Ranges
[Index
], End
+ 1 - Index
,
2071 Scratch
, &ActualScratchSize
,
2072 VariableMtrr
, VariableMtrrCapacity
, VariableMtrrCount
2074 if (Status
== RETURN_BUFFER_TOO_SMALL
) {
2075 BiggestScratchSize
= MAX (BiggestScratchSize
, ActualScratchSize
);
2077 // Ignore this error, because we need to calculate the biggest
2078 // scratch buffer size.
2080 Status
= RETURN_SUCCESS
;
2082 if (RETURN_ERROR (Status
)) {
2086 if (Length
!= Ranges
[End
].Length
) {
2087 Ranges
[End
].BaseAddress
= Base1
;
2088 Ranges
[End
].Length
= Length
- Ranges
[End
].Length
;
2095 if (*ScratchSize
< BiggestScratchSize
) {
2096 *ScratchSize
= BiggestScratchSize
;
2097 return RETURN_BUFFER_TOO_SMALL
;
2099 return RETURN_SUCCESS
;
2103 Set the below-1MB memory attribute to fixed MTRR buffer.
2104 Modified flag array indicates which fixed MTRR is modified.
2106 @param [in, out] FixedSettings Fixed MTRR buffer.
2107 @param [out] Modified Flag array indicating which MTRR is modified.
2108 @param [in] BaseAddress Base address.
2109 @param [in] Length Length.
2110 @param [in] Type Memory type.
2112 @retval RETURN_SUCCESS The memory attribute is set successfully.
2113 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
2114 for the fixed MTRRs.
2117 MtrrLibSetBelow1MBMemoryAttribute (
2118 IN OUT MTRR_FIXED_SETTINGS
*FixedSettings
,
2119 OUT BOOLEAN
*Modified
,
2120 IN PHYSICAL_ADDRESS BaseAddress
,
2122 IN MTRR_MEMORY_CACHE_TYPE Type
2125 RETURN_STATUS Status
;
2129 UINT64 ClearMasks
[ARRAY_SIZE (mMtrrLibFixedMtrrTable
)];
2130 UINT64 OrMasks
[ARRAY_SIZE (mMtrrLibFixedMtrrTable
)];
2131 BOOLEAN LocalModified
[ARRAY_SIZE (mMtrrLibFixedMtrrTable
)];
2133 ASSERT (BaseAddress
< BASE_1MB
);
2135 SetMem (LocalModified
, sizeof (LocalModified
), FALSE
);
2138 // (Value & ~0 | 0) still equals to (Value)
2140 SetMem (ClearMasks
, sizeof (ClearMasks
), 0);
2141 SetMem (OrMasks
, sizeof (OrMasks
), 0);
2143 MsrIndex
= (UINT32
)-1;
2144 while ((BaseAddress
< BASE_1MB
) && (Length
!= 0)) {
2145 Status
= MtrrLibProgramFixedMtrr (Type
, &BaseAddress
, &Length
, &MsrIndex
, &ClearMask
, &OrMask
);
2146 if (RETURN_ERROR (Status
)) {
2149 ClearMasks
[MsrIndex
] = ClearMask
;
2150 OrMasks
[MsrIndex
] = OrMask
;
2151 Modified
[MsrIndex
] = TRUE
;
2152 LocalModified
[MsrIndex
] = TRUE
;
2155 for (MsrIndex
= 0; MsrIndex
< ARRAY_SIZE (mMtrrLibFixedMtrrTable
); MsrIndex
++) {
2156 if (LocalModified
[MsrIndex
]) {
2157 FixedSettings
->Mtrr
[MsrIndex
] = (FixedSettings
->Mtrr
[MsrIndex
] & ~ClearMasks
[MsrIndex
]) | OrMasks
[MsrIndex
];
2160 return RETURN_SUCCESS
;
2164 This function attempts to set the attributes into MTRR setting buffer for multiple memory ranges.
2166 @param[in, out] MtrrSetting MTRR setting buffer to be set.
2167 @param[in] Scratch A temporary scratch buffer that is used to perform the calculation.
2168 @param[in, out] ScratchSize Pointer to the size in bytes of the scratch buffer.
2169 It may be updated to the actual required size when the calculation
2170 needs more scratch buffer.
2171 @param[in] Ranges Pointer to an array of MTRR_MEMORY_RANGE.
2172 When range overlap happens, the last one takes higher priority.
2173 When the function returns, either all the attributes are set successfully,
2174 or none of them is set.
2175 @param[in] RangeCount Count of MTRR_MEMORY_RANGE.
2177 @retval RETURN_SUCCESS The attributes were set for all the memory ranges.
2178 @retval RETURN_INVALID_PARAMETER Length in any range is zero.
2179 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
2180 memory resource range specified by BaseAddress and Length in any range.
2181 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
2182 range specified by BaseAddress and Length in any range.
2183 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
2184 the memory resource ranges.
2185 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
2186 BaseAddress and Length cannot be modified.
2187 @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
2191 MtrrSetMemoryAttributesInMtrrSettings (
2192 IN OUT MTRR_SETTINGS
*MtrrSetting
,
2194 IN OUT UINTN
*ScratchSize
,
2195 IN CONST MTRR_MEMORY_RANGE
*Ranges
,
2199 RETURN_STATUS Status
;
2203 BOOLEAN Above1MbExist
;
2205 UINT64 MtrrValidBitsMask
;
2206 UINT64 MtrrValidAddressMask
;
2207 MTRR_MEMORY_CACHE_TYPE DefaultType
;
2208 MTRR_VARIABLE_SETTINGS VariableSettings
;
2209 MTRR_MEMORY_RANGE WorkingRanges
[2 * ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
) + 2];
2210 UINTN WorkingRangeCount
;
2212 MTRR_VARIABLE_SETTING VariableSetting
;
2213 UINT32 OriginalVariableMtrrCount
;
2214 UINT32 FirmwareVariableMtrrCount
;
2215 UINT32 WorkingVariableMtrrCount
;
2216 MTRR_MEMORY_RANGE OriginalVariableMtrr
[ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
)];
2217 MTRR_MEMORY_RANGE WorkingVariableMtrr
[ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
)];
2218 BOOLEAN VariableSettingModified
[ARRAY_SIZE (MtrrSetting
->Variables
.Mtrr
)];
2220 BOOLEAN FixedSettingsModified
[ARRAY_SIZE (mMtrrLibFixedMtrrTable
)];
2221 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
2223 MTRR_CONTEXT MtrrContext
;
2224 BOOLEAN MtrrContextValid
;
2226 Status
= RETURN_SUCCESS
;
2227 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
2230 // TRUE indicating the accordingly Variable setting needs modificaiton in OriginalVariableMtrr.
2232 SetMem (VariableSettingModified
, ARRAY_SIZE (VariableSettingModified
), FALSE
);
2234 // TRUE indicating the accordingly Fixed setting needs modification in WorkingFixedSettings.
2236 SetMem (FixedSettingsModified
, ARRAY_SIZE (FixedSettingsModified
), FALSE
);
2239 // TRUE indicating the caller requests to set variable MTRRs.
2241 Above1MbExist
= FALSE
;
2242 OriginalVariableMtrrCount
= 0;
2245 // 0. Dump the requests.
2248 DEBUG ((DEBUG_CACHE
, "Mtrr: Set Mem Attribute to %a, ScratchSize = %x%a",
2249 (MtrrSetting
== NULL
) ? "Hardware" : "Buffer", *ScratchSize
,
2250 (RangeCount
<= 1) ? "," : "\n"
2252 for (Index
= 0; Index
< RangeCount
; Index
++) {
2253 DEBUG ((DEBUG_CACHE
, " %a: [%016lx, %016lx)\n",
2254 mMtrrMemoryCacheTypeShortName
[MIN (Ranges
[Index
].Type
, CacheInvalid
)],
2255 Ranges
[Index
].BaseAddress
, Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
2261 // 1. Validate the parameters.
2263 if (!IsMtrrSupported ()) {
2264 Status
= RETURN_UNSUPPORTED
;
2268 for (Index
= 0; Index
< RangeCount
; Index
++) {
2269 if (Ranges
[Index
].Length
== 0) {
2270 Status
= RETURN_INVALID_PARAMETER
;
2273 if (((Ranges
[Index
].BaseAddress
& ~MtrrValidAddressMask
) != 0) ||
2274 ((((Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
) & ~MtrrValidAddressMask
) != 0) &&
2275 (Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
) != MtrrValidBitsMask
+ 1)
2278 // Either the BaseAddress or the Limit doesn't follow the alignment requirement.
2279 // Note: It's still valid if Limit doesn't follow the alignment requirement but equals to MAX Address.
2281 Status
= RETURN_UNSUPPORTED
;
2284 if ((Ranges
[Index
].Type
!= CacheUncacheable
) &&
2285 (Ranges
[Index
].Type
!= CacheWriteCombining
) &&
2286 (Ranges
[Index
].Type
!= CacheWriteThrough
) &&
2287 (Ranges
[Index
].Type
!= CacheWriteProtected
) &&
2288 (Ranges
[Index
].Type
!= CacheWriteBack
)) {
2289 Status
= RETURN_INVALID_PARAMETER
;
2292 if (Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
> BASE_1MB
) {
2293 Above1MbExist
= TRUE
;
2298 // 2. Apply the above-1MB memory attribute settings.
2300 if (Above1MbExist
) {
2302 // 2.1. Read all variable MTRRs and convert to Ranges.
2304 OriginalVariableMtrrCount
= GetVariableMtrrCountWorker ();
2305 MtrrGetVariableMtrrWorker (MtrrSetting
, OriginalVariableMtrrCount
, &VariableSettings
);
2306 MtrrLibGetRawVariableRanges (
2307 &VariableSettings
, OriginalVariableMtrrCount
,
2308 MtrrValidBitsMask
, MtrrValidAddressMask
, OriginalVariableMtrr
2311 DefaultType
= MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
2312 WorkingRangeCount
= 1;
2313 WorkingRanges
[0].BaseAddress
= 0;
2314 WorkingRanges
[0].Length
= MtrrValidBitsMask
+ 1;
2315 WorkingRanges
[0].Type
= DefaultType
;
2317 Status
= MtrrLibApplyVariableMtrrs (
2318 OriginalVariableMtrr
, OriginalVariableMtrrCount
,
2319 WorkingRanges
, ARRAY_SIZE (WorkingRanges
), &WorkingRangeCount
);
2320 ASSERT_RETURN_ERROR (Status
);
2322 ASSERT (OriginalVariableMtrrCount
>= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
));
2323 FirmwareVariableMtrrCount
= OriginalVariableMtrrCount
- PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
2324 ASSERT (WorkingRangeCount
<= 2 * FirmwareVariableMtrrCount
+ 1);
2327 // 2.2. Force [0, 1M) to UC, so that it doesn't impact subtraction algorithm.
2329 Status
= MtrrLibSetMemoryType (
2330 WorkingRanges
, ARRAY_SIZE (WorkingRanges
), &WorkingRangeCount
,
2331 0, SIZE_1MB
, CacheUncacheable
2333 ASSERT (Status
!= RETURN_OUT_OF_RESOURCES
);
2336 // 2.3. Apply the new memory attribute settings to Ranges.
2339 for (Index
= 0; Index
< RangeCount
; Index
++) {
2340 BaseAddress
= Ranges
[Index
].BaseAddress
;
2341 Length
= Ranges
[Index
].Length
;
2342 if (BaseAddress
< BASE_1MB
) {
2343 if (Length
<= BASE_1MB
- BaseAddress
) {
2346 Length
-= BASE_1MB
- BaseAddress
;
2347 BaseAddress
= BASE_1MB
;
2349 Status
= MtrrLibSetMemoryType (
2350 WorkingRanges
, ARRAY_SIZE (WorkingRanges
), &WorkingRangeCount
,
2351 BaseAddress
, Length
, Ranges
[Index
].Type
2353 if (Status
== RETURN_ALREADY_STARTED
) {
2354 Status
= RETURN_SUCCESS
;
2355 } else if (Status
== RETURN_OUT_OF_RESOURCES
) {
2358 ASSERT_RETURN_ERROR (Status
);
2365 // 2.4. Calculate the Variable MTRR settings based on the Ranges.
2366 // Buffer Too Small may be returned if the scratch buffer size is insufficient.
2368 Status
= MtrrLibSetMemoryRanges (
2369 DefaultType
, LShiftU64 (1, (UINTN
)HighBitSet64 (MtrrValidBitsMask
)), WorkingRanges
, WorkingRangeCount
,
2370 Scratch
, ScratchSize
,
2371 WorkingVariableMtrr
, FirmwareVariableMtrrCount
+ 1, &WorkingVariableMtrrCount
2373 if (RETURN_ERROR (Status
)) {
2378 // 2.5. Remove the [0, 1MB) MTRR if it still exists (not merged with other range)
2380 for (Index
= 0; Index
< WorkingVariableMtrrCount
; Index
++) {
2381 if (WorkingVariableMtrr
[Index
].BaseAddress
== 0 && WorkingVariableMtrr
[Index
].Length
== SIZE_1MB
) {
2382 ASSERT (WorkingVariableMtrr
[Index
].Type
== CacheUncacheable
);
2383 WorkingVariableMtrrCount
--;
2385 &WorkingVariableMtrr
[Index
], &WorkingVariableMtrr
[Index
+ 1],
2386 (WorkingVariableMtrrCount
- Index
) * sizeof (WorkingVariableMtrr
[0])
2392 if (WorkingVariableMtrrCount
> FirmwareVariableMtrrCount
) {
2393 Status
= RETURN_OUT_OF_RESOURCES
;
2398 // 2.6. Merge the WorkingVariableMtrr to OriginalVariableMtrr
2399 // Make sure least modification is made to OriginalVariableMtrr.
2401 MtrrLibMergeVariableMtrr (
2402 OriginalVariableMtrr
, OriginalVariableMtrrCount
,
2403 WorkingVariableMtrr
, WorkingVariableMtrrCount
,
2404 VariableSettingModified
2410 // 3. Apply the below-1MB memory attribute settings.
2412 ZeroMem (WorkingFixedSettings
.Mtrr
, sizeof (WorkingFixedSettings
.Mtrr
));
2413 for (Index
= 0; Index
< RangeCount
; Index
++) {
2414 if (Ranges
[Index
].BaseAddress
>= BASE_1MB
) {
2418 Status
= MtrrLibSetBelow1MBMemoryAttribute (
2419 &WorkingFixedSettings
, FixedSettingsModified
,
2420 Ranges
[Index
].BaseAddress
, Ranges
[Index
].Length
, Ranges
[Index
].Type
2422 if (RETURN_ERROR (Status
)) {
2427 MtrrContextValid
= FALSE
;
2429 // 4. Write fixed MTRRs that have been modified
2431 for (Index
= 0; Index
< ARRAY_SIZE (FixedSettingsModified
); Index
++) {
2432 if (FixedSettingsModified
[Index
]) {
2433 if (MtrrSetting
!= NULL
) {
2434 MtrrSetting
->Fixed
.Mtrr
[Index
] = WorkingFixedSettings
.Mtrr
[Index
];
2436 if (!MtrrContextValid
) {
2437 MtrrLibPreMtrrChange (&MtrrContext
);
2438 MtrrContextValid
= TRUE
;
2441 mMtrrLibFixedMtrrTable
[Index
].Msr
,
2442 WorkingFixedSettings
.Mtrr
[Index
]
2449 // 5. Write variable MTRRs that have been modified
2451 for (Index
= 0; Index
< OriginalVariableMtrrCount
; Index
++) {
2452 if (VariableSettingModified
[Index
]) {
2453 if (OriginalVariableMtrr
[Index
].Length
!= 0) {
2454 VariableSetting
.Base
= (OriginalVariableMtrr
[Index
].BaseAddress
& MtrrValidAddressMask
)
2455 | (UINT8
)OriginalVariableMtrr
[Index
].Type
;
2456 VariableSetting
.Mask
= ((~(OriginalVariableMtrr
[Index
].Length
- 1)) & MtrrValidAddressMask
) | BIT11
;
2458 VariableSetting
.Base
= 0;
2459 VariableSetting
.Mask
= 0;
2461 if (MtrrSetting
!= NULL
) {
2462 CopyMem (&MtrrSetting
->Variables
.Mtrr
[Index
], &VariableSetting
, sizeof (VariableSetting
));
2464 if (!MtrrContextValid
) {
2465 MtrrLibPreMtrrChange (&MtrrContext
);
2466 MtrrContextValid
= TRUE
;
2469 MSR_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
2470 VariableSetting
.Base
2473 MSR_IA32_MTRR_PHYSMASK0
+ (Index
<< 1),
2474 VariableSetting
.Mask
2480 if (MtrrSetting
!= NULL
) {
2481 ((MSR_IA32_MTRR_DEF_TYPE_REGISTER
*)&MtrrSetting
->MtrrDefType
)->Bits
.E
= 1;
2482 ((MSR_IA32_MTRR_DEF_TYPE_REGISTER
*)&MtrrSetting
->MtrrDefType
)->Bits
.FE
= 1;
2484 if (MtrrContextValid
) {
2485 MtrrLibPostMtrrChange (&MtrrContext
);
2490 DEBUG ((DEBUG_CACHE
, " Result = %r\n", Status
));
2491 if (!RETURN_ERROR (Status
)) {
2492 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
2498 This function attempts to set the attributes into MTRR setting buffer for a memory range.
2500 @param[in, out] MtrrSetting MTRR setting buffer to be set.
2501 @param[in] BaseAddress The physical address that is the start address
2503 @param[in] Length The size in bytes of the memory range.
2504 @param[in] Attribute The bit mask of attributes to set for the
2507 @retval RETURN_SUCCESS The attributes were set for the memory range.
2508 @retval RETURN_INVALID_PARAMETER Length is zero.
2509 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
2510 memory resource range specified by BaseAddress and Length.
2511 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
2512 range specified by BaseAddress and Length.
2513 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
2514 BaseAddress and Length cannot be modified.
2515 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
2516 the memory resource range.
2517 @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
2521 MtrrSetMemoryAttributeInMtrrSettings (
2522 IN OUT MTRR_SETTINGS
*MtrrSetting
,
2523 IN PHYSICAL_ADDRESS BaseAddress
,
2525 IN MTRR_MEMORY_CACHE_TYPE Attribute
2528 UINT8 Scratch
[SCRATCH_BUFFER_SIZE
];
2530 MTRR_MEMORY_RANGE Range
;
2532 Range
.BaseAddress
= BaseAddress
;
2533 Range
.Length
= Length
;
2534 Range
.Type
= Attribute
;
2535 ScratchSize
= sizeof (Scratch
);
2536 return MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting
, Scratch
, &ScratchSize
, &Range
, 1);
2540 This function attempts to set the attributes for a memory range.
2542 @param[in] BaseAddress The physical address that is the start
2543 address of a memory range.
2544 @param[in] Length The size in bytes of the memory range.
2545 @param[in] Attributes The bit mask of attributes to set for the
2548 @retval RETURN_SUCCESS The attributes were set for the memory
2550 @retval RETURN_INVALID_PARAMETER Length is zero.
2551 @retval RETURN_UNSUPPORTED The processor does not support one or
2552 more bytes of the memory resource range
2553 specified by BaseAddress and Length.
2554 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
2555 for the memory resource range specified
2556 by BaseAddress and Length.
2557 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
2558 range specified by BaseAddress and Length
2560 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
2561 modify the attributes of the memory
2563 @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
2567 MtrrSetMemoryAttribute (
2568 IN PHYSICAL_ADDRESS BaseAddress
,
2570 IN MTRR_MEMORY_CACHE_TYPE Attribute
2573 return MtrrSetMemoryAttributeInMtrrSettings (NULL
, BaseAddress
, Length
, Attribute
);
2577 Worker function setting variable MTRRs
2579 @param[in] VariableSettings A buffer to hold variable MTRRs content.
2583 MtrrSetVariableMtrrWorker (
2584 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
2588 UINT32 VariableMtrrCount
;
2590 VariableMtrrCount
= GetVariableMtrrCountWorker ();
2591 ASSERT (VariableMtrrCount
<= ARRAY_SIZE (VariableSettings
->Mtrr
));
2593 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
2595 // Mask MSR is always updated since caller might need to invalidate the MSR pair.
2596 // Base MSR is skipped when Mask.V is not set.
2598 AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0
+ (Index
<< 1), VariableSettings
->Mtrr
[Index
].Mask
);
2599 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER
*)&VariableSettings
->Mtrr
[Index
].Mask
)->Bits
.V
!= 0) {
2600 AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0
+ (Index
<< 1), VariableSettings
->Mtrr
[Index
].Base
);
2607 This function sets variable MTRRs
2609 @param[in] VariableSettings A buffer to hold variable MTRRs content.
2611 @return The pointer of VariableSettings
2614 MTRR_VARIABLE_SETTINGS
*
2616 MtrrSetVariableMtrr (
2617 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
2620 MTRR_CONTEXT MtrrContext
;
2622 if (!IsMtrrSupported ()) {
2623 return VariableSettings
;
2626 MtrrLibPreMtrrChange (&MtrrContext
);
2627 MtrrSetVariableMtrrWorker (VariableSettings
);
2628 MtrrLibPostMtrrChange (&MtrrContext
);
2629 MtrrDebugPrintAllMtrrs ();
2631 return VariableSettings
;
2635 Worker function setting fixed MTRRs
2637 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
2641 MtrrSetFixedMtrrWorker (
2642 IN MTRR_FIXED_SETTINGS
*FixedSettings
2647 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
2649 mMtrrLibFixedMtrrTable
[Index
].Msr
,
2650 FixedSettings
->Mtrr
[Index
]
2657 This function sets fixed MTRRs
2659 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
2661 @retval The pointer of FixedSettings
2664 MTRR_FIXED_SETTINGS
*
2667 IN MTRR_FIXED_SETTINGS
*FixedSettings
2670 MTRR_CONTEXT MtrrContext
;
2672 if (!IsMtrrSupported ()) {
2673 return FixedSettings
;
2676 MtrrLibPreMtrrChange (&MtrrContext
);
2677 MtrrSetFixedMtrrWorker (FixedSettings
);
2678 MtrrLibPostMtrrChange (&MtrrContext
);
2679 MtrrDebugPrintAllMtrrs ();
2681 return FixedSettings
;
2686 This function gets the content in all MTRRs (variable and fixed)
2688 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2690 @retval the pointer of MtrrSetting
2696 OUT MTRR_SETTINGS
*MtrrSetting
2699 if (!IsMtrrSupported ()) {
2706 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2709 // Get variable MTRRs
2711 MtrrGetVariableMtrrWorker (
2713 GetVariableMtrrCountWorker (),
2714 &MtrrSetting
->Variables
2718 // Get MTRR_DEF_TYPE value
2720 MtrrSetting
->MtrrDefType
= AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE
);
2727 This function sets all MTRRs (variable and fixed)
2729 @param[in] MtrrSetting A buffer holding all MTRRs content.
2731 @retval The pointer of MtrrSetting
2737 IN MTRR_SETTINGS
*MtrrSetting
2740 MTRR_CONTEXT MtrrContext
;
2742 if (!IsMtrrSupported ()) {
2746 MtrrLibPreMtrrChange (&MtrrContext
);
2751 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2754 // Set variable MTRRs
2756 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2759 // Set MTRR_DEF_TYPE value
2761 AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2763 MtrrLibPostMtrrChangeEnableCache (&MtrrContext
);
2770 Checks if MTRR is supported.
2772 @retval TRUE MTRR is supported.
2773 @retval FALSE MTRR is not supported.
2782 CPUID_VERSION_INFO_EDX Edx
;
2783 MSR_IA32_MTRRCAP_REGISTER MtrrCap
;
2786 // Check CPUID(1).EDX[12] for MTRR capability
2788 AsmCpuid (CPUID_VERSION_INFO
, NULL
, NULL
, NULL
, &Edx
.Uint32
);
2789 if (Edx
.Bits
.MTRR
== 0) {
2794 // Check number of variable MTRRs and fixed MTRRs existence.
2795 // If number of variable MTRRs is zero, or fixed MTRRs do not
2796 // exist, return false.
2798 MtrrCap
.Uint64
= AsmReadMsr64 (MSR_IA32_MTRRCAP
);
2799 if ((MtrrCap
.Bits
.VCNT
== 0) || (MtrrCap
.Bits
.FIX
== 0)) {
2807 Worker function prints all MTRRs for debugging.
2809 If MtrrSetting is not NULL, print MTRR settings from input MTRR
2811 If MtrrSetting is NULL, print MTRR settings from MTRRs.
2813 @param MtrrSetting A buffer holding all MTRRs content.
2816 MtrrDebugPrintAllMtrrsWorker (
2817 IN MTRR_SETTINGS
*MtrrSetting
2821 MTRR_SETTINGS LocalMtrrs
;
2822 MTRR_SETTINGS
*Mtrrs
;
2825 UINT64 MtrrValidBitsMask
;
2826 UINT64 MtrrValidAddressMask
;
2827 UINT32 VariableMtrrCount
;
2828 BOOLEAN ContainVariableMtrr
;
2829 MTRR_MEMORY_RANGE Ranges
[
2830 ARRAY_SIZE (mMtrrLibFixedMtrrTable
) * sizeof (UINT64
) + 2 * ARRAY_SIZE (Mtrrs
->Variables
.Mtrr
) + 1
2832 MTRR_MEMORY_RANGE RawVariableRanges
[ARRAY_SIZE (Mtrrs
->Variables
.Mtrr
)];
2834 if (!IsMtrrSupported ()) {
2838 VariableMtrrCount
= GetVariableMtrrCountWorker ();
2840 if (MtrrSetting
!= NULL
) {
2841 Mtrrs
= MtrrSetting
;
2843 MtrrGetAllMtrrs (&LocalMtrrs
);
2844 Mtrrs
= &LocalMtrrs
;
2848 // Dump RAW MTRR contents
2850 DEBUG ((DEBUG_CACHE
, "MTRR Settings:\n"));
2851 DEBUG ((DEBUG_CACHE
, "=============\n"));
2852 DEBUG ((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
2853 for (Index
= 0; Index
< ARRAY_SIZE (mMtrrLibFixedMtrrTable
); Index
++) {
2854 DEBUG ((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
2856 ContainVariableMtrr
= FALSE
;
2857 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
2858 if (((MSR_IA32_MTRR_PHYSMASK_REGISTER
*)&Mtrrs
->Variables
.Mtrr
[Index
].Mask
)->Bits
.V
== 0) {
2860 // If mask is not valid, then do not display range
2864 ContainVariableMtrr
= TRUE
;
2865 DEBUG ((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
2867 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
2868 Mtrrs
->Variables
.Mtrr
[Index
].Mask
2871 if (!ContainVariableMtrr
) {
2872 DEBUG ((DEBUG_CACHE
, "Variable MTRR : None.\n"));
2874 DEBUG((DEBUG_CACHE
, "\n"));
2877 // Dump MTRR setting in ranges
2879 DEBUG((DEBUG_CACHE
, "Memory Ranges:\n"));
2880 DEBUG((DEBUG_CACHE
, "====================================\n"));
2881 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
2882 Ranges
[0].BaseAddress
= 0;
2883 Ranges
[0].Length
= MtrrValidBitsMask
+ 1;
2884 Ranges
[0].Type
= MtrrGetDefaultMemoryTypeWorker (Mtrrs
);
2887 MtrrLibGetRawVariableRanges (
2888 &Mtrrs
->Variables
, VariableMtrrCount
,
2889 MtrrValidBitsMask
, MtrrValidAddressMask
, RawVariableRanges
2891 MtrrLibApplyVariableMtrrs (
2892 RawVariableRanges
, VariableMtrrCount
,
2893 Ranges
, ARRAY_SIZE (Ranges
), &RangeCount
2896 MtrrLibApplyFixedMtrrs (&Mtrrs
->Fixed
, Ranges
, ARRAY_SIZE (Ranges
), &RangeCount
);
2898 for (Index
= 0; Index
< RangeCount
; Index
++) {
2899 DEBUG ((DEBUG_CACHE
, "%a:%016lx-%016lx\n",
2900 mMtrrMemoryCacheTypeShortName
[Ranges
[Index
].Type
],
2901 Ranges
[Index
].BaseAddress
, Ranges
[Index
].BaseAddress
+ Ranges
[Index
].Length
- 1
2908 This function prints all MTRRs for debugging.
2912 MtrrDebugPrintAllMtrrs (
2916 MtrrDebugPrintAllMtrrsWorker (NULL
);