UefiCpuPkg/MtrrLib: Update APIs related to set memory attributes.
Update APIs related to set memory attributes to handle the fixed MTRR is not always supported. There are 3 APIs in MtrrLib that can set memory attributes: 1. MtrrSetMemoryAttributesInMtrrSettings 2. MtrrSetMemoryAttributeInMtrrSettings 3. MtrrSetMemoryAttribute The general idea applied in MtrrSetMemoryAttributesInMtrrSettings is: 1. MtrrLibPreMtrrChange saves the old MTRR default type which contains bit to enable fixed MTRR. 2. Main logic in MtrrSetMemoryAttributesInMtrrSettings applies memory attribute settings for below 1MB to variable MTRRs if fixed MTRR is not supported. 3. MtrrLibPostMtrrChange unconditionally sets E bit in MTRR default type MSR but only set FE bit when fixed MTRRs are modified. Signed-off-by: Ray Ni <ray.ni@intel.com> Cc: Eric Dong <eric.dong@intel.com> Cc: Rahul Kumar <rahul1.kumar@intel.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Eric Dong <eric.dong@intel.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
This commit is contained in:
@ -33,8 +33,9 @@
|
|||||||
// Context to save and restore when MTRRs are programmed
|
// Context to save and restore when MTRRs are programmed
|
||||||
//
|
//
|
||||||
typedef struct {
|
typedef struct {
|
||||||
UINTN Cr4;
|
UINTN Cr4;
|
||||||
BOOLEAN InterruptState;
|
BOOLEAN InterruptState;
|
||||||
|
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
|
||||||
} MTRR_CONTEXT;
|
} MTRR_CONTEXT;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -362,10 +363,11 @@ MtrrLibPreMtrrChange (
|
|||||||
CpuFlushTlb ();
|
CpuFlushTlb ();
|
||||||
|
|
||||||
//
|
//
|
||||||
// Disable MTRRs
|
// Save current MTRR default type and disable MTRRs
|
||||||
//
|
//
|
||||||
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
|
MtrrContext->DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
|
||||||
DefType.Bits.E = 0;
|
DefType.Uint64 = MtrrContext->DefType.Uint64;
|
||||||
|
DefType.Bits.E = 0;
|
||||||
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
|
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,15 +420,13 @@ MtrrLibPostMtrrChange (
|
|||||||
IN MTRR_CONTEXT *MtrrContext
|
IN MTRR_CONTEXT *MtrrContext
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// Enable Cache MTRR
|
// Enable Cache MTRR
|
||||||
|
// Note: It's possible that MTRR was not enabled earlier.
|
||||||
|
// But it will be enabled here unconditionally.
|
||||||
//
|
//
|
||||||
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
|
MtrrContext->DefType.Bits.E = 1;
|
||||||
DefType.Bits.E = 1;
|
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, MtrrContext->DefType.Uint64);
|
||||||
DefType.Bits.FE = 1;
|
|
||||||
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
|
|
||||||
|
|
||||||
MtrrLibPostMtrrChangeEnableCache (MtrrContext);
|
MtrrLibPostMtrrChangeEnableCache (MtrrContext);
|
||||||
}
|
}
|
||||||
@ -1058,6 +1058,8 @@ MtrrLibSetMemoryType (
|
|||||||
UINTN EndIndex;
|
UINTN EndIndex;
|
||||||
UINTN DeltaCount;
|
UINTN DeltaCount;
|
||||||
|
|
||||||
|
ASSERT (Length != 0);
|
||||||
|
|
||||||
LengthRight = 0;
|
LengthRight = 0;
|
||||||
LengthLeft = 0;
|
LengthLeft = 0;
|
||||||
Limit = BaseAddress + Length;
|
Limit = BaseAddress + Length;
|
||||||
@ -2336,7 +2338,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
UINT32 Index;
|
UINT32 Index;
|
||||||
UINT64 BaseAddress;
|
UINT64 BaseAddress;
|
||||||
UINT64 Length;
|
UINT64 Length;
|
||||||
BOOLEAN Above1MbExist;
|
BOOLEAN VariableMtrrNeeded;
|
||||||
|
|
||||||
UINT64 MtrrValidBitsMask;
|
UINT64 MtrrValidBitsMask;
|
||||||
UINT64 MtrrValidAddressMask;
|
UINT64 MtrrValidAddressMask;
|
||||||
@ -2353,8 +2355,10 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
|
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
|
||||||
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
|
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
|
||||||
|
|
||||||
UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
|
UINT64 FixedMtrrMemoryLimit;
|
||||||
UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
|
BOOLEAN FixedMtrrSupported;
|
||||||
|
UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
|
||||||
|
UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
|
||||||
|
|
||||||
MTRR_CONTEXT MtrrContext;
|
MTRR_CONTEXT MtrrContext;
|
||||||
BOOLEAN MtrrContextValid;
|
BOOLEAN MtrrContextValid;
|
||||||
@ -2370,7 +2374,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
//
|
//
|
||||||
// TRUE indicating the caller requests to set variable MTRRs.
|
// TRUE indicating the caller requests to set variable MTRRs.
|
||||||
//
|
//
|
||||||
Above1MbExist = FALSE;
|
VariableMtrrNeeded = FALSE;
|
||||||
OriginalVariableMtrrCount = 0;
|
OriginalVariableMtrrCount = 0;
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -2399,11 +2403,13 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
//
|
//
|
||||||
// 1. Validate the parameters.
|
// 1. Validate the parameters.
|
||||||
//
|
//
|
||||||
if (!IsMtrrSupported ()) {
|
if (!MtrrLibIsMtrrSupported (&FixedMtrrSupported, &OriginalVariableMtrrCount)) {
|
||||||
Status = RETURN_UNSUPPORTED;
|
Status = RETURN_UNSUPPORTED;
|
||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FixedMtrrMemoryLimit = FixedMtrrSupported ? BASE_1MB : 0;
|
||||||
|
|
||||||
for (Index = 0; Index < RangeCount; Index++) {
|
for (Index = 0; Index < RangeCount; Index++) {
|
||||||
if (Ranges[Index].Length == 0) {
|
if (Ranges[Index].Length == 0) {
|
||||||
Status = RETURN_INVALID_PARAMETER;
|
Status = RETURN_INVALID_PARAMETER;
|
||||||
@ -2433,19 +2439,18 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
goto Exit;
|
goto Exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Ranges[Index].BaseAddress + Ranges[Index].Length > BASE_1MB) {
|
if (Ranges[Index].BaseAddress + Ranges[Index].Length > FixedMtrrMemoryLimit) {
|
||||||
Above1MbExist = TRUE;
|
VariableMtrrNeeded = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 2. Apply the above-1MB memory attribute settings.
|
// 2. Apply the above-1MB memory attribute settings.
|
||||||
//
|
//
|
||||||
if (Above1MbExist) {
|
if (VariableMtrrNeeded) {
|
||||||
//
|
//
|
||||||
// 2.1. Read all variable MTRRs and convert to Ranges.
|
// 2.1. Read all variable MTRRs and convert to Ranges.
|
||||||
//
|
//
|
||||||
OriginalVariableMtrrCount = GetVariableMtrrCountWorker ();
|
|
||||||
MtrrGetVariableMtrrWorker (MtrrSetting, OriginalVariableMtrrCount, &VariableSettings);
|
MtrrGetVariableMtrrWorker (MtrrSetting, OriginalVariableMtrrCount, &VariableSettings);
|
||||||
MtrrLibGetRawVariableRanges (
|
MtrrLibGetRawVariableRanges (
|
||||||
&VariableSettings,
|
&VariableSettings,
|
||||||
@ -2477,15 +2482,17 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
//
|
//
|
||||||
// 2.2. Force [0, 1M) to UC, so that it doesn't impact subtraction algorithm.
|
// 2.2. Force [0, 1M) to UC, so that it doesn't impact subtraction algorithm.
|
||||||
//
|
//
|
||||||
Status = MtrrLibSetMemoryType (
|
if (FixedMtrrMemoryLimit != 0) {
|
||||||
WorkingRanges,
|
Status = MtrrLibSetMemoryType (
|
||||||
ARRAY_SIZE (WorkingRanges),
|
WorkingRanges,
|
||||||
&WorkingRangeCount,
|
ARRAY_SIZE (WorkingRanges),
|
||||||
0,
|
&WorkingRangeCount,
|
||||||
SIZE_1MB,
|
0,
|
||||||
CacheUncacheable
|
FixedMtrrMemoryLimit,
|
||||||
);
|
CacheUncacheable
|
||||||
ASSERT (Status != RETURN_OUT_OF_RESOURCES);
|
);
|
||||||
|
ASSERT (Status != RETURN_OUT_OF_RESOURCES);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// 2.3. Apply the new memory attribute settings to Ranges.
|
// 2.3. Apply the new memory attribute settings to Ranges.
|
||||||
@ -2494,13 +2501,13 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
for (Index = 0; Index < RangeCount; Index++) {
|
for (Index = 0; Index < RangeCount; Index++) {
|
||||||
BaseAddress = Ranges[Index].BaseAddress;
|
BaseAddress = Ranges[Index].BaseAddress;
|
||||||
Length = Ranges[Index].Length;
|
Length = Ranges[Index].Length;
|
||||||
if (BaseAddress < BASE_1MB) {
|
if (BaseAddress < FixedMtrrMemoryLimit) {
|
||||||
if (Length <= BASE_1MB - BaseAddress) {
|
if (Length <= FixedMtrrMemoryLimit - BaseAddress) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
Length -= BASE_1MB - BaseAddress;
|
Length -= FixedMtrrMemoryLimit - BaseAddress;
|
||||||
BaseAddress = BASE_1MB;
|
BaseAddress = FixedMtrrMemoryLimit;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = MtrrLibSetMemoryType (
|
Status = MtrrLibSetMemoryType (
|
||||||
@ -2545,7 +2552,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
// 2.5. Remove the [0, 1MB) MTRR if it still exists (not merged with other range)
|
// 2.5. Remove the [0, 1MB) MTRR if it still exists (not merged with other range)
|
||||||
//
|
//
|
||||||
for (Index = 0; Index < WorkingVariableMtrrCount; Index++) {
|
for (Index = 0; Index < WorkingVariableMtrrCount; Index++) {
|
||||||
if ((WorkingVariableMtrr[Index].BaseAddress == 0) && (WorkingVariableMtrr[Index].Length == SIZE_1MB)) {
|
if ((WorkingVariableMtrr[Index].BaseAddress == 0) && (WorkingVariableMtrr[Index].Length == FixedMtrrMemoryLimit)) {
|
||||||
ASSERT (WorkingVariableMtrr[Index].Type == CacheUncacheable);
|
ASSERT (WorkingVariableMtrr[Index].Type == CacheUncacheable);
|
||||||
WorkingVariableMtrrCount--;
|
WorkingVariableMtrrCount--;
|
||||||
CopyMem (
|
CopyMem (
|
||||||
@ -2584,7 +2591,7 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
ZeroMem (ClearMasks, sizeof (ClearMasks));
|
ZeroMem (ClearMasks, sizeof (ClearMasks));
|
||||||
ZeroMem (OrMasks, sizeof (OrMasks));
|
ZeroMem (OrMasks, sizeof (OrMasks));
|
||||||
for (Index = 0; Index < RangeCount; Index++) {
|
for (Index = 0; Index < RangeCount; Index++) {
|
||||||
if (Ranges[Index].BaseAddress >= BASE_1MB) {
|
if (Ranges[Index].BaseAddress >= FixedMtrrMemoryLimit) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2607,11 +2614,19 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {
|
for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {
|
||||||
if (ClearMasks[Index] != 0) {
|
if (ClearMasks[Index] != 0) {
|
||||||
if (MtrrSetting != NULL) {
|
if (MtrrSetting != NULL) {
|
||||||
MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];
|
//
|
||||||
|
// Fixed MTRR is modified indicating fixed MTRR should be enabled in the end of MTRR programming.
|
||||||
|
//
|
||||||
|
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.FE = 1;
|
||||||
|
MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];
|
||||||
} else {
|
} else {
|
||||||
if (!MtrrContextValid) {
|
if (!MtrrContextValid) {
|
||||||
MtrrLibPreMtrrChange (&MtrrContext);
|
MtrrLibPreMtrrChange (&MtrrContext);
|
||||||
MtrrContextValid = TRUE;
|
//
|
||||||
|
// Fixed MTRR is modified indicating fixed MTRR should be enabled in the end of MTRR programming.
|
||||||
|
//
|
||||||
|
MtrrContext.DefType.Bits.FE = 1;
|
||||||
|
MtrrContextValid = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);
|
AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);
|
||||||
@ -2654,8 +2669,10 @@ MtrrSetMemoryAttributesInMtrrSettings (
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (MtrrSetting != NULL) {
|
if (MtrrSetting != NULL) {
|
||||||
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.E = 1;
|
//
|
||||||
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.FE = 1;
|
// Enable MTRR unconditionally
|
||||||
|
//
|
||||||
|
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.E = 1;
|
||||||
} else {
|
} else {
|
||||||
if (MtrrContextValid) {
|
if (MtrrContextValid) {
|
||||||
MtrrLibPostMtrrChange (&MtrrContext);
|
MtrrLibPostMtrrChange (&MtrrContext);
|
||||||
|
Reference in New Issue
Block a user