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
473 for (MsrNum
= 0; MsrNum
< MTRR_NUMBER_OF_FIXED_MTRR
; MsrNum
++) {
474 if ((*Base
>= mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
) &&
477 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
478 (8 * mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
486 if (MsrNum
== MTRR_NUMBER_OF_FIXED_MTRR
) {
487 return RETURN_UNSUPPORTED
;
491 // We found the fixed MTRR to be programmed
493 for (ByteShift
= 0; ByteShift
< 8; ByteShift
++) {
496 mMtrrLibFixedMtrrTable
[MsrNum
].BaseAddress
+
497 (ByteShift
* mMtrrLibFixedMtrrTable
[MsrNum
].Length
)
504 if (ByteShift
== 8) {
505 return RETURN_UNSUPPORTED
;
510 ((ByteShift
< 8) && (*Length
>= mMtrrLibFixedMtrrTable
[MsrNum
].Length
));
513 OrMask
|= LShiftU64 ((UINT64
) MemoryCacheType
, (UINT32
) (ByteShift
* 8));
514 ClearMask
|= LShiftU64 ((UINT64
) 0xFF, (UINT32
) (ByteShift
* 8));
515 *Length
-= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
516 *Base
+= mMtrrLibFixedMtrrTable
[MsrNum
].Length
;
519 if (ByteShift
< 8 && (*Length
!= 0)) {
520 return RETURN_UNSUPPORTED
;
523 *ReturnMsrNum
= MsrNum
;
524 *ReturnClearMask
= ClearMask
;
525 *ReturnOrMask
= OrMask
;
527 return RETURN_SUCCESS
;
532 Worker function gets the attribute of variable MTRRs.
534 This function shadows the content of variable MTRRs into an
535 internal array: VariableMtrr.
537 @param[in] VariableSettings The variable MTRR values to shadow
538 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware
539 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
540 @param[in] MtrrValidAddressMask The valid address mask for MTRR
541 @param[out] VariableMtrr The array to shadow variable MTRRs content
543 @return The return value of this parameter indicates the
544 number of MTRRs which has been used.
548 MtrrGetMemoryAttributeInVariableMtrrWorker (
549 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
,
550 IN UINTN FirmwareVariableMtrrCount
,
551 IN UINT64 MtrrValidBitsMask
,
552 IN UINT64 MtrrValidAddressMask
,
553 OUT VARIABLE_MTRR
*VariableMtrr
559 ZeroMem (VariableMtrr
, sizeof (VARIABLE_MTRR
) * MTRR_NUMBER_OF_VARIABLE_MTRR
);
560 for (Index
= 0, UsedMtrr
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
561 if ((VariableSettings
->Mtrr
[Index
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) != 0) {
562 VariableMtrr
[Index
].Msr
= (UINT32
)Index
;
563 VariableMtrr
[Index
].BaseAddress
= (VariableSettings
->Mtrr
[Index
].Base
& MtrrValidAddressMask
);
564 VariableMtrr
[Index
].Length
= ((~(VariableSettings
->Mtrr
[Index
].Mask
& MtrrValidAddressMask
)) & MtrrValidBitsMask
) + 1;
565 VariableMtrr
[Index
].Type
= (VariableSettings
->Mtrr
[Index
].Base
& 0x0ff);
566 VariableMtrr
[Index
].Valid
= TRUE
;
567 VariableMtrr
[Index
].Used
= TRUE
;
576 Gets the attribute of variable MTRRs.
578 This function shadows the content of variable MTRRs into an
579 internal array: VariableMtrr.
581 @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
582 @param[in] MtrrValidAddressMask The valid address mask for MTRR
583 @param[out] VariableMtrr The array to shadow variable MTRRs content
585 @return The return value of this paramter indicates the
586 number of MTRRs which has been used.
591 MtrrGetMemoryAttributeInVariableMtrr (
592 IN UINT64 MtrrValidBitsMask
,
593 IN UINT64 MtrrValidAddressMask
,
594 OUT VARIABLE_MTRR
*VariableMtrr
597 MTRR_VARIABLE_SETTINGS VariableSettings
;
599 if (!IsMtrrSupported ()) {
603 MtrrGetVariableMtrrWorker (
605 GetVariableMtrrCountWorker (),
609 return MtrrGetMemoryAttributeInVariableMtrrWorker (
611 GetFirmwareVariableMtrrCountWorker (),
613 MtrrValidAddressMask
,
620 Checks overlap between given memory range and MTRRs.
622 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs available
624 @param[in] Start The start address of memory range.
625 @param[in] End The end address of memory range.
626 @param[in] VariableMtrr The array to shadow variable MTRRs content
628 @retval TRUE Overlap exists.
629 @retval FALSE No overlap.
633 CheckMemoryAttributeOverlap (
634 IN UINTN FirmwareVariableMtrrCount
,
635 IN PHYSICAL_ADDRESS Start
,
636 IN PHYSICAL_ADDRESS End
,
637 IN VARIABLE_MTRR
*VariableMtrr
642 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
644 VariableMtrr
[Index
].Valid
&&
646 (Start
> (VariableMtrr
[Index
].BaseAddress
+
647 VariableMtrr
[Index
].Length
- 1)
649 (End
< VariableMtrr
[Index
].BaseAddress
)
661 Marks a variable MTRR as non-valid.
663 @param[in] Index The index of the array VariableMtrr to be invalidated
664 @param[in] VariableMtrr The array to shadow variable MTRRs content
665 @param[out] UsedMtrr The number of MTRRs which has already been used
669 InvalidateShadowMtrr (
671 IN VARIABLE_MTRR
*VariableMtrr
,
675 VariableMtrr
[Index
].Valid
= FALSE
;
676 *UsedMtrr
= *UsedMtrr
- 1;
681 Combines memory attributes.
683 If overlap exists between given memory range and MTRRs, try to combine them.
685 @param[in] FirmwareVariableMtrrCount The number of variable MTRRs
686 available to firmware.
687 @param[in] Attributes The memory type to set.
688 @param[in, out] Base The base address of memory range.
689 @param[in, out] Length The length of memory range.
690 @param[in] VariableMtrr The array to shadow variable MTRRs content
691 @param[in, out] UsedMtrr The number of MTRRs which has already been used
692 @param[out] OverwriteExistingMtrr Returns whether an existing MTRR was used
694 @retval EFI_SUCCESS Memory region successfully combined.
695 @retval EFI_ACCESS_DENIED Memory region cannot be combined.
699 CombineMemoryAttribute (
700 IN UINT32 FirmwareVariableMtrrCount
,
701 IN UINT64 Attributes
,
703 IN OUT UINT64
*Length
,
704 IN VARIABLE_MTRR
*VariableMtrr
,
705 IN OUT UINT32
*UsedMtrr
,
706 OUT BOOLEAN
*OverwriteExistingMtrr
714 BOOLEAN CoveredByExistingMtrr
;
716 *OverwriteExistingMtrr
= FALSE
;
717 CoveredByExistingMtrr
= FALSE
;
718 EndAddress
= *Base
+*Length
- 1;
720 for (Index
= 0; Index
< FirmwareVariableMtrrCount
; Index
++) {
722 MtrrEnd
= VariableMtrr
[Index
].BaseAddress
+ VariableMtrr
[Index
].Length
- 1;
724 !VariableMtrr
[Index
].Valid
||
727 (EndAddress
< VariableMtrr
[Index
].BaseAddress
)
734 // Combine same attribute MTRR range
736 if (Attributes
== VariableMtrr
[Index
].Type
) {
738 // if the MTRR range contain the request range, set a flag, then continue to
739 // invalidate any MTRR of the same request range with higher priority cache type.
741 if (VariableMtrr
[Index
].BaseAddress
<= *Base
&& MtrrEnd
>= EndAddress
) {
742 CoveredByExistingMtrr
= TRUE
;
746 // invalid this MTRR, and program the combine range
749 (*Base
) < VariableMtrr
[Index
].BaseAddress
?
751 VariableMtrr
[Index
].BaseAddress
;
752 CombineEnd
= EndAddress
> MtrrEnd
? EndAddress
: MtrrEnd
;
755 // Record the MTRR usage status in VariableMtrr array.
757 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
758 *Base
= CombineStart
;
759 *Length
= CombineEnd
- CombineStart
+ 1;
760 EndAddress
= CombineEnd
;
761 *OverwriteExistingMtrr
= TRUE
;
765 // The cache type is different, but the range is convered by one MTRR
767 if (VariableMtrr
[Index
].BaseAddress
== *Base
&& MtrrEnd
== EndAddress
) {
768 InvalidateShadowMtrr (Index
, VariableMtrr
, UsedMtrr
);
774 if ((Attributes
== MTRR_CACHE_WRITE_THROUGH
&&
775 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_BACK
) ||
776 (Attributes
== MTRR_CACHE_WRITE_BACK
&&
777 VariableMtrr
[Index
].Type
== MTRR_CACHE_WRITE_THROUGH
) ||
778 (Attributes
== MTRR_CACHE_UNCACHEABLE
) ||
779 (VariableMtrr
[Index
].Type
== MTRR_CACHE_UNCACHEABLE
)
781 *OverwriteExistingMtrr
= TRUE
;
785 // Other type memory overlap is invalid
787 return RETURN_ACCESS_DENIED
;
790 if (CoveredByExistingMtrr
) {
794 return RETURN_SUCCESS
;
799 Calculates the maximum value which is a power of 2, but less the MemoryLength.
801 @param[in] MemoryLength The number to pass in.
803 @return The maximum value which is align to power of 2 and less the MemoryLength
808 IN UINT64 MemoryLength
813 if (RShiftU64 (MemoryLength
, 32) != 0) {
815 (UINT64
) GetPowerOfTwo32 (
816 (UINT32
) RShiftU64 (MemoryLength
, 32)
821 Result
= (UINT64
) GetPowerOfTwo32 ((UINT32
) MemoryLength
);
829 Determines the MTRR numbers used to program a memory range.
831 This function first checks the alignment of the base address.
832 If the alignment of the base address <= Length, cover the memory range
833 (BaseAddress, alignment) by a MTRR, then BaseAddress += alignment and
834 Length -= alignment. Repeat the step until alignment > Length.
836 Then this function determines which direction of programming the variable
837 MTRRs for the remaining length will use fewer MTRRs.
839 @param[in] BaseAddress Length of Memory to program MTRR
840 @param[in] Length Length of Memory to program MTRR
841 @param[in] MtrrNumber Pointer to the number of necessary MTRRs
843 @retval TRUE Positive direction is better.
844 FALSE Negative direction is better.
848 GetMtrrNumberAndDirection (
849 IN UINT64 BaseAddress
,
861 if (BaseAddress
!= 0) {
864 // Calculate the alignment of the base address.
866 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
868 if (Alignment
> Length
) {
873 BaseAddress
+= Alignment
;
887 TempQword
-= Power2MaxMemory (TempQword
);
889 } while (TempQword
!= 0);
891 TempQword
= Power2MaxMemory (LShiftU64 (Length
, 1)) - Length
;
894 TempQword
-= Power2MaxMemory (TempQword
);
896 } while (TempQword
!= 0);
898 if (Positive
<= Subtractive
) {
899 *MtrrNumber
+= Positive
;
902 *MtrrNumber
+= Subtractive
;
908 Invalid variable MTRRs according to the value in the shadow array.
910 This function programs MTRRs according to the values specified
913 @param[in, out] VariableSettings Variable MTRR settings
914 @param[in] VariableMtrrCount Number of variable MTRRs
915 @param[in, out] VariableMtrr Shadow of variable MTRR contents
920 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
921 IN UINTN VariableMtrrCount
,
922 IN OUT VARIABLE_MTRR
*VariableMtrr
927 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
928 if (!VariableMtrr
[Index
].Valid
&& VariableMtrr
[Index
].Used
) {
929 VariableSettings
->Mtrr
[Index
].Base
= 0;
930 VariableSettings
->Mtrr
[Index
].Mask
= 0;
931 VariableMtrr
[Index
].Used
= FALSE
;
938 Programs variable MTRRs
940 This function programs variable MTRRs
942 @param[in, out] VariableSettings Variable MTRR settings.
943 @param[in] MtrrNumber Index of MTRR to program.
944 @param[in] BaseAddress Base address of memory region.
945 @param[in] Length Length of memory region.
946 @param[in] MemoryCacheType Memory type to set.
947 @param[in] MtrrValidAddressMask The valid address mask for MTRR
951 ProgramVariableMtrr (
952 IN OUT MTRR_VARIABLE_SETTINGS
*VariableSettings
,
954 IN PHYSICAL_ADDRESS BaseAddress
,
956 IN UINT64 MemoryCacheType
,
957 IN UINT64 MtrrValidAddressMask
963 // MTRR Physical Base
965 TempQword
= (BaseAddress
& MtrrValidAddressMask
) | MemoryCacheType
;
966 VariableSettings
->Mtrr
[MtrrNumber
].Base
= TempQword
;
969 // MTRR Physical Mask
971 TempQword
= ~(Length
- 1);
972 VariableSettings
->Mtrr
[MtrrNumber
].Mask
= (TempQword
& MtrrValidAddressMask
) | MTRR_LIB_CACHE_MTRR_ENABLED
;
977 Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
979 If MtrrSetting is not NULL, gets the default memory attribute from input
980 MTRR settings buffer.
981 If MtrrSetting is NULL, gets the default memory attribute from MSR.
983 @param[in] MtrrSetting A buffer holding all MTRRs content.
984 @param[in] MtrrType MTRR memory type
986 @return The enum item in MTRR_MEMORY_CACHE_TYPE
989 MTRR_MEMORY_CACHE_TYPE
990 GetMemoryCacheTypeFromMtrrType (
991 IN MTRR_SETTINGS
*MtrrSetting
,
996 case MTRR_CACHE_UNCACHEABLE
:
997 return CacheUncacheable
;
998 case MTRR_CACHE_WRITE_COMBINING
:
999 return CacheWriteCombining
;
1000 case MTRR_CACHE_WRITE_THROUGH
:
1001 return CacheWriteThrough
;
1002 case MTRR_CACHE_WRITE_PROTECTED
:
1003 return CacheWriteProtected
;
1004 case MTRR_CACHE_WRITE_BACK
:
1005 return CacheWriteBack
;
1008 // MtrrType is MTRR_CACHE_INVALID_TYPE, that means
1009 // no MTRR covers the range
1011 return MtrrGetDefaultMemoryTypeWorker (MtrrSetting
);
1016 Initializes the valid bits mask and valid address mask for MTRRs.
1018 This function initializes the valid bits mask and valid address mask for MTRRs.
1020 @param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
1021 @param[out] MtrrValidAddressMask The valid address mask for the MTRR
1025 MtrrLibInitializeMtrrMask (
1026 OUT UINT64
*MtrrValidBitsMask
,
1027 OUT UINT64
*MtrrValidAddressMask
1031 UINT8 PhysicalAddressBits
;
1033 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1035 if (RegEax
>= 0x80000008) {
1036 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1038 PhysicalAddressBits
= (UINT8
) RegEax
;
1040 *MtrrValidBitsMask
= LShiftU64 (1, PhysicalAddressBits
) - 1;
1041 *MtrrValidAddressMask
= *MtrrValidBitsMask
& 0xfffffffffffff000ULL
;
1043 *MtrrValidBitsMask
= MTRR_LIB_MSR_VALID_MASK
;
1044 *MtrrValidAddressMask
= MTRR_LIB_CACHE_VALID_ADDRESS
;
1050 Determines the real attribute of a memory range.
1052 This function is to arbitrate the real attribute of the memory when
1053 there are 2 MTRRs covers the same memory range. For further details,
1054 please refer the IA32 Software Developer's Manual, Volume 3,
1057 @param[in] MtrrType1 The first kind of Memory type
1058 @param[in] MtrrType2 The second kind of memory type
1063 IN UINT64 MtrrType1
,
1069 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1070 switch (MtrrType1
) {
1071 case MTRR_CACHE_UNCACHEABLE
:
1072 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1074 case MTRR_CACHE_WRITE_COMBINING
:
1076 MtrrType2
==MTRR_CACHE_WRITE_COMBINING
||
1077 MtrrType2
==MTRR_CACHE_UNCACHEABLE
1079 MtrrType
= MtrrType2
;
1082 case MTRR_CACHE_WRITE_THROUGH
:
1084 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1085 MtrrType2
==MTRR_CACHE_WRITE_BACK
1087 MtrrType
= MTRR_CACHE_WRITE_THROUGH
;
1088 } else if(MtrrType2
==MTRR_CACHE_UNCACHEABLE
) {
1089 MtrrType
= MTRR_CACHE_UNCACHEABLE
;
1092 case MTRR_CACHE_WRITE_PROTECTED
:
1093 if (MtrrType2
== MTRR_CACHE_WRITE_PROTECTED
||
1094 MtrrType2
== MTRR_CACHE_UNCACHEABLE
) {
1095 MtrrType
= MtrrType2
;
1098 case MTRR_CACHE_WRITE_BACK
:
1100 MtrrType2
== MTRR_CACHE_UNCACHEABLE
||
1101 MtrrType2
==MTRR_CACHE_WRITE_THROUGH
||
1102 MtrrType2
== MTRR_CACHE_WRITE_BACK
1104 MtrrType
= MtrrType2
;
1107 case MTRR_CACHE_INVALID_TYPE
:
1108 MtrrType
= MtrrType2
;
1114 if (MtrrType2
== MTRR_CACHE_INVALID_TYPE
) {
1115 MtrrType
= MtrrType1
;
1121 Worker function will get the memory cache type of the specific address.
1123 If MtrrSetting is not NULL, gets the memory cache type from input
1124 MTRR settings buffer.
1125 If MtrrSetting is NULL, gets the memory cache type from MTRRs.
1127 @param[in] MtrrSetting A buffer holding all MTRRs content.
1128 @param[in] Address The specific address
1130 @return Memory cache type of the specific address
1133 MTRR_MEMORY_CACHE_TYPE
1134 MtrrGetMemoryAttributeByAddressWorker (
1135 IN MTRR_SETTINGS
*MtrrSetting
,
1136 IN PHYSICAL_ADDRESS Address
1143 UINT64 TempMtrrType
;
1144 MTRR_MEMORY_CACHE_TYPE CacheType
;
1145 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1146 UINT64 MtrrValidBitsMask
;
1147 UINT64 MtrrValidAddressMask
;
1148 UINTN VariableMtrrCount
;
1149 MTRR_VARIABLE_SETTINGS VariableSettings
;
1152 // Check if MTRR is enabled, if not, return UC as attribute
1154 if (MtrrSetting
== NULL
) {
1155 TempQword
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
1157 TempQword
= MtrrSetting
->MtrrDefType
;
1159 MtrrType
= MTRR_CACHE_INVALID_TYPE
;
1161 if ((TempQword
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1162 return CacheUncacheable
;
1166 // If address is less than 1M, then try to go through the fixed MTRR
1168 if (Address
< BASE_1MB
) {
1169 if ((TempQword
& MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
) != 0) {
1171 // Go through the fixed MTRR
1173 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1174 if (Address
>= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
&&
1176 mMtrrLibFixedMtrrTable
[Index
].BaseAddress
+
1177 (mMtrrLibFixedMtrrTable
[Index
].Length
* 8)
1181 ((UINTN
)Address
- mMtrrLibFixedMtrrTable
[Index
].BaseAddress
) /
1182 mMtrrLibFixedMtrrTable
[Index
].Length
;
1183 if (MtrrSetting
== NULL
) {
1184 TempQword
= MtrrRegisterRead (mMtrrLibFixedMtrrTable
[Index
].Msr
);
1186 TempQword
= MtrrSetting
->Fixed
.Mtrr
[Index
];
1188 MtrrType
= RShiftU64 (TempQword
, SubIndex
* 8) & 0xFF;
1189 return GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1194 MtrrLibInitializeMtrrMask(&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1196 MtrrGetVariableMtrrWorker (
1198 GetVariableMtrrCountWorker (),
1202 MtrrGetMemoryAttributeInVariableMtrrWorker (
1204 GetFirmwareVariableMtrrCountWorker (),
1206 MtrrValidAddressMask
,
1211 // Go through the variable MTRR
1213 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1214 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1216 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1217 if (VariableMtrr
[Index
].Valid
) {
1218 if (Address
>= VariableMtrr
[Index
].BaseAddress
&&
1219 Address
< VariableMtrr
[Index
].BaseAddress
+VariableMtrr
[Index
].Length
) {
1220 TempMtrrType
= VariableMtrr
[Index
].Type
;
1221 MtrrType
= MtrrPrecedence (MtrrType
, TempMtrrType
);
1225 CacheType
= GetMemoryCacheTypeFromMtrrType (MtrrSetting
, MtrrType
);
1232 This function will get the memory cache type of the specific address.
1234 This function is mainly for debug purpose.
1236 @param[in] Address The specific address
1238 @return Memory cache type of the specific address
1241 MTRR_MEMORY_CACHE_TYPE
1243 MtrrGetMemoryAttribute (
1244 IN PHYSICAL_ADDRESS Address
1247 if (!IsMtrrSupported ()) {
1248 return CacheUncacheable
;
1251 return MtrrGetMemoryAttributeByAddressWorker (NULL
, Address
);
1255 Worker function prints all MTRRs for debugging.
1257 If MtrrSetting is not NULL, print MTRR settings from from input MTRR
1259 If MtrrSetting is NULL, print MTRR settings from MTRRs.
1261 @param MtrrSetting A buffer holding all MTRRs content.
1264 MtrrDebugPrintAllMtrrsWorker (
1265 IN MTRR_SETTINGS
*MtrrSetting
1269 MTRR_SETTINGS LocalMtrrs
;
1270 MTRR_SETTINGS
*Mtrrs
;
1273 UINTN VariableMtrrCount
;
1281 UINT64 NoRangeLimit
;
1284 UINTN PreviousMemoryType
;
1287 if (!IsMtrrSupported ()) {
1291 DEBUG((DEBUG_CACHE
, "MTRR Settings\n"));
1292 DEBUG((DEBUG_CACHE
, "=============\n"));
1294 if (MtrrSetting
!= NULL
) {
1295 Mtrrs
= MtrrSetting
;
1297 MtrrGetAllMtrrs (&LocalMtrrs
);
1298 Mtrrs
= &LocalMtrrs
;
1301 DEBUG((DEBUG_CACHE
, "MTRR Default Type: %016lx\n", Mtrrs
->MtrrDefType
));
1302 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1303 DEBUG((DEBUG_CACHE
, "Fixed MTRR[%02d] : %016lx\n", Index
, Mtrrs
->Fixed
.Mtrr
[Index
]));
1306 VariableMtrrCount
= GetVariableMtrrCount ();
1307 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1308 DEBUG((DEBUG_CACHE
, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
1310 Mtrrs
->Variables
.Mtrr
[Index
].Base
,
1311 Mtrrs
->Variables
.Mtrr
[Index
].Mask
1314 DEBUG((DEBUG_CACHE
, "\n"));
1315 DEBUG((DEBUG_CACHE
, "MTRR Ranges\n"));
1316 DEBUG((DEBUG_CACHE
, "====================================\n"));
1319 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1320 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1321 Base
= mMtrrLibFixedMtrrTable
[Index
].BaseAddress
;
1322 for (Index1
= 0; Index1
< 8; Index1
++) {
1323 MemoryType
= (UINTN
)(RShiftU64 (Mtrrs
->Fixed
.Mtrr
[Index
], Index1
* 8) & 0xff);
1324 if (MemoryType
> CacheWriteBack
) {
1325 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1327 if (MemoryType
!= PreviousMemoryType
) {
1328 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1329 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1331 PreviousMemoryType
= MemoryType
;
1332 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1334 Base
+= mMtrrLibFixedMtrrTable
[Index
].Length
;
1337 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1339 VariableMtrrCount
= GetVariableMtrrCount ();
1342 AsmCpuid (0x80000000, &RegEax
, NULL
, NULL
, NULL
);
1343 if (RegEax
>= 0x80000008) {
1344 AsmCpuid (0x80000008, &RegEax
, NULL
, NULL
, NULL
);
1345 Limit
= LShiftU64 (1, RegEax
& 0xff) - 1;
1348 PreviousMemoryType
= MTRR_CACHE_INVALID_TYPE
;
1350 MemoryType
= MtrrGetMemoryAttributeByAddressWorker (Mtrrs
, Base
);
1351 if (MemoryType
> CacheWriteBack
) {
1352 MemoryType
= MTRR_CACHE_INVALID_TYPE
;
1355 if (MemoryType
!= PreviousMemoryType
) {
1356 if (PreviousMemoryType
!= MTRR_CACHE_INVALID_TYPE
) {
1357 DEBUG((DEBUG_CACHE
, "%016lx\n", Base
- 1));
1359 PreviousMemoryType
= MemoryType
;
1360 DEBUG((DEBUG_CACHE
, "%a:%016lx-", mMtrrMemoryCacheTypeShortName
[MemoryType
], Base
));
1363 RangeBase
= BASE_1MB
;
1364 NoRangeBase
= BASE_1MB
;
1366 NoRangeLimit
= Limit
;
1368 for (Index
= 0, Found
= FALSE
; Index
< VariableMtrrCount
; Index
++) {
1369 if ((Mtrrs
->Variables
.Mtrr
[Index
].Mask
& BIT11
) == 0) {
1371 // If mask is not valid, then do not display range
1375 MtrrBase
= (Mtrrs
->Variables
.Mtrr
[Index
].Base
& (~(SIZE_4KB
- 1)));
1376 MtrrLimit
= MtrrBase
+ ((~(Mtrrs
->Variables
.Mtrr
[Index
].Mask
& (~(SIZE_4KB
- 1)))) & Limit
);
1378 if (Base
>= MtrrBase
&& Base
< MtrrLimit
) {
1382 if (Base
>= MtrrBase
&& MtrrBase
> RangeBase
) {
1383 RangeBase
= MtrrBase
;
1385 if (Base
> MtrrLimit
&& MtrrLimit
> RangeBase
) {
1386 RangeBase
= MtrrLimit
+ 1;
1388 if (Base
< MtrrBase
&& MtrrBase
< RangeLimit
) {
1389 RangeLimit
= MtrrBase
- 1;
1391 if (Base
< MtrrLimit
&& MtrrLimit
<= RangeLimit
) {
1392 RangeLimit
= MtrrLimit
;
1395 if (Base
> MtrrLimit
&& NoRangeBase
< MtrrLimit
) {
1396 NoRangeBase
= MtrrLimit
+ 1;
1398 if (Base
< MtrrBase
&& NoRangeLimit
> MtrrBase
) {
1399 NoRangeLimit
= MtrrBase
- 1;
1404 Base
= RangeLimit
+ 1;
1406 Base
= NoRangeLimit
+ 1;
1408 } while (Base
< Limit
);
1409 DEBUG((DEBUG_CACHE
, "%016lx\n\n", Base
- 1));
1415 This function prints all MTRRs for debugging.
1419 MtrrDebugPrintAllMtrrs (
1423 MtrrDebugPrintAllMtrrsWorker (NULL
);
1428 Worker function attempts to set the attributes for a memory range.
1430 If MtrrSettings is not NULL, set the attributes into the input MTRR
1432 If MtrrSettings is NULL, set the attributes into MTRRs registers.
1434 @param[in, out] MtrrSetting A buffer holding all MTRRs content.
1435 @param[in] BaseAddress The physical address that is the start
1436 address of a memory region.
1437 @param[in] Length The size in bytes of the memory region.
1438 @param[in] Attribute The bit mask of attributes to set for the
1441 @retval RETURN_SUCCESS The attributes were set for the memory
1443 @retval RETURN_INVALID_PARAMETER Length is zero.
1444 @retval RETURN_UNSUPPORTED The processor does not support one or
1445 more bytes of the memory resource range
1446 specified by BaseAddress and Length.
1447 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1448 for the memory resource range specified
1449 by BaseAddress and Length.
1450 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1451 range specified by BaseAddress and Length
1453 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1454 modify the attributes of the memory
1459 MtrrSetMemoryAttributeWorker (
1460 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1461 IN PHYSICAL_ADDRESS BaseAddress
,
1463 IN MTRR_MEMORY_CACHE_TYPE Attribute
1467 RETURN_STATUS Status
;
1474 VARIABLE_MTRR VariableMtrr
[MTRR_NUMBER_OF_VARIABLE_MTRR
];
1476 UINT64 MtrrValidBitsMask
;
1477 UINT64 MtrrValidAddressMask
;
1478 BOOLEAN OverwriteExistingMtrr
;
1479 UINT32 FirmwareVariableMtrrCount
;
1480 MTRR_CONTEXT MtrrContext
;
1481 BOOLEAN MtrrContextValid
;
1482 BOOLEAN FixedSettingsValid
[MTRR_NUMBER_OF_FIXED_MTRR
];
1483 BOOLEAN FixedSettingsModified
[MTRR_NUMBER_OF_FIXED_MTRR
];
1484 MTRR_FIXED_SETTINGS WorkingFixedSettings
;
1485 UINT32 VariableMtrrCount
;
1486 MTRR_VARIABLE_SETTINGS OriginalVariableSettings
;
1487 BOOLEAN ProgramVariableSettings
;
1488 MTRR_VARIABLE_SETTINGS WorkingVariableSettings
;
1493 MTRR_VARIABLE_SETTINGS
*VariableSettings
;
1495 MtrrContextValid
= FALSE
;
1496 VariableMtrrCount
= 0;
1497 ZeroMem (&WorkingFixedSettings
, sizeof (WorkingFixedSettings
));
1498 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1499 FixedSettingsValid
[Index
] = FALSE
;
1500 FixedSettingsModified
[Index
] = FALSE
;
1502 ProgramVariableSettings
= FALSE
;
1504 if (!IsMtrrSupported ()) {
1505 Status
= RETURN_UNSUPPORTED
;
1509 MtrrLibInitializeMtrrMask (&MtrrValidBitsMask
, &MtrrValidAddressMask
);
1512 MemoryType
= (UINT64
)Attribute
;
1513 OverwriteExistingMtrr
= FALSE
;
1516 // Check for an invalid parameter
1519 Status
= RETURN_INVALID_PARAMETER
;
1524 (BaseAddress
& ~MtrrValidAddressMask
) != 0 ||
1525 (Length
& ~MtrrValidAddressMask
) != 0
1527 Status
= RETURN_UNSUPPORTED
;
1532 // Check if Fixed MTRR
1534 Status
= RETURN_SUCCESS
;
1535 if (BaseAddress
< BASE_1MB
) {
1536 while ((BaseAddress
< BASE_1MB
) && (Length
> 0) && Status
== RETURN_SUCCESS
) {
1537 Status
= ProgramFixedMtrr (MemoryType
, &BaseAddress
, &Length
, &MsrNum
, &ClearMask
, &OrMask
);
1538 if (RETURN_ERROR (Status
)) {
1541 if (MtrrSetting
!= NULL
) {
1542 MtrrSetting
->Fixed
.Mtrr
[MsrNum
] = (MtrrSetting
->Fixed
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1543 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_FIXED_MTRR_ENABLED
;
1545 if (!FixedSettingsValid
[MsrNum
]) {
1546 WorkingFixedSettings
.Mtrr
[MsrNum
] = MtrrRegisterRead (mMtrrLibFixedMtrrTable
[MsrNum
].Msr
);
1547 FixedSettingsValid
[MsrNum
] = TRUE
;
1549 NewValue
= (WorkingFixedSettings
.Mtrr
[MsrNum
] & ~ClearMask
) | OrMask
;
1550 if (WorkingFixedSettings
.Mtrr
[MsrNum
] != NewValue
) {
1551 WorkingFixedSettings
.Mtrr
[MsrNum
] = NewValue
;
1552 FixedSettingsModified
[MsrNum
] = TRUE
;
1559 // A Length of 0 can only make sense for fixed MTTR ranges.
1560 // Since we just handled the fixed MTRRs, we can skip the
1561 // variable MTRR section.
1568 // Since memory ranges below 1MB will be overridden by the fixed MTRRs,
1569 // we can set the base to 0 to save variable MTRRs.
1571 if (BaseAddress
== BASE_1MB
) {
1577 // Read all variable MTRRs
1579 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1580 FirmwareVariableMtrrCount
= GetFirmwareVariableMtrrCountWorker ();
1581 if (MtrrSetting
!= NULL
) {
1582 VariableSettings
= &MtrrSetting
->Variables
;
1584 MtrrGetVariableMtrrWorker (NULL
, VariableMtrrCount
, &OriginalVariableSettings
);
1585 CopyMem (&WorkingVariableSettings
, &OriginalVariableSettings
, sizeof (WorkingVariableSettings
));
1586 ProgramVariableSettings
= TRUE
;
1587 VariableSettings
= &WorkingVariableSettings
;
1591 // Check for overlap
1593 UsedMtrr
= MtrrGetMemoryAttributeInVariableMtrrWorker (
1595 FirmwareVariableMtrrCount
,
1597 MtrrValidAddressMask
,
1600 OverLap
= CheckMemoryAttributeOverlap (
1601 FirmwareVariableMtrrCount
,
1603 BaseAddress
+ Length
- 1,
1607 Status
= CombineMemoryAttribute (
1608 FirmwareVariableMtrrCount
,
1614 &OverwriteExistingMtrr
1616 if (RETURN_ERROR (Status
)) {
1622 // Combined successfully, invalidate the now-unused MTRRs
1624 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1625 Status
= RETURN_SUCCESS
;
1631 // The memory type is the same with the type specified by
1632 // MTRR_LIB_IA32_MTRR_DEF_TYPE.
1634 if ((!OverwriteExistingMtrr
) && (Attribute
== MtrrGetDefaultMemoryType ())) {
1636 // Invalidate the now-unused MTRRs
1638 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1642 Positive
= GetMtrrNumberAndDirection (BaseAddress
, Length
, &MtrrNumber
);
1644 if ((UsedMtrr
+ MtrrNumber
) > FirmwareVariableMtrrCount
) {
1645 Status
= RETURN_OUT_OF_RESOURCES
;
1650 // Invalidate the now-unused MTRRs
1652 InvalidateMtrr (VariableSettings
, VariableMtrrCount
, VariableMtrr
);
1655 // Find first unused MTRR
1657 for (MsrNum
= 0; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1658 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1663 if (BaseAddress
!= 0) {
1666 // Calculate the alignment of the base address.
1668 Alignment
= LShiftU64 (1, (UINTN
)LowBitSet64 (BaseAddress
));
1670 if (Alignment
> Length
) {
1677 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1678 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1683 ProgramVariableMtrr (
1689 MtrrValidAddressMask
1691 BaseAddress
+= Alignment
;
1692 Length
-= Alignment
;
1703 Length
= Power2MaxMemory (LShiftU64 (TempQword
, 1));
1708 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1709 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1714 ProgramVariableMtrr (
1720 MtrrValidAddressMask
1722 BaseAddress
+= Length
;
1723 TempQword
= Length
- TempQword
;
1724 MemoryType
= MTRR_CACHE_UNCACHEABLE
;
1731 for (; MsrNum
< VariableMtrrCount
; MsrNum
++) {
1732 if ((VariableSettings
->Mtrr
[MsrNum
].Mask
& MTRR_LIB_CACHE_MTRR_ENABLED
) == 0) {
1737 Length
= Power2MaxMemory (TempQword
);
1739 BaseAddress
-= Length
;
1742 ProgramVariableMtrr (
1748 MtrrValidAddressMask
1752 BaseAddress
+= Length
;
1754 TempQword
-= Length
;
1756 } while (TempQword
> 0);
1761 // Write fixed MTRRs that have been modified
1763 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1764 if (FixedSettingsModified
[Index
]) {
1765 if (!MtrrContextValid
) {
1766 PreMtrrChange (&MtrrContext
);
1767 MtrrContextValid
= TRUE
;
1770 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1771 WorkingFixedSettings
.Mtrr
[Index
]
1777 // Write variable MTRRs
1779 if (ProgramVariableSettings
) {
1780 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1781 if (WorkingVariableSettings
.Mtrr
[Index
].Base
!= OriginalVariableSettings
.Mtrr
[Index
].Base
||
1782 WorkingVariableSettings
.Mtrr
[Index
].Mask
!= OriginalVariableSettings
.Mtrr
[Index
].Mask
) {
1783 if (!MtrrContextValid
) {
1784 PreMtrrChange (&MtrrContext
);
1785 MtrrContextValid
= TRUE
;
1788 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1789 WorkingVariableSettings
.Mtrr
[Index
].Base
1792 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1793 WorkingVariableSettings
.Mtrr
[Index
].Mask
1798 if (MtrrContextValid
) {
1799 PostMtrrChange (&MtrrContext
);
1802 DEBUG((DEBUG_CACHE
, " Status = %r\n", Status
));
1803 if (!RETURN_ERROR (Status
)) {
1804 if (MtrrSetting
!= NULL
) {
1805 MtrrSetting
->MtrrDefType
|= MTRR_LIB_CACHE_MTRR_ENABLED
;
1807 MtrrDebugPrintAllMtrrsWorker (MtrrSetting
);
1814 This function attempts to set the attributes for a memory range.
1816 @param[in] BaseAddress The physical address that is the start
1817 address of a memory region.
1818 @param[in] Length The size in bytes of the memory region.
1819 @param[in] Attributes The bit mask of attributes to set for the
1822 @retval RETURN_SUCCESS The attributes were set for the memory
1824 @retval RETURN_INVALID_PARAMETER Length is zero.
1825 @retval RETURN_UNSUPPORTED The processor does not support one or
1826 more bytes of the memory resource range
1827 specified by BaseAddress and Length.
1828 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support
1829 for the memory resource range specified
1830 by BaseAddress and Length.
1831 @retval RETURN_ACCESS_DENIED The attributes for the memory resource
1832 range specified by BaseAddress and Length
1834 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to
1835 modify the attributes of the memory
1841 MtrrSetMemoryAttribute (
1842 IN PHYSICAL_ADDRESS BaseAddress
,
1844 IN MTRR_MEMORY_CACHE_TYPE Attribute
1847 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1848 return MtrrSetMemoryAttributeWorker (
1857 This function attempts to set the attributes into MTRR setting buffer for a memory range.
1859 @param[in, out] MtrrSetting MTRR setting buffer to be set.
1860 @param[in] BaseAddress The physical address that is the start address
1862 @param[in] Length The size in bytes of the memory region.
1863 @param[in] Attribute The bit mask of attributes to set for the
1866 @retval RETURN_SUCCESS The attributes were set for the memory region.
1867 @retval RETURN_INVALID_PARAMETER Length is zero.
1868 @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
1869 memory resource range specified by BaseAddress and Length.
1870 @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
1871 range specified by BaseAddress and Length.
1872 @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
1873 BaseAddress and Length cannot be modified.
1874 @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
1875 the memory resource range.
1880 MtrrSetMemoryAttributeInMtrrSettings (
1881 IN OUT MTRR_SETTINGS
*MtrrSetting
,
1882 IN PHYSICAL_ADDRESS BaseAddress
,
1884 IN MTRR_MEMORY_CACHE_TYPE Attribute
1887 DEBUG((DEBUG_CACHE
, "MtrrSetMemoryAttributeMtrrSettings(%p) %a:%016lx-%016lx\n", MtrrSetting
, mMtrrMemoryCacheTypeShortName
[Attribute
], BaseAddress
, Length
));
1888 return MtrrSetMemoryAttributeWorker (
1897 Worker function setting variable MTRRs
1899 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1903 MtrrSetVariableMtrrWorker (
1904 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1908 UINT32 VariableMtrrCount
;
1910 VariableMtrrCount
= GetVariableMtrrCountWorker ();
1911 ASSERT (VariableMtrrCount
<= MTRR_NUMBER_OF_VARIABLE_MTRR
);
1913 for (Index
= 0; Index
< VariableMtrrCount
; Index
++) {
1915 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1),
1916 VariableSettings
->Mtrr
[Index
].Base
1919 QUARK_NC_HOST_BRIDGE_IA32_MTRR_PHYSBASE0
+ (Index
<< 1) + 1,
1920 VariableSettings
->Mtrr
[Index
].Mask
1927 This function sets variable MTRRs
1929 @param[in] VariableSettings A buffer to hold variable MTRRs content.
1931 @return The pointer of VariableSettings
1934 MTRR_VARIABLE_SETTINGS
*
1936 MtrrSetVariableMtrr (
1937 IN MTRR_VARIABLE_SETTINGS
*VariableSettings
1940 MTRR_CONTEXT MtrrContext
;
1942 if (!IsMtrrSupported ()) {
1943 return VariableSettings
;
1946 PreMtrrChange (&MtrrContext
);
1947 MtrrSetVariableMtrrWorker (VariableSettings
);
1948 PostMtrrChange (&MtrrContext
);
1949 MtrrDebugPrintAllMtrrs ();
1951 return VariableSettings
;
1955 Worker function setting fixed MTRRs
1957 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1961 MtrrSetFixedMtrrWorker (
1962 IN MTRR_FIXED_SETTINGS
*FixedSettings
1967 for (Index
= 0; Index
< MTRR_NUMBER_OF_FIXED_MTRR
; Index
++) {
1969 mMtrrLibFixedMtrrTable
[Index
].Msr
,
1970 FixedSettings
->Mtrr
[Index
]
1977 This function sets fixed MTRRs
1979 @param[in] FixedSettings A buffer to hold fixed MTRRs content.
1981 @retval The pointer of FixedSettings
1984 MTRR_FIXED_SETTINGS
*
1987 IN MTRR_FIXED_SETTINGS
*FixedSettings
1990 MTRR_CONTEXT MtrrContext
;
1992 if (!IsMtrrSupported ()) {
1993 return FixedSettings
;
1996 PreMtrrChange (&MtrrContext
);
1997 MtrrSetFixedMtrrWorker (FixedSettings
);
1998 PostMtrrChange (&MtrrContext
);
1999 MtrrDebugPrintAllMtrrs ();
2001 return FixedSettings
;
2006 This function gets the content in all MTRRs (variable and fixed)
2008 @param[out] MtrrSetting A buffer to hold all MTRRs content.
2010 @retval the pointer of MtrrSetting
2016 OUT MTRR_SETTINGS
*MtrrSetting
2019 if (!IsMtrrSupported ()) {
2026 MtrrGetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2029 // Get variable MTRRs
2031 MtrrGetVariableMtrrWorker (
2033 GetVariableMtrrCountWorker (),
2034 &MtrrSetting
->Variables
2038 // Get MTRR_DEF_TYPE value
2040 MtrrSetting
->MtrrDefType
= MtrrRegisterRead (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
);
2047 This function sets all MTRRs (variable and fixed)
2049 @param[in] MtrrSetting A buffer holding all MTRRs content.
2051 @retval The pointer of MtrrSetting
2057 IN MTRR_SETTINGS
*MtrrSetting
2060 MTRR_CONTEXT MtrrContext
;
2062 if (!IsMtrrSupported ()) {
2066 PreMtrrChange (&MtrrContext
);
2071 MtrrSetFixedMtrrWorker (&MtrrSetting
->Fixed
);
2074 // Set variable MTRRs
2076 MtrrSetVariableMtrrWorker (&MtrrSetting
->Variables
);
2079 // Set MTRR_DEF_TYPE value
2081 MtrrRegisterWrite (QUARK_NC_HOST_BRIDGE_IA32_MTRR_DEF_TYPE
, MtrrSetting
->MtrrDefType
);
2083 PostMtrrChangeEnableCache (&MtrrContext
);
2085 MtrrDebugPrintAllMtrrs ();
2092 Checks if MTRR is supported.
2094 @retval TRUE MTRR is supported.
2095 @retval FALSE MTRR is not supported.
2107 // Check CPUID(1).EAX[0..11] for Quark SoC
2109 AsmCpuid (1, &RegEax
, NULL
, NULL
, NULL
);
2110 if ((RegEax
& 0xfff) == QUARK_SOC_CPUID_FAMILY_MODEL_STEPPING
) {