Most of services in this library instance are suggested to be invoked by BSP only,\r
except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.\r
\r
- Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR>\r
- This program and the accompanying materials\r
- are licensed and made available under the terms and conditions of the BSD License\r
- which accompanies this distribution. The full text of the license may be found at\r
- http://opensource.org/licenses/bsd-license.php\r
-\r
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+ Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>\r
+ SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
if (MtrrSetting == NULL) {\r
- VariableSettings->Mtrr[Index].Mask = AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));\r
- //\r
- // Skip to read the Base MSR when the Mask.V is not set.\r
- //\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {\r
- VariableSettings->Mtrr[Index].Base = AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));\r
- }\r
+ VariableSettings->Mtrr[Index].Base =\r
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));\r
+ VariableSettings->Mtrr[Index].Mask =\r
+ AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));\r
} else {\r
VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;\r
VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;\r
Set the below-1MB memory attribute to fixed MTRR buffer.\r
Modified flag array indicates which fixed MTRR is modified.\r
\r
- @param [in, out] FixedSettings Fixed MTRR buffer.\r
- @param [out] Modified Flag array indicating which MTRR is modified.\r
+ @param [in, out] ClearMasks The bits (when set) to clear in the fixed MTRR MSR.\r
+ @param [in, out] OrMasks The bits to set in the fixed MTRR MSR.\r
@param [in] BaseAddress Base address.\r
@param [in] Length Length.\r
@param [in] Type Memory type.\r
**/\r
RETURN_STATUS\r
MtrrLibSetBelow1MBMemoryAttribute (\r
- IN OUT MTRR_FIXED_SETTINGS *FixedSettings,\r
- OUT BOOLEAN *Modified,\r
+ IN OUT UINT64 *ClearMasks,\r
+ IN OUT UINT64 *OrMasks,\r
IN PHYSICAL_ADDRESS BaseAddress,\r
IN UINT64 Length,\r
IN MTRR_MEMORY_CACHE_TYPE Type\r
UINT32 MsrIndex;\r
UINT64 ClearMask;\r
UINT64 OrMask;\r
- UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- BOOLEAN LocalModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
\r
ASSERT (BaseAddress < BASE_1MB);\r
\r
- SetMem (LocalModified, sizeof (LocalModified), FALSE);\r
-\r
- //\r
- // (Value & ~0 | 0) still equals to (Value)\r
- //\r
- SetMem (ClearMasks, sizeof (ClearMasks), 0);\r
- SetMem (OrMasks, sizeof (OrMasks), 0);\r
-\r
MsrIndex = (UINT32)-1;\r
while ((BaseAddress < BASE_1MB) && (Length != 0)) {\r
Status = MtrrLibProgramFixedMtrr (Type, &BaseAddress, &Length, &MsrIndex, &ClearMask, &OrMask);\r
if (RETURN_ERROR (Status)) {\r
return Status;\r
}\r
- ClearMasks[MsrIndex] = ClearMask;\r
- OrMasks[MsrIndex] = OrMask;\r
- Modified[MsrIndex] = TRUE;\r
- LocalModified[MsrIndex] = TRUE;\r
- }\r
-\r
- for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {\r
- if (LocalModified[MsrIndex]) {\r
- FixedSettings->Mtrr[MsrIndex] = (FixedSettings->Mtrr[MsrIndex] & ~ClearMasks[MsrIndex]) | OrMasks[MsrIndex];\r
- }\r
+ ClearMasks[MsrIndex] = ClearMasks[MsrIndex] | ClearMask;\r
+ OrMasks[MsrIndex] = (OrMasks[MsrIndex] & ~ClearMask) | OrMask;\r
}\r
return RETURN_SUCCESS;\r
}\r
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];\r
\r
- BOOLEAN FixedSettingsModified[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
- MTRR_FIXED_SETTINGS WorkingFixedSettings;\r
+ UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
+ UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];\r
\r
MTRR_CONTEXT MtrrContext;\r
BOOLEAN MtrrContextValid;\r
// TRUE indicating the accordingly Variable setting needs modificaiton in OriginalVariableMtrr.\r
//\r
SetMem (VariableSettingModified, ARRAY_SIZE (VariableSettingModified), FALSE);\r
- //\r
- // TRUE indicating the accordingly Fixed setting needs modification in WorkingFixedSettings.\r
- //\r
- SetMem (FixedSettingsModified, ARRAY_SIZE (FixedSettingsModified), FALSE);\r
\r
//\r
// TRUE indicating the caller requests to set variable MTRRs.\r
//\r
// 3. Apply the below-1MB memory attribute settings.\r
//\r
- ZeroMem (WorkingFixedSettings.Mtrr, sizeof (WorkingFixedSettings.Mtrr));\r
+ // (Value & ~0 | 0) still equals to (Value)\r
+ //\r
+ ZeroMem (ClearMasks, sizeof (ClearMasks));\r
+ ZeroMem (OrMasks, sizeof (OrMasks));\r
for (Index = 0; Index < RangeCount; Index++) {\r
if (Ranges[Index].BaseAddress >= BASE_1MB) {\r
continue;\r
}\r
\r
Status = MtrrLibSetBelow1MBMemoryAttribute (\r
- &WorkingFixedSettings, FixedSettingsModified,\r
+ ClearMasks, OrMasks,\r
Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type\r
);\r
if (RETURN_ERROR (Status)) {\r
//\r
// 4. Write fixed MTRRs that have been modified\r
//\r
- for (Index = 0; Index < ARRAY_SIZE (FixedSettingsModified); Index++) {\r
- if (FixedSettingsModified[Index]) {\r
+ for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {\r
+ if (ClearMasks[Index] != 0) {\r
if (MtrrSetting != NULL) {\r
- MtrrSetting->Fixed.Mtrr[Index] = WorkingFixedSettings.Mtrr[Index];\r
+ MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];\r
} else {\r
if (!MtrrContextValid) {\r
MtrrLibPreMtrrChange (&MtrrContext);\r
MtrrContextValid = TRUE;\r
}\r
- AsmWriteMsr64 (\r
- mMtrrLibFixedMtrrTable[Index].Msr,\r
- WorkingFixedSettings.Mtrr[Index]\r
- );\r
+ AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);\r
}\r
}\r
}\r
BaseAddress and Length cannot be modified.\r
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of\r
the memory resource range.\r
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.\r
+ Multiple memory range attributes setting by calling this API multiple\r
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean\r
+ the number of CPU MTRRs are too small to set such memory attributes.\r
+ Pass the multiple memory range attributes to one call of\r
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.\r
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.\r
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify\r
+ external scratch buffer.\r
**/\r
RETURN_STATUS\r
EFIAPI\r
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to\r
modify the attributes of the memory\r
resource range.\r
- @retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.\r
+ Multiple memory range attributes setting by calling this API multiple\r
+ times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean\r
+ the number of CPU MTRRs are too small to set such memory attributes.\r
+ Pass the multiple memory range attributes to one call of\r
+ MtrrSetMemoryAttributesInMtrrSettings() may succeed.\r
+ @retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.\r
+ Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify\r
+ external scratch buffer.\r
**/\r
RETURN_STATUS\r
EFIAPI\r
ASSERT (VariableMtrrCount <= ARRAY_SIZE (VariableSettings->Mtrr));\r
\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- //\r
- // Mask MSR is always updated since caller might need to invalidate the MSR pair.\r
- // Base MSR is skipped when Mask.V is not set.\r
- //\r
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), VariableSettings->Mtrr[Index].Mask);\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {\r
- AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), VariableSettings->Mtrr[Index].Base);\r
- }\r
+ AsmWriteMsr64 (\r
+ MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),\r
+ VariableSettings->Mtrr[Index].Base\r
+ );\r
+ AsmWriteMsr64 (\r
+ MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),\r
+ VariableSettings->Mtrr[Index].Mask\r
+ );\r
}\r
}\r
\r
}\r
ContainVariableMtrr = FALSE;\r
for (Index = 0; Index < VariableMtrrCount; Index++) {\r
- if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *)&Mtrrs->Variables.Mtrr[Index].Mask)->Bits.V == 0) {\r
+ if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {\r
//\r
// If mask is not valid, then do not display range\r
//\r