diff options
Diffstat (limited to 'ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c')
-rw-r--r-- | ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c | 338 |
1 files changed, 338 insertions, 0 deletions
diff --git a/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c b/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c new file mode 100644 index 0000000..a696e6b --- /dev/null +++ b/ReferenceCode/Haswell/CpuInit/Dxe/MtrrSync.c @@ -0,0 +1,338 @@ +/** @file + Code which support multi-processor + +@copyright + Copyright (c) 1999 - 2012 Intel Corporation. All rights reserved + This software and associated documentation (if any) is furnished + under a license and may only be used or copied in accordance + with the terms of the license. Except as permitted by such + license, no part of this software or documentation may be + reproduced, stored in a retrieval system, or transmitted in any + form or by any means without the express written consent of + Intel Corporation. + + This file contains an 'Intel Peripheral Driver' and is + licensed for Intel CPUs and chipsets under the terms of your + license agreement with Intel or your vendor. This file may + be modified by the user, subject to additional terms of the + license agreement +**/ +#if !defined(EDK_RELEASE_VERSION) || (EDK_RELEASE_VERSION < 0x00020000) +#include "EdkIIGlueDxe.h" +#include "MpService.h" +#endif + +extern MP_SYSTEM_DATA *mMPSystemData; + +EFI_MTRR_VALUES mFixedMtrrValues[] = { + { + IA32_MTRR_FIX64K_00000, + 0 + }, + { + IA32_MTRR_FIX16K_80000, + 0 + }, + { + IA32_MTRR_FIX16K_A0000, + 0 + }, + { + IA32_MTRR_FIX4K_C0000, + 0 + }, + { + IA32_MTRR_FIX4K_C8000, + 0 + }, + { + IA32_MTRR_FIX4K_D0000, + 0 + }, + { + IA32_MTRR_FIX4K_D8000, + 0 + }, + { + IA32_MTRR_FIX4K_E0000, + 0 + }, + { + IA32_MTRR_FIX4K_E8000, + 0 + }, + { + IA32_MTRR_FIX4K_F0000, + 0 + }, + { + IA32_MTRR_FIX4K_F8000, + 0 + } +}; + +EFI_MTRR_VALUES mMtrrDefType[] = { { CACHE_IA32_MTRR_DEF_TYPE, 0 } }; + +/// +/// Pre-defined Variable MTRR number to 20 +/// +EFI_MTRR_VALUES mVariableMtrrValues[] = { + { + CACHE_VARIABLE_MTRR_BASE, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 1, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 2, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 3, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 4, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 5, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 6, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 7, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 8, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 9, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 10, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 11, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 12, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 13, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 14, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 15, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 16, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 17, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 18, + 0 + }, + { + CACHE_VARIABLE_MTRR_BASE + 19, + 0 + } +}; + +/** + Save the MTRR registers to global variables +**/ +VOID +ReadMtrrRegisters ( + VOID + ) +{ + + UINT32 Index; + UINT32 VariableMtrrLimit; + + VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT); + /// + /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR + /// + ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER); + if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) { + VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER; + } + /// + /// Read Fixed Mtrrs + /// + for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) { + mFixedMtrrValues[Index].Value = AsmReadMsr64 (mFixedMtrrValues[Index].Index); + } + /// + /// Read def type Fixed Mtrrs + /// + mMtrrDefType[0].Value = AsmReadMsr64 (CACHE_IA32_MTRR_DEF_TYPE); + + /// + /// Read Variable Mtrr + /// + for (Index = 0; Index < VariableMtrrLimit * 2; Index++) { + mVariableMtrrValues[Index].Value = AsmReadMsr64 (mVariableMtrrValues[Index].Index); + } + + return; +} + +/** + Synch up the MTRR values for all processors + + @param[in] Buffer - Not used. +**/ +VOID +EFIAPI +MpMtrrSynchUp ( + IN VOID *Buffer + ) +{ + UINT32 Index; + UINTN Cr4; + UINT64 MsrValue; + UINT64 ValidMtrrAddressMask; + EFI_CPUID_REGISTER FeatureInfo; + EFI_CPUID_REGISTER FunctionInfo; + UINT8 PhysicalAddressBits; + UINT32 VariableMtrrLimit; + + VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT); + /// + /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR + /// + ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER); + if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) { + VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER; + } + /// + /// ASM code to setup processor register before synching up the MTRRs + /// + Cr4 = MpMtrrSynchUpEntry (); + + /// + /// Get physical CPU MTRR width in case of difference from BSP + /// + AsmCpuid ( + CPUID_EXTENDED_FUNCTION, + &FunctionInfo.RegEax, + &FunctionInfo.RegEbx, + &FunctionInfo.RegEcx, + &FunctionInfo.RegEdx + ); + PhysicalAddressBits = 36; + if (FunctionInfo.RegEax >= CPUID_VIR_PHY_ADDRESS_SIZE) { + AsmCpuid ( + CPUID_VIR_PHY_ADDRESS_SIZE, + &FeatureInfo.RegEax, + &FeatureInfo.RegEbx, + &FeatureInfo.RegEcx, + &FeatureInfo.RegEdx + ); + PhysicalAddressBits = (UINT8) FeatureInfo.RegEax; + } + + ValidMtrrAddressMask = ((((UINT64) 1) << PhysicalAddressBits) - 1) & 0xfffffffffffff000; + + /// + /// Disable Fixed Mtrrs + /// + AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value & 0xFFFFF7FF); + + /// + /// Update Fixed Mtrrs + /// + for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) { + AsmWriteMsr64 (mFixedMtrrValues[Index].Index, mFixedMtrrValues[Index].Value); + } + /// + /// Synchup def type Fixed Mtrrs + /// + AsmWriteMsr64 (CACHE_IA32_MTRR_DEF_TYPE, mMtrrDefType[0].Value); + + /// + /// Synchup Base Variable Mtrr + /// + for (Index = 0; Index < VariableMtrrLimit * 2 - 1; Index += 2) { + MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask); + AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue); + } + /// + /// Synchup Mask Variable Mtrr including valid bit + /// + for (Index = 1; Index < VariableMtrrLimit * 2; Index += 2) { + MsrValue = (mVariableMtrrValues[Index].Value & 0x0FFF) | (mVariableMtrrValues[Index].Value & ValidMtrrAddressMask); + AsmWriteMsr64 (mVariableMtrrValues[Index].Index, MsrValue); + } + /// + /// ASM code to setup processor register after synching up the MTRRs + /// + MpMtrrSynchUpExit (Cr4); + + return; +} + +/** + Copy Global MTRR data to S3 +**/ +VOID +SaveBspMtrrForS3 ( + VOID + ) +{ + UINTN Index; + UINTN TableIndex; + UINT32 VariableMtrrLimit; + + VariableMtrrLimit = (UINT32) (AsmReadMsr64 (IA32_MTRR_CAP) & B_IA32_MTRR_VARIABLE_SUPPORT); + /// + /// Only support MAXIMUM_VARIABLE_MTRR_NUMBER variable MTRR + /// + ASSERT (VariableMtrrLimit <= V_MAXIMUM_VARIABLE_MTRR_NUMBER); + if (VariableMtrrLimit > V_MAXIMUM_VARIABLE_MTRR_NUMBER) { + VariableMtrrLimit = V_MAXIMUM_VARIABLE_MTRR_NUMBER; + } + + TableIndex = 0; + for (Index = 0; Index < sizeof (mFixedMtrrValues) / sizeof (EFI_MTRR_VALUES); Index++) { + mMPSystemData->S3BspMtrrTable[TableIndex].Index = mFixedMtrrValues[Index].Index; + mMPSystemData->S3BspMtrrTable[TableIndex].Value = mFixedMtrrValues[Index].Value; + TableIndex++; + } + + for (Index = 0; Index < VariableMtrrLimit * 2; Index++) { + mMPSystemData->S3BspMtrrTable[TableIndex].Index = mVariableMtrrValues[Index].Index; + mMPSystemData->S3BspMtrrTable[TableIndex].Value = mVariableMtrrValues[Index].Value; + TableIndex++; + } + + mMPSystemData->S3BspMtrrTable[TableIndex].Index = CACHE_IA32_MTRR_DEF_TYPE; + mMPSystemData->S3BspMtrrTable[TableIndex].Value = mMtrrDefType[0].Value; + + ASSERT (TableIndex < MAX_CPU_S3_MTRR_ENTRY); + + return; +} |