X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMtrrLib%2FMtrrLib.c;h=0e76e2f92ad54822c9a00e8b0443fee771eae4f0;hb=b0fa5d29d08e61fd7f2178aa3b455e41374b36c4;hp=697dc4352f61dd1540035ebdd139ed97d0c9e16f;hpb=d0baed7db51382d17efe92b1fc8fb741052f116a;p=mirror_edk2.git diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c index 697dc4352f..0e76e2f92a 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c @@ -415,6 +415,9 @@ MtrrGetVariableMtrr ( @param[in] MemoryCacheType The memory type to set. @param[in, out] Base The base address of memory range. @param[in, out] Length The length of memory range. + @param[out] ReturnMsrNum The index of the fixed MTRR MSR to program. + @param[out] ReturnClearMask The bits to clear in the fixed MTRR MSR. + @param[out] ReturnOrMask The bits to set in the fixed MTRR MSR. @retval RETURN_SUCCESS The cache type was updated successfully @retval RETURN_UNSUPPORTED The requested range or cache type was invalid @@ -423,9 +426,12 @@ MtrrGetVariableMtrr ( **/ RETURN_STATUS ProgramFixedMtrr ( - IN UINT64 MemoryCacheType, - IN OUT UINT64 *Base, - IN OUT UINT64 *Length + IN UINT64 MemoryCacheType, + IN OUT UINT64 *Base, + IN OUT UINT64 *Length, + OUT UINT32 *ReturnMsrNum, + OUT UINT64 *ReturnClearMask, + OUT UINT64 *ReturnOrMask ) { UINT32 MsrNum; @@ -488,9 +494,10 @@ ProgramFixedMtrr ( return RETURN_UNSUPPORTED; } - TempQword = - (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask; - AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword); + *ReturnMsrNum = MsrNum; + *ReturnClearMask = ClearMask; + *ReturnOrMask = OrMask; + return RETURN_SUCCESS; } @@ -876,30 +883,27 @@ GetMtrrNumberAndDirection ( This function programs MTRRs according to the values specified in the shadow array. + @param[in, out] VariableSettings Variable MTRR settings @param[in] VariableMtrrCount Number of variable MTRRs @param[in, out] VariableMtrr Shadow of variable MTRR contents **/ VOID InvalidateMtrr ( + IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings, IN UINTN VariableMtrrCount, IN OUT VARIABLE_MTRR *VariableMtrr ) { UINTN Index; - MTRR_CONTEXT MtrrContext; - PreMtrrChange (&MtrrContext); - Index = 0; - while (Index < VariableMtrrCount) { + for (Index = 0; Index < VariableMtrrCount; Index++) { if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) { - AsmWriteMsr64 (VariableMtrr[Index].Msr, 0); - AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0); + VariableSettings->Mtrr[Index].Base = 0; + VariableSettings->Mtrr[Index].Mask = 0; VariableMtrr[Index].Used = FALSE; } - Index ++; } - PostMtrrChange (&MtrrContext); } @@ -908,6 +912,7 @@ InvalidateMtrr ( This function programs variable MTRRs + @param[in, out] VariableSettings Variable MTRR settings. @param[in] MtrrNumber Index of MTRR to program. @param[in] BaseAddress Base address of memory region. @param[in] Length Length of memory region. @@ -917,34 +922,27 @@ InvalidateMtrr ( **/ VOID ProgramVariableMtrr ( - IN UINTN MtrrNumber, - IN PHYSICAL_ADDRESS BaseAddress, - IN UINT64 Length, - IN UINT64 MemoryCacheType, - IN UINT64 MtrrValidAddressMask + IN OUT MTRR_VARIABLE_SETTINGS *VariableSettings, + IN UINTN MtrrNumber, + IN PHYSICAL_ADDRESS BaseAddress, + IN UINT64 Length, + IN UINT64 MemoryCacheType, + IN UINT64 MtrrValidAddressMask ) { UINT64 TempQword; - MTRR_CONTEXT MtrrContext; - - PreMtrrChange (&MtrrContext); // // MTRR Physical Base // TempQword = (BaseAddress & MtrrValidAddressMask) | MemoryCacheType; - AsmWriteMsr64 ((UINT32) MtrrNumber, TempQword); + VariableSettings->Mtrr[MtrrNumber].Base = TempQword; // // MTRR Physical Mask // TempQword = ~(Length - 1); - AsmWriteMsr64 ( - (UINT32) (MtrrNumber + 1), - (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED - ); - - PostMtrrChange (&MtrrContext); + VariableSettings->Mtrr[MtrrNumber].Mask = (TempQword & MtrrValidAddressMask) | MTRR_LIB_CACHE_MTRR_ENABLED; } @@ -1386,24 +1384,35 @@ MtrrSetMemoryAttribute ( UINT64 MtrrValidAddressMask; BOOLEAN OverwriteExistingMtrr; UINT32 FirmwareVariableMtrrCount; - UINT32 VariableMtrrEnd; MTRR_CONTEXT MtrrContext; + BOOLEAN MtrrContextValid; + BOOLEAN FixedSettingsValid[MTRR_NUMBER_OF_FIXED_MTRR]; + BOOLEAN FixedSettingsModified[MTRR_NUMBER_OF_FIXED_MTRR]; + MTRR_FIXED_SETTINGS WorkingFixedSettings; UINT32 VariableMtrrCount; MTRR_VARIABLE_SETTINGS OriginalVariableSettings; + BOOLEAN ProgramVariableSettings; MTRR_VARIABLE_SETTINGS WorkingVariableSettings; + UINT32 Index; + UINT64 ClearMask; + UINT64 OrMask; + UINT64 NewValue; MTRR_VARIABLE_SETTINGS *VariableSettings; DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length)); + MtrrContextValid = FALSE; + for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { + FixedSettingsValid[Index] = FALSE; + FixedSettingsModified[Index] = FALSE; + } + ProgramVariableSettings = FALSE; if (!IsMtrrSupported ()) { Status = RETURN_UNSUPPORTED; goto Done; } - FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker (); - VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; - - MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); + MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask); TempQword = 0; MemoryType = (UINT64)Attribute; @@ -1429,22 +1438,31 @@ MtrrSetMemoryAttribute ( // Check if Fixed MTRR // Status = RETURN_SUCCESS; - while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) { - PreMtrrChange (&MtrrContext); - Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length); - PostMtrrChange (&MtrrContext); - if (RETURN_ERROR (Status)) { - goto Done; + if (BaseAddress < BASE_1MB) { + while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) { + Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length, &MsrNum, &ClearMask, &OrMask); + if (RETURN_ERROR (Status)) { + goto Done; + } + if (!FixedSettingsValid[MsrNum]) { + WorkingFixedSettings.Mtrr[MsrNum] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr); + FixedSettingsValid[MsrNum] = TRUE; + } + NewValue = (WorkingFixedSettings.Mtrr[MsrNum] & ~ClearMask) | OrMask; + if (WorkingFixedSettings.Mtrr[MsrNum] != NewValue) { + WorkingFixedSettings.Mtrr[MsrNum] = NewValue; + FixedSettingsModified[MsrNum] = TRUE; + } } - } - if (Length == 0) { - // - // A Length of 0 can only make sense for fixed MTTR ranges. - // Since we just handled the fixed MTRRs, we can skip the - // variable MTRR section. - // - goto Done; + if (Length == 0) { + // + // A Length of 0 can only make sense for fixed MTTR ranges. + // Since we just handled the fixed MTRRs, we can skip the + // variable MTRR section. + // + goto Done; + } } // @@ -1460,8 +1478,10 @@ MtrrSetMemoryAttribute ( // Read all variable MTRRs // VariableMtrrCount = GetVariableMtrrCountWorker (); + FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCountWorker (); MtrrGetVariableMtrrWorker (VariableMtrrCount, &OriginalVariableSettings); CopyMem (&WorkingVariableSettings, &OriginalVariableSettings, sizeof (WorkingVariableSettings)); + ProgramVariableSettings = TRUE; VariableSettings = &WorkingVariableSettings; // @@ -1480,7 +1500,6 @@ MtrrSetMemoryAttribute ( BaseAddress + Length - 1, VariableMtrr ); - if (OverLap) { Status = CombineMemoryAttribute ( FirmwareVariableMtrrCount, @@ -1499,7 +1518,7 @@ MtrrSetMemoryAttribute ( // // Combined successfully, invalidate the now-unused MTRRs // - InvalidateMtrr(VariableMtrrCount, VariableMtrr); + InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr); Status = RETURN_SUCCESS; goto Done; } @@ -1513,7 +1532,7 @@ MtrrSetMemoryAttribute ( // // Invalidate the now-unused MTRRs // - InvalidateMtrr(VariableMtrrCount, VariableMtrr); + InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr); goto Done; } @@ -1527,16 +1546,13 @@ MtrrSetMemoryAttribute ( // // Invalidate the now-unused MTRRs // - InvalidateMtrr(VariableMtrrCount, VariableMtrr); + InvalidateMtrr (VariableSettings, VariableMtrrCount, VariableMtrr); // // Find first unused MTRR // - for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE; - MsrNum < VariableMtrrEnd; - MsrNum += 2 - ) { - if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { + for (MsrNum = 0; MsrNum < VariableMtrrCount; MsrNum++) { + if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } @@ -1555,13 +1571,14 @@ MtrrSetMemoryAttribute ( // // Find unused MTRR // - for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { - if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { + for (; MsrNum < VariableMtrrCount; MsrNum++) { + if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } ProgramVariableMtrr ( + VariableSettings, MsrNum, BaseAddress, Alignment, @@ -1585,13 +1602,14 @@ MtrrSetMemoryAttribute ( // // Find unused MTRR // - for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { - if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { + for (; MsrNum < VariableMtrrCount; MsrNum++) { + if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } ProgramVariableMtrr ( + VariableSettings, MsrNum, BaseAddress, Length, @@ -1607,8 +1625,8 @@ MtrrSetMemoryAttribute ( // // Find unused MTRR // - for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { - if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { + for (; MsrNum < VariableMtrrCount; MsrNum++) { + if ((VariableSettings->Mtrr[MsrNum].Mask & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } @@ -1619,6 +1637,7 @@ MtrrSetMemoryAttribute ( } ProgramVariableMtrr ( + VariableSettings, MsrNum, BaseAddress, Length, @@ -1634,6 +1653,49 @@ MtrrSetMemoryAttribute ( } while (TempQword > 0); Done: + + // + // Write fixed MTRRs that have been modified + // + for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { + if (FixedSettingsModified[Index]) { + if (!MtrrContextValid) { + PreMtrrChange (&MtrrContext); + MtrrContextValid = TRUE; + } + AsmWriteMsr64 ( + mMtrrLibFixedMtrrTable[Index].Msr, + WorkingFixedSettings.Mtrr[Index] + ); + } + } + + // + // Write variable MTRRs + // + if (ProgramVariableSettings) { + for (Index = 0; Index < VariableMtrrCount; Index++) { + if (WorkingVariableSettings.Mtrr[Index].Base != OriginalVariableSettings.Mtrr[Index].Base || + WorkingVariableSettings.Mtrr[Index].Mask != OriginalVariableSettings.Mtrr[Index].Mask ) { + if (!MtrrContextValid) { + PreMtrrChange (&MtrrContext); + MtrrContextValid = TRUE; + } + AsmWriteMsr64 ( + MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1), + WorkingVariableSettings.Mtrr[Index].Base + ); + AsmWriteMsr64 ( + MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1, + WorkingVariableSettings.Mtrr[Index].Mask + ); + } + } + } + if (MtrrContextValid) { + PostMtrrChange (&MtrrContext); + } + DEBUG((DEBUG_CACHE, " Status = %r\n", Status)); if (!RETURN_ERROR (Status)) { MtrrDebugPrintAllMtrrs ();