X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=blobdiff_plain;f=UefiCpuPkg%2FLibrary%2FMtrrLib%2FMtrrLib.c;h=3cf5f1392a652b00c54de71afb44ffed62b0eaa7;hp=4e6878f2825333910d1ee23df8dedb1c485eeeaa;hb=f877f3006efcb6225d8392e61b934b61077a5881;hpb=5bdfa4e58ad64cbc825d03397b15f5b2bcebda4e diff --git a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c index 4e6878f282..3cf5f1392a 100644 --- a/UefiCpuPkg/Library/MtrrLib/MtrrLib.c +++ b/UefiCpuPkg/Library/MtrrLib/MtrrLib.c @@ -1,8 +1,8 @@ /** @file MTRR setting library - Copyright (c) 2008 - 2010, Intel Corporation - All rights reserved. This program and the accompanying materials + Copyright (c) 2008 - 2011, Intel Corporation. All rights reserved.
+ This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php @@ -23,8 +23,7 @@ // // This table defines the offset, base and length of the fixed MTRRs // -STATIC -FIXED_MTRR MtrrLibFixedMtrrTable[] = { +CONST FIXED_MTRR mMtrrLibFixedMtrrTable[] = { { MTRR_LIB_IA32_MTRR_FIX64K_00000, 0, @@ -82,6 +81,20 @@ FIXED_MTRR MtrrLibFixedMtrrTable[] = { }, }; +// +// Lookup table used to print MTRRs +// +GLOBAL_REMOVE_IF_UNREFERENCED CONST CHAR8 *mMtrrMemoryCacheTypeShortName[] = { + "UC", // CacheUncacheable + "WC", // CacheWriteCombining + "R*", // Invalid + "R*", // Invalid + "WT", // CacheWriteThrough + "WP", // CacheWriteProtected + "WB", // CacheWriteBack + "R*" // Invalid +}; + /** Returns the variable MTRR count for the CPU. @@ -89,11 +102,21 @@ FIXED_MTRR MtrrLibFixedMtrrTable[] = { **/ UINT32 +EFIAPI GetVariableMtrrCount ( VOID ) { - return (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK); + UINT32 VariableMtrrCount; + + if (!IsMtrrSupported ()) { + return 0; + } + + VariableMtrrCount = (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK); + ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR); + + return VariableMtrrCount; } /** @@ -103,11 +126,19 @@ GetVariableMtrrCount ( **/ UINT32 +EFIAPI GetFirmwareVariableMtrrCount ( VOID ) { - return GetVariableMtrrCount () - RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER; + UINT32 VariableMtrrCount; + + VariableMtrrCount = GetVariableMtrrCount (); + if (VariableMtrrCount < RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER) { + return 0; + } + + return VariableMtrrCount - RESERVED_FIRMWARE_VARIABLE_MTRR_NUMBER; } /** @@ -235,11 +266,11 @@ ProgramFixedMtrr ( ClearMask = 0; for (MsrNum = 0; MsrNum < MTRR_NUMBER_OF_FIXED_MTRR; MsrNum++) { - if ((*Base >= MtrrLibFixedMtrrTable[MsrNum].BaseAddress) && + if ((*Base >= mMtrrLibFixedMtrrTable[MsrNum].BaseAddress) && (*Base < ( - MtrrLibFixedMtrrTable[MsrNum].BaseAddress + - (8 * MtrrLibFixedMtrrTable[MsrNum].Length) + mMtrrLibFixedMtrrTable[MsrNum].BaseAddress + + (8 * mMtrrLibFixedMtrrTable[MsrNum].Length) ) ) ) { @@ -257,8 +288,8 @@ ProgramFixedMtrr ( for (ByteShift = 0; ByteShift < 8; ByteShift++) { if (*Base == ( - MtrrLibFixedMtrrTable[MsrNum].BaseAddress + - (ByteShift * MtrrLibFixedMtrrTable[MsrNum].Length) + mMtrrLibFixedMtrrTable[MsrNum].BaseAddress + + (ByteShift * mMtrrLibFixedMtrrTable[MsrNum].Length) ) ) { break; @@ -271,13 +302,13 @@ ProgramFixedMtrr ( for ( ; - ((ByteShift < 8) && (*Length >= MtrrLibFixedMtrrTable[MsrNum].Length)); + ((ByteShift < 8) && (*Length >= mMtrrLibFixedMtrrTable[MsrNum].Length)); ByteShift++ ) { OrMask |= LShiftU64 ((UINT64) MemoryCacheType, (UINT32) (ByteShift * 8)); ClearMask |= LShiftU64 ((UINT64) 0xFF, (UINT32) (ByteShift * 8)); - *Length -= MtrrLibFixedMtrrTable[MsrNum].Length; - *Base += MtrrLibFixedMtrrTable[MsrNum].Length; + *Length -= mMtrrLibFixedMtrrTable[MsrNum].Length; + *Base += mMtrrLibFixedMtrrTable[MsrNum].Length; } if (ByteShift < 8 && (*Length != 0)) { @@ -285,8 +316,8 @@ ProgramFixedMtrr ( } TempQword = - (AsmReadMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask; - AsmWriteMsr64 (MtrrLibFixedMtrrTable[MsrNum].Msr, TempQword); + (AsmReadMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr) & ~ClearMask) | OrMask; + AsmWriteMsr64 (mMtrrLibFixedMtrrTable[MsrNum].Msr, TempQword); return RETURN_SUCCESS; } @@ -319,6 +350,10 @@ MtrrGetMemoryAttributeInVariableMtrr ( UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; + if (!IsMtrrSupported ()) { + return 0; + } + FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount (); VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; @@ -535,7 +570,7 @@ Power2MaxMemory ( { UINT64 Result; - if (RShiftU64 (MemoryLength, 32)) { + if (RShiftU64 (MemoryLength, 32) != 0) { Result = LShiftU64 ( (UINT64) GetPowerOfTwo32 ( (UINT32) RShiftU64 (MemoryLength, 32) @@ -607,7 +642,6 @@ GetDirection ( @param VariableMtrr The array to shadow variable MTRRs content **/ -STATIC VOID InvalidateMtrr ( IN VARIABLE_MTRR *VariableMtrr @@ -621,7 +655,7 @@ InvalidateMtrr ( Index = 0; VariableMtrrCount = GetVariableMtrrCount (); while (Index < VariableMtrrCount) { - if (VariableMtrr[Index].Valid == FALSE && VariableMtrr[Index].Used == TRUE ) { + if (!VariableMtrr[Index].Valid && VariableMtrr[Index].Used) { AsmWriteMsr64 (VariableMtrr[Index].Msr, 0); AsmWriteMsr64 (VariableMtrr[Index].Msr + 1, 0); VariableMtrr[Index].Used = FALSE; @@ -644,7 +678,6 @@ InvalidateMtrr ( @param MtrrValidAddressMask The valid address mask for MTRR **/ -STATIC VOID ProgramVariableMtrr ( IN UINTN MtrrNumber, @@ -686,7 +719,6 @@ ProgramVariableMtrr ( @return The enum item in MTRR_MEMORY_CACHE_TYPE **/ -STATIC MTRR_MEMORY_CACHE_TYPE GetMemoryCacheTypeFromMtrrType ( IN UINT64 MtrrType @@ -721,15 +753,14 @@ GetMemoryCacheTypeFromMtrrType ( @param MtrrValidAddressMask The valid address mask for the MTRR **/ -STATIC VOID MtrrLibInitializeMtrrMask ( OUT UINT64 *MtrrValidBitsMask, OUT UINT64 *MtrrValidAddressMask ) { - UINT32 RegEax; - UINT8 PhysicalAddressBits; + UINT32 RegEax; + UINT8 PhysicalAddressBits; AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); @@ -870,6 +901,13 @@ MtrrSetMemoryAttribute ( UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; + DEBUG((DEBUG_CACHE, "MtrrSetMemoryAttribute() %a:%016lx-%016lx\n", mMtrrMemoryCacheTypeShortName[Attribute], BaseAddress, Length)); + + if (!IsMtrrSupported ()) { + Status = RETURN_UNSUPPORTED; + goto Done; + } + FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount (); VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; @@ -883,14 +921,16 @@ MtrrSetMemoryAttribute ( // Check for an invalid parameter // if (Length == 0) { - return RETURN_INVALID_PARAMETER; + Status = RETURN_INVALID_PARAMETER; + goto Done; } if ( - (BaseAddress &~MtrrValidAddressMask) != 0 || - (Length &~MtrrValidAddressMask) != 0 + (BaseAddress & ~MtrrValidAddressMask) != 0 || + (Length & ~MtrrValidAddressMask) != 0 ) { - return RETURN_UNSUPPORTED; + Status = RETURN_UNSUPPORTED; + goto Done; } // @@ -902,7 +942,7 @@ MtrrSetMemoryAttribute ( Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length); PostMtrrChange (Cr4); if (RETURN_ERROR (Status)) { - return Status; + goto Done; } } @@ -917,7 +957,7 @@ MtrrSetMemoryAttribute ( // // Since memory ranges below 1MB will be overridden by the fixed MTRRs, - // we can set the bade to 0 to save variable MTRRs. + // we can set the base to 0 to save variable MTRRs. // if (BaseAddress == BASE_1MB) { BaseAddress = 0; @@ -1078,8 +1118,12 @@ MtrrSetMemoryAttribute ( } Done: - return Status; + DEBUG((DEBUG_CACHE, " Status = %r\n", Status)); + if (!RETURN_ERROR (Status)) { + MtrrDebugPrintAllMtrrs (); + } + return Status; } @@ -1110,6 +1154,10 @@ MtrrGetMemoryAttribute ( UINT64 MtrrValidAddressMask; UINTN VariableMtrrCount; + if (!IsMtrrSupported ()) { + return CacheUncacheable; + } + // // Check if MTRR is enabled, if not, return UC as attribute // @@ -1129,16 +1177,16 @@ MtrrGetMemoryAttribute ( // Go through the fixed MTRR // for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { - if (Address >= MtrrLibFixedMtrrTable[Index].BaseAddress && + if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress && Address < ( - MtrrLibFixedMtrrTable[Index].BaseAddress + - (MtrrLibFixedMtrrTable[Index].Length * 8) + mMtrrLibFixedMtrrTable[Index].BaseAddress + + (mMtrrLibFixedMtrrTable[Index].Length * 8) ) ) { SubIndex = - ((UINTN)Address - MtrrLibFixedMtrrTable[Index].BaseAddress) / - MtrrLibFixedMtrrTable[Index].Length; - TempQword = AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr); + ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) / + mMtrrLibFixedMtrrTable[Index].Length; + TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF; return GetMemoryCacheTypeFromMtrrType (MtrrType); } @@ -1190,6 +1238,10 @@ MtrrGetVariableMtrr ( UINT32 Index; UINT32 VariableMtrrCount; + if (!IsMtrrSupported ()) { + return VariableSettings; + } + VariableMtrrCount = GetVariableMtrrCount (); ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR); @@ -1250,6 +1302,10 @@ MtrrSetVariableMtrr ( { UINTN Cr4; + if (!IsMtrrSupported ()) { + return VariableSettings; + } + Cr4 = PreMtrrChange (); MtrrSetVariableMtrrWorker (VariableSettings); PostMtrrChange (Cr4); @@ -1273,9 +1329,13 @@ MtrrGetFixedMtrr ( { UINT32 Index; + if (!IsMtrrSupported ()) { + return FixedSettings; + } + for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { FixedSettings->Mtrr[Index] = - AsmReadMsr64 (MtrrLibFixedMtrrTable[Index].Msr); + AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); }; return FixedSettings; @@ -1296,7 +1356,7 @@ MtrrSetFixedMtrrWorker ( for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { AsmWriteMsr64 ( - MtrrLibFixedMtrrTable[Index].Msr, + mMtrrLibFixedMtrrTable[Index].Msr, FixedSettings->Mtrr[Index] ); } @@ -1319,6 +1379,10 @@ MtrrSetFixedMtrr ( { UINTN Cr4; + if (!IsMtrrSupported ()) { + return FixedSettings; + } + Cr4 = PreMtrrChange (); MtrrSetFixedMtrrWorker (FixedSettings); PostMtrrChange (Cr4); @@ -1341,6 +1405,10 @@ MtrrGetAllMtrrs ( OUT MTRR_SETTINGS *MtrrSetting ) { + if (!IsMtrrSupported ()) { + return MtrrSetting; + } + // // Get fixed MTRRs // @@ -1376,6 +1444,10 @@ MtrrSetAllMtrrs ( { UINTN Cr4; + if (!IsMtrrSupported ()) { + return MtrrSetting; + } + Cr4 = PreMtrrChange (); // @@ -1398,40 +1470,188 @@ MtrrSetAllMtrrs ( return MtrrSetting; } - /** This function prints all MTRRs for debugging. **/ VOID +EFIAPI MtrrDebugPrintAllMtrrs ( + VOID ) { DEBUG_CODE ( { MTRR_SETTINGS MtrrSettings; UINTN Index; + UINTN Index1; UINTN VariableMtrrCount; + UINT64 Base; + UINT64 Limit; + UINT64 MtrrBase; + UINT64 MtrrLimit; + UINT64 RangeBase; + UINT64 RangeLimit; + UINT64 NoRangeBase; + UINT64 NoRangeLimit; + UINT32 RegEax; + UINTN MemoryType; + UINTN PreviousMemoryType; + BOOLEAN Found; + + if (!IsMtrrSupported ()) { + return; + } + DEBUG((DEBUG_CACHE, "MTRR Settings\n")); + DEBUG((DEBUG_CACHE, "=============\n")); + MtrrGetAllMtrrs (&MtrrSettings); - DEBUG((EFI_D_ERROR, "DefaultType = %016lx\n", MtrrSettings.MtrrDefType)); + DEBUG((DEBUG_CACHE, "MTRR Default Type: %016lx\n", MtrrSettings.MtrrDefType)); for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { - DEBUG(( - EFI_D_ERROR, "Fixed[%02d] = %016lx\n", - Index, - MtrrSettings.Fixed.Mtrr[Index] - )); + DEBUG((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, MtrrSettings.Fixed.Mtrr[Index])); } VariableMtrrCount = GetVariableMtrrCount (); for (Index = 0; Index < VariableMtrrCount; Index++) { - DEBUG(( - EFI_D_ERROR, "Variable[%02d] = %016lx, %016lx\n", + DEBUG((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n", Index, MtrrSettings.Variables.Mtrr[Index].Base, MtrrSettings.Variables.Mtrr[Index].Mask )); } + DEBUG((DEBUG_CACHE, "\n")); + DEBUG((DEBUG_CACHE, "MTRR Ranges\n")); + DEBUG((DEBUG_CACHE, "====================================\n")); + + Base = 0; + PreviousMemoryType = MTRR_CACHE_INVALID_TYPE; + for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { + Base = mMtrrLibFixedMtrrTable[Index].BaseAddress; + for (Index1 = 0; Index1 < 8; Index1++) { + MemoryType = RShiftU64 (MtrrSettings.Fixed.Mtrr[Index], Index1 * 8) & 0xff; + if (MemoryType > CacheWriteBack) { + MemoryType = MTRR_CACHE_INVALID_TYPE; + } + if (MemoryType != PreviousMemoryType) { + if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) { + DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1)); + } + PreviousMemoryType = MemoryType; + DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base)); + } + Base += mMtrrLibFixedMtrrTable[Index].Length; + } + } + DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1)); + + VariableMtrrCount = GetVariableMtrrCount (); + + Base = BASE_1MB; + PreviousMemoryType = MTRR_CACHE_INVALID_TYPE; + do { + MemoryType = MtrrGetMemoryAttribute (Base); + if (MemoryType > CacheWriteBack) { + MemoryType = MTRR_CACHE_INVALID_TYPE; + } + + if (MemoryType != PreviousMemoryType) { + if (PreviousMemoryType != MTRR_CACHE_INVALID_TYPE) { + DEBUG((DEBUG_CACHE, "%016lx\n", Base - 1)); + } + PreviousMemoryType = MemoryType; + DEBUG((DEBUG_CACHE, "%a:%016lx-", mMtrrMemoryCacheTypeShortName[MemoryType], Base)); + } + + RangeBase = BASE_1MB; + NoRangeBase = BASE_1MB; + Limit = BIT36 - 1; + AsmCpuid (0x80000000, &RegEax, NULL, NULL, NULL); + if (RegEax >= 0x80000008) { + AsmCpuid (0x80000008, &RegEax, NULL, NULL, NULL); + Limit = LShiftU64 (1, RegEax & 0xff) - 1; + } + RangeLimit = Limit; + NoRangeLimit = Limit; + + for (Index = 0, Found = FALSE; Index < VariableMtrrCount; Index++) { + if ((MtrrSettings.Variables.Mtrr[Index].Mask & BIT11) == 0) { + // + // If mask is not valid, then do not display range + // + continue; + } + MtrrBase = (MtrrSettings.Variables.Mtrr[Index].Base & (~(SIZE_4KB - 1))); + MtrrLimit = MtrrBase + ((~(MtrrSettings.Variables.Mtrr[Index].Mask & (~(SIZE_4KB - 1)))) & Limit); + + if (Base >= MtrrBase && Base < MtrrLimit) { + Found = TRUE; + } + + if (Base >= MtrrBase && MtrrBase > RangeBase) { + RangeBase = MtrrBase; + } + if (Base > MtrrLimit && MtrrLimit > RangeBase) { + RangeBase = MtrrLimit + 1; + } + if (Base < MtrrBase && MtrrBase < RangeLimit) { + RangeLimit = MtrrBase - 1; + } + if (Base < MtrrLimit && MtrrLimit <= RangeLimit) { + RangeLimit = MtrrLimit; + } + + if (Base > MtrrLimit && NoRangeBase < MtrrLimit) { + NoRangeBase = MtrrLimit + 1; + } + if (Base < MtrrBase && NoRangeLimit > MtrrBase) { + NoRangeLimit = MtrrBase - 1; + } + } + + if (Found) { + Base = RangeLimit + 1; + } else { + Base = NoRangeLimit + 1; + } + } while (Found); + DEBUG((DEBUG_CACHE, "%016lx\n\n", Base - 1)); } ); } +/** + Checks if MTRR is supported. + + @retval TRUE MTRR is supported. + @retval FALSE MTRR is not supported. + +**/ +BOOLEAN +EFIAPI +IsMtrrSupported ( + VOID + ) +{ + UINT32 RegEdx; + UINT64 MtrrCap; + + // + // Check CPUID(1).EDX[12] for MTRR capability + // + AsmCpuid (1, NULL, NULL, NULL, &RegEdx); + if (BitFieldRead32 (RegEdx, 12, 12) == 0) { + return FALSE; + } + + // + // Check IA32_MTRRCAP.[0..7] for number of variable MTRRs and IA32_MTRRCAP[8] for + // fixed MTRRs existence. If number of variable MTRRs is zero, or fixed MTRRs do not + // exist, return false. + // + MtrrCap = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP); + if ((BitFieldRead64 (MtrrCap, 0, 7) == 0) || (BitFieldRead64 (MtrrCap, 8, 8) == 0)) { + return FALSE; + } + + return TRUE; +}