4 Copyright (c) 2008 - 2015, 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
27 // Context to save and restore when MTRRs are programmed
31 BOOLEAN InterruptState
;
35 // This table defines the offset, base and length of the fixed MTRRs
37 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
38 { QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
, 0, SIZE_64KB
},
39 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000
, 0x80000, SIZE_16KB
},
40 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000
, 0xA0000, SIZE_16KB
},
41 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000
, 0xC0000, SIZE_4KB
},
42 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000
, 0xC8000, SIZE_4KB
},
43 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000
, 0xD0000, SIZE_4KB
},
44 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000
, 0xD8000, SIZE_4KB
},
45 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000
, 0xE0000, SIZE_4KB
},
46 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000
, 0xE8000, SIZE_4KB
},
47 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000
, 0xF0000, SIZE_4KB
},
48 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
, 0xF8000, SIZE_4KB
}
52 // Lookup table used to print MTRRs
54 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
55 "UC", // CacheUncacheable
56 "WC", // CacheWriteCombining
59 "WT", // CacheWriteThrough
60 "WP", // CacheWriteProtected
61 "WB", // CacheWriteBack
67 IN UINT32 MtrrRegister
72 Result
= (UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
);
73 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
74 Result
= Result
| LShiftU64 ((UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1), 32);
81 IN UINT32 MtrrRegister
,
85 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
, (UINT32
)Value
);
86 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
87 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1, (UINT32
)RShiftU64 (Value
, 32));
93 MtrrRegisterBitFieldWrite (
94 IN UINT32 MtrrRegister
,
100 return MtrrRegisterWrite (
103 MtrrRegisterRead (MtrrRegister
),
112 Worker function returns the variable MTRR count for the CPU.
114 @return Variable MTRR count
118 GetVariableMtrrCountWorker (
122 UINT32 VariableMtrrCount
;
124 VariableMtrrCount
= (UINT32
)(MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP
) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK
);
125 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
126 return VariableMtrrCount
;
130 Returns the variable MTRR count for the CPU.
132 @return Variable MTRR count
137 GetVariableMtrrCount (
141 if (!IsMtrrSupported ()) {
144 return GetVariableMtrrCountWorker ();
148 Worker function returns the firmware usable variable MTRR count for the CPU.
150 @return Firmware usable variable MTRR count
154 GetFirmwareVariableMtrrCountWorker (
158 UINT32 VariableMtrrCount
;
159 UINT32 ReservedMtrrNumber
;
161 VariableMtrrCount
= GetVariableMtrrCountWorker ();
162 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
163 if (VariableMtrrCount
< ReservedMtrrNumber
) {
167 return VariableMtrrCount
- ReservedMtrrNumber
;
171 Returns the firmware usable variable MTRR count for the CPU.
173 @return Firmware usable variable MTRR count
178 GetFirmwareVariableMtrrCount (
182 if (!IsMtrrSupported ()) {
185 return GetFirmwareVariableMtrrCountWorker ();
189 Worker function returns the default MTRR cache type for the system.
191 If MtrrSetting is not NULL, returns the default MTRR cache type from input
192 MTRR settings buffer.
193 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
195 @param[in] MtrrSetting A buffer holding all MTRRs content.
197 @return The default MTRR cache type.
200 MTRR_MEMORY_CACHE_TYPE
201 MtrrGetDefaultMemoryTypeWorker (
202 IN MTRR_SETTINGS
*MtrrSetting
205 if (MtrrSetting
== NULL
) {
206 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
) & 0x7);
208 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
214 Returns the default MTRR cache type for the system.
216 @return The default MTRR cache type.
219 MTRR_MEMORY_CACHE_TYPE
221 MtrrGetDefaultMemoryType (
225 if (!IsMtrrSupported ()) {
226 return CacheUncacheable
;
228 return MtrrGetDefaultMemoryTypeWorker (NULL
);
232 Preparation before programming MTRR.
234 This function will do some preparation for programming MTRRs:
235 disable cache, invalid cache and disable MTRR caching functionality
237 @param[out] MtrrContext Pointer to context to save
242 OUT MTRR_CONTEXT
*MtrrContext
246 // Disable interrupts and save current interrupt state
248 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
251 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
256 // Save original CR4 value and clear PGE flag (Bit 7)
258 MtrrContext
->Cr4
= AsmReadCr4 ();
259 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
269 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
273 Cleaning up after programming MTRRs.
275 This function will do some clean up after programming MTRRs:
276 Flush all TLBs, re-enable caching, restore CR4.
278 @param[in] MtrrContext Pointer to context to restore
282 PostMtrrChangeEnableCache (
283 IN MTRR_CONTEXT
*MtrrContext
292 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
297 // Restore original CR4 value
299 AsmWriteCr4 (MtrrContext
->Cr4
);
302 // Restore original interrupt state
304 SetInterruptState (MtrrContext
->InterruptState
);
308 Cleaning up after programming MTRRs.
310 This function will do some clean up after programming MTRRs:
311 enable MTRR caching functionality, and enable cache
313 @param[in] MtrrContext Pointer to context to restore
318 IN MTRR_CONTEXT
*MtrrContext
324 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
326 PostMtrrChangeEnableCache (MtrrContext
);
330 Worker function gets the content in fixed MTRRs
332 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
334 @retval The pointer of FixedSettings
338 MtrrGetFixedMtrrWorker (
339 OUT MTRR_FIXED_SETTINGS
*FixedSettings
344 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
345 FixedSettings
->Mtrr
[Index
] =
346 MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
349 return FixedSettings
;
354 This function gets the content in fixed MTRRs
356 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
358 @retval The pointer of FixedSettings
364 OUT MTRR_FIXED_SETTINGS
*FixedSettings
367 if (!IsMtrrSupported ()) {
368 return FixedSettings
;
371 return MtrrGetFixedMtrrWorker (FixedSettings
);
376 Worker function will get the raw value in variable MTRRs
378 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
379 MTRR settings buffer.
380 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
382 @param[in] MtrrSetting A buffer holding all MTRRs content.
383 @param[in] VariableMtrrCount Number of variable MTRRs.
384 @param[out] VariableSettings A buffer to hold variable MTRRs content.
386 @return The VariableSettings input pointer
389 MTRR_VARIABLE_SETTINGS
*
390 MtrrGetVariableMtrrWorker (
391 IN MTRR_SETTINGS
*MtrrSetting
,
392 IN UINT32 VariableMtrrCount
,
393 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
398 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
400 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
401 if (MtrrSetting
== NULL
) {
402 VariableSettings
->Mtrr
[Index
].Base
=
403 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1));
404 VariableSettings
->Mtrr
[Index
].Mask
=
405 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1);
407 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
408 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
412 return VariableSettings
;
416 This function will get the raw value in variable MTRRs
418 @param[out] VariableSettings A buffer to hold variable MTRRs content.
420 @return The VariableSettings input pointer
423 MTRR_VARIABLE_SETTINGS
*
425 MtrrGetVariableMtrr (
426 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
429 if (!IsMtrrSupported ()) {
430 return VariableSettings
;
433 return MtrrGetVariableMtrrWorker (
435 GetVariableMtrrCountWorker (),
441 Programs fixed MTRRs registers.
443 @param[in] MemoryCacheType The memory type to set.
444 @param[in, out] Base The base address of memory range.
445 @param[in, out] Length The length of memory range.
446 @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.
447 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
448 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
450 @retval RETURN_SUCCESS The cache type was updated successfully
451 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
457 IN UINT64 MemoryCacheType
,
459 IN OUT UINT64
*Length
,
460 OUT UINT32
*ReturnMsrNum
,
461 OUT UINT64
*ReturnClearMask
,
462 OUT UINT64
*ReturnOrMask
475 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
476 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
479 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
480 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
488 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
489 return RETURN_UNSUPPORTED
;
493 // We found the fixed MTRR to be programmed
495 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
498 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
499 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
506 if (ByteShift
== 8) {
507 return RETURN_UNSUPPORTED
;
512 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
515 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
516 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
517 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
518 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
521 if (ByteShift
< 8 && (*Length
!= 0)) {
522 return RETURN_UNSUPPORTED
;
525 *ReturnMsrNum
= MsrNum
;
526 *ReturnClearMask
= ClearMask
;
527 *ReturnOrMask
= OrMask
;
529 return RETURN_SUCCESS
;
534 Worker function gets the attribute of variable MTRRs.
536 This function shadows the content of variable MTRRs into an
537 internal array: VariableMtrr.
539 @param[in] VariableSettings The variable MTRR values to shadow
540 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
541 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
542 @param[in] MtrrValidAddressMask The valid address mask for MTRR
543 @param[out] VariableMtrr The array to shadow variable MTRRs content
545 @return The return value of this parameter indicates the
546 number of MTRRs which has been used.
550 MtrrGetMemoryAttributeInVariableMtrrWorker (
551 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
552 IN UINTN FirmwareVariableMtrrCount
,
553 IN UINT64 MtrrValidBitsMask
,
554 IN UINT64 MtrrValidAddressMask
,
555 OUT VARIABLE_MTRR
*VariableMtrr
561 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
562 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
563 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
564 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
565 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
566 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
567 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
568 VariableMtrr
[Index
].Valid
= TRUE
;
569 VariableMtrr
[Index
].Used
= TRUE
;
578 Gets the attribute of variable MTRRs.
580 This function shadows the content of variable MTRRs into an
581 internal array: VariableMtrr.
583 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
584 @param[in] MtrrValidAddressMask The valid address mask for MTRR
585 @param[out] VariableMtrr The array to shadow variable MTRRs content
587 @return The return value of this paramter indicates the
588 number of MTRRs which has been used.
593 MtrrGetMemoryAttributeInVariableMtrr (
594 IN UINT64 MtrrValidBitsMask
,
595 IN UINT64 MtrrValidAddressMask
,
596 OUT VARIABLE_MTRR
*VariableMtrr
599 MTRR_VARIABLE_SETTINGS VariableSettings
;
601 if (!IsMtrrSupported ()) {
605 MtrrGetVariableMtrrWorker (
607 GetVariableMtrrCountWorker (),
611 return MtrrGetMemoryAttributeInVariableMtrrWorker (
613 GetFirmwareVariableMtrrCountWorker (),
615 MtrrValidAddressMask
,
622 Checks overlap between given memory range and MTRRs.
624 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
626 @param[in] Start The start address of memory range.
627 @param[in] End The end address of memory range.
628 @param[in] VariableMtrr The array to shadow variable MTRRs content
630 @retval TRUE Overlap exists.
631 @retval FALSE No overlap.
635 CheckMemoryAttributeOverlap (
636 IN UINTN FirmwareVariableMtrrCount
,
637 IN PHYSICAL_ADDRESS Start
,
638 IN PHYSICAL_ADDRESS End
,
639 IN VARIABLE_MTRR
*VariableMtrr
644 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
646 VariableMtrr
[Index
].Valid
&&
648 (Start
> (VariableMtrr
[Index
].BaseAddress
+
649 VariableMtrr
[Index
].Length
- 1)
651 (End
< VariableMtrr
[Index
].BaseAddress
)
663 Marks a variable MTRR as non-valid.
665 @param[in] Index The index of the array VariableMtrr to be invalidated
666 @param[in] VariableMtrr The array to shadow variable MTRRs content
667 @param[out] UsedMtrr The number of MTRRs which has already been used
671 InvalidateShadowMtrr (
673 IN VARIABLE_MTRR
*VariableMtrr
,
677 VariableMtrr
[Index
].Valid
= FALSE
;
678 *UsedMtrr
= *UsedMtrr
- 1;
683 Combines memory attributes.
685 If overlap exists between given memory range and MTRRs, try to combine them.
687 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
688 available to firmware.
689 @param[in] Attributes The memory type to set.
690 @param[in, out] Base The base address of memory range.
691 @param[in, out] Length The length of memory range.
692 @param[in] VariableMtrr The array to shadow variable MTRRs content
693 @param[in, out] UsedMtrr The number of MTRRs which has already been used
694 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
696 @retval EFI_SUCCESS Memory region successfully combined.
697 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
701 CombineMemoryAttribute (
702 IN UINT32 FirmwareVariableMtrrCount
,
703 IN UINT64 Attributes
,
705 IN OUT UINT64
*Length
,
706 IN VARIABLE_MTRR
*VariableMtrr
,
707 IN OUT UINT32
*UsedMtrr
,
708 OUT BOOLEAN
*OverwriteExistingMtrr
716 BOOLEAN CoveredByExistingMtrr
;
718 *OverwriteExistingMtrr
= FALSE
;
719 CoveredByExistingMtrr
= FALSE
;
720 EndAddress
= *Base
+*Length
- 1;
722 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
724 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
726 !VariableMtrr
[Index
].Valid
||
729 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
736 // Combine same attribute MTRR range
738 if (Attributes
== VariableMtrr
[Index
].Type
) {
740 // if the MTRR range contain the request range, set a flag, then continue to
741 // invalidate any MTRR of the same request range with higher priority cache type.
743 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
744 CoveredByExistingMtrr
= TRUE
;
748 // invalid this MTRR, and program the combine range
751 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
753 VariableMtrr
[Index
].BaseAddress
;
754 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
757 // Record the MTRR usage status in VariableMtrr array.
759 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
760 *Base
= CombineStart
;
761 *Length
= CombineEnd
- CombineStart
+ 1;
762 EndAddress
= CombineEnd
;
763 *OverwriteExistingMtrr
= TRUE
;
767 // The cache type is different, but the range is convered by one MTRR
769 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
770 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
776 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
777 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
778 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
779 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
780 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
781 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
783 *OverwriteExistingMtrr
= TRUE
;
787 // Other type memory overlap is invalid
789 return RETURN_ACCESS_DENIED
;
792 if (CoveredByExistingMtrr
) {
796 return RETURN_SUCCESS
;
801 Calculates the maximum value which is a power of 2, but less the MemoryLength.
803 @param[in] MemoryLength The number to pass in.
805 @return The maximum value which is align to power of 2 and less the MemoryLength
810 IN UINT64 MemoryLength
815 if (RShiftU64 (MemoryLength
, 32) != 0) {
817 (UINT64
) GetPowerOfTwo32 (
818 (UINT32
) RShiftU64 (MemoryLength
, 32)
823 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
831 Determines the MTRR numbers used to program a memory range.
833 This function first checks the alignment of the base address.
834 If the alignment of the base address <= Length, cover the memory range
835 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
836 Length -= alignment. Repeat the step until alignment > Length.
838 Then this function determines which direction of programming the variable
839 MTRRs for the remaining length will use fewer MTRRs.
841 @param[in] BaseAddress Length of Memory to program MTRR
842 @param[in] Length Length of Memory to program MTRR
843 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
845 @retval TRUE Positive direction is better.
846 FALSE Negative direction is better.
850 GetMtrrNumberAndDirection (
851 IN UINT64 BaseAddress
,
863 if (BaseAddress
!= 0) {
866 // Calculate the alignment of the base address.
868 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
870 if (Alignment
> Length
) {
875 BaseAddress
+= Alignment
;
889 TempQword
-= Power2MaxMemory (TempQword
);
891 } while (TempQword
!= 0);
893 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
896 TempQword
-= Power2MaxMemory (TempQword
);
898 } while (TempQword
!= 0);
900 if (Positive
<= Subtractive
) {
901 *MtrrNumber
+= Positive
;
904 *MtrrNumber
+= Subtractive
;
910 Invalid variable MTRRs according to the value in the shadow array.
912 This function programs MTRRs according to the values specified
915 @param[in, out] VariableSettings Variable MTRR settings
916 @param[in] VariableMtrrCount Number of variable MTRRs
917 @param[in, out] VariableMtrr Shadow of variable MTRR contents
922 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
923 IN UINTN VariableMtrrCount
,
924 IN OUT VARIABLE_MTRR
*VariableMtrr
929 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
930 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
931 VariableSettings
->Mtrr
[Index
].Base
= 0;
932 VariableSettings
->Mtrr
[Index
].Mask
= 0;
933 VariableMtrr
[Index
].Used
= FALSE
;
940 Programs variable MTRRs
942 This function programs variable MTRRs
944 @param[in, out] VariableSettings Variable MTRR settings.
945 @param[in] MtrrNumber Index of MTRR to program.
946 @param[in] BaseAddress Base address of memory region.
947 @param[in] Length Length of memory region.
948 @param[in] MemoryCacheType Memory type to set.
949 @param[in] MtrrValidAddressMask The valid address mask for MTRR
953 ProgramVariableMtrr (
954 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
956 IN PHYSICAL_ADDRESS BaseAddress
,
958 IN UINT64 MemoryCacheType
,
959 IN UINT64 MtrrValidAddressMask
965 // MTRR Physical Base
967 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
968 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
971 // MTRR Physical Mask
973 TempQword
= ~(Length
- 1);
974 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
979 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
981 If MtrrSetting is not NULL, gets the default memory attribute from input
982 MTRR settings buffer.
983 If MtrrSetting is NULL, gets the default memory attribute from MSR.
985 @param[in] MtrrSetting A buffer holding all MTRRs content.
986 @param[in] MtrrType MTRR memory type
988 @return The enum item in MTRR_MEMORY_CACHE_TYPE
991 MTRR_MEMORY_CACHE_TYPE
992 GetMemoryCacheTypeFromMtrrType (
993 IN MTRR_SETTINGS
*MtrrSetting
,
998 case MTRR_CACHE_UNCACHEABLE
:
999 return CacheUncacheable
;
1000 case MTRR_CACHE_WRITE_COMBINING
:
1001 return CacheWriteCombining
;
1002 case MTRR_CACHE_WRITE_THROUGH
:
1003 return CacheWriteThrough
;
1004 case MTRR_CACHE_WRITE_PROTECTED
:
1005 return CacheWriteProtected
;
1006 case MTRR_CACHE_WRITE_BACK
:
1007 return CacheWriteBack
;
1010 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1011 // no MTRR covers the range
1013 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1018 Initializes the valid bits mask and valid address mask for MTRRs.
1020 This function initializes the valid bits mask and valid address mask for MTRRs.
1022 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1023 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1027 MtrrLibInitializeMtrrMask (
1028 OUT UINT64
*MtrrValidBitsMask
,
1029 OUT UINT64
*MtrrValidAddressMask
1033 UINT8 PhysicalAddressBits
;
1035 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1037 if (RegEax
>= 0x80000008) {
1038 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1040 PhysicalAddressBits
= (UINT8
) RegEax
;
1042 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1043 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1045 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1046 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1052 Determines the real attribute of a memory range.
1054 This function is to arbitrate the real attribute of the memory when
1055 there are 2 MTRRs covers the same memory range. For further details,
1056 please refer the IA32 Software Developer's Manual, Volume 3,
1059 @param[in] MtrrType1 The first kind of Memory type
1060 @param[in] MtrrType2 The second kind of memory type
1065 IN UINT64 MtrrType1
,
1071 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1072 switch (MtrrType1
) {
1073 case MTRR_CACHE_UNCACHEABLE
:
1074 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1076 case MTRR_CACHE_WRITE_COMBINING
:
1078 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1079 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1081 MtrrType
= MtrrType2
;
1084 case MTRR_CACHE_WRITE_THROUGH
:
1086 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1087 MtrrType2
==MTRR_CACHE_WRITE_BACK
1089 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1090 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1091 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1094 case MTRR_CACHE_WRITE_PROTECTED
:
1095 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1096 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1097 MtrrType
= MtrrType2
;
1100 case MTRR_CACHE_WRITE_BACK
:
1102 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1103 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1104 MtrrType2
== MTRR_CACHE_WRITE_BACK
1106 MtrrType
= MtrrType2
;
1109 case MTRR_CACHE_INVALID_TYPE
:
1110 MtrrType
= MtrrType2
;
1116 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1117 MtrrType
= MtrrType1
;
1123 Worker function will get the memory cache type of the specific address.
1125 If MtrrSetting is not NULL, gets the memory cache type from input
1126 MTRR settings buffer.
1127 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1129 @param[in] MtrrSetting A buffer holding all MTRRs content.
1130 @param[in] Address The specific address
1132 @return Memory cache type of the specific address
1135 MTRR_MEMORY_CACHE_TYPE
1136 MtrrGetMemoryAttributeByAddressWorker (
1137 IN MTRR_SETTINGS
*MtrrSetting
,
1138 IN PHYSICAL_ADDRESS Address
1145 UINT64 TempMtrrType
;
1146 MTRR_MEMORY_CACHE_TYPE CacheType
;
1147 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1148 UINT64 MtrrValidBitsMask
;
1149 UINT64 MtrrValidAddressMask
;
1150 UINTN VariableMtrrCount
;
1151 MTRR_VARIABLE_SETTINGS VariableSettings
;
1154 // Check if MTRR is enabled, if not, return UC as attribute
1156 if (MtrrSetting
== NULL
) {
1157 TempQword
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
1159 TempQword
= MtrrSetting
->MtrrDefType
;
1161 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1163 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1164 return CacheUncacheable
;
1168 // If address is less than 1M, then try to go through the fixed MTRR
1170 if (Address
< BASE_1MB
) {
1171 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1173 // Go through the fixed MTRR
1175 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1176 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1178 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1179 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1183 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1184 mMtrrLibFixedMtrrTable
[Index
].Length
;
1185 if (MtrrSetting
== NULL
) {
1186 TempQword
= MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1188 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1190 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1191 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1196 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1198 MtrrGetVariableMtrrWorker (
1200 GetVariableMtrrCountWorker (),
1204 MtrrGetMemoryAttributeInVariableMtrrWorker (
1206 GetFirmwareVariableMtrrCountWorker (),
1208 MtrrValidAddressMask
,
1213 // Go through the variable MTRR
1215 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1216 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1218 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1219 if (VariableMtrr
[Index
].Valid
) {
1220 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1221 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1222 TempMtrrType
= VariableMtrr
[Index
].Type
;
1223 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1227 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1234 This function will get the memory cache type of the specific address.
1236 This function is mainly for debug purpose.
1238 @param[in] Address The specific address
1240 @return Memory cache type of the specific address
1243 MTRR_MEMORY_CACHE_TYPE
1245 MtrrGetMemoryAttribute (
1246 IN PHYSICAL_ADDRESS Address
1249 if (!IsMtrrSupported ()) {
1250 return CacheUncacheable
;
1253 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1257 Worker function prints all MTRRs for debugging.
1259 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1261 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1263 @param MtrrSetting A buffer holding all MTRRs content.
1266 MtrrDebugPrintAllMtrrsWorker (
1267 IN MTRR_SETTINGS
*MtrrSetting
1271 MTRR_SETTINGS LocalMtrrs
;
1272 MTRR_SETTINGS
*Mtrrs
;
1275 UINTN VariableMtrrCount
;
1283 UINT64 NoRangeLimit
;
1286 UINTN PreviousMemoryType
;
1289 if (!IsMtrrSupported ()) {
1293 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1294 DEBUG((DEBUG_CACHE
, "=============\n"));
1296 if (MtrrSetting
!= NULL
) {
1297 Mtrrs
= MtrrSetting
;
1299 MtrrGetAllMtrrs (&LocalMtrrs
);
1300 Mtrrs
= &LocalMtrrs
;
1303 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1304 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1305 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1308 VariableMtrrCount
= GetVariableMtrrCount ();
1309 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1310 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1312 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1313 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1316 DEBUG((DEBUG_CACHE
, "\n"));
1317 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1318 DEBUG((DEBUG_CACHE
, "====================================\n"));
1321 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1322 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1323 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1324 for (Index1
= 0; Index1
< 8; Index1
++) {
1325 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1326 if (MemoryType
> CacheWriteBack
) {
1327 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1329 if (MemoryType
!= PreviousMemoryType
) {
1330 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1331 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1333 PreviousMemoryType
= MemoryType
;
1334 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1336 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1339 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1341 VariableMtrrCount
= GetVariableMtrrCount ();
1344 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1345 if (RegEax
>= 0x80000008) {
1346 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1347 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1350 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1352 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1353 if (MemoryType
> CacheWriteBack
) {
1354 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1357 if (MemoryType
!= PreviousMemoryType
) {
1358 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1359 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1361 PreviousMemoryType
= MemoryType
;
1362 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1365 RangeBase
= BASE_1MB
;
1366 NoRangeBase
= BASE_1MB
;
1368 NoRangeLimit
= Limit
;
1370 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1371 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1373 // If mask is not valid, then do not display range
1377 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1378 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1380 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1384 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1385 RangeBase
= MtrrBase
;
1387 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1388 RangeBase
= MtrrLimit
+ 1;
1390 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1391 RangeLimit
= MtrrBase
- 1;
1393 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1394 RangeLimit
= MtrrLimit
;
1397 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1398 NoRangeBase
= MtrrLimit
+ 1;
1400 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1401 NoRangeLimit
= MtrrBase
- 1;
1406 Base
= RangeLimit
+ 1;
1408 Base
= NoRangeLimit
+ 1;
1410 } while (Base
< Limit
);
1411 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1417 This function prints all MTRRs for debugging.
1421 MtrrDebugPrintAllMtrrs (
1425 MtrrDebugPrintAllMtrrsWorker (NULL
);
1430 Worker function attempts to set the attributes for a memory range.
1432 If MtrrSettings is not NULL, set the attributes into the input MTRR
1434 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1436 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1437 @param[in] BaseAddress The physical address that is the start
1438 address of a memory region.
1439 @param[in] Length The size in bytes of the memory region.
1440 @param[in] Attribute The bit mask of attributes to set for the
1443 @retval RETURN_SUCCESS The attributes were set for the memory
1445 @retval RETURN_INVALID_PARAMETER Length is zero.
1446 @retval RETURN_UNSUPPORTED The processor does not support one or
1447 more bytes of the memory resource range
1448 specified by BaseAddress and Length.
1449 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1450 for the memory resource range specified
1451 by BaseAddress and Length.
1452 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1453 range specified by BaseAddress and Length
1455 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1456 modify the attributes of the memory
1461 MtrrSetMemoryAttributeWorker (
1462 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1463 IN PHYSICAL_ADDRESS BaseAddress
,
1465 IN MTRR_MEMORY_CACHE_TYPE Attribute
1469 RETURN_STATUS Status
;
1476 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1478 UINT64 MtrrValidBitsMask
;
1479 UINT64 MtrrValidAddressMask
;
1480 BOOLEAN OverwriteExistingMtrr
;
1481 UINT32 FirmwareVariableMtrrCount
;
1482 MTRR_CONTEXT MtrrContext
;
1483 BOOLEAN MtrrContextValid
;
1484 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1485 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1486 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1487 UINT32 VariableMtrrCount
;
1488 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1489 BOOLEAN ProgramVariableSettings
;
1490 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1495 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1497 MtrrContextValid
= FALSE
;
1498 VariableMtrrCount
= 0;
1499 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1500 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1501 FixedSettingsValid
[Index
] = FALSE
;
1502 FixedSettingsModified
[Index
] = FALSE
;
1504 ProgramVariableSettings
= FALSE
;
1506 if (!IsMtrrSupported ()) {
1507 Status
= RETURN_UNSUPPORTED
;
1511 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1514 MemoryType
= (UINT64
)Attribute
;
1515 OverwriteExistingMtrr
= FALSE
;
1518 // Check for an invalid parameter
1521 Status
= RETURN_INVALID_PARAMETER
;
1526 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1527 (Length
& ~MtrrValidAddressMask
) != 0
1529 Status
= RETURN_UNSUPPORTED
;
1534 // Check if Fixed MTRR
1536 Status
= RETURN_SUCCESS
;
1537 if (BaseAddress
< BASE_1MB
) {
1538 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1539 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1540 if (RETURN_ERROR (Status
)) {
1543 if (MtrrSetting
!= NULL
) {
1544 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1545 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1547 if (!FixedSettingsValid
[MsrNum
]) {
1548 WorkingFixedSettings
.Mtrr
[MsrNum
] = MtrrRegisterRead (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1549 FixedSettingsValid
[MsrNum
] = TRUE
;
1551 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1552 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1553 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1554 FixedSettingsModified
[MsrNum
] = TRUE
;
1561 // A Length of 0 can only make sense for fixed MTTR ranges.
1562 // Since we just handled the fixed MTRRs, we can skip the
1563 // variable MTRR section.
1570 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1571 // we can set the base to 0 to save variable MTRRs.
1573 if (BaseAddress
== BASE_1MB
) {
1579 // Read all variable MTRRs
1581 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1582 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1583 if (MtrrSetting
!= NULL
) {
1584 VariableSettings
= &MtrrSetting
->Variables
;
1586 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1587 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1588 ProgramVariableSettings
= TRUE
;
1589 VariableSettings
= &WorkingVariableSettings
;
1593 // Check for overlap
1595 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1597 FirmwareVariableMtrrCount
,
1599 MtrrValidAddressMask
,
1602 OverLap
= CheckMemoryAttributeOverlap (
1603 FirmwareVariableMtrrCount
,
1605 BaseAddress
+ Length
- 1,
1609 Status
= CombineMemoryAttribute (
1610 FirmwareVariableMtrrCount
,
1616 &OverwriteExistingMtrr
1618 if (RETURN_ERROR (Status
)) {
1624 // Combined successfully, invalidate the now-unused MTRRs
1626 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1627 Status
= RETURN_SUCCESS
;
1633 // The memory type is the same with the type specified by
1634 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1636 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1638 // Invalidate the now-unused MTRRs
1640 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1644 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1646 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1647 Status
= RETURN_OUT_OF_RESOURCES
;
1652 // Invalidate the now-unused MTRRs
1654 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1657 // Find first unused MTRR
1659 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1660 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1665 if (BaseAddress
!= 0) {
1668 // Calculate the alignment of the base address.
1670 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1672 if (Alignment
> Length
) {
1679 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1680 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1685 ProgramVariableMtrr (
1691 MtrrValidAddressMask
1693 BaseAddress
+= Alignment
;
1694 Length
-= Alignment
;
1705 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1710 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1711 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1716 ProgramVariableMtrr (
1722 MtrrValidAddressMask
1724 BaseAddress
+= Length
;
1725 TempQword
= Length
- TempQword
;
1726 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1733 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1734 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1739 Length
= Power2MaxMemory (TempQword
);
1741 BaseAddress
-= Length
;
1744 ProgramVariableMtrr (
1750 MtrrValidAddressMask
1754 BaseAddress
+= Length
;
1756 TempQword
-= Length
;
1758 } while (TempQword
> 0);
1763 // Write fixed MTRRs that have been modified
1765 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1766 if (FixedSettingsModified
[Index
]) {
1767 if (!MtrrContextValid
) {
1768 PreMtrrChange (&MtrrContext
);
1769 MtrrContextValid
= TRUE
;
1772 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1773 WorkingFixedSettings
.Mtrr
[Index
]
1779 // Write variable MTRRs
1781 if (ProgramVariableSettings
) {
1782 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1783 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1784 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1785 if (!MtrrContextValid
) {
1786 PreMtrrChange (&MtrrContext
);
1787 MtrrContextValid
= TRUE
;
1790 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1791 WorkingVariableSettings
.Mtrr
[Index
].Base
1794 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1795 WorkingVariableSettings
.Mtrr
[Index
].Mask
1800 if (MtrrContextValid
) {
1801 PostMtrrChange (&MtrrContext
);
1804 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1805 if (!RETURN_ERROR (Status
)) {
1806 if (MtrrSetting
!= NULL
) {
1807 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1809 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1816 This function attempts to set the attributes for a memory range.
1818 @param[in] BaseAddress The physical address that is the start
1819 address of a memory region.
1820 @param[in] Length The size in bytes of the memory region.
1821 @param[in] Attributes The bit mask of attributes to set for the
1824 @retval RETURN_SUCCESS The attributes were set for the memory
1826 @retval RETURN_INVALID_PARAMETER Length is zero.
1827 @retval RETURN_UNSUPPORTED The processor does not support one or
1828 more bytes of the memory resource range
1829 specified by BaseAddress and Length.
1830 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1831 for the memory resource range specified
1832 by BaseAddress and Length.
1833 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1834 range specified by BaseAddress and Length
1836 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1837 modify the attributes of the memory
1843 MtrrSetMemoryAttribute (
1844 IN PHYSICAL_ADDRESS BaseAddress
,
1846 IN MTRR_MEMORY_CACHE_TYPE Attribute
1849 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1850 return MtrrSetMemoryAttributeWorker (
1859 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1861 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1862 @param[in] BaseAddress The physical address that is the start address
1864 @param[in] Length The size in bytes of the memory region.
1865 @param[in] Attribute The bit mask of attributes to set for the
1868 @retval RETURN_SUCCESS The attributes were set for the memory region.
1869 @retval RETURN_INVALID_PARAMETER Length is zero.
1870 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1871 memory resource range specified by BaseAddress and Length.
1872 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1873 range specified by BaseAddress and Length.
1874 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1875 BaseAddress and Length cannot be modified.
1876 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1877 the memory resource range.
1882 MtrrSetMemoryAttributeInMtrrSettings (
1883 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1884 IN PHYSICAL_ADDRESS BaseAddress
,
1886 IN MTRR_MEMORY_CACHE_TYPE Attribute
1889 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1890 return MtrrSetMemoryAttributeWorker (
1899 Worker function setting variable MTRRs
1901 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1905 MtrrSetVariableMtrrWorker (
1906 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1910 UINT32 VariableMtrrCount
;
1912 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1913 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1915 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1917 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1918 VariableSettings
->Mtrr
[Index
].Base
1921 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1922 VariableSettings
->Mtrr
[Index
].Mask
1929 This function sets variable MTRRs
1931 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1933 @return The pointer of VariableSettings
1936 MTRR_VARIABLE_SETTINGS
*
1938 MtrrSetVariableMtrr (
1939 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1942 MTRR_CONTEXT MtrrContext
;
1944 if (!IsMtrrSupported ()) {
1945 return VariableSettings
;
1948 PreMtrrChange (&MtrrContext
);
1949 MtrrSetVariableMtrrWorker (VariableSettings
);
1950 PostMtrrChange (&MtrrContext
);
1951 MtrrDebugPrintAllMtrrs ();
1953 return VariableSettings
;
1957 Worker function setting fixed MTRRs
1959 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1963 MtrrSetFixedMtrrWorker (
1964 IN MTRR_FIXED_SETTINGS
*FixedSettings
1969 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1971 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1972 FixedSettings
->Mtrr
[Index
]
1979 This function sets fixed MTRRs
1981 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1983 @retval The pointer of FixedSettings
1986 MTRR_FIXED_SETTINGS
*
1989 IN MTRR_FIXED_SETTINGS
*FixedSettings
1992 MTRR_CONTEXT MtrrContext
;
1994 if (!IsMtrrSupported ()) {
1995 return FixedSettings
;
1998 PreMtrrChange (&MtrrContext
);
1999 MtrrSetFixedMtrrWorker (FixedSettings
);
2000 PostMtrrChange (&MtrrContext
);
2001 MtrrDebugPrintAllMtrrs ();
2003 return FixedSettings
;
2008 This function gets the content in all MTRRs (variable and fixed)
2010 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2012 @retval the pointer of MtrrSetting
2018 OUT MTRR_SETTINGS
*MtrrSetting
2021 if (!IsMtrrSupported ()) {
2028 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2031 // Get variable MTRRs
2033 MtrrGetVariableMtrrWorker (
2035 GetVariableMtrrCountWorker (),
2036 &MtrrSetting
->Variables
2040 // Get MTRR_DEF_TYPE value
2042 MtrrSetting
->MtrrDefType
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
2049 This function sets all MTRRs (variable and fixed)
2051 @param[in] MtrrSetting A buffer holding all MTRRs content.
2053 @retval The pointer of MtrrSetting
2059 IN MTRR_SETTINGS
*MtrrSetting
2062 MTRR_CONTEXT MtrrContext
;
2064 if (!IsMtrrSupported ()) {
2068 PreMtrrChange (&MtrrContext
);
2073 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2076 // Set variable MTRRs
2078 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2081 // Set MTRR_DEF_TYPE value
2083 MtrrRegisterWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2085 PostMtrrChangeEnableCache (&MtrrContext
);
2087 MtrrDebugPrintAllMtrrs ();
2094 Checks if MTRR is supported.
2096 @retval TRUE MTRR is supported.
2097 @retval FALSE MTRR is not supported.
2109 // Check CPUID(1).EAX[0..11] for Quark SoC
2111 AsmCpuid (1, &RegEax
, NULL
, NULL
, NULL
);
2112 if ((RegEax
& 0xfff) == QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING
) {