UefiCpuPkg/MtrrLib: Refine MtrrGetMemoryAttributeByAddressWorker

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Jeff Fan <jeff.fan@intel.com>
This commit is contained in:
Ruiyu Ni 2016-09-02 18:10:45 +08:00
parent 8051302a36
commit 10c361ad02
1 changed files with 80 additions and 157 deletions

View File

@ -568,20 +568,19 @@ MtrrLibProgramFixedMtrr (
This function shadows the content of variable MTRRs into an This function shadows the content of variable MTRRs into an
internal array: VariableMtrr. internal array: VariableMtrr.
@param[in] VariableSettings The variable MTRR values to shadow @param[in] VariableSettings The variable MTRR values to shadow
@param[in] FirmwareVariableMtrrCount The number of variable MTRRs available to firmware @param[in] VariableMtrrCount The number of variable MTRRs
@param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR @param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
@param[in] MtrrValidAddressMask The valid address mask for MTRR @param[in] MtrrValidAddressMask The valid address mask for MTRR
@param[out] VariableMtrr The array to shadow variable MTRRs content @param[out] VariableMtrr The array to shadow variable MTRRs content
@return The return value of this parameter indicates the @return Number of MTRRs which has been used.
number of MTRRs which has been used.
**/ **/
UINT32 UINT32
MtrrGetMemoryAttributeInVariableMtrrWorker ( MtrrGetMemoryAttributeInVariableMtrrWorker (
IN MTRR_VARIABLE_SETTINGS *VariableSettings, IN MTRR_VARIABLE_SETTINGS *VariableSettings,
IN UINTN FirmwareVariableMtrrCount, IN UINTN VariableMtrrCount,
IN UINT64 MtrrValidBitsMask, IN UINT64 MtrrValidBitsMask,
IN UINT64 MtrrValidAddressMask, IN UINT64 MtrrValidAddressMask,
OUT VARIABLE_MTRR *VariableMtrr OUT VARIABLE_MTRR *VariableMtrr
@ -591,7 +590,7 @@ MtrrGetMemoryAttributeInVariableMtrrWorker (
UINT32 UsedMtrr; UINT32 UsedMtrr;
ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR); ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR);
for (Index = 0, UsedMtrr = 0; Index < FirmwareVariableMtrrCount; Index++) { for (Index = 0, UsedMtrr = 0; Index < VariableMtrrCount; Index++) {
if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) { if ((VariableSettings->Mtrr[Index].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) {
VariableMtrr[Index].Msr = (UINT32)Index; VariableMtrr[Index].Msr = (UINT32)Index;
VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask); VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);
@ -724,8 +723,10 @@ MtrrLibGetPositiveMtrrNumber (
Return whether the left MTRR type precedes the right MTRR type. Return whether the left MTRR type precedes the right MTRR type.
The MTRR type precedence rules are: The MTRR type precedence rules are:
1. UC precedes any other type 1. UC precedes any other type
2. WT precedes WB 2. WT precedes WB
For further details, please refer the IA32 Software Developer's Manual,
Volume 3, Section "MTRR Precedences".
@param Left The left MTRR type. @param Left The left MTRR type.
@param Right The right MTRR type. @param Right The right MTRR type.
@ -954,46 +955,6 @@ MtrrLibGetMtrrNumber (
return LeastSubtractiveMtrrNumber + MiddleMtrrNumber + LeastRightMtrrNumber; return LeastSubtractiveMtrrNumber + MiddleMtrrNumber + LeastRightMtrrNumber;
} }
/**
Converts the Memory attribute value to MTRR_MEMORY_CACHE_TYPE.
If MtrrSetting is not NULL, gets the default memory attribute from input
MTRR settings buffer.
If MtrrSetting is NULL, gets the default memory attribute from MSR.
@param[in] MtrrSetting A buffer holding all MTRRs content.
@param[in] MtrrType MTRR memory type
@return The enum item in MTRR_MEMORY_CACHE_TYPE
**/
MTRR_MEMORY_CACHE_TYPE
GetMemoryCacheTypeFromMtrrType (
IN MTRR_SETTINGS *MtrrSetting,
IN UINT64 MtrrType
)
{
switch (MtrrType) {
case MTRR_CACHE_UNCACHEABLE:
return CacheUncacheable;
case MTRR_CACHE_WRITE_COMBINING:
return CacheWriteCombining;
case MTRR_CACHE_WRITE_THROUGH:
return CacheWriteThrough;
case MTRR_CACHE_WRITE_PROTECTED:
return CacheWriteProtected;
case MTRR_CACHE_WRITE_BACK:
return CacheWriteBack;
default:
//
// MtrrType is MTRR_CACHE_INVALID_TYPE, that means
// no MTRR covers the range
//
return MtrrGetDefaultMemoryTypeWorker (MtrrSetting);
}
}
/** /**
Initializes the valid bits mask and valid address mask for MTRRs. Initializes the valid bits mask and valid address mask for MTRRs.
@ -1030,71 +991,34 @@ MtrrLibInitializeMtrrMask (
Determines the real attribute of a memory range. Determines the real attribute of a memory range.
This function is to arbitrate the real attribute of the memory when This function is to arbitrate the real attribute of the memory when
there are 2 MTRRs covers the same memory range. For further details, there are 2 MTRRs covers the same memory range. For further details,
please refer the IA32 Software Developer's Manual, Volume 3, please refer the IA32 Software Developer's Manual, Volume 3,
Section 10.11.4.1. Section "MTRR Precedences".
@param[in] MtrrType1 The first kind of Memory type @param[in] MtrrType1 The first kind of Memory type
@param[in] MtrrType2 The second kind of memory type @param[in] MtrrType2 The second kind of memory type
**/ **/
UINT64 MTRR_MEMORY_CACHE_TYPE
MtrrLibPrecedence ( MtrrLibPrecedence (
IN UINT64 MtrrType1, IN MTRR_MEMORY_CACHE_TYPE MtrrType1,
IN UINT64 MtrrType2 IN MTRR_MEMORY_CACHE_TYPE MtrrType2
) )
{ {
UINT64 MtrrType; if (MtrrType1 == MtrrType2) {
return MtrrType1;
MtrrType = MTRR_CACHE_INVALID_TYPE;
switch (MtrrType1) {
case MTRR_CACHE_UNCACHEABLE:
MtrrType = MTRR_CACHE_UNCACHEABLE;
break;
case MTRR_CACHE_WRITE_COMBINING:
if (
MtrrType2==MTRR_CACHE_WRITE_COMBINING ||
MtrrType2==MTRR_CACHE_UNCACHEABLE
) {
MtrrType = MtrrType2;
}
break;
case MTRR_CACHE_WRITE_THROUGH:
if (
MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
MtrrType2==MTRR_CACHE_WRITE_BACK
) {
MtrrType = MTRR_CACHE_WRITE_THROUGH;
} else if(MtrrType2==MTRR_CACHE_UNCACHEABLE) {
MtrrType = MTRR_CACHE_UNCACHEABLE;
}
break;
case MTRR_CACHE_WRITE_PROTECTED:
if (MtrrType2 == MTRR_CACHE_WRITE_PROTECTED ||
MtrrType2 == MTRR_CACHE_UNCACHEABLE) {
MtrrType = MtrrType2;
}
break;
case MTRR_CACHE_WRITE_BACK:
if (
MtrrType2== MTRR_CACHE_UNCACHEABLE ||
MtrrType2==MTRR_CACHE_WRITE_THROUGH ||
MtrrType2== MTRR_CACHE_WRITE_BACK
) {
MtrrType = MtrrType2;
}
break;
case MTRR_CACHE_INVALID_TYPE:
MtrrType = MtrrType2;
break;
default:
break;
} }
if (MtrrType2 == MTRR_CACHE_INVALID_TYPE) { ASSERT (
MtrrType = MtrrType1; MtrrLibTypeLeftPrecedeRight (MtrrType1, MtrrType2) ||
MtrrLibTypeLeftPrecedeRight (MtrrType2, MtrrType1)
);
if (MtrrLibTypeLeftPrecedeRight (MtrrType1, MtrrType2)) {
return MtrrType1;
} else {
return MtrrType2;
} }
return MtrrType;
} }
/** /**
@ -1116,29 +1040,27 @@ MtrrGetMemoryAttributeByAddressWorker (
IN PHYSICAL_ADDRESS Address IN PHYSICAL_ADDRESS Address
) )
{ {
UINT64 TempQword; MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
UINTN Index; UINT64 FixedMtrr;
UINTN SubIndex; UINTN Index;
UINT64 MtrrType; UINTN SubIndex;
UINT64 TempMtrrType; MTRR_MEMORY_CACHE_TYPE MtrrType;
MTRR_MEMORY_CACHE_TYPE CacheType; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR];
VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT64 MtrrValidBitsMask;
UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask;
UINT64 MtrrValidAddressMask; UINT32 VariableMtrrCount;
UINTN VariableMtrrCount; MTRR_VARIABLE_SETTINGS VariableSettings;
MTRR_VARIABLE_SETTINGS VariableSettings;
// //
// Check if MTRR is enabled, if not, return UC as attribute // Check if MTRR is enabled, if not, return UC as attribute
// //
if (MtrrSetting == NULL) { if (MtrrSetting == NULL) {
TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE); DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
} else { } else {
TempQword = MtrrSetting->MtrrDefType; DefType.Uint64 = MtrrSetting->MtrrDefType;
} }
MtrrType = MTRR_CACHE_INVALID_TYPE;
if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { if (DefType.Bits.E == 0) {
return CacheUncacheable; return CacheUncacheable;
} }
@ -1146,65 +1068,66 @@ MtrrGetMemoryAttributeByAddressWorker (
// If address is less than 1M, then try to go through the fixed MTRR // If address is less than 1M, then try to go through the fixed MTRR
// //
if (Address < BASE_1MB) { if (Address < BASE_1MB) {
if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) { if (DefType.Bits.FE != 0) {
// //
// Go through the fixed MTRR // Go through the fixed MTRR
// //
for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress && if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress &&
Address < ( Address < mMtrrLibFixedMtrrTable[Index].BaseAddress +
mMtrrLibFixedMtrrTable[Index].BaseAddress + (mMtrrLibFixedMtrrTable[Index].Length * 8)) {
(mMtrrLibFixedMtrrTable[Index].Length * 8) SubIndex =
) ((UINTN) Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) /
) { mMtrrLibFixedMtrrTable[Index].Length;
SubIndex = if (MtrrSetting == NULL) {
((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) / FixedMtrr = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
mMtrrLibFixedMtrrTable[Index].Length; } else {
if (MtrrSetting == NULL) { FixedMtrr = MtrrSetting->Fixed.Mtrr[Index];
TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); }
} else { return (MTRR_MEMORY_CACHE_TYPE) (RShiftU64 (FixedMtrr, SubIndex * 8) & 0xFF);
TempQword = MtrrSetting->Fixed.Mtrr[Index]; }
}
MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF;
return GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);
}
} }
} }
} }
MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask);
MtrrGetVariableMtrrWorker ( VariableMtrrCount = GetVariableMtrrCountWorker ();
MtrrSetting, ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
GetVariableMtrrCountWorker (), MtrrGetVariableMtrrWorker (MtrrSetting, VariableMtrrCount, &VariableSettings);
&VariableSettings
);
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
MtrrGetMemoryAttributeInVariableMtrrWorker ( MtrrGetMemoryAttributeInVariableMtrrWorker (
&VariableSettings, &VariableSettings,
GetFirmwareVariableMtrrCountWorker (), VariableMtrrCount,
MtrrValidBitsMask, MtrrValidBitsMask,
MtrrValidAddressMask, MtrrValidAddressMask,
VariableMtrr VariableMtrr
); );
// //
// Go through the variable MTRR // Go through the variable MTRR
// //
VariableMtrrCount = GetVariableMtrrCountWorker (); MtrrType = CacheInvalid;
ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR);
for (Index = 0; Index < VariableMtrrCount; Index++) { for (Index = 0; Index < VariableMtrrCount; Index++) {
if (VariableMtrr[Index].Valid) { if (VariableMtrr[Index].Valid) {
if (Address >= VariableMtrr[Index].BaseAddress && if (Address >= VariableMtrr[Index].BaseAddress &&
Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) { Address < VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length) {
TempMtrrType = VariableMtrr[Index].Type; if (MtrrType == CacheInvalid) {
MtrrType = MtrrLibPrecedence (MtrrType, TempMtrrType); MtrrType = (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type;
} else {
MtrrType = MtrrLibPrecedence (MtrrType, (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type);
}
} }
} }
} }
CacheType = GetMemoryCacheTypeFromMtrrType (MtrrSetting, MtrrType);
return CacheType; //
// If there is no MTRR which covers the Address, use the default MTRR type.
//
if (MtrrType == CacheInvalid) {
MtrrType = (MTRR_MEMORY_CACHE_TYPE) DefType.Bits.Type;
}
return MtrrType;
} }