4 Copyright (c) 2008 - 2016, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/MtrrLib.h>
12 #include <Library/BaseLib.h>
13 #include <Library/CpuLib.h>
14 #include <Library/BaseMemoryLib.h>
15 #include <Library/DebugLib.h>
16 #include <Library/QNCAccessLib.h>
18 #define QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING 0x590
20 #define CACHE_MTRR_ENABLED 0x800
21 #define CACHE_FIXED_MTRR_ENABLED 0x400
22 #define IA32_MTRR_CAP_VCNT_MASK 0xFF
25 // Context to save and restore when MTRRs are programmed
29 BOOLEAN InterruptState
;
33 // This table defines the offset, base and length of the fixed MTRRs
35 CONST FIXED_MTRR mMtrrLibFixedMtrrTable
[] = {
36 { QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
, 0, SIZE_64KB
},
37 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_80000
, 0x80000, SIZE_16KB
},
38 { QUARK_NC_HOST_BRIDGE_MTRR_FIX16K_A0000
, 0xA0000, SIZE_16KB
},
39 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C0000
, 0xC0000, SIZE_4KB
},
40 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_C8000
, 0xC8000, SIZE_4KB
},
41 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D0000
, 0xD0000, SIZE_4KB
},
42 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_D8000
, 0xD8000, SIZE_4KB
},
43 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E0000
, 0xE0000, SIZE_4KB
},
44 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_E8000
, 0xE8000, SIZE_4KB
},
45 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F0000
, 0xF0000, SIZE_4KB
},
46 { QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
, 0xF8000, SIZE_4KB
}
50 // Lookup table used to print MTRRs
52 GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8
*mMtrrMemoryCacheTypeShortName
[] = {
53 "UC", // CacheUncacheable
54 "WC", // CacheWriteCombining
57 "WT", // CacheWriteThrough
58 "WP", // CacheWriteProtected
59 "WB", // CacheWriteBack
65 IN UINT32 MtrrRegister
70 Result
= (UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
);
71 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
72 Result
= Result
| LShiftU64 ((UINT64
)QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1), 32);
79 IN UINT32 MtrrRegister
,
83 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
, (UINT32
)Value
);
84 if (MtrrRegister
>= QUARK_NC_HOST_BRIDGE_MTRR_FIX64K_00000
&& MtrrRegister
<= QUARK_NC_HOST_BRIDGE_MTRR_FIX4K_F8000
) {
85 QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID
, MtrrRegister
+ 1, (UINT32
)RShiftU64 (Value
, 32));
91 MtrrRegisterBitFieldWrite (
92 IN UINT32 MtrrRegister
,
98 return MtrrRegisterWrite (
101 MtrrRegisterRead (MtrrRegister
),
110 Worker function returns the variable MTRR count for the CPU.
112 @return Variable MTRR count
116 GetVariableMtrrCountWorker (
120 UINT32 VariableMtrrCount
;
122 VariableMtrrCount
= (UINT32
)(MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_CAP
) & IA32_MTRR_CAP_VCNT_MASK
);
123 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
124 return VariableMtrrCount
;
128 Returns the variable MTRR count for the CPU.
130 @return Variable MTRR count
135 GetVariableMtrrCount (
139 if (!IsMtrrSupported ()) {
142 return GetVariableMtrrCountWorker ();
146 Worker function returns the firmware usable variable MTRR count for the CPU.
148 @return Firmware usable variable MTRR count
152 GetFirmwareVariableMtrrCountWorker (
156 UINT32 VariableMtrrCount
;
157 UINT32 ReservedMtrrNumber
;
159 VariableMtrrCount
= GetVariableMtrrCountWorker ();
160 ReservedMtrrNumber
= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs
);
161 if (VariableMtrrCount
< ReservedMtrrNumber
) {
165 return VariableMtrrCount
- ReservedMtrrNumber
;
169 Returns the firmware usable variable MTRR count for the CPU.
171 @return Firmware usable variable MTRR count
176 GetFirmwareVariableMtrrCount (
180 if (!IsMtrrSupported ()) {
183 return GetFirmwareVariableMtrrCountWorker ();
187 Worker function returns the default MTRR cache type for the system.
189 If MtrrSetting is not NULL, returns the default MTRR cache type from input
190 MTRR settings buffer.
191 If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
193 @param[in] MtrrSetting A buffer holding all MTRRs content.
195 @return The default MTRR cache type.
198 MTRR_MEMORY_CACHE_TYPE
199 MtrrGetDefaultMemoryTypeWorker (
200 IN MTRR_SETTINGS
*MtrrSetting
203 if (MtrrSetting
== NULL
) {
204 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
) & 0x7);
206 return (MTRR_MEMORY_CACHE_TYPE
) (MtrrSetting
->MtrrDefType
& 0x7);
212 Returns the default MTRR cache type for the system.
214 @return The default MTRR cache type.
217 MTRR_MEMORY_CACHE_TYPE
219 MtrrGetDefaultMemoryType (
223 if (!IsMtrrSupported ()) {
224 return CacheUncacheable
;
226 return MtrrGetDefaultMemoryTypeWorker (NULL
);
230 Preparation before programming MTRR.
232 This function will do some preparation for programming MTRRs:
233 disable cache, invalid cache and disable MTRR caching functionality
235 @param[out] MtrrContext Pointer to context to save
240 OUT MTRR_CONTEXT
*MtrrContext
244 // Disable interrupts and save current interrupt state
246 MtrrContext
->InterruptState
= SaveAndDisableInterrupts();
249 // Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
254 // Save original CR4 value and clear PGE flag (Bit 7)
256 MtrrContext
->Cr4
= AsmReadCr4 ();
257 AsmWriteCr4 (MtrrContext
->Cr4
& (~BIT7
));
267 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 0);
271 Cleaning up after programming MTRRs.
273 This function will do some clean up after programming MTRRs:
274 Flush all TLBs, re-enable caching, restore CR4.
276 @param[in] MtrrContext Pointer to context to restore
280 PostMtrrChangeEnableCache (
281 IN MTRR_CONTEXT
*MtrrContext
290 // Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
295 // Restore original CR4 value
297 AsmWriteCr4 (MtrrContext
->Cr4
);
300 // Restore original interrupt state
302 SetInterruptState (MtrrContext
->InterruptState
);
306 Cleaning up after programming MTRRs.
308 This function will do some clean up after programming MTRRs:
309 enable MTRR caching functionality, and enable cache
311 @param[in] MtrrContext Pointer to context to restore
316 IN MTRR_CONTEXT
*MtrrContext
322 MtrrRegisterBitFieldWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, 10, 11, 3);
324 PostMtrrChangeEnableCache (MtrrContext
);
328 Worker function gets the content in fixed MTRRs
330 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
332 @retval The pointer of FixedSettings
336 MtrrGetFixedMtrrWorker (
337 OUT MTRR_FIXED_SETTINGS
*FixedSettings
342 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
343 FixedSettings
->Mtrr
[Index
] =
344 MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
347 return FixedSettings
;
352 This function gets the content in fixed MTRRs
354 @param[out] FixedSettings A buffer to hold fixed MTRRs content.
356 @retval The pointer of FixedSettings
362 OUT MTRR_FIXED_SETTINGS
*FixedSettings
365 if (!IsMtrrSupported ()) {
366 return FixedSettings
;
369 return MtrrGetFixedMtrrWorker (FixedSettings
);
374 Worker function will get the raw value in variable MTRRs
376 If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
377 MTRR settings buffer.
378 If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
380 @param[in] MtrrSetting A buffer holding all MTRRs content.
381 @param[in] VariableMtrrCount Number of variable MTRRs.
382 @param[out] VariableSettings A buffer to hold variable MTRRs content.
384 @return The VariableSettings input pointer
387 MTRR_VARIABLE_SETTINGS
*
388 MtrrGetVariableMtrrWorker (
389 IN MTRR_SETTINGS
*MtrrSetting
,
390 IN UINT32 VariableMtrrCount
,
391 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
396 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
398 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
399 if (MtrrSetting
== NULL
) {
400 VariableSettings
->Mtrr
[Index
].Base
=
401 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1));
402 VariableSettings
->Mtrr
[Index
].Mask
=
403 MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1);
405 VariableSettings
->Mtrr
[Index
].Base
= MtrrSetting
->Variables
.Mtrr
[Index
].Base
;
406 VariableSettings
->Mtrr
[Index
].Mask
= MtrrSetting
->Variables
.Mtrr
[Index
].Mask
;
410 return VariableSettings
;
414 This function will get the raw value in variable MTRRs
416 @param[out] VariableSettings A buffer to hold variable MTRRs content.
418 @return The VariableSettings input pointer
421 MTRR_VARIABLE_SETTINGS
*
423 MtrrGetVariableMtrr (
424 OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
427 if (!IsMtrrSupported ()) {
428 return VariableSettings
;
431 return MtrrGetVariableMtrrWorker (
433 GetVariableMtrrCountWorker (),
439 Programs fixed MTRRs registers.
441 @param[in] MemoryCacheType The memory type to set.
442 @param[in, out] Base The base address of memory range.
443 @param[in, out] Length The length of memory range.
444 @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program.
445 @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR.
446 @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR.
448 @retval RETURN_SUCCESS The cache type was updated successfully
449 @retval RETURN_UNSUPPORTED The requested range or cache type was invalid
455 IN UINT64 MemoryCacheType
,
457 IN OUT UINT64
*Length
,
458 OUT UINT32
*ReturnMsrNum
,
459 OUT UINT64
*ReturnClearMask
,
460 OUT UINT64
*ReturnOrMask
471 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
472 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
475 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
476 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
484 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
485 return RETURN_UNSUPPORTED
;
489 // We found the fixed MTRR to be programmed
491 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
494 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
495 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
502 if (ByteShift
== 8) {
503 return RETURN_UNSUPPORTED
;
508 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
511 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
512 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
513 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
514 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
517 if (ByteShift
< 8 && (*Length
!= 0)) {
518 return RETURN_UNSUPPORTED
;
521 *ReturnMsrNum
= MsrNum
;
522 *ReturnClearMask
= ClearMask
;
523 *ReturnOrMask
= OrMask
;
525 return RETURN_SUCCESS
;
530 Worker function gets the attribute of variable MTRRs.
532 This function shadows the content of variable MTRRs into an
533 internal array: VariableMtrr.
535 @param[in] VariableSettings The variable MTRR values to shadow
536 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
537 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
538 @param[in] MtrrValidAddressMask The valid address mask for MTRR
539 @param[out] VariableMtrr The array to shadow variable MTRRs content
541 @return The return value of this parameter indicates the
542 number of MTRRs which has been used.
546 MtrrGetMemoryAttributeInVariableMtrrWorker (
547 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
548 IN UINTN FirmwareVariableMtrrCount
,
549 IN UINT64 MtrrValidBitsMask
,
550 IN UINT64 MtrrValidAddressMask
,
551 OUT VARIABLE_MTRR
*VariableMtrr
557 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
558 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
559 if ((VariableSettings
->Mtrr
[Index
].Mask
& CACHE_MTRR_ENABLED
) != 0) {
560 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
561 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
562 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
563 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
564 VariableMtrr
[Index
].Valid
= TRUE
;
565 VariableMtrr
[Index
].Used
= TRUE
;
574 Gets the attribute of variable MTRRs.
576 This function shadows the content of variable MTRRs into an
577 internal array: VariableMtrr.
579 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
580 @param[in] MtrrValidAddressMask The valid address mask for MTRR
581 @param[out] VariableMtrr The array to shadow variable MTRRs content
583 @return The return value of this parameter indicates the
584 number of MTRRs which has been used.
589 MtrrGetMemoryAttributeInVariableMtrr (
590 IN UINT64 MtrrValidBitsMask
,
591 IN UINT64 MtrrValidAddressMask
,
592 OUT VARIABLE_MTRR
*VariableMtrr
595 MTRR_VARIABLE_SETTINGS VariableSettings
;
597 if (!IsMtrrSupported ()) {
601 MtrrGetVariableMtrrWorker (
603 GetVariableMtrrCountWorker (),
607 return MtrrGetMemoryAttributeInVariableMtrrWorker (
609 GetFirmwareVariableMtrrCountWorker (),
611 MtrrValidAddressMask
,
618 Checks overlap between given memory range and MTRRs.
620 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
622 @param[in] Start The start address of memory range.
623 @param[in] End The end address of memory range.
624 @param[in] VariableMtrr The array to shadow variable MTRRs content
626 @retval TRUE Overlap exists.
627 @retval FALSE No overlap.
631 CheckMemoryAttributeOverlap (
632 IN UINTN FirmwareVariableMtrrCount
,
633 IN PHYSICAL_ADDRESS Start
,
634 IN PHYSICAL_ADDRESS End
,
635 IN VARIABLE_MTRR
*VariableMtrr
640 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
642 VariableMtrr
[Index
].Valid
&&
644 (Start
> (VariableMtrr
[Index
].BaseAddress
+
645 VariableMtrr
[Index
].Length
- 1)
647 (End
< VariableMtrr
[Index
].BaseAddress
)
659 Marks a variable MTRR as non-valid.
661 @param[in] Index The index of the array VariableMtrr to be invalidated
662 @param[in] VariableMtrr The array to shadow variable MTRRs content
663 @param[out] UsedMtrr The number of MTRRs which has already been used
667 InvalidateShadowMtrr (
669 IN VARIABLE_MTRR
*VariableMtrr
,
673 VariableMtrr
[Index
].Valid
= FALSE
;
674 *UsedMtrr
= *UsedMtrr
- 1;
679 Combines memory attributes.
681 If overlap exists between given memory range and MTRRs, try to combine them.
683 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
684 available to firmware.
685 @param[in] Attributes The memory type to set.
686 @param[in, out] Base The base address of memory range.
687 @param[in, out] Length The length of memory range.
688 @param[in] VariableMtrr The array to shadow variable MTRRs content
689 @param[in, out] UsedMtrr The number of MTRRs which has already been used
690 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
692 @retval EFI_SUCCESS Memory region successfully combined.
693 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
697 CombineMemoryAttribute (
698 IN UINT32 FirmwareVariableMtrrCount
,
699 IN UINT64 Attributes
,
701 IN OUT UINT64
*Length
,
702 IN VARIABLE_MTRR
*VariableMtrr
,
703 IN OUT UINT32
*UsedMtrr
,
704 OUT BOOLEAN
*OverwriteExistingMtrr
712 BOOLEAN CoveredByExistingMtrr
;
714 *OverwriteExistingMtrr
= FALSE
;
715 CoveredByExistingMtrr
= FALSE
;
716 EndAddress
= *Base
+*Length
- 1;
718 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
720 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
722 !VariableMtrr
[Index
].Valid
||
725 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
732 // Combine same attribute MTRR range
734 if (Attributes
== VariableMtrr
[Index
].Type
) {
736 // if the MTRR range contain the request range, set a flag, then continue to
737 // invalidate any MTRR of the same request range with higher priority cache type.
739 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
740 CoveredByExistingMtrr
= TRUE
;
744 // invalid this MTRR, and program the combine range
747 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
749 VariableMtrr
[Index
].BaseAddress
;
750 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
753 // Record the MTRR usage status in VariableMtrr array.
755 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
756 *Base
= CombineStart
;
757 *Length
= CombineEnd
- CombineStart
+ 1;
758 EndAddress
= CombineEnd
;
759 *OverwriteExistingMtrr
= TRUE
;
763 // The cache type is different, but the range is convered by one MTRR
765 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
766 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
772 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
773 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
774 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
775 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
776 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
777 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
779 *OverwriteExistingMtrr
= TRUE
;
783 // Other type memory overlap is invalid
785 return RETURN_ACCESS_DENIED
;
788 if (CoveredByExistingMtrr
) {
792 return RETURN_SUCCESS
;
797 Calculates the maximum value which is a power of 2, but less the MemoryLength.
799 @param[in] MemoryLength The number to pass in.
801 @return The maximum value which is align to power of 2 and less the MemoryLength
806 IN UINT64 MemoryLength
811 if (RShiftU64 (MemoryLength
, 32) != 0) {
813 (UINT64
) GetPowerOfTwo32 (
814 (UINT32
) RShiftU64 (MemoryLength
, 32)
819 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
827 Determines the MTRR numbers used to program a memory range.
829 This function first checks the alignment of the base address.
830 If the alignment of the base address <= Length, cover the memory range
831 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
832 Length -= alignment. Repeat the step until alignment > Length.
834 Then this function determines which direction of programming the variable
835 MTRRs for the remaining length will use fewer MTRRs.
837 @param[in] BaseAddress Length of Memory to program MTRR
838 @param[in] Length Length of Memory to program MTRR
839 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
841 @retval TRUE Positive direction is better.
842 FALSE Negative direction is better.
846 GetMtrrNumberAndDirection (
847 IN UINT64 BaseAddress
,
859 if (BaseAddress
!= 0) {
862 // Calculate the alignment of the base address.
864 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
866 if (Alignment
> Length
) {
871 BaseAddress
+= Alignment
;
885 TempQword
-= Power2MaxMemory (TempQword
);
887 } while (TempQword
!= 0);
889 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
892 TempQword
-= Power2MaxMemory (TempQword
);
894 } while (TempQword
!= 0);
896 if (Positive
<= Subtractive
) {
897 *MtrrNumber
+= Positive
;
900 *MtrrNumber
+= Subtractive
;
906 Invalid variable MTRRs according to the value in the shadow array.
908 This function programs MTRRs according to the values specified
911 @param[in, out] VariableSettings Variable MTRR settings
912 @param[in] VariableMtrrCount Number of variable MTRRs
913 @param[in, out] VariableMtrr Shadow of variable MTRR contents
918 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
919 IN UINTN VariableMtrrCount
,
920 IN OUT VARIABLE_MTRR
*VariableMtrr
925 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
926 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
927 VariableSettings
->Mtrr
[Index
].Base
= 0;
928 VariableSettings
->Mtrr
[Index
].Mask
= 0;
929 VariableMtrr
[Index
].Used
= FALSE
;
936 Programs variable MTRRs
938 This function programs variable MTRRs
940 @param[in, out] VariableSettings Variable MTRR settings.
941 @param[in] MtrrNumber Index of MTRR to program.
942 @param[in] BaseAddress Base address of memory region.
943 @param[in] Length Length of memory region.
944 @param[in] MemoryCacheType Memory type to set.
945 @param[in] MtrrValidAddressMask The valid address mask for MTRR
949 ProgramVariableMtrr (
950 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
952 IN PHYSICAL_ADDRESS BaseAddress
,
954 IN UINT64 MemoryCacheType
,
955 IN UINT64 MtrrValidAddressMask
961 // MTRR Physical Base
963 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
964 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
967 // MTRR Physical Mask
969 TempQword
= ~(Length
- 1);
970 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | CACHE_MTRR_ENABLED
;
975 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
977 If MtrrSetting is not NULL, gets the default memory attribute from input
978 MTRR settings buffer.
979 If MtrrSetting is NULL, gets the default memory attribute from MSR.
981 @param[in] MtrrSetting A buffer holding all MTRRs content.
982 @param[in] MtrrType MTRR memory type
984 @return The enum item in MTRR_MEMORY_CACHE_TYPE
987 MTRR_MEMORY_CACHE_TYPE
988 GetMemoryCacheTypeFromMtrrType (
989 IN MTRR_SETTINGS
*MtrrSetting
,
994 case MTRR_CACHE_UNCACHEABLE
:
995 return CacheUncacheable
;
996 case MTRR_CACHE_WRITE_COMBINING
:
997 return CacheWriteCombining
;
998 case MTRR_CACHE_WRITE_THROUGH
:
999 return CacheWriteThrough
;
1000 case MTRR_CACHE_WRITE_PROTECTED
:
1001 return CacheWriteProtected
;
1002 case MTRR_CACHE_WRITE_BACK
:
1003 return CacheWriteBack
;
1006 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1007 // no MTRR covers the range
1009 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1014 Initializes the valid bits mask and valid address mask for MTRRs.
1016 This function initializes the valid bits mask and valid address mask for MTRRs.
1018 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1019 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1023 MtrrLibInitializeMtrrMask (
1024 OUT UINT64
*MtrrValidBitsMask
,
1025 OUT UINT64
*MtrrValidAddressMask
1029 UINT8 PhysicalAddressBits
;
1031 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1033 if (RegEax
>= 0x80000008) {
1034 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1036 PhysicalAddressBits
= (UINT8
) RegEax
;
1038 PhysicalAddressBits
= 36;
1041 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1042 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1047 Determines the real attribute of a memory range.
1049 This function is to arbitrate the real attribute of the memory when
1050 there are 2 MTRRs covers the same memory range. For further details,
1051 please refer the IA32 Software Developer's Manual, Volume 3,
1054 @param[in] MtrrType1 The first kind of Memory type
1055 @param[in] MtrrType2 The second kind of memory type
1060 IN UINT64 MtrrType1
,
1066 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1067 switch (MtrrType1
) {
1068 case MTRR_CACHE_UNCACHEABLE
:
1069 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1071 case MTRR_CACHE_WRITE_COMBINING
:
1073 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1074 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1076 MtrrType
= MtrrType2
;
1079 case MTRR_CACHE_WRITE_THROUGH
:
1081 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1082 MtrrType2
==MTRR_CACHE_WRITE_BACK
1084 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1085 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1086 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1089 case MTRR_CACHE_WRITE_PROTECTED
:
1090 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1091 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1092 MtrrType
= MtrrType2
;
1095 case MTRR_CACHE_WRITE_BACK
:
1097 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1098 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1099 MtrrType2
== MTRR_CACHE_WRITE_BACK
1101 MtrrType
= MtrrType2
;
1104 case MTRR_CACHE_INVALID_TYPE
:
1105 MtrrType
= MtrrType2
;
1111 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1112 MtrrType
= MtrrType1
;
1118 Worker function will get the memory cache type of the specific address.
1120 If MtrrSetting is not NULL, gets the memory cache type from input
1121 MTRR settings buffer.
1122 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1124 @param[in] MtrrSetting A buffer holding all MTRRs content.
1125 @param[in] Address The specific address
1127 @return Memory cache type of the specific address
1130 MTRR_MEMORY_CACHE_TYPE
1131 MtrrGetMemoryAttributeByAddressWorker (
1132 IN MTRR_SETTINGS
*MtrrSetting
,
1133 IN PHYSICAL_ADDRESS Address
1140 UINT64 TempMtrrType
;
1141 MTRR_MEMORY_CACHE_TYPE CacheType
;
1142 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1143 UINT64 MtrrValidBitsMask
;
1144 UINT64 MtrrValidAddressMask
;
1145 UINTN VariableMtrrCount
;
1146 MTRR_VARIABLE_SETTINGS VariableSettings
;
1149 // Check if MTRR is enabled, if not, return UC as attribute
1151 if (MtrrSetting
== NULL
) {
1152 TempQword
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
1154 TempQword
= MtrrSetting
->MtrrDefType
;
1156 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1158 if ((TempQword
& CACHE_MTRR_ENABLED
) == 0) {
1159 return CacheUncacheable
;
1163 // If address is less than 1M, then try to go through the fixed MTRR
1165 if (Address
< BASE_1MB
) {
1166 if ((TempQword
& CACHE_FIXED_MTRR_ENABLED
) != 0) {
1168 // Go through the fixed MTRR
1170 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1171 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1173 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1174 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1178 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1179 mMtrrLibFixedMtrrTable
[Index
].Length
;
1180 if (MtrrSetting
== NULL
) {
1181 TempQword
= MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1183 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1185 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1186 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1191 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1193 MtrrGetVariableMtrrWorker (
1195 GetVariableMtrrCountWorker (),
1199 MtrrGetMemoryAttributeInVariableMtrrWorker (
1201 GetFirmwareVariableMtrrCountWorker (),
1203 MtrrValidAddressMask
,
1208 // Go through the variable MTRR
1210 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1211 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1213 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1214 if (VariableMtrr
[Index
].Valid
) {
1215 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1216 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1217 TempMtrrType
= VariableMtrr
[Index
].Type
;
1218 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1222 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1229 This function will get the memory cache type of the specific address.
1231 This function is mainly for debug purpose.
1233 @param[in] Address The specific address
1235 @return Memory cache type of the specific address
1238 MTRR_MEMORY_CACHE_TYPE
1240 MtrrGetMemoryAttribute (
1241 IN PHYSICAL_ADDRESS Address
1244 if (!IsMtrrSupported ()) {
1245 return CacheUncacheable
;
1248 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1252 Worker function prints all MTRRs for debugging.
1254 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1256 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1258 @param MtrrSetting A buffer holding all MTRRs content.
1261 MtrrDebugPrintAllMtrrsWorker (
1262 IN MTRR_SETTINGS
*MtrrSetting
1266 MTRR_SETTINGS LocalMtrrs
;
1267 MTRR_SETTINGS
*Mtrrs
;
1270 UINTN VariableMtrrCount
;
1278 UINT64 NoRangeLimit
;
1281 UINTN PreviousMemoryType
;
1284 if (!IsMtrrSupported ()) {
1288 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1289 DEBUG((DEBUG_CACHE
, "=============\n"));
1291 if (MtrrSetting
!= NULL
) {
1292 Mtrrs
= MtrrSetting
;
1294 MtrrGetAllMtrrs (&LocalMtrrs
);
1295 Mtrrs
= &LocalMtrrs
;
1298 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1299 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1300 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1303 VariableMtrrCount
= GetVariableMtrrCount ();
1304 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1305 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1307 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1308 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1311 DEBUG((DEBUG_CACHE
, "\n"));
1312 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1313 DEBUG((DEBUG_CACHE
, "====================================\n"));
1316 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1317 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1318 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1319 for (Index1
= 0; Index1
< 8; Index1
++) {
1320 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1321 if (MemoryType
> CacheWriteBack
) {
1322 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1324 if (MemoryType
!= PreviousMemoryType
) {
1325 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1326 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1328 PreviousMemoryType
= MemoryType
;
1329 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1331 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1334 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1336 VariableMtrrCount
= GetVariableMtrrCount ();
1339 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1340 if (RegEax
>= 0x80000008) {
1341 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1342 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1345 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1347 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1348 if (MemoryType
> CacheWriteBack
) {
1349 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1352 if (MemoryType
!= PreviousMemoryType
) {
1353 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1354 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1356 PreviousMemoryType
= MemoryType
;
1357 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1360 RangeBase
= BASE_1MB
;
1361 NoRangeBase
= BASE_1MB
;
1363 NoRangeLimit
= Limit
;
1365 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1366 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1368 // If mask is not valid, then do not display range
1372 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1373 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1375 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1379 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1380 RangeBase
= MtrrBase
;
1382 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1383 RangeBase
= MtrrLimit
+ 1;
1385 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1386 RangeLimit
= MtrrBase
- 1;
1388 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1389 RangeLimit
= MtrrLimit
;
1392 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1393 NoRangeBase
= MtrrLimit
+ 1;
1395 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1396 NoRangeLimit
= MtrrBase
- 1;
1401 Base
= RangeLimit
+ 1;
1403 Base
= NoRangeLimit
+ 1;
1405 } while (Base
< Limit
);
1406 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1412 This function prints all MTRRs for debugging.
1416 MtrrDebugPrintAllMtrrs (
1420 MtrrDebugPrintAllMtrrsWorker (NULL
);
1425 Worker function attempts to set the attributes for a memory range.
1427 If MtrrSettings is not NULL, set the attributes into the input MTRR
1429 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1431 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1432 @param[in] BaseAddress The physical address that is the start
1433 address of a memory region.
1434 @param[in] Length The size in bytes of the memory region.
1435 @param[in] Attribute The bit mask of attributes to set for the
1438 @retval RETURN_SUCCESS The attributes were set for the memory
1440 @retval RETURN_INVALID_PARAMETER Length is zero.
1441 @retval RETURN_UNSUPPORTED The processor does not support one or
1442 more bytes of the memory resource range
1443 specified by BaseAddress and Length.
1444 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1445 for the memory resource range specified
1446 by BaseAddress and Length.
1447 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1448 range specified by BaseAddress and Length
1450 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1451 modify the attributes of the memory
1456 MtrrSetMemoryAttributeWorker (
1457 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1458 IN PHYSICAL_ADDRESS BaseAddress
,
1460 IN MTRR_MEMORY_CACHE_TYPE Attribute
1464 RETURN_STATUS Status
;
1471 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1473 UINT64 MtrrValidBitsMask
;
1474 UINT64 MtrrValidAddressMask
;
1475 BOOLEAN OverwriteExistingMtrr
;
1476 UINT32 FirmwareVariableMtrrCount
;
1477 MTRR_CONTEXT MtrrContext
;
1478 BOOLEAN MtrrContextValid
;
1479 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1480 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1481 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1482 UINT32 VariableMtrrCount
;
1483 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1484 BOOLEAN ProgramVariableSettings
;
1485 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1490 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1492 MtrrContextValid
= FALSE
;
1493 VariableMtrrCount
= 0;
1494 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1495 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1496 FixedSettingsValid
[Index
] = FALSE
;
1497 FixedSettingsModified
[Index
] = FALSE
;
1499 ProgramVariableSettings
= FALSE
;
1501 if (!IsMtrrSupported ()) {
1502 Status
= RETURN_UNSUPPORTED
;
1506 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1509 MemoryType
= (UINT64
)Attribute
;
1510 OverwriteExistingMtrr
= FALSE
;
1513 // Check for an invalid parameter
1516 Status
= RETURN_INVALID_PARAMETER
;
1521 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1522 (Length
& ~MtrrValidAddressMask
) != 0
1524 Status
= RETURN_UNSUPPORTED
;
1529 // Check if Fixed MTRR
1531 Status
= RETURN_SUCCESS
;
1532 if (BaseAddress
< BASE_1MB
) {
1533 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1534 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1535 if (RETURN_ERROR (Status
)) {
1538 if (MtrrSetting
!= NULL
) {
1539 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1540 MtrrSetting
->MtrrDefType
|= CACHE_FIXED_MTRR_ENABLED
;
1542 if (!FixedSettingsValid
[MsrNum
]) {
1543 WorkingFixedSettings
.Mtrr
[MsrNum
] = MtrrRegisterRead (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1544 FixedSettingsValid
[MsrNum
] = TRUE
;
1546 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1547 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1548 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1549 FixedSettingsModified
[MsrNum
] = TRUE
;
1556 // A Length of 0 can only make sense for fixed MTTR ranges.
1557 // Since we just handled the fixed MTRRs, we can skip the
1558 // variable MTRR section.
1565 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1566 // we can set the base to 0 to save variable MTRRs.
1568 if (BaseAddress
== BASE_1MB
) {
1574 // Read all variable MTRRs
1576 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1577 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1578 if (MtrrSetting
!= NULL
) {
1579 VariableSettings
= &MtrrSetting
->Variables
;
1581 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1582 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1583 ProgramVariableSettings
= TRUE
;
1584 VariableSettings
= &WorkingVariableSettings
;
1588 // Check for overlap
1590 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1592 FirmwareVariableMtrrCount
,
1594 MtrrValidAddressMask
,
1597 OverLap
= CheckMemoryAttributeOverlap (
1598 FirmwareVariableMtrrCount
,
1600 BaseAddress
+ Length
- 1,
1604 Status
= CombineMemoryAttribute (
1605 FirmwareVariableMtrrCount
,
1611 &OverwriteExistingMtrr
1613 if (RETURN_ERROR (Status
)) {
1619 // Combined successfully, invalidate the now-unused MTRRs
1621 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1622 Status
= RETURN_SUCCESS
;
1628 // The memory type is the same with the type specified by
1629 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1631 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1633 // Invalidate the now-unused MTRRs
1635 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1639 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1641 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1642 Status
= RETURN_OUT_OF_RESOURCES
;
1647 // Invalidate the now-unused MTRRs
1649 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1652 // Find first unused MTRR
1654 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1655 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1660 if (BaseAddress
!= 0) {
1663 // Calculate the alignment of the base address.
1665 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1667 if (Alignment
> Length
) {
1674 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1675 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1680 ProgramVariableMtrr (
1686 MtrrValidAddressMask
1688 BaseAddress
+= Alignment
;
1689 Length
-= Alignment
;
1700 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1705 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1706 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1711 ProgramVariableMtrr (
1717 MtrrValidAddressMask
1719 BaseAddress
+= Length
;
1720 TempQword
= Length
- TempQword
;
1721 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1728 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1729 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& CACHE_MTRR_ENABLED
) == 0) {
1734 Length
= Power2MaxMemory (TempQword
);
1736 BaseAddress
-= Length
;
1739 ProgramVariableMtrr (
1745 MtrrValidAddressMask
1749 BaseAddress
+= Length
;
1751 TempQword
-= Length
;
1753 } while (TempQword
> 0);
1758 // Write fixed MTRRs that have been modified
1760 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1761 if (FixedSettingsModified
[Index
]) {
1762 if (!MtrrContextValid
) {
1763 PreMtrrChange (&MtrrContext
);
1764 MtrrContextValid
= TRUE
;
1767 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1768 WorkingFixedSettings
.Mtrr
[Index
]
1774 // Write variable MTRRs
1776 if (ProgramVariableSettings
) {
1777 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1778 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1779 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1780 if (!MtrrContextValid
) {
1781 PreMtrrChange (&MtrrContext
);
1782 MtrrContextValid
= TRUE
;
1785 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1786 WorkingVariableSettings
.Mtrr
[Index
].Base
1789 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1790 WorkingVariableSettings
.Mtrr
[Index
].Mask
1795 if (MtrrContextValid
) {
1796 PostMtrrChange (&MtrrContext
);
1799 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1800 if (!RETURN_ERROR (Status
)) {
1801 if (MtrrSetting
!= NULL
) {
1802 MtrrSetting
->MtrrDefType
|= CACHE_MTRR_ENABLED
;
1804 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1811 This function attempts to set the attributes for a memory range.
1813 @param[in] BaseAddress The physical address that is the start
1814 address of a memory region.
1815 @param[in] Length The size in bytes of the memory region.
1816 @param[in] Attributes The bit mask of attributes to set for the
1819 @retval RETURN_SUCCESS The attributes were set for the memory
1821 @retval RETURN_INVALID_PARAMETER Length is zero.
1822 @retval RETURN_UNSUPPORTED The processor does not support one or
1823 more bytes of the memory resource range
1824 specified by BaseAddress and Length.
1825 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1826 for the memory resource range specified
1827 by BaseAddress and Length.
1828 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1829 range specified by BaseAddress and Length
1831 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1832 modify the attributes of the memory
1838 MtrrSetMemoryAttribute (
1839 IN PHYSICAL_ADDRESS BaseAddress
,
1841 IN MTRR_MEMORY_CACHE_TYPE Attribute
1844 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1845 return MtrrSetMemoryAttributeWorker (
1854 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1856 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1857 @param[in] BaseAddress The physical address that is the start address
1859 @param[in] Length The size in bytes of the memory region.
1860 @param[in] Attribute The bit mask of attributes to set for the
1863 @retval RETURN_SUCCESS The attributes were set for the memory region.
1864 @retval RETURN_INVALID_PARAMETER Length is zero.
1865 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1866 memory resource range specified by BaseAddress and Length.
1867 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1868 range specified by BaseAddress and Length.
1869 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1870 BaseAddress and Length cannot be modified.
1871 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1872 the memory resource range.
1877 MtrrSetMemoryAttributeInMtrrSettings (
1878 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1879 IN PHYSICAL_ADDRESS BaseAddress
,
1881 IN MTRR_MEMORY_CACHE_TYPE Attribute
1884 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1885 return MtrrSetMemoryAttributeWorker (
1894 Worker function setting variable MTRRs
1896 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1900 MtrrSetVariableMtrrWorker (
1901 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1905 UINT32 VariableMtrrCount
;
1907 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1908 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1910 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1912 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1913 VariableSettings
->Mtrr
[Index
].Base
1916 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1917 VariableSettings
->Mtrr
[Index
].Mask
1924 This function sets variable MTRRs
1926 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1928 @return The pointer of VariableSettings
1931 MTRR_VARIABLE_SETTINGS
*
1933 MtrrSetVariableMtrr (
1934 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1937 MTRR_CONTEXT MtrrContext
;
1939 if (!IsMtrrSupported ()) {
1940 return VariableSettings
;
1943 PreMtrrChange (&MtrrContext
);
1944 MtrrSetVariableMtrrWorker (VariableSettings
);
1945 PostMtrrChange (&MtrrContext
);
1946 MtrrDebugPrintAllMtrrs ();
1948 return VariableSettings
;
1952 Worker function setting fixed MTRRs
1954 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1958 MtrrSetFixedMtrrWorker (
1959 IN MTRR_FIXED_SETTINGS
*FixedSettings
1964 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1966 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1967 FixedSettings
->Mtrr
[Index
]
1974 This function sets fixed MTRRs
1976 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1978 @retval The pointer of FixedSettings
1981 MTRR_FIXED_SETTINGS
*
1984 IN MTRR_FIXED_SETTINGS
*FixedSettings
1987 MTRR_CONTEXT MtrrContext
;
1989 if (!IsMtrrSupported ()) {
1990 return FixedSettings
;
1993 PreMtrrChange (&MtrrContext
);
1994 MtrrSetFixedMtrrWorker (FixedSettings
);
1995 PostMtrrChange (&MtrrContext
);
1996 MtrrDebugPrintAllMtrrs ();
1998 return FixedSettings
;
2003 This function gets the content in all MTRRs (variable and fixed)
2005 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2007 @retval the pointer of MtrrSetting
2013 OUT MTRR_SETTINGS
*MtrrSetting
2016 if (!IsMtrrSupported ()) {
2023 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2026 // Get variable MTRRs
2028 MtrrGetVariableMtrrWorker (
2030 GetVariableMtrrCountWorker (),
2031 &MtrrSetting
->Variables
2035 // Get MTRR_DEF_TYPE value
2037 MtrrSetting
->MtrrDefType
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
2044 This function sets all MTRRs (variable and fixed)
2046 @param[in] MtrrSetting A buffer holding all MTRRs content.
2048 @retval The pointer of MtrrSetting
2054 IN MTRR_SETTINGS
*MtrrSetting
2057 MTRR_CONTEXT MtrrContext
;
2059 if (!IsMtrrSupported ()) {
2063 PreMtrrChange (&MtrrContext
);
2068 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2071 // Set variable MTRRs
2073 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2076 // Set MTRR_DEF_TYPE value
2078 MtrrRegisterWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2080 PostMtrrChangeEnableCache (&MtrrContext
);
2082 MtrrDebugPrintAllMtrrs ();
2089 Checks if MTRR is supported.
2091 @retval TRUE MTRR is supported.
2092 @retval FALSE MTRR is not supported.
2104 // Check CPUID(1).EAX[0..11] for Quark SoC
2106 AsmCpuid (1, &RegEax
, NULL
, NULL
, NULL
);
2107 if ((RegEax
& 0xfff) == QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING
) {