EFIAPI MtrrSetAllMtrrs ( IN MTRR_SETTINGS *MtrrSetting ) { MTRR_CONTEXT MtrrContext; if (!IsMtrrSupported ()) { return MtrrSetting; } PreMtrrChange (&MtrrContext); // // Set fixed MTRRs // MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed); // // Set variable MTRRs // MtrrSetVariableMtrrWorker (&MtrrSetting->Variables); // // Set MTRR_DEF_TYPE value // AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType); PostMtrrChangeEnableCache (&MtrrContext); return MtrrSetting; }
EFIAPI MtrrSetAllMtrrs ( IN MTRR_SETTINGS *MtrrSetting ) { UINTN Cr4; if (!IsMtrrSupported ()) { return MtrrSetting; } Cr4 = PreMtrrChange (); // // Set fixed MTRRs // MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed); // // Set variable MTRRs // MtrrSetVariableMtrrWorker (&MtrrSetting->Variables); // // Set MTRR_DEF_TYPE value // AsmWriteMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType); PostMtrrChange (Cr4); return MtrrSetting; }
EFIAPI MtrrGetAllMtrrs ( OUT MTRR_SETTINGS *MtrrSetting ) { if (!IsMtrrSupported ()) { return MtrrSetting; } // // Get fixed MTRRs // MtrrGetFixedMtrr (&MtrrSetting->Fixed); // // Get variable MTRRs // MtrrGetVariableMtrr (&MtrrSetting->Variables); // // Get MTRR_DEF_TYPE value // MtrrSetting->MtrrDefType = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE); return MtrrSetting; }
/** Returns the variable MTRR count for the CPU. @return Variable MTRR count **/ UINT32 GetVariableMtrrCount ( VOID ) { if (!IsMtrrSupported ()) { return 0; } return (UINT32)(AsmReadMsr64 (MTRR_LIB_IA32_MTRR_CAP) & MTRR_LIB_IA32_MTRR_CAP_VCNT_MASK); }
/** Returns the default MTRR cache type for the system. @return The default MTRR cache type. **/ MTRR_MEMORY_CACHE_TYPE EFIAPI MtrrGetDefaultMemoryType ( VOID ) { if (!IsMtrrSupported ()) { return CacheUncacheable; } return (MTRR_MEMORY_CACHE_TYPE) (AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE) & 0x7); }
/** Get the attribute of variable MTRRs. This function shadows the content of variable MTRRs into an internal array: VariableMtrr. @param MtrrValidBitsMask The mask for the valid bit of the MTRR @param MtrrValidAddressMask The valid address mask for MTRR @param VariableMtrr The array to shadow variable MTRRs content @return The return value of this paramter indicates the number of MTRRs which has been used. **/ UINT32 EFIAPI MtrrGetMemoryAttributeInVariableMtrr ( IN UINT64 MtrrValidBitsMask, IN UINT64 MtrrValidAddressMask, OUT VARIABLE_MTRR *VariableMtrr ) { UINTN Index; UINT32 MsrNum; UINT32 UsedMtrr; UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; if (!IsMtrrSupported ()) { return 0; } FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount (); VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * MTRR_NUMBER_OF_VARIABLE_MTRR); UsedMtrr = 0; for (MsrNum = MTRR_LIB_IA32_VARIABLE_MTRR_BASE, Index = 0; ( (MsrNum < VariableMtrrEnd) && (Index < FirmwareVariableMtrrCount) ); MsrNum += 2 ) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) != 0) { VariableMtrr[Index].Msr = MsrNum; VariableMtrr[Index].BaseAddress = (AsmReadMsr64 (MsrNum) & MtrrValidAddressMask); VariableMtrr[Index].Length = ((~(AsmReadMsr64 (MsrNum + 1) & MtrrValidAddressMask) ) & MtrrValidBitsMask ) + 1; VariableMtrr[Index].Type = (AsmReadMsr64 (MsrNum) & 0x0ff); VariableMtrr[Index].Valid = TRUE; VariableMtrr[Index].Used = TRUE; UsedMtrr = UsedMtrr + 1; Index++; } } return UsedMtrr; }
EFIAPI MtrrSetVariableMtrr ( IN MTRR_VARIABLE_SETTINGS *VariableSettings ) { MTRR_CONTEXT MtrrContext; if (!IsMtrrSupported ()) { return VariableSettings; } PreMtrrChange (&MtrrContext); MtrrSetVariableMtrrWorker (VariableSettings); PostMtrrChange (&MtrrContext); return VariableSettings; }
EFIAPI MtrrSetVariableMtrr ( IN MTRR_VARIABLE_SETTINGS *VariableSettings ) { UINTN Cr4; if (!IsMtrrSupported ()) { return VariableSettings; } Cr4 = PreMtrrChange (); MtrrSetVariableMtrrWorker (VariableSettings); PostMtrrChange (Cr4); return VariableSettings; }
EFIAPI MtrrSetFixedMtrr ( IN MTRR_FIXED_SETTINGS *FixedSettings ) { MTRR_CONTEXT MtrrContext; if (!IsMtrrSupported ()) { return FixedSettings; } PreMtrrChange (&MtrrContext); MtrrSetFixedMtrrWorker (FixedSettings); PostMtrrChange (&MtrrContext); return FixedSettings; }
/** Returns the variable MTRR count for the CPU. @return Variable MTRR count **/ UINT32 EFIAPI GetVariableMtrrCount ( VOID ) { 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; }
EFIAPI MtrrSetFixedMtrr ( IN MTRR_FIXED_SETTINGS *FixedSettings ) { UINTN Cr4; if (!IsMtrrSupported ()) { return FixedSettings; } Cr4 = PreMtrrChange (); MtrrSetFixedMtrrWorker (FixedSettings); PostMtrrChange (Cr4); return FixedSettings; }
EFIAPI MtrrGetFixedMtrr ( OUT MTRR_FIXED_SETTINGS *FixedSettings ) { UINT32 Index; if (!IsMtrrSupported ()) { return FixedSettings; } for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { FixedSettings->Mtrr[Index] = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); }; return FixedSettings; }
EFIAPI MtrrGetVariableMtrr ( OUT MTRR_VARIABLE_SETTINGS *VariableSettings ) { UINT32 Index; UINT32 VariableMtrrCount; if (!IsMtrrSupported ()) { return VariableSettings; } VariableMtrrCount = GetVariableMtrrCount (); ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR); for (Index = 0; Index < VariableMtrrCount; Index++) { VariableSettings->Mtrr[Index].Base = AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1)); VariableSettings->Mtrr[Index].Mask = AsmReadMsr64 (MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (Index << 1) + 1); } return VariableSettings; }
/** This function will get the memory cache type of the specific address. This function is mainly for debug purpose. @param Address The specific address @return Memory cache type of the sepcific address **/ MTRR_MEMORY_CACHE_TYPE EFIAPI MtrrGetMemoryAttribute ( IN PHYSICAL_ADDRESS Address ) { UINT64 TempQword; UINTN Index; UINTN SubIndex; UINT64 MtrrType; UINT64 TempMtrrType; MTRR_MEMORY_CACHE_TYPE CacheType; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask; UINTN VariableMtrrCount; if (!IsMtrrSupported ()) { return CacheUncacheable; } // // Check if MTRR is enabled, if not, return UC as attribute // TempQword = AsmReadMsr64 (MTRR_LIB_IA32_MTRR_DEF_TYPE); MtrrType = MTRR_CACHE_INVALID_TYPE; if ((TempQword & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { return CacheUncacheable; } // // If address is less than 1M, then try to go through the fixed MTRR // if (Address < BASE_1MB) { if ((TempQword & MTRR_LIB_CACHE_FIXED_MTRR_ENABLED) != 0) { // // Go through the fixed MTRR // for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) { if (Address >= mMtrrLibFixedMtrrTable[Index].BaseAddress && Address < ( mMtrrLibFixedMtrrTable[Index].BaseAddress + (mMtrrLibFixedMtrrTable[Index].Length * 8) ) ) { SubIndex = ((UINTN)Address - mMtrrLibFixedMtrrTable[Index].BaseAddress) / mMtrrLibFixedMtrrTable[Index].Length; TempQword = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr); MtrrType = RShiftU64 (TempQword, SubIndex * 8) & 0xFF; return GetMemoryCacheTypeFromMtrrType (MtrrType); } } } } MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); MtrrGetMemoryAttributeInVariableMtrr( MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr ); // // Go through the variable MTRR // VariableMtrrCount = GetVariableMtrrCount (); ASSERT (VariableMtrrCount <= MTRR_NUMBER_OF_VARIABLE_MTRR); for (Index = 0; Index < VariableMtrrCount; Index++) { if (VariableMtrr[Index].Valid) { if (Address >= VariableMtrr[Index].BaseAddress && Address < VariableMtrr[Index].BaseAddress+VariableMtrr[Index].Length) { TempMtrrType = VariableMtrr[Index].Type; MtrrType = MtrrPrecedence (MtrrType, TempMtrrType); } } } CacheType = GetMemoryCacheTypeFromMtrrType (MtrrType); return CacheType; }
/** This function attempts to set the attributes for a memory range. @param BaseAddress The physical address that is the start address of a memory region. @param Length The size in bytes of the memory region. @param Attributes The bit mask of attributes to set for the memory region. @retval RETURN_SUCCESS The attributes were set for the memory region. @retval RETURN_INVALID_PARAMETER Length is zero. @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. **/ RETURN_STATUS EFIAPI MtrrSetMemoryAttribute ( IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN MTRR_MEMORY_CACHE_TYPE Attribute ) { UINT64 TempQword; RETURN_STATUS Status; UINT64 MemoryType; UINT64 Remainder; BOOLEAN OverLap; BOOLEAN Positive; UINT32 MsrNum; UINTN MtrrNumber; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT32 UsedMtrr; UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask; UINTN Cr4; BOOLEAN OverwriteExistingMtrr; UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; if (!IsMtrrSupported ()) { return RETURN_UNSUPPORTED; } FirmwareVariableMtrrCount = GetFirmwareVariableMtrrCount (); VariableMtrrEnd = MTRR_LIB_IA32_VARIABLE_MTRR_BASE + (2 * GetVariableMtrrCount ()) - 1; MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); TempQword = 0; MemoryType = (UINT64)Attribute; OverwriteExistingMtrr = FALSE; // // Check for an invalid parameter // if (Length == 0) { return RETURN_INVALID_PARAMETER; } if ( (BaseAddress &~MtrrValidAddressMask) != 0 || (Length &~MtrrValidAddressMask) != 0 ) { return RETURN_UNSUPPORTED; } // // Check if Fixed MTRR // Status = RETURN_SUCCESS; while ((BaseAddress < BASE_1MB) && (Length > 0) && Status == RETURN_SUCCESS) { Cr4 = PreMtrrChange (); Status = ProgramFixedMtrr (MemoryType, &BaseAddress, &Length); PostMtrrChange (Cr4); if (RETURN_ERROR (Status)) { return Status; } } 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; } // // Since memory ranges below 1MB will be overridden by the fixed MTRRs, // we can set the bade to 0 to save variable MTRRs. // if (BaseAddress == BASE_1MB) { BaseAddress = 0; Length += SIZE_1MB; } // // Check memory base address alignment // DivU64x64Remainder (BaseAddress, Power2MaxMemory (LShiftU64 (Length, 1)), &Remainder); if (Remainder != 0) { DivU64x64Remainder (BaseAddress, Power2MaxMemory (Length), &Remainder); if (Remainder != 0) { Status = RETURN_UNSUPPORTED; goto Done; } } // // Check for overlap // UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr); OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr); if (OverLap) { Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr); if (RETURN_ERROR (Status)) { goto Done; } if (Length == 0) { // // Combined successfully // Status = RETURN_SUCCESS; goto Done; } } // // Program Variable MTRRs // // Avoid hardcode here and read data dynamically // if (UsedMtrr >= FirmwareVariableMtrrCount) { Status = RETURN_OUT_OF_RESOURCES; goto Done; } // // The memory type is the same with the type specified by // MTRR_LIB_IA32_MTRR_DEF_TYPE. // if ((!OverwriteExistingMtrr) && (Attribute == GetMtrrDefaultMemoryType ())) { // // Invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); goto Done; } TempQword = Length; if (TempQword == Power2MaxMemory (TempQword)) { // // Invalidate the now-unused MTRRs // InvalidateMtrr(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) { break; } } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); } else { Positive = GetDirection (TempQword, &MtrrNumber); if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) { Status = RETURN_OUT_OF_RESOURCES; goto Done; } // // Invalidate the now-unused MTRRs // InvalidateMtrr(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) { break; } } if (!Positive) { Length = Power2MaxMemory (LShiftU64 (TempQword, 1)); ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); BaseAddress += Length; TempQword = Length - TempQword; MemoryType = MTRR_CACHE_UNCACHEABLE; } do { // // Find unused MTRR // for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } Length = Power2MaxMemory (TempQword); if (!Positive) { BaseAddress -= Length; } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); if (Positive) { BaseAddress += Length; } TempQword -= Length; } while (TempQword > 0); } Done: return Status; }
/** This function attempts to set the attributes for a memory range. @param BaseAddress The physical address that is the start address of a memory region. @param Length The size in bytes of the memory region. @param Attributes The bit mask of attributes to set for the memory region. @retval RETURN_SUCCESS The attributes were set for the memory region. @retval RETURN_INVALID_PARAMETER Length is zero. @retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the memory resource range specified by BaseAddress and Length. @retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource range specified by BaseAddress and Length. @retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by BaseAddress and Length cannot be modified. @retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of the memory resource range. **/ RETURN_STATUS EFIAPI MtrrSetMemoryAttribute ( IN PHYSICAL_ADDRESS BaseAddress, IN UINT64 Length, IN MTRR_MEMORY_CACHE_TYPE Attribute ) { UINT64 TempQword; RETURN_STATUS Status; UINT64 MemoryType; UINT64 Alignment; BOOLEAN OverLap; BOOLEAN Positive; UINT32 MsrNum; UINTN MtrrNumber; VARIABLE_MTRR VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; UINT32 UsedMtrr; UINT64 MtrrValidBitsMask; UINT64 MtrrValidAddressMask; BOOLEAN OverwriteExistingMtrr; UINT32 FirmwareVariableMtrrCount; UINT32 VariableMtrrEnd; MTRR_CONTEXT MtrrContext; 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; MtrrLibInitializeMtrrMask(&MtrrValidBitsMask, &MtrrValidAddressMask); TempQword = 0; MemoryType = (UINT64)Attribute; OverwriteExistingMtrr = FALSE; // // Check for an invalid parameter // if (Length == 0) { Status = RETURN_INVALID_PARAMETER; goto Done; } if ( (BaseAddress & ~MtrrValidAddressMask) != 0 || (Length & ~MtrrValidAddressMask) != 0 ) { Status = RETURN_UNSUPPORTED; goto Done; } // // 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 (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; } // // Since memory ranges below 1MB will be overridden by the fixed MTRRs, // we can set the base to 0 to save variable MTRRs. // if (BaseAddress == BASE_1MB) { BaseAddress = 0; Length += SIZE_1MB; } // // Check for overlap // UsedMtrr = MtrrGetMemoryAttributeInVariableMtrr (MtrrValidBitsMask, MtrrValidAddressMask, VariableMtrr); OverLap = CheckMemoryAttributeOverlap (BaseAddress, BaseAddress + Length - 1, VariableMtrr); if (OverLap) { Status = CombineMemoryAttribute (MemoryType, &BaseAddress, &Length, VariableMtrr, &UsedMtrr, &OverwriteExistingMtrr); if (RETURN_ERROR (Status)) { goto Done; } if (Length == 0) { // // Combined successfully, invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); Status = RETURN_SUCCESS; goto Done; } } // // The memory type is the same with the type specified by // MTRR_LIB_IA32_MTRR_DEF_TYPE. // if ((!OverwriteExistingMtrr) && (Attribute == MtrrGetDefaultMemoryType ())) { // // Invalidate the now-unused MTRRs // InvalidateMtrr(VariableMtrr); goto Done; } Positive = GetMtrrNumberAndDirection (BaseAddress, Length, &MtrrNumber); if ((UsedMtrr + MtrrNumber) > FirmwareVariableMtrrCount) { Status = RETURN_OUT_OF_RESOURCES; goto Done; } // // Invalidate the now-unused MTRRs // InvalidateMtrr(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) { break; } } if (BaseAddress != 0) { do { // // Calculate the alignment of the base address. // Alignment = LShiftU64 (1, (UINTN)LowBitSet64 (BaseAddress)); if (Alignment > Length) { break; } // // Find unused MTRR // for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } ProgramVariableMtrr ( MsrNum, BaseAddress, Alignment, MemoryType, MtrrValidAddressMask ); BaseAddress += Alignment; Length -= Alignment; } while (TRUE); if (Length == 0) { goto Done; } } TempQword = Length; if (!Positive) { Length = Power2MaxMemory (LShiftU64 (TempQword, 1)); // // Find unused MTRR // for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); BaseAddress += Length; TempQword = Length - TempQword; MemoryType = MTRR_CACHE_UNCACHEABLE; } do { // // Find unused MTRR // for (; MsrNum < VariableMtrrEnd; MsrNum += 2) { if ((AsmReadMsr64 (MsrNum + 1) & MTRR_LIB_CACHE_MTRR_ENABLED) == 0) { break; } } Length = Power2MaxMemory (TempQword); if (!Positive) { BaseAddress -= Length; } ProgramVariableMtrr ( MsrNum, BaseAddress, Length, MemoryType, MtrrValidAddressMask ); if (Positive) { BaseAddress += Length; } TempQword -= Length; } while (TempQword > 0); Done: DEBUG((DEBUG_CACHE, " Status = %r\n", Status)); if (!RETURN_ERROR (Status)) { MtrrDebugPrintAllMtrrs (); } return Status; }
/** Display the memory type registers @param [in] SocketFD The socket's file descriptor to add to the list. @param [in] pPort The WSDT_PORT structure address @param [out] pbDone Address to receive the request completion status @retval EFI_SUCCESS The request was successfully processed **/ EFI_STATUS MemoryTypeRegistersPage ( IN int SocketFD, IN WSDT_PORT * pPort, OUT BOOLEAN * pbDone ) { UINT64 Addr; BOOLEAN bValid; MSR_IA32_MTRRCAP_REGISTER Capabilities; UINTN Count; MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType; UINTN Index; UINT64 Mask; CONST UINT64 mFixedAddresses [( 8 * MTRR_NUMBER_OF_FIXED_MTRR ) + 1 ] = { 0ULL, 0x10000ULL, 0x20000ULL, 0x30000ULL, 0x40000ULL, 0x50000ULL, 0x60000ULL, 0x70000ULL, 0x80000ULL, 0x84000ULL, 0x88000ULL, 0x8c000ULL, 0x90000ULL, 0x94000ULL, 0x98000ULL, 0x9c000ULL, 0xa0000ULL, 0xa4000ULL, 0xa8000ULL, 0xac000ULL, 0xb0000ULL, 0xb4000ULL, 0xb8000ULL, 0xbc000ULL, 0xc0000ULL, 0xc1000ULL, 0xc2000ULL, 0xc3000ULL, 0xc4000ULL, 0xc5000ULL, 0xc6000ULL, 0xc7000ULL, 0xc8000ULL, 0xc9000ULL, 0xca000ULL, 0xcb000ULL, 0xcc000ULL, 0xcd000ULL, 0xce000ULL, 0xcf000ULL, 0xd0000ULL, 0xd1000ULL, 0xd2000ULL, 0xd3000ULL, 0xd4000ULL, 0xd5000ULL, 0xd6000ULL, 0xd7000ULL, 0xd8000ULL, 0xd9000ULL, 0xda000ULL, 0xdb000ULL, 0xdc000ULL, 0xdd000ULL, 0xde000ULL, 0xdf000ULL, 0xe0000ULL, 0xe1000ULL, 0xe2000ULL, 0xe3000ULL, 0xe4000ULL, 0xe5000ULL, 0xe6000ULL, 0xe7000ULL, 0xe8000ULL, 0xe9000ULL, 0xea000ULL, 0xeb000ULL, 0xec000ULL, 0xed000ULL, 0xee000ULL, 0xef000ULL, 0xf0000ULL, 0xf1000ULL, 0xf2000ULL, 0xf3000ULL, 0xf4000ULL, 0xf5000ULL, 0xf6000ULL, 0xf7000ULL, 0xf8000ULL, 0xf9000ULL, 0xfa000ULL, 0xfb000ULL, 0xfc000ULL, 0xfd000ULL, 0xfe000ULL, 0xff000ULL, 0x100000ULL }; MTRR_SETTINGS Mtrr; CONST UINT64 * pMemEnd; CONST UINT64 * pMemStart; UINT64 PreviousType; UINT64 ShiftCount; EFI_STATUS Status; UINT64 Type; INT64 Value; DBG_ENTER ( ); // // Send the Memory Type Registers page // for ( ; ; ) { // // Send the page header // Status = HttpPageHeader ( SocketFD, pPort, L"Memory Type Range Registers" ); if ( EFI_ERROR ( Status )) { break; } // // Send the header // Status = HttpSendAnsiString ( SocketFD, pPort, "<h1>Memory Type Range Registers</h1>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Determine if MTRRs are supported // if ( !IsMtrrSupported ( )) { Status = HttpSendAnsiString ( SocketFD, pPort, "<p>Memory Type Range Registers are not supported!\r\n" ); if ( EFI_ERROR ( Status )) { break; } } else { // // Get the capabilities // Capabilities.Uint64 = AsmReadMsr64 ( MSR_IA32_MTRRCAP ); DefType.Uint64 = AsmReadMsr64 ( MSR_IA32_MTRR_DEF_TYPE ); // // Display the capabilities // Status = HttpSendAnsiString ( SocketFD, pPort, "<p>Capabilities: " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Capabilities.Uint64 ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "<br>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Display the default type // Status = HttpSendAnsiString ( SocketFD, pPort, "Def Type: " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, DefType.Uint64); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", MTRRs " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ( 0 != DefType.Bits.E ) ? "Enabled" : "Disabled" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", Fixed MTRRs " ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ( 0 != DefType.Bits.FE ) ? "Enabled" : "Disabled" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, ", " ); if ( EFI_ERROR ( Status )) { break; } Type = DefType.Uint64 & 0xff; Status = HttpSendAnsiString ( SocketFD, pPort, ( DIM ( mMemoryType ) > Type ) ? mMemoryType [ Type ] : "Reserved" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendAnsiString ( SocketFD, pPort, "</p>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Determine if MTRRs are enabled // if ( 0 == DefType.Bits.E ) { Status = HttpSendAnsiString ( SocketFD, pPort, "<p>All memory is uncached!</p>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } else { // // Get the MTRRs // MtrrGetAllMtrrs ( &Mtrr ); // // Determine if the fixed MTRRs are supported // if (( 0 != Capabilities.Bits.FIX ) && ( 0 != DefType.Bits.FE)) { // // Beginning of table // Status = HttpSendAnsiString ( SocketFD, pPort, "<h2>Fixed MTRRs</h2>\r\n" "<table>\r\n" " <tr><th>Index</th><th align=\"right\">Value</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Display the fixed MTRRs // pMemStart = &mFixedAddresses[ 0 ]; for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { // // Start the row // Status = HttpSendAnsiString ( SocketFD, pPort, " <tr><td>" ); if ( EFI_ERROR ( Status )) { break; } // // Index // Status = HttpSendValue ( SocketFD, pPort, Count ); if ( EFI_ERROR ( Status )) { break; } // // Value // Status = HttpSendAnsiString ( SocketFD, pPort, "</td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Mtrr.Fixed.Mtrr[ Count ]); if ( EFI_ERROR ( Status )) { break; } // // Start // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, *pMemStart ); if ( EFI_ERROR ( Status )) { break; } pMemStart += 8; // // Value // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, *pMemStart - 1 ); if ( EFI_ERROR ( Status )) { break; } // // End of row // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } if ( EFI_ERROR ( Status )) { break; } // // End of table // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Beginning of table // Status = HttpSendAnsiString ( SocketFD, pPort, "<table>\r\n" " <tr><th align=\"right\">Start</th><th align=\"right\">End</th><th align=\"left\">Type</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Decode the fixed MTRRs // PreviousType = Mtrr.Fixed.Mtrr[ 0 ] & 0xff; pMemStart = &mFixedAddresses[ 0 ]; pMemEnd = pMemStart; for ( Count = 0; DIM ( Mtrr.Fixed.Mtrr ) > Count; Count++ ) { // // Get the memory types // Type = Mtrr.Fixed.Mtrr[ Count ]; // // Walk the memory range // for ( Index = 0; 8 > Index; Index++ ) { // // Determine if this is the same memory type // if ( PreviousType != ( Type & 0xff )) { // // Display the row // Status = MtrrDisplayFixedRow ( SocketFD, pPort, *pMemStart, *pMemEnd, PreviousType ); if ( EFI_ERROR ( Status )) { break; } // // Start the next range of addresses // pMemStart = pMemEnd; PreviousType = Type & 0xff; } // // Set the next memory range and type // Type >>= 8; pMemEnd += 1; } if ( EFI_ERROR ( Status )) { break; } } if ( EFI_ERROR ( Status )) { break; } // // Display the final row // Status = MtrrDisplayFixedRow ( SocketFD, pPort, *pMemStart, *pMemEnd, PreviousType ); if ( EFI_ERROR ( Status )) { break; } // // End of table // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } // // Determine if the variable MTRRs are supported // if ( 0 < Capabilities.Bits.VCNT ) { // // Beginning of table // Status = HttpSendAnsiString ( SocketFD, pPort, "<h2>Variable MTRRs</h2>\r\n" "<table>\r\n" " <tr><th>Index</th><th align=\"right\">Base</th><th align=\"right\">Mask</th><th align=\"right\">Start</th><th align=\"right\">End</th></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } // // Display the variable MTRRs // for ( Count = 0; Capabilities.Bits.VCNT > Count; Count++ ) { // // Start the row // Status = HttpSendAnsiString ( SocketFD, pPort, " <tr><td>" ); if ( EFI_ERROR ( Status )) { break; } // // Index // Status = HttpSendValue ( SocketFD, pPort, Count ); if ( EFI_ERROR ( Status )) { break; } // // Base // Status = HttpSendAnsiString ( SocketFD, pPort, "</td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Mtrr.Variables.Mtrr[ Count ].Base ); if ( EFI_ERROR ( Status )) { break; } // // Mask // Status = HttpSendAnsiString ( SocketFD, pPort, "</td><td align=\"right\"><code>0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Mtrr.Variables.Mtrr[ Count ].Mask ); if ( EFI_ERROR ( Status )) { break; } // // Determine if the entry is valid // bValid = ( Mtrr.Variables.Mtrr[ Count ].Mask & VARIABLE_MTRR_VALID ) ? TRUE : FALSE; // // Start // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>" ); if ( EFI_ERROR ( Status )) { break; } Addr = Mtrr.Variables.Mtrr[ Count ].Base & 0xfffffffffffff000ULL; if ( bValid ) { Status = HttpSendAnsiString ( SocketFD, pPort, "0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Addr ); } else { Status = HttpSendAnsiString ( SocketFD, pPort, "Invalid" ); } if ( EFI_ERROR ( Status )) { break; } // // End // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td align=\"right\"><code>" ); if ( EFI_ERROR ( Status )) { break; } if ( bValid ) { // // Determine the end address // Mask = Mtrr.Variables.Mtrr[ Count ].Mask; Value = Mask; ShiftCount = 0; while ( 0 < Value ) { Value <<= 1; ShiftCount += 1; } Value = 1; Value <<= 64 - ShiftCount; Value -= 1; Value = ~Value; Value |= Mask; Value &= ~VARIABLE_MTRR_VALID; Value = ~Value; Status = HttpSendAnsiString ( SocketFD, pPort, "0x" ); if ( EFI_ERROR ( Status )) { break; } Status = HttpSendHexValue ( SocketFD, pPort, Addr + Value ); } if ( EFI_ERROR ( Status )) { break; } // // Type // Status = HttpSendAnsiString ( SocketFD, pPort, "</code></td><td>" ); if ( EFI_ERROR ( Status )) { break; } if ( bValid ) { Type = Mtrr.Variables.Mtrr[ Count ].Base & 0xFF; Status = HttpSendAnsiString ( SocketFD, pPort, ( DIM ( mMemoryType ) > Type ) ? mMemoryType [ Type ] : "Reserved" ); } if ( EFI_ERROR ( Status )) { break; } // // End of row // Status = HttpSendAnsiString ( SocketFD, pPort, "</td></tr>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } if ( EFI_ERROR ( Status )) { break; } // // End of table // Status = HttpSendAnsiString ( SocketFD, pPort, "</table>\r\n" ); if ( EFI_ERROR ( Status )) { break; } } } } // // Send the page trailer // Status = HttpPageTrailer ( SocketFD, pPort, pbDone ); break; }