4 Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/MtrrLib.h>
18 #include <Library/BaseLib.h>
19 #include <Library/CpuLib.h>
20 #include <Library/BaseMemoryLib.h>
21 #include <Library/DebugLib.h>
22 #include <Library/QNCAccessLib.h>
24 #define QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING 0x590
26 #define CACHE_MTRR_ENABLED 0x800
27 #define CACHE_FIXED_MTRR_ENABLED 0x400
28 #define IA32_MTRR_CAP_VCNT_MASK 0xFF
31 // Context to save and restore when MTRRs are programmed
35 BOOLEAN InterruptState
;
39 // This table defines the offset, base and length of the fixed MTRRs
41 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
42 { QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
, 0, SIZE_64KB
},
43 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000
, 0x80000, SIZE_16KB
},
44 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000
, 0xA0000, SIZE_16KB
},
45 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000
, 0xC0000, SIZE_4KB
},
46 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000
, 0xC8000, SIZE_4KB
},
47 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000
, 0xD0000, SIZE_4KB
},
48 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000
, 0xD8000, SIZE_4KB
},
49 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000
, 0xE0000, SIZE_4KB
},
50 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000
, 0xE8000, SIZE_4KB
},
51 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000
, 0xF0000, SIZE_4KB
},
52 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
, 0xF8000, SIZE_4KB
}
56 // Lookup table used to print MTRRs
58 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
59 "UC", // CacheUncacheable
60 "WC", // CacheWriteCombining
63 "WT", // CacheWriteThrough
64 "WP", // CacheWriteProtected
65 "WB", // CacheWriteBack
71 IN UINT32 MtrrRegister
76 Result
= (UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
);
77 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
78 Result
= Result
| LShiftU64 ((UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1), 32);
85 IN UINT32 MtrrRegister
,
89 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
, (UINT32
)Value
);
90 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
91 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1, (UINT32
)RShiftU64 (Value
, 32));
97 MtrrRegisterBitFieldWrite (
98 IN UINT32 MtrrRegister
,
104 return MtrrRegisterWrite (
107 MtrrRegisterRead (MtrrRegister
),
116 Worker function returns the variable MTRR count for the CPU.
118 @return Variable MTRR count
122 GetVariableMtrrCountWorker (
126 UINT32 VariableMtrrCount
;
128 VariableMtrrCount
= (UINT32
)(MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP
) & IA32_MTRR_CAP_VCNT_MASK
);
129 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
130 return VariableMtrrCount
;
134 Returns the variable MTRR count for the CPU.
136 @return Variable MTRR count
141 GetVariableMtrrCount (
145 if (!IsMtrrSupported ()) {
148 return GetVariableMtrrCountWorker ();
152 Worker function returns the firmware usable variable MTRR count for the CPU.
154 @return Firmware usable variable MTRR count
158 GetFirmwareVariableMtrrCountWorker (
162 UINT32 VariableMtrrCount
;
163 UINT32 ReservedMtrrNumber
;
165 VariableMtrrCount
= GetVariableMtrrCountWorker ();
166 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
167 if (VariableMtrrCount
< ReservedMtrrNumber
) {
171 return VariableMtrrCount
- ReservedMtrrNumber
;
175 Returns the firmware usable variable MTRR count for the CPU.
177 @return Firmware usable variable MTRR count
182 GetFirmwareVariableMtrrCount (
186 if (!IsMtrrSupported ()) {
189 return GetFirmwareVariableMtrrCountWorker ();
193 Worker function returns the default MTRR cache type for the system.
195 If MtrrSetting is not NULL, returns the default MTRR cache type from input
196 MTRR settings buffer.
197 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
199 @param[in] MtrrSetting A buffer holding all MTRRs content.
201 @return The default MTRR cache type.
204 MTRR_MEMORY_CACHE_TYPE
205 MtrrGetDefaultMemoryTypeWorker (
206 IN MTRR_SETTINGS
*MtrrSetting
209 if (MtrrSetting
== NULL
) {
210 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
) & 0x7);
212 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
218 Returns the default MTRR cache type for the system.
220 @return The default MTRR cache type.
223 MTRR_MEMORY_CACHE_TYPE
225 MtrrGetDefaultMemoryType (
229 if (!IsMtrrSupported ()) {
230 return CacheUncacheable
;
232 return MtrrGetDefaultMemoryTypeWorker (NULL
);
236 Preparation before programming MTRR.
238 This function will do some preparation for programming MTRRs:
239 disable cache, invalid cache and disable MTRR caching functionality
241 @param[out] MtrrContext Pointer to context to save
246 OUT MTRR_CONTEXT
*MtrrContext
250 // Disable interrupts and save current interrupt state
252 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
255 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
260 // Save original CR4 value and clear PGE flag (Bit 7)
262 MtrrContext
->Cr4
= AsmReadCr4 ();
263 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
273 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
277 Cleaning up after programming MTRRs.
279 This function will do some clean up after programming MTRRs:
280 Flush all TLBs, re-enable caching, restore CR4.
282 @param[in] MtrrContext Pointer to context to restore
286 PostMtrrChangeEnableCache (
287 IN MTRR_CONTEXT
*MtrrContext
296 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
301 // Restore original CR4 value
303 AsmWriteCr4 (MtrrContext
->Cr4
);
306 // Restore original interrupt state
308 SetInterruptState (MtrrContext
->InterruptState
);
312 Cleaning up after programming MTRRs.
314 This function will do some clean up after programming MTRRs:
315 enable MTRR caching functionality, and enable cache
317 @param[in] MtrrContext Pointer to context to restore
322 IN MTRR_CONTEXT
*MtrrContext
328 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
330 PostMtrrChangeEnableCache (MtrrContext
);
334 Worker function gets the content in fixed MTRRs
336 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
338 @retval The pointer of FixedSettings
342 MtrrGetFixedMtrrWorker (
343 OUT MTRR_FIXED_SETTINGS
*FixedSettings
348 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
349 FixedSettings
->Mtrr
[Index
] =
350 MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
353 return FixedSettings
;
358 This function gets the content in fixed MTRRs
360 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
362 @retval The pointer of FixedSettings
368 OUT MTRR_FIXED_SETTINGS
*FixedSettings
371 if (!IsMtrrSupported ()) {
372 return FixedSettings
;
375 return MtrrGetFixedMtrrWorker (FixedSettings
);
380 Worker function will get the raw value in variable MTRRs
382 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
383 MTRR settings buffer.
384 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
386 @param[in] MtrrSetting A buffer holding all MTRRs content.
387 @param[in] VariableMtrrCount Number of variable MTRRs.
388 @param[out] VariableSettings A buffer to hold variable MTRRs content.
390 @return The VariableSettings input pointer
393 MTRR_VARIABLE_SETTINGS
*
394 MtrrGetVariableMtrrWorker (
395 IN MTRR_SETTINGS
*MtrrSetting
,
396 IN UINT32 VariableMtrrCount
,
397 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
402 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
404 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
405 if (MtrrSetting
== NULL
) {
406 VariableSettings
->Mtrr
[Index
].Base
=
407 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1));
408 VariableSettings
->Mtrr
[Index
].Mask
=
409 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1);
411 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
412 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
416 return VariableSettings
;
420 This function will get the raw value in variable MTRRs
422 @param[out] VariableSettings A buffer to hold variable MTRRs content.
424 @return The VariableSettings input pointer
427 MTRR_VARIABLE_SETTINGS
*
429 MtrrGetVariableMtrr (
430 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
433 if (!IsMtrrSupported ()) {
434 return VariableSettings
;
437 return MtrrGetVariableMtrrWorker (
439 GetVariableMtrrCountWorker (),
445 Programs fixed MTRRs registers.
447 @param[in] MemoryCacheType The memory type to set.
448 @param[in, out] Base The base address of memory range.
449 @param[in, out] Length The length of memory range.
450 @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.
451 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
452 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
454 @retval RETURN_SUCCESS The cache type was updated successfully
455 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
461 IN UINT64 MemoryCacheType
,
463 IN OUT UINT64
*Length
,
464 OUT UINT32
*ReturnMsrNum
,
465 OUT UINT64
*ReturnClearMask
,
466 OUT UINT64
*ReturnOrMask
477 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
478 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
481 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
482 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
490 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
491 return RETURN_UNSUPPORTED
;
495 // We found the fixed MTRR to be programmed
497 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
500 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
501 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
508 if (ByteShift
== 8) {
509 return RETURN_UNSUPPORTED
;
514 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
517 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
518 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
519 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
520 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
523 if (ByteShift
< 8 && (*Length
!= 0)) {
524 return RETURN_UNSUPPORTED
;
527 *ReturnMsrNum
= MsrNum
;
528 *ReturnClearMask
= ClearMask
;
529 *ReturnOrMask
= OrMask
;
531 return RETURN_SUCCESS
;
536 Worker function gets the attribute of variable MTRRs.
538 This function shadows the content of variable MTRRs into an
539 internal array: VariableMtrr.
541 @param[in] VariableSettings The variable MTRR values to shadow
542 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
543 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
544 @param[in] MtrrValidAddressMask The valid address mask for MTRR
545 @param[out] VariableMtrr The array to shadow variable MTRRs content
547 @return The return value of this parameter indicates the
548 number of MTRRs which has been used.
552 MtrrGetMemoryAttributeInVariableMtrrWorker (
553 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
554 IN UINTN FirmwareVariableMtrrCount
,
555 IN UINT64 MtrrValidBitsMask
,
556 IN UINT64 MtrrValidAddressMask
,
557 OUT VARIABLE_MTRR
*VariableMtrr
563 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
564 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
565 if ((VariableSettings
->Mtrr
[Index
].Mask
& CACHE_MTRR_ENABLED
) != 0) {
566 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
567 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
568 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
569 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
570 VariableMtrr
[Index
].Valid
= TRUE
;
571 VariableMtrr
[Index
].Used
= TRUE
;
580 Gets the attribute of variable MTRRs.
582 This function shadows the content of variable MTRRs into an
583 internal array: VariableMtrr.
585 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
586 @param[in] MtrrValidAddressMask The valid address mask for MTRR
587 @param[out] VariableMtrr The array to shadow variable MTRRs content
589 @return The return value of this parameter indicates the
590 number of MTRRs which has been used.
595 MtrrGetMemoryAttributeInVariableMtrr (
596 IN UINT64 MtrrValidBitsMask
,
597 IN UINT64 MtrrValidAddressMask
,
598 OUT VARIABLE_MTRR
*VariableMtrr
601 MTRR_VARIABLE_SETTINGS VariableSettings
;
603 if (!IsMtrrSupported ()) {
607 MtrrGetVariableMtrrWorker (
609 GetVariableMtrrCountWorker (),
613 return MtrrGetMemoryAttributeInVariableMtrrWorker (
615 GetFirmwareVariableMtrrCountWorker (),
617 MtrrValidAddressMask
,
624 Checks overlap between given memory range and MTRRs.
626 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
628 @param[in] Start The start address of memory range.
629 @param[in] End The end address of memory range.
630 @param[in] VariableMtrr The array to shadow variable MTRRs content
632 @retval TRUE Overlap exists.
633 @retval FALSE No overlap.
637 CheckMemoryAttributeOverlap (
638 IN UINTN FirmwareVariableMtrrCount
,
639 IN PHYSICAL_ADDRESS Start
,
640 IN PHYSICAL_ADDRESS End
,
641 IN VARIABLE_MTRR
*VariableMtrr
646 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
648 VariableMtrr
[Index
].Valid
&&
650 (Start
> (VariableMtrr
[Index
].BaseAddress
+
651 VariableMtrr
[Index
].Length
- 1)
653 (End
< VariableMtrr
[Index
].BaseAddress
)
665 Marks a variable MTRR as non-valid.
667 @param[in] Index The index of the array VariableMtrr to be invalidated
668 @param[in] VariableMtrr The array to shadow variable MTRRs content
669 @param[out] UsedMtrr The number of MTRRs which has already been used
673 InvalidateShadowMtrr (
675 IN VARIABLE_MTRR
*VariableMtrr
,
679 VariableMtrr
[Index
].Valid
= FALSE
;
680 *UsedMtrr
= *UsedMtrr
- 1;
685 Combines memory attributes.
687 If overlap exists between given memory range and MTRRs, try to combine them.
689 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
690 available to firmware.
691 @param[in] Attributes The memory type to set.
692 @param[in, out] Base The base address of memory range.
693 @param[in, out] Length The length of memory range.
694 @param[in] VariableMtrr The array to shadow variable MTRRs content
695 @param[in, out] UsedMtrr The number of MTRRs which has already been used
696 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
698 @retval EFI_SUCCESS Memory region successfully combined.
699 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
703 CombineMemoryAttribute (
704 IN UINT32 FirmwareVariableMtrrCount
,
705 IN UINT64 Attributes
,
707 IN OUT UINT64
*Length
,
708 IN VARIABLE_MTRR
*VariableMtrr
,
709 IN OUT UINT32
*UsedMtrr
,
710 OUT BOOLEAN
*OverwriteExistingMtrr
718 BOOLEAN CoveredByExistingMtrr
;
720 *OverwriteExistingMtrr
= FALSE
;
721 CoveredByExistingMtrr
= FALSE
;
722 EndAddress
= *Base
+*Length
- 1;
724 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
726 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
728 !VariableMtrr
[Index
].Valid
||
731 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
738 // Combine same attribute MTRR range
740 if (Attributes
== VariableMtrr
[Index
].Type
) {
742 // if the MTRR range contain the request range, set a flag, then continue to
743 // invalidate any MTRR of the same request range with higher priority cache type.
745 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
746 CoveredByExistingMtrr
= TRUE
;
750 // invalid this MTRR, and program the combine range
753 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
755 VariableMtrr
[Index
].BaseAddress
;
756 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
759 // Record the MTRR usage status in VariableMtrr array.
761 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
762 *Base
= CombineStart
;
763 *Length
= CombineEnd
- CombineStart
+ 1;
764 EndAddress
= CombineEnd
;
765 *OverwriteExistingMtrr
= TRUE
;
769 // The cache type is different, but the range is convered by one MTRR
771 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
772 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
778 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
779 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
780 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
781 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
782 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
783 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
785 *OverwriteExistingMtrr
= TRUE
;
789 // Other type memory overlap is invalid
791 return RETURN_ACCESS_DENIED
;
794 if (CoveredByExistingMtrr
) {
798 return RETURN_SUCCESS
;
803 Calculates the maximum value which is a power of 2, but less the MemoryLength.
805 @param[in] MemoryLength The number to pass in.
807 @return The maximum value which is align to power of 2 and less the MemoryLength
812 IN UINT64 MemoryLength
817 if (RShiftU64 (MemoryLength
, 32) != 0) {
819 (UINT64
) GetPowerOfTwo32 (
820 (UINT32
) RShiftU64 (MemoryLength
, 32)
825 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
833 Determines the MTRR numbers used to program a memory range.
835 This function first checks the alignment of the base address.
836 If the alignment of the base address <= Length, cover the memory range
837 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
838 Length -= alignment. Repeat the step until alignment > Length.
840 Then this function determines which direction of programming the variable
841 MTRRs for the remaining length will use fewer MTRRs.
843 @param[in] BaseAddress Length of Memory to program MTRR
844 @param[in] Length Length of Memory to program MTRR
845 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
847 @retval TRUE Positive direction is better.
848 FALSE Negative direction is better.
852 GetMtrrNumberAndDirection (
853 IN UINT64 BaseAddress
,
865 if (BaseAddress
!= 0) {
868 // Calculate the alignment of the base address.
870 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
872 if (Alignment
> Length
) {
877 BaseAddress
+= Alignment
;
891 TempQword
-= Power2MaxMemory (TempQword
);
893 } while (TempQword
!= 0);
895 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
898 TempQword
-= Power2MaxMemory (TempQword
);
900 } while (TempQword
!= 0);
902 if (Positive
<= Subtractive
) {
903 *MtrrNumber
+= Positive
;
906 *MtrrNumber
+= Subtractive
;
912 Invalid variable MTRRs according to the value in the shadow array.
914 This function programs MTRRs according to the values specified
917 @param[in, out] VariableSettings Variable MTRR settings
918 @param[in] VariableMtrrCount Number of variable MTRRs
919 @param[in, out] VariableMtrr Shadow of variable MTRR contents
924 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
925 IN UINTN VariableMtrrCount
,
926 IN OUT VARIABLE_MTRR
*VariableMtrr
931 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
932 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
933 VariableSettings
->Mtrr
[Index
].Base
= 0;
934 VariableSettings
->Mtrr
[Index
].Mask
= 0;
935 VariableMtrr
[Index
].Used
= FALSE
;
942 Programs variable MTRRs
944 This function programs variable MTRRs
946 @param[in, out] VariableSettings Variable MTRR settings.
947 @param[in] MtrrNumber Index of MTRR to program.
948 @param[in] BaseAddress Base address of memory region.
949 @param[in] Length Length of memory region.
950 @param[in] MemoryCacheType Memory type to set.
951 @param[in] MtrrValidAddressMask The valid address mask for MTRR
955 ProgramVariableMtrr (
956 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
958 IN PHYSICAL_ADDRESS BaseAddress
,
960 IN UINT64 MemoryCacheType
,
961 IN UINT64 MtrrValidAddressMask
967 // MTRR Physical Base
969 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
970 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
973 // MTRR Physical Mask
975 TempQword
= ~(Length
- 1);
976 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | CACHE_MTRR_ENABLED
;
981 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
983 If MtrrSetting is not NULL, gets the default memory attribute from input
984 MTRR settings buffer.
985 If MtrrSetting is NULL, gets the default memory attribute from MSR.
987 @param[in] MtrrSetting A buffer holding all MTRRs content.
988 @param[in] MtrrType MTRR memory type
990 @return The enum item in MTRR_MEMORY_CACHE_TYPE
993 MTRR_MEMORY_CACHE_TYPE
994 GetMemoryCacheTypeFromMtrrType (
995 IN MTRR_SETTINGS
*MtrrSetting
,
1000 case MTRR_CACHE_UNCACHEABLE
:
1001 return CacheUncacheable
;
1002 case MTRR_CACHE_WRITE_COMBINING
:
1003 return CacheWriteCombining
;
1004 case MTRR_CACHE_WRITE_THROUGH
:
1005 return CacheWriteThrough
;
1006 case MTRR_CACHE_WRITE_PROTECTED
:
1007 return CacheWriteProtected
;
1008 case MTRR_CACHE_WRITE_BACK
:
1009 return CacheWriteBack
;
1012 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1013 // no MTRR covers the range
1015 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1020 Initializes the valid bits mask and valid address mask for MTRRs.
1022 This function initializes the valid bits mask and valid address mask for MTRRs.
1024 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1025 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1029 MtrrLibInitializeMtrrMask (
1030 OUT UINT64
*MtrrValidBitsMask
,
1031 OUT UINT64
*MtrrValidAddressMask
1035 UINT8 PhysicalAddressBits
;
1037 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1039 if (RegEax
>= 0x80000008) {
1040 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1042 PhysicalAddressBits
= (UINT8
) RegEax
;
1044 PhysicalAddressBits
= 36;
1047 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1048 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1053 Determines the real attribute of a memory range.
1055 This function is to arbitrate the real attribute of the memory when
1056 there are 2 MTRRs covers the same memory range. For further details,
1057 please refer the IA32 Software Developer's Manual, Volume 3,
1060 @param[in] MtrrType1 The first kind of Memory type
1061 @param[in] MtrrType2 The second kind of memory type
1066 IN UINT64 MtrrType1
,
1072 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1073 switch (MtrrType1
) {
1074 case MTRR_CACHE_UNCACHEABLE
:
1075 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1077 case MTRR_CACHE_WRITE_COMBINING
:
1079 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1080 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1082 MtrrType
= MtrrType2
;
1085 case MTRR_CACHE_WRITE_THROUGH
:
1087 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1088 MtrrType2
==MTRR_CACHE_WRITE_BACK
1090 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1091 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1092 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1095 case MTRR_CACHE_WRITE_PROTECTED
:
1096 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1097 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1098 MtrrType
= MtrrType2
;
1101 case MTRR_CACHE_WRITE_BACK
:
1103 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1104 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1105 MtrrType2
== MTRR_CACHE_WRITE_BACK
1107 MtrrType
= MtrrType2
;
1110 case MTRR_CACHE_INVALID_TYPE
:
1111 MtrrType
= MtrrType2
;
1117 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1118 MtrrType
= MtrrType1
;
1124 Worker function will get the memory cache type of the specific address.
1126 If MtrrSetting is not NULL, gets the memory cache type from input
1127 MTRR settings buffer.
1128 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1130 @param[in] MtrrSetting A buffer holding all MTRRs content.
1131 @param[in] Address The specific address
1133 @return Memory cache type of the specific address
1136 MTRR_MEMORY_CACHE_TYPE
1137 MtrrGetMemoryAttributeByAddressWorker (
1138 IN MTRR_SETTINGS
*MtrrSetting
,
1139 IN PHYSICAL_ADDRESS Address
1146 UINT64 TempMtrrType
;
1147 MTRR_MEMORY_CACHE_TYPE CacheType
;
1148 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1149 UINT64 MtrrValidBitsMask
;
1150 UINT64 MtrrValidAddressMask
;
1151 UINTN VariableMtrrCount
;
1152 MTRR_VARIABLE_SETTINGS VariableSettings
;
1155 // Check if MTRR is enabled, if not, return UC as attribute
1157 if (MtrrSetting
== NULL
) {
1158 TempQword
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
1160 TempQword
= MtrrSetting
->MtrrDefType
;
1162 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1164 if ((TempQword
& CACHE_MTRR_ENABLED
) == 0) {
1165 return CacheUncacheable
;
1169 // If address is less than 1M, then try to go through the fixed MTRR
1171 if (Address
< BASE_1MB
) {
1172 if ((TempQword
& CACHE_FIXED_MTRR_ENABLED
) != 0) {
1174 // Go through the fixed MTRR
1176 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1177 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1179 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1180 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1184 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1185 mMtrrLibFixedMtrrTable
[Index
].Length
;
1186 if (MtrrSetting
== NULL
) {
1187 TempQword
= MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1189 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1191 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1192 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1197 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1199 MtrrGetVariableMtrrWorker (
1201 GetVariableMtrrCountWorker (),
1205 MtrrGetMemoryAttributeInVariableMtrrWorker (
1207 GetFirmwareVariableMtrrCountWorker (),
1209 MtrrValidAddressMask
,
1214 // Go through the variable MTRR
1216 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1217 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1219 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1220 if (VariableMtrr
[Index
].Valid
) {
1221 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1222 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1223 TempMtrrType
= VariableMtrr
[Index
].Type
;
1224 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1228 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1235 This function will get the memory cache type of the specific address.
1237 This function is mainly for debug purpose.
1239 @param[in] Address The specific address
1241 @return Memory cache type of the specific address
1244 MTRR_MEMORY_CACHE_TYPE
1246 MtrrGetMemoryAttribute (
1247 IN PHYSICAL_ADDRESS Address
1250 if (!IsMtrrSupported ()) {
1251 return CacheUncacheable
;
1254 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1258 Worker function prints all MTRRs for debugging.
1260 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1262 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1264 @param MtrrSetting A buffer holding all MTRRs content.
1267 MtrrDebugPrintAllMtrrsWorker (
1268 IN MTRR_SETTINGS
*MtrrSetting
1272 MTRR_SETTINGS LocalMtrrs
;
1273 MTRR_SETTINGS
*Mtrrs
;
1276 UINTN VariableMtrrCount
;
1284 UINT64 NoRangeLimit
;
1287 UINTN PreviousMemoryType
;
1290 if (!IsMtrrSupported ()) {
1294 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1295 DEBUG((DEBUG_CACHE
, "=============\n"));
1297 if (MtrrSetting
!= NULL
) {
1298 Mtrrs
= MtrrSetting
;
1300 MtrrGetAllMtrrs (&LocalMtrrs
);
1301 Mtrrs
= &LocalMtrrs
;
1304 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1305 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1306 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1309 VariableMtrrCount
= GetVariableMtrrCount ();
1310 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1311 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1313 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1314 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1317 DEBUG((DEBUG_CACHE
, "\n"));
1318 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1319 DEBUG((DEBUG_CACHE
, "====================================\n"));
1322 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1323 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1324 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1325 for (Index1
= 0; Index1
< 8; Index1
++) {
1326 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1327 if (MemoryType
> CacheWriteBack
) {
1328 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1330 if (MemoryType
!= PreviousMemoryType
) {
1331 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1332 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1334 PreviousMemoryType
= MemoryType
;
1335 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1337 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1340 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1342 VariableMtrrCount
= GetVariableMtrrCount ();
1345 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1346 if (RegEax
>= 0x80000008) {
1347 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1348 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1351 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1353 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1354 if (MemoryType
> CacheWriteBack
) {
1355 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1358 if (MemoryType
!= PreviousMemoryType
) {
1359 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1360 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1362 PreviousMemoryType
= MemoryType
;
1363 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1366 RangeBase
= BASE_1MB
;
1367 NoRangeBase
= BASE_1MB
;
1369 NoRangeLimit
= Limit
;
1371 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1372 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1374 // If mask is not valid, then do not display range
1378 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1379 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1381 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1385 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1386 RangeBase
= MtrrBase
;
1388 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1389 RangeBase
= MtrrLimit
+ 1;
1391 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1392 RangeLimit
= MtrrBase
- 1;
1394 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1395 RangeLimit
= MtrrLimit
;
1398 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1399 NoRangeBase
= MtrrLimit
+ 1;
1401 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1402 NoRangeLimit
= MtrrBase
- 1;
1407 Base
= RangeLimit
+ 1;
1409 Base
= NoRangeLimit
+ 1;
1411 } while (Base
< Limit
);
1412 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1418 This function prints all MTRRs for debugging.
1422 MtrrDebugPrintAllMtrrs (
1426 MtrrDebugPrintAllMtrrsWorker (NULL
);
1431 Worker function attempts to set the attributes for a memory range.
1433 If MtrrSettings is not NULL, set the attributes into the input MTRR
1435 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1437 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1438 @param[in] BaseAddress The physical address that is the start
1439 address of a memory region.
1440 @param[in] Length The size in bytes of the memory region.
1441 @param[in] Attribute The bit mask of attributes to set for the
1444 @retval RETURN_SUCCESS The attributes were set for the memory
1446 @retval RETURN_INVALID_PARAMETER Length is zero.
1447 @retval RETURN_UNSUPPORTED The processor does not support one or
1448 more bytes of the memory resource range
1449 specified by BaseAddress and Length.
1450 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1451 for the memory resource range specified
1452 by BaseAddress and Length.
1453 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1454 range specified by BaseAddress and Length
1456 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1457 modify the attributes of the memory
1462 MtrrSetMemoryAttributeWorker (
1463 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1464 IN PHYSICAL_ADDRESS BaseAddress
,
1466 IN MTRR_MEMORY_CACHE_TYPE Attribute
1470 RETURN_STATUS Status
;
1477 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1479 UINT64 MtrrValidBitsMask
;
1480 UINT64 MtrrValidAddressMask
;
1481 BOOLEAN OverwriteExistingMtrr
;
1482 UINT32 FirmwareVariableMtrrCount
;
1483 MTRR_CONTEXT MtrrContext
;
1484 BOOLEAN MtrrContextValid
;
1485 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1486 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1487 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1488 UINT32 VariableMtrrCount
;
1489 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1490 BOOLEAN ProgramVariableSettings
;
1491 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1496 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1498 MtrrContextValid
= FALSE
;
1499 VariableMtrrCount
= 0;
1500 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1501 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1502 FixedSettingsValid
[Index
] = FALSE
;
1503 FixedSettingsModified
[Index
] = FALSE
;
1505 ProgramVariableSettings
= FALSE
;
1507 if (!IsMtrrSupported ()) {
1508 Status
= RETURN_UNSUPPORTED
;
1512 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1515 MemoryType
= (UINT64
)Attribute
;
1516 OverwriteExistingMtrr
= FALSE
;
1519 // Check for an invalid parameter
1522 Status
= RETURN_INVALID_PARAMETER
;
1527 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1528 (Length
& ~MtrrValidAddressMask
) != 0
1530 Status
= RETURN_UNSUPPORTED
;
1535 // Check if Fixed MTRR
1537 Status
= RETURN_SUCCESS
;
1538 if (BaseAddress
< BASE_1MB
) {
1539 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1540 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1541 if (RETURN_ERROR (Status
)) {
1544 if (MtrrSetting
!= NULL
) {
1545 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1546 MtrrSetting
->MtrrDefType
|= CACHE_FIXED_MTRR_ENABLED
;
1548 if (!FixedSettingsValid
[MsrNum
]) {
1549 WorkingFixedSettings
.Mtrr
[MsrNum
] = MtrrRegisterRead (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1550 FixedSettingsValid
[MsrNum
] = TRUE
;
1552 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1553 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1554 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1555 FixedSettingsModified
[MsrNum
] = TRUE
;
1562 // A Length of 0 can only make sense for fixed MTTR ranges.
1563 // Since we just handled the fixed MTRRs, we can skip the
1564 // variable MTRR section.
1571 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1572 // we can set the base to 0 to save variable MTRRs.
1574 if (BaseAddress
== BASE_1MB
) {
1580 // Read all variable MTRRs
1582 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1583 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1584 if (MtrrSetting
!= NULL
) {
1585 VariableSettings
= &MtrrSetting
->Variables
;
1587 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1588 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1589 ProgramVariableSettings
= TRUE
;
1590 VariableSettings
= &WorkingVariableSettings
;
1594 // Check for overlap
1596 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1598 FirmwareVariableMtrrCount
,
1600 MtrrValidAddressMask
,
1603 OverLap
= CheckMemoryAttributeOverlap (
1604 FirmwareVariableMtrrCount
,
1606 BaseAddress
+ Length
- 1,
1610 Status
= CombineMemoryAttribute (
1611 FirmwareVariableMtrrCount
,
1617 &OverwriteExistingMtrr
1619 if (RETURN_ERROR (Status
)) {
1625 // Combined successfully, invalidate the now-unused MTRRs
1627 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1628 Status
= RETURN_SUCCESS
;
1634 // The memory type is the same with the type specified by
1635 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1637 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1639 // Invalidate the now-unused MTRRs
1641 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1645 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1647 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1648 Status
= RETURN_OUT_OF_RESOURCES
;
1653 // Invalidate the now-unused MTRRs
1655 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1658 // Find first unused MTRR
1660 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1661 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1666 if (BaseAddress
!= 0) {
1669 // Calculate the alignment of the base address.
1671 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1673 if (Alignment
> Length
) {
1680 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1681 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1686 ProgramVariableMtrr (
1692 MtrrValidAddressMask
1694 BaseAddress
+= Alignment
;
1695 Length
-= Alignment
;
1706 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1711 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1712 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1717 ProgramVariableMtrr (
1723 MtrrValidAddressMask
1725 BaseAddress
+= Length
;
1726 TempQword
= Length
- TempQword
;
1727 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1734 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1735 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1740 Length
= Power2MaxMemory (TempQword
);
1742 BaseAddress
-= Length
;
1745 ProgramVariableMtrr (
1751 MtrrValidAddressMask
1755 BaseAddress
+= Length
;
1757 TempQword
-= Length
;
1759 } while (TempQword
> 0);
1764 // Write fixed MTRRs that have been modified
1766 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1767 if (FixedSettingsModified
[Index
]) {
1768 if (!MtrrContextValid
) {
1769 PreMtrrChange (&MtrrContext
);
1770 MtrrContextValid
= TRUE
;
1773 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1774 WorkingFixedSettings
.Mtrr
[Index
]
1780 // Write variable MTRRs
1782 if (ProgramVariableSettings
) {
1783 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1784 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1785 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1786 if (!MtrrContextValid
) {
1787 PreMtrrChange (&MtrrContext
);
1788 MtrrContextValid
= TRUE
;
1791 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1792 WorkingVariableSettings
.Mtrr
[Index
].Base
1795 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1796 WorkingVariableSettings
.Mtrr
[Index
].Mask
1801 if (MtrrContextValid
) {
1802 PostMtrrChange (&MtrrContext
);
1805 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1806 if (!RETURN_ERROR (Status
)) {
1807 if (MtrrSetting
!= NULL
) {
1808 MtrrSetting
->MtrrDefType
|= CACHE_MTRR_ENABLED
;
1810 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1817 This function attempts to set the attributes for a memory range.
1819 @param[in] BaseAddress The physical address that is the start
1820 address of a memory region.
1821 @param[in] Length The size in bytes of the memory region.
1822 @param[in] Attributes The bit mask of attributes to set for the
1825 @retval RETURN_SUCCESS The attributes were set for the memory
1827 @retval RETURN_INVALID_PARAMETER Length is zero.
1828 @retval RETURN_UNSUPPORTED The processor does not support one or
1829 more bytes of the memory resource range
1830 specified by BaseAddress and Length.
1831 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1832 for the memory resource range specified
1833 by BaseAddress and Length.
1834 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1835 range specified by BaseAddress and Length
1837 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1838 modify the attributes of the memory
1844 MtrrSetMemoryAttribute (
1845 IN PHYSICAL_ADDRESS BaseAddress
,
1847 IN MTRR_MEMORY_CACHE_TYPE Attribute
1850 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1851 return MtrrSetMemoryAttributeWorker (
1860 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1862 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1863 @param[in] BaseAddress The physical address that is the start address
1865 @param[in] Length The size in bytes of the memory region.
1866 @param[in] Attribute The bit mask of attributes to set for the
1869 @retval RETURN_SUCCESS The attributes were set for the memory region.
1870 @retval RETURN_INVALID_PARAMETER Length is zero.
1871 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1872 memory resource range specified by BaseAddress and Length.
1873 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1874 range specified by BaseAddress and Length.
1875 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1876 BaseAddress and Length cannot be modified.
1877 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1878 the memory resource range.
1883 MtrrSetMemoryAttributeInMtrrSettings (
1884 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1885 IN PHYSICAL_ADDRESS BaseAddress
,
1887 IN MTRR_MEMORY_CACHE_TYPE Attribute
1890 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1891 return MtrrSetMemoryAttributeWorker (
1900 Worker function setting variable MTRRs
1902 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1906 MtrrSetVariableMtrrWorker (
1907 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1911 UINT32 VariableMtrrCount
;
1913 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1914 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1916 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1918 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1919 VariableSettings
->Mtrr
[Index
].Base
1922 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1923 VariableSettings
->Mtrr
[Index
].Mask
1930 This function sets variable MTRRs
1932 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1934 @return The pointer of VariableSettings
1937 MTRR_VARIABLE_SETTINGS
*
1939 MtrrSetVariableMtrr (
1940 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1943 MTRR_CONTEXT MtrrContext
;
1945 if (!IsMtrrSupported ()) {
1946 return VariableSettings
;
1949 PreMtrrChange (&MtrrContext
);
1950 MtrrSetVariableMtrrWorker (VariableSettings
);
1951 PostMtrrChange (&MtrrContext
);
1952 MtrrDebugPrintAllMtrrs ();
1954 return VariableSettings
;
1958 Worker function setting fixed MTRRs
1960 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1964 MtrrSetFixedMtrrWorker (
1965 IN MTRR_FIXED_SETTINGS
*FixedSettings
1970 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1972 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1973 FixedSettings
->Mtrr
[Index
]
1980 This function sets fixed MTRRs
1982 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1984 @retval The pointer of FixedSettings
1987 MTRR_FIXED_SETTINGS
*
1990 IN MTRR_FIXED_SETTINGS
*FixedSettings
1993 MTRR_CONTEXT MtrrContext
;
1995 if (!IsMtrrSupported ()) {
1996 return FixedSettings
;
1999 PreMtrrChange (&MtrrContext
);
2000 MtrrSetFixedMtrrWorker (FixedSettings
);
2001 PostMtrrChange (&MtrrContext
);
2002 MtrrDebugPrintAllMtrrs ();
2004 return FixedSettings
;
2009 This function gets the content in all MTRRs (variable and fixed)
2011 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2013 @retval the pointer of MtrrSetting
2019 OUT MTRR_SETTINGS
*MtrrSetting
2022 if (!IsMtrrSupported ()) {
2029 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2032 // Get variable MTRRs
2034 MtrrGetVariableMtrrWorker (
2036 GetVariableMtrrCountWorker (),
2037 &MtrrSetting
->Variables
2041 // Get MTRR_DEF_TYPE value
2043 MtrrSetting
->MtrrDefType
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
2050 This function sets all MTRRs (variable and fixed)
2052 @param[in] MtrrSetting A buffer holding all MTRRs content.
2054 @retval The pointer of MtrrSetting
2060 IN MTRR_SETTINGS
*MtrrSetting
2063 MTRR_CONTEXT MtrrContext
;
2065 if (!IsMtrrSupported ()) {
2069 PreMtrrChange (&MtrrContext
);
2074 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2077 // Set variable MTRRs
2079 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2082 // Set MTRR_DEF_TYPE value
2084 MtrrRegisterWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2086 PostMtrrChangeEnableCache (&MtrrContext
);
2088 MtrrDebugPrintAllMtrrs ();
2095 Checks if MTRR is supported.
2097 @retval TRUE MTRR is supported.
2098 @retval FALSE MTRR is not supported.
2110 // Check CPUID(1).EAX[0..11] for Quark SoC
2112 AsmCpuid (1, &RegEax
, NULL
, NULL
, NULL
);
2113 if ((RegEax
& 0xfff) == QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING
) {