audk/UefiCpuPkg/Library/MtrrLib/MtrrLib.c

2899 lines
90 KiB
C
Raw Normal View History

/** @file
MTRR setting library
@par Note:
Most of services in this library instance are suggested to be invoked by BSP only,
except for MtrrSetAllMtrrs() which is used to sync BSP's MTRR setting to APs.
Copyright (c) 2008 - 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
#include <Uefi.h>
#include <Register/Intel/Cpuid.h>
#include <Register/Intel/Msr.h>
#include <Library/MtrrLib.h>
#include <Library/BaseLib.h>
#include <Library/CpuLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/DebugLib.h>
#define OR_SEED 0x0101010101010101ull
#define CLEAR_SEED 0xFFFFFFFFFFFFFFFFull
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
#define MAX_WEIGHT MAX_UINT8
#define SCRATCH_BUFFER_SIZE (4 * SIZE_4KB)
#define MTRR_LIB_ASSERT_ALIGNED(B, L) ASSERT ((B & ~(L - 1)) == B);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
#define M(x,y) ((x) * VertexCount + (y))
#define O(x,y) ((y) * VertexCount + (x))
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Context to save and restore when MTRRs are programmed
//
typedef struct {
UINTN Cr4;
BOOLEAN InterruptState;
} MTRR_CONTEXT;
typedef struct {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT64 Address;
UINT64 Alignment;
UINT64 Length;
MTRR_MEMORY_CACHE_TYPE Type : 7;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Temprary use for calculating the best MTRR settings.
//
BOOLEAN Visited : 1;
UINT8 Weight;
UINT16 Previous;
} MTRR_LIB_ADDRESS;
//
// This table defines the offset, base and length of the fixed MTRRs
//
CONST FIXED_MTRR mMtrrLibFixedMtrrTable[] = {
{
MSR_IA32_MTRR_FIX64K_00000,
0,
SIZE_64KB
},
{
MSR_IA32_MTRR_FIX16K_80000,
0x80000,
SIZE_16KB
},
{
MSR_IA32_MTRR_FIX16K_A0000,
0xA0000,
SIZE_16KB
},
{
MSR_IA32_MTRR_FIX4K_C0000,
0xC0000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_C8000,
0xC8000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_D0000,
0xD0000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_D8000,
0xD8000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_E0000,
0xE0000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_E8000,
0xE8000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_F0000,
0xF0000,
SIZE_4KB
},
{
MSR_IA32_MTRR_FIX4K_F8000,
0xF8000,
SIZE_4KB
}
};
//
// 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
};
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Worker function prints all MTRRs for debugging.
If MtrrSetting is not NULL, print MTRR settings from input MTRR
settings buffer.
If MtrrSetting is NULL, print MTRR settings from MTRRs.
@param MtrrSetting A buffer holding all MTRRs content.
**/
VOID
MtrrDebugPrintAllMtrrsWorker (
IN MTRR_SETTINGS *MtrrSetting
);
/**
Worker function returns the variable MTRR count for the CPU.
@return Variable MTRR count
**/
UINT32
GetVariableMtrrCountWorker (
VOID
)
{
MSR_IA32_MTRRCAP_REGISTER MtrrCap;
MtrrCap.Uint64 = AsmReadMsr64 (MSR_IA32_MTRRCAP);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (MtrrCap.Bits.VCNT <= ARRAY_SIZE (((MTRR_VARIABLE_SETTINGS *) 0)->Mtrr));
return MtrrCap.Bits.VCNT;
}
/**
Returns the variable MTRR count for the CPU.
@return Variable MTRR count
**/
UINT32
EFIAPI
GetVariableMtrrCount (
VOID
)
{
if (!IsMtrrSupported ()) {
return 0;
}
return GetVariableMtrrCountWorker ();
}
/**
Worker function returns the firmware usable variable MTRR count for the CPU.
@return Firmware usable variable MTRR count
**/
UINT32
GetFirmwareVariableMtrrCountWorker (
VOID
)
{
UINT32 VariableMtrrCount;
UINT32 ReservedMtrrNumber;
VariableMtrrCount = GetVariableMtrrCountWorker ();
ReservedMtrrNumber = PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
if (VariableMtrrCount < ReservedMtrrNumber) {
return 0;
}
return VariableMtrrCount - ReservedMtrrNumber;
}
/**
Returns the firmware usable variable MTRR count for the CPU.
@return Firmware usable variable MTRR count
**/
UINT32
EFIAPI
GetFirmwareVariableMtrrCount (
VOID
)
{
if (!IsMtrrSupported ()) {
return 0;
}
return GetFirmwareVariableMtrrCountWorker ();
}
/**
Worker function returns the default MTRR cache type for the system.
If MtrrSetting is not NULL, returns the default MTRR cache type from input
MTRR settings buffer.
If MtrrSetting is NULL, returns the default MTRR cache type from MSR.
@param[in] MtrrSetting A buffer holding all MTRRs content.
@return The default MTRR cache type.
**/
MTRR_MEMORY_CACHE_TYPE
MtrrGetDefaultMemoryTypeWorker (
IN MTRR_SETTINGS *MtrrSetting
)
{
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
if (MtrrSetting == NULL) {
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
} else {
DefType.Uint64 = MtrrSetting->MtrrDefType;
}
return (MTRR_MEMORY_CACHE_TYPE) DefType.Bits.Type;
}
/**
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 MtrrGetDefaultMemoryTypeWorker (NULL);
}
/**
Preparation before programming MTRR.
This function will do some preparation for programming MTRRs:
disable cache, invalid cache and disable MTRR caching functionality
@param[out] MtrrContext Pointer to context to save
**/
VOID
MtrrLibPreMtrrChange (
OUT MTRR_CONTEXT *MtrrContext
)
{
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
//
// Disable interrupts and save current interrupt state
//
MtrrContext->InterruptState = SaveAndDisableInterrupts();
//
// Enter no fill cache mode, CD=1(Bit30), NW=0 (Bit29)
//
AsmDisableCache ();
//
// Save original CR4 value and clear PGE flag (Bit 7)
//
MtrrContext->Cr4 = AsmReadCr4 ();
AsmWriteCr4 (MtrrContext->Cr4 & (~BIT7));
//
// Flush all TLBs
//
CpuFlushTlb ();
//
// Disable MTRRs
//
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
DefType.Bits.E = 0;
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
}
/**
Cleaning up after programming MTRRs.
This function will do some clean up after programming MTRRs:
Flush all TLBs, re-enable caching, restore CR4.
@param[in] MtrrContext Pointer to context to restore
**/
VOID
MtrrLibPostMtrrChangeEnableCache (
IN MTRR_CONTEXT *MtrrContext
)
{
//
// Flush all TLBs
//
CpuFlushTlb ();
//
// Enable Normal Mode caching CD=NW=0, CD(Bit30), NW(Bit29)
//
AsmEnableCache ();
//
// Restore original CR4 value
//
AsmWriteCr4 (MtrrContext->Cr4);
//
// Restore original interrupt state
//
SetInterruptState (MtrrContext->InterruptState);
}
/**
Cleaning up after programming MTRRs.
This function will do some clean up after programming MTRRs:
enable MTRR caching functionality, and enable cache
@param[in] MtrrContext Pointer to context to restore
**/
VOID
MtrrLibPostMtrrChange (
IN MTRR_CONTEXT *MtrrContext
)
{
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
//
// Enable Cache MTRR
//
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
DefType.Bits.E = 1;
DefType.Bits.FE = 1;
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, DefType.Uint64);
MtrrLibPostMtrrChangeEnableCache (MtrrContext);
}
/**
Worker function gets the content in fixed MTRRs
@param[out] FixedSettings A buffer to hold fixed MTRRs content.
@retval The pointer of FixedSettings
**/
MTRR_FIXED_SETTINGS*
MtrrGetFixedMtrrWorker (
OUT MTRR_FIXED_SETTINGS *FixedSettings
)
{
UINT32 Index;
for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
FixedSettings->Mtrr[Index] =
AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
}
return FixedSettings;
}
/**
This function gets the content in fixed MTRRs
@param[out] FixedSettings A buffer to hold fixed MTRRs content.
@retval The pointer of FixedSettings
**/
MTRR_FIXED_SETTINGS*
EFIAPI
MtrrGetFixedMtrr (
OUT MTRR_FIXED_SETTINGS *FixedSettings
)
{
if (!IsMtrrSupported ()) {
return FixedSettings;
}
return MtrrGetFixedMtrrWorker (FixedSettings);
}
/**
Worker function will get the raw value in variable MTRRs
If MtrrSetting is not NULL, gets the variable MTRRs raw value from input
MTRR settings buffer.
If MtrrSetting is NULL, gets the variable MTRRs raw value from MTRRs.
@param[in] MtrrSetting A buffer holding all MTRRs content.
@param[in] VariableMtrrCount Number of variable MTRRs.
@param[out] VariableSettings A buffer to hold variable MTRRs content.
@return The VariableSettings input pointer
**/
MTRR_VARIABLE_SETTINGS*
MtrrGetVariableMtrrWorker (
IN MTRR_SETTINGS *MtrrSetting,
IN UINT32 VariableMtrrCount,
OUT MTRR_VARIABLE_SETTINGS *VariableSettings
)
{
UINT32 Index;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (VariableMtrrCount <= ARRAY_SIZE (VariableSettings->Mtrr));
for (Index = 0; Index < VariableMtrrCount; Index++) {
if (MtrrSetting == NULL) {
VariableSettings->Mtrr[Index].Base =
AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1));
VariableSettings->Mtrr[Index].Mask =
AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1));
} else {
VariableSettings->Mtrr[Index].Base = MtrrSetting->Variables.Mtrr[Index].Base;
VariableSettings->Mtrr[Index].Mask = MtrrSetting->Variables.Mtrr[Index].Mask;
}
}
return VariableSettings;
}
/**
This function will get the raw value in variable MTRRs
@param[out] VariableSettings A buffer to hold variable MTRRs content.
@return The VariableSettings input pointer
**/
MTRR_VARIABLE_SETTINGS*
EFIAPI
MtrrGetVariableMtrr (
OUT MTRR_VARIABLE_SETTINGS *VariableSettings
)
{
if (!IsMtrrSupported ()) {
return VariableSettings;
}
return MtrrGetVariableMtrrWorker (
NULL,
GetVariableMtrrCountWorker (),
VariableSettings
);
}
/**
Programs fixed MTRRs registers.
@param[in] Type 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[in, out] LastMsrIndex On input, the last index of the fixed MTRR MSR to program.
On return, the current index of the fixed MTRR MSR to program.
@param[out] ClearMask The bits to clear in the fixed MTRR MSR.
@param[out] OrMask 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
for the fixed MTRRs.
**/
RETURN_STATUS
MtrrLibProgramFixedMtrr (
IN MTRR_MEMORY_CACHE_TYPE Type,
IN OUT UINT64 *Base,
IN OUT UINT64 *Length,
IN OUT UINT32 *LastMsrIndex,
OUT UINT64 *ClearMask,
OUT UINT64 *OrMask
)
{
UINT32 MsrIndex;
UINT32 LeftByteShift;
UINT32 RightByteShift;
UINT64 SubLength;
//
// Find the fixed MTRR index to be programmed
//
for (MsrIndex = *LastMsrIndex + 1; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {
if ((*Base >= mMtrrLibFixedMtrrTable[MsrIndex].BaseAddress) &&
(*Base <
(
mMtrrLibFixedMtrrTable[MsrIndex].BaseAddress +
(8 * mMtrrLibFixedMtrrTable[MsrIndex].Length)
)
)
) {
break;
}
}
ASSERT (MsrIndex != ARRAY_SIZE (mMtrrLibFixedMtrrTable));
//
// Find the begin offset in fixed MTRR and calculate byte offset of left shift
//
if ((((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrIndex].BaseAddress) % mMtrrLibFixedMtrrTable[MsrIndex].Length) != 0) {
//
// Base address should be aligned to the begin of a certain Fixed MTRR range.
//
return RETURN_UNSUPPORTED;
}
LeftByteShift = ((UINT32)*Base - mMtrrLibFixedMtrrTable[MsrIndex].BaseAddress) / mMtrrLibFixedMtrrTable[MsrIndex].Length;
ASSERT (LeftByteShift < 8);
//
// Find the end offset in fixed MTRR and calculate byte offset of right shift
//
SubLength = mMtrrLibFixedMtrrTable[MsrIndex].Length * (8 - LeftByteShift);
if (*Length >= SubLength) {
RightByteShift = 0;
} else {
if (((UINT32)(*Length) % mMtrrLibFixedMtrrTable[MsrIndex].Length) != 0) {
//
// Length should be aligned to the end of a certain Fixed MTRR range.
//
return RETURN_UNSUPPORTED;
}
RightByteShift = 8 - LeftByteShift - (UINT32)(*Length) / mMtrrLibFixedMtrrTable[MsrIndex].Length;
//
// Update SubLength by actual length
//
SubLength = *Length;
}
*ClearMask = CLEAR_SEED;
*OrMask = MultU64x32 (OR_SEED, (UINT32) Type);
if (LeftByteShift != 0) {
//
// Clear the low bits by LeftByteShift
//
*ClearMask &= LShiftU64 (*ClearMask, LeftByteShift * 8);
*OrMask &= LShiftU64 (*OrMask, LeftByteShift * 8);
}
if (RightByteShift != 0) {
//
// Clear the high bits by RightByteShift
//
*ClearMask &= RShiftU64 (*ClearMask, RightByteShift * 8);
*OrMask &= RShiftU64 (*OrMask, RightByteShift * 8);
}
*Length -= SubLength;
*Base += SubLength;
*LastMsrIndex = MsrIndex;
return RETURN_SUCCESS;
}
/**
Worker function gets the attribute of variable MTRRs.
This function shadows the content of variable MTRRs into an
internal array: VariableMtrr.
@param[in] VariableSettings The variable MTRR values to shadow
@param[in] VariableMtrrCount The number of variable MTRRs
@param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
@param[in] MtrrValidAddressMask The valid address mask for MTRR
@param[out] VariableMtrr The array to shadow variable MTRRs content
@return Number of MTRRs which has been used.
**/
UINT32
MtrrGetMemoryAttributeInVariableMtrrWorker (
IN MTRR_VARIABLE_SETTINGS *VariableSettings,
IN UINTN VariableMtrrCount,
IN UINT64 MtrrValidBitsMask,
IN UINT64 MtrrValidAddressMask,
OUT VARIABLE_MTRR *VariableMtrr
)
{
UINTN Index;
UINT32 UsedMtrr;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ZeroMem (VariableMtrr, sizeof (VARIABLE_MTRR) * ARRAY_SIZE (VariableSettings->Mtrr));
for (Index = 0, UsedMtrr = 0; Index < VariableMtrrCount; Index++) {
if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {
VariableMtrr[Index].Msr = (UINT32)Index;
VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
VariableMtrr[Index].Length =
((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
VariableMtrr[Index].Type = (VariableSettings->Mtrr[Index].Base & 0x0ff);
VariableMtrr[Index].Valid = TRUE;
VariableMtrr[Index].Used = TRUE;
UsedMtrr++;
}
}
return UsedMtrr;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Convert variable MTRRs to a RAW MTRR_MEMORY_RANGE array.
One MTRR_MEMORY_RANGE element is created for each MTRR setting.
The routine doesn't remove the overlap or combine the near-by region.
@param[in] VariableSettings The variable MTRR values to shadow
@param[in] VariableMtrrCount The number of variable MTRRs
@param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
@param[in] MtrrValidAddressMask The valid address mask for MTRR
@param[out] VariableMtrr The array to shadow variable MTRRs content
@return Number of MTRRs which has been used.
**/
UINT32
MtrrLibGetRawVariableRanges (
IN MTRR_VARIABLE_SETTINGS *VariableSettings,
IN UINTN VariableMtrrCount,
IN UINT64 MtrrValidBitsMask,
IN UINT64 MtrrValidAddressMask,
OUT MTRR_MEMORY_RANGE *VariableMtrr
)
{
UINTN Index;
UINT32 UsedMtrr;
ZeroMem (VariableMtrr, sizeof (MTRR_MEMORY_RANGE) * ARRAY_SIZE (VariableSettings->Mtrr));
for (Index = 0, UsedMtrr = 0; Index < VariableMtrrCount; Index++) {
if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &VariableSettings->Mtrr[Index].Mask)->Bits.V != 0) {
VariableMtrr[Index].BaseAddress = (VariableSettings->Mtrr[Index].Base & MtrrValidAddressMask);
VariableMtrr[Index].Length =
((~(VariableSettings->Mtrr[Index].Mask & MtrrValidAddressMask)) & MtrrValidBitsMask) + 1;
VariableMtrr[Index].Type = (MTRR_MEMORY_CACHE_TYPE)(VariableSettings->Mtrr[Index].Base & 0x0ff);
UsedMtrr++;
}
}
return UsedMtrr;
}
/**
Gets the attribute of variable MTRRs.
This function shadows the content of variable MTRRs into an
internal array: VariableMtrr.
@param[in] MtrrValidBitsMask The mask for the valid bit of the MTRR
@param[in] MtrrValidAddressMask The valid address mask for MTRR
@param[out] VariableMtrr The array to shadow variable MTRRs content
@return The return value of this parameter indicates the
number of MTRRs which has been used.
**/
UINT32
EFIAPI
MtrrGetMemoryAttributeInVariableMtrr (
IN UINT64 MtrrValidBitsMask,
IN UINT64 MtrrValidAddressMask,
OUT VARIABLE_MTRR *VariableMtrr
)
{
MTRR_VARIABLE_SETTINGS VariableSettings;
if (!IsMtrrSupported ()) {
return 0;
}
MtrrGetVariableMtrrWorker (
NULL,
GetVariableMtrrCountWorker (),
&VariableSettings
);
return MtrrGetMemoryAttributeInVariableMtrrWorker (
&VariableSettings,
GetFirmwareVariableMtrrCountWorker (),
MtrrValidBitsMask,
MtrrValidAddressMask,
VariableMtrr
);
}
/**
Return the biggest alignment (lowest set bit) of address.
The function is equivalent to: 1 << LowBitSet64 (Address).
@param Address The address to return the alignment.
@param Alignment0 The alignment to return when Address is 0.
@return The least alignment of the Address.
**/
UINT64
MtrrLibBiggestAlignment (
UINT64 Address,
UINT64 Alignment0
)
{
if (Address == 0) {
return Alignment0;
}
return Address & ((~Address) + 1);
}
/**
Return whether the left MTRR type precedes the right MTRR type.
The MTRR type precedence rules are:
1. UC precedes any other type
2. WT precedes WB
For further details, please refer the IA32 Software Developer's Manual,
Volume 3, Section "MTRR Precedences".
@param Left The left MTRR type.
@param Right The right MTRR type.
@retval TRUE Left precedes Right.
@retval FALSE Left doesn't precede Right.
**/
BOOLEAN
MtrrLibTypeLeftPrecedeRight (
IN MTRR_MEMORY_CACHE_TYPE Left,
IN MTRR_MEMORY_CACHE_TYPE Right
)
{
return (BOOLEAN) (Left == CacheUncacheable || (Left == CacheWriteThrough && Right == CacheWriteBack));
}
/**
Initializes the valid bits mask and valid address mask for MTRRs.
This function initializes the valid bits mask and valid address mask for MTRRs.
@param[out] MtrrValidBitsMask The mask for the valid bit of the MTRR
@param[out] MtrrValidAddressMask The valid address mask for the MTRR
**/
VOID
MtrrLibInitializeMtrrMask (
OUT UINT64 *MtrrValidBitsMask,
OUT UINT64 *MtrrValidAddressMask
)
{
UINT32 MaxExtendedFunction;
CPUID_VIR_PHY_ADDRESS_SIZE_EAX VirPhyAddressSize;
AsmCpuid (CPUID_EXTENDED_FUNCTION, &MaxExtendedFunction, NULL, NULL, NULL);
if (MaxExtendedFunction >= CPUID_VIR_PHY_ADDRESS_SIZE) {
AsmCpuid (CPUID_VIR_PHY_ADDRESS_SIZE, &VirPhyAddressSize.Uint32, NULL, NULL, NULL);
} else {
VirPhyAddressSize.Bits.PhysicalAddressBits = 36;
}
*MtrrValidBitsMask = LShiftU64 (1, VirPhyAddressSize.Bits.PhysicalAddressBits) - 1;
*MtrrValidAddressMask = *MtrrValidBitsMask & 0xfffffffffffff000ULL;
}
/**
Determines the real attribute of a memory range.
This function is to arbitrate the real attribute of the memory when
there are 2 MTRRs covers the same memory range. For further details,
please refer the IA32 Software Developer's Manual, Volume 3,
Section "MTRR Precedences".
@param[in] MtrrType1 The first kind of Memory type
@param[in] MtrrType2 The second kind of memory type
**/
MTRR_MEMORY_CACHE_TYPE
MtrrLibPrecedence (
IN MTRR_MEMORY_CACHE_TYPE MtrrType1,
IN MTRR_MEMORY_CACHE_TYPE MtrrType2
)
{
if (MtrrType1 == MtrrType2) {
return MtrrType1;
}
ASSERT (
MtrrLibTypeLeftPrecedeRight (MtrrType1, MtrrType2) ||
MtrrLibTypeLeftPrecedeRight (MtrrType2, MtrrType1)
);
if (MtrrLibTypeLeftPrecedeRight (MtrrType1, MtrrType2)) {
return MtrrType1;
} else {
return MtrrType2;
}
}
/**
Worker function will get the memory cache type of the specific address.
If MtrrSetting is not NULL, gets the memory cache type from input
MTRR settings buffer.
If MtrrSetting is NULL, gets the memory cache type from MTRRs.
@param[in] MtrrSetting A buffer holding all MTRRs content.
@param[in] Address The specific address
@return Memory cache type of the specific address
**/
MTRR_MEMORY_CACHE_TYPE
MtrrGetMemoryAttributeByAddressWorker (
IN MTRR_SETTINGS *MtrrSetting,
IN PHYSICAL_ADDRESS Address
)
{
MSR_IA32_MTRR_DEF_TYPE_REGISTER DefType;
UINT64 FixedMtrr;
UINTN Index;
UINTN SubIndex;
MTRR_MEMORY_CACHE_TYPE MtrrType;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MTRR_MEMORY_RANGE VariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
UINT64 MtrrValidBitsMask;
UINT64 MtrrValidAddressMask;
UINT32 VariableMtrrCount;
MTRR_VARIABLE_SETTINGS VariableSettings;
//
// Check if MTRR is enabled, if not, return UC as attribute
//
if (MtrrSetting == NULL) {
DefType.Uint64 = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
} else {
DefType.Uint64 = MtrrSetting->MtrrDefType;
}
if (DefType.Bits.E == 0) {
return CacheUncacheable;
}
//
// If address is less than 1M, then try to go through the fixed MTRR
//
if (Address < BASE_1MB) {
if (DefType.Bits.FE != 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;
if (MtrrSetting == NULL) {
FixedMtrr = AsmReadMsr64 (mMtrrLibFixedMtrrTable[Index].Msr);
} else {
FixedMtrr = MtrrSetting->Fixed.Mtrr[Index];
}
return (MTRR_MEMORY_CACHE_TYPE) (RShiftU64 (FixedMtrr, SubIndex * 8) & 0xFF);
}
}
}
}
VariableMtrrCount = GetVariableMtrrCountWorker ();
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (VariableMtrrCount <= ARRAY_SIZE (MtrrSetting->Variables.Mtrr));
MtrrGetVariableMtrrWorker (MtrrSetting, VariableMtrrCount, &VariableSettings);
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibGetRawVariableRanges (
&VariableSettings,
VariableMtrrCount,
MtrrValidBitsMask,
MtrrValidAddressMask,
VariableMtrr
);
//
// Go through the variable MTRR
//
MtrrType = CacheInvalid;
for (Index = 0; Index < VariableMtrrCount; Index++) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (VariableMtrr[Index].Length != 0) {
if (Address >= VariableMtrr[Index].BaseAddress &&
Address < VariableMtrr[Index].BaseAddress + VariableMtrr[Index].Length) {
if (MtrrType == CacheInvalid) {
MtrrType = (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type;
} else {
MtrrType = MtrrLibPrecedence (MtrrType, (MTRR_MEMORY_CACHE_TYPE) VariableMtrr[Index].Type);
}
}
}
}
//
// If there is no MTRR which covers the Address, use the default MTRR type.
//
if (MtrrType == CacheInvalid) {
MtrrType = (MTRR_MEMORY_CACHE_TYPE) DefType.Bits.Type;
}
return MtrrType;
}
/**
This function will get the memory cache type of the specific address.
This function is mainly for debug purpose.
@param[in] Address The specific address
@return Memory cache type of the specific address
**/
MTRR_MEMORY_CACHE_TYPE
EFIAPI
MtrrGetMemoryAttribute (
IN PHYSICAL_ADDRESS Address
)
{
if (!IsMtrrSupported ()) {
return CacheUncacheable;
}
return MtrrGetMemoryAttributeByAddressWorker (NULL, Address);
}
/**
Update the Ranges array to change the specified range identified by
BaseAddress and Length to Type.
@param Ranges Array holding memory type settings for all memory regions.
@param Capacity The maximum count of memory ranges the array can hold.
@param Count Return the new memory range count in the array.
@param BaseAddress The base address of the memory range to change type.
@param Length The length of the memory range to change type.
@param Type The new type of the specified memory range.
@retval RETURN_SUCCESS The type of the specified memory range is
changed successfully.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval RETURN_ALREADY_STARTED The type of the specified memory range equals
to the desired type.
@retval RETURN_OUT_OF_RESOURCES The new type set causes the count of memory
range exceeds capacity.
**/
RETURN_STATUS
MtrrLibSetMemoryType (
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
IN MTRR_MEMORY_RANGE *Ranges,
IN UINTN Capacity,
IN OUT UINTN *Count,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Type
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINTN Index;
UINT64 Limit;
UINT64 LengthLeft;
UINT64 LengthRight;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINTN StartIndex;
UINTN EndIndex;
UINTN DeltaCount;
LengthRight = 0;
LengthLeft = 0;
Limit = BaseAddress + Length;
StartIndex = *Count;
EndIndex = *Count;
for (Index = 0; Index < *Count; Index++) {
if ((StartIndex == *Count) &&
(Ranges[Index].BaseAddress <= BaseAddress) &&
(BaseAddress < Ranges[Index].BaseAddress + Ranges[Index].Length)) {
StartIndex = Index;
LengthLeft = BaseAddress - Ranges[Index].BaseAddress;
}
if ((EndIndex == *Count) &&
(Ranges[Index].BaseAddress < Limit) &&
(Limit <= Ranges[Index].BaseAddress + Ranges[Index].Length)) {
EndIndex = Index;
LengthRight = Ranges[Index].BaseAddress + Ranges[Index].Length - Limit;
break;
}
}
ASSERT (StartIndex != *Count && EndIndex != *Count);
if (StartIndex == EndIndex && Ranges[StartIndex].Type == Type) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
return RETURN_ALREADY_STARTED;
}
//
// The type change may cause merging with previous range or next range.
// Update the StartIndex, EndIndex, BaseAddress, Length so that following
// logic doesn't need to consider merging.
//
if (StartIndex != 0) {
if (LengthLeft == 0 && Ranges[StartIndex - 1].Type == Type) {
StartIndex--;
Length += Ranges[StartIndex].Length;
BaseAddress -= Ranges[StartIndex].Length;
}
}
if (EndIndex != (*Count) - 1) {
if (LengthRight == 0 && Ranges[EndIndex + 1].Type == Type) {
EndIndex++;
Length += Ranges[EndIndex].Length;
}
}
//
// |- 0 -|- 1 -|- 2 -|- 3 -| StartIndex EndIndex DeltaCount Count (Count = 4)
// |++++++++++++++++++| 0 3 1=3-0-2 3
// |+++++++| 0 1 -1=1-0-2 5
// |+| 0 0 -2=0-0-2 6
// |+++| 0 0 -1=0-0-2+1 5
//
//
DeltaCount = EndIndex - StartIndex - 2;
if (LengthLeft == 0) {
DeltaCount++;
}
if (LengthRight == 0) {
DeltaCount++;
}
if (*Count - DeltaCount > Capacity) {
return RETURN_OUT_OF_RESOURCES;
}
//
// Reserve (-DeltaCount) space
//
CopyMem (&Ranges[EndIndex + 1 - DeltaCount], &Ranges[EndIndex + 1], (*Count - EndIndex - 1) * sizeof (Ranges[0]));
*Count -= DeltaCount;
if (LengthLeft != 0) {
Ranges[StartIndex].Length = LengthLeft;
StartIndex++;
}
if (LengthRight != 0) {
Ranges[EndIndex - DeltaCount].BaseAddress = BaseAddress + Length;
Ranges[EndIndex - DeltaCount].Length = LengthRight;
Ranges[EndIndex - DeltaCount].Type = Ranges[EndIndex].Type;
}
Ranges[StartIndex].BaseAddress = BaseAddress;
Ranges[StartIndex].Length = Length;
Ranges[StartIndex].Type = Type;
return RETURN_SUCCESS;
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Return the number of memory types in range [BaseAddress, BaseAddress + Length).
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param Ranges Array holding memory type settings for all memory regions.
@param RangeCount The count of memory ranges the array holds.
@param BaseAddress Base address.
@param Length Length.
@param Types Return bit mask to indicate all memory types in the specified range.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval Number of memory types.
**/
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT8
MtrrLibGetNumberOfTypes (
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN OUT UINT8 *Types OPTIONAL
)
{
UINTN Index;
UINT8 TypeCount;
UINT8 LocalTypes;
TypeCount = 0;
LocalTypes = 0;
for (Index = 0; Index < RangeCount; Index++) {
if ((Ranges[Index].BaseAddress <= BaseAddress) &&
(BaseAddress < Ranges[Index].BaseAddress + Ranges[Index].Length)
) {
if ((LocalTypes & (1 << Ranges[Index].Type)) == 0) {
LocalTypes |= (UINT8)(1 << Ranges[Index].Type);
TypeCount++;
}
if (BaseAddress + Length > Ranges[Index].BaseAddress + Ranges[Index].Length) {
Length -= Ranges[Index].BaseAddress + Ranges[Index].Length - BaseAddress;
BaseAddress = Ranges[Index].BaseAddress + Ranges[Index].Length;
} else {
break;
}
}
}
if (Types != NULL) {
*Types = LocalTypes;
}
return TypeCount;
}
/**
Calculate the least MTRR number from vertex Start to Stop and update
the Previous of all vertices from Start to Stop is updated to reflect
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
how the memory range is covered by MTRR.
@param VertexCount The count of vertices in the graph.
@param Vertices Array holding all vertices.
@param Weight 2-dimention array holding weights between vertices.
@param Start Start vertex.
@param Stop Stop vertex.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param IncludeOptional TRUE to count the optional weight.
**/
VOID
MtrrLibCalculateLeastMtrrs (
IN UINT16 VertexCount,
IN MTRR_LIB_ADDRESS *Vertices,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
IN OUT CONST UINT8 *Weight,
IN UINT16 Start,
IN UINT16 Stop,
IN BOOLEAN IncludeOptional
)
{
UINT16 Index;
UINT8 MinWeight;
UINT16 MinI;
UINT8 Mandatory;
UINT8 Optional;
for (Index = Start; Index <= Stop; Index++) {
Vertices[Index].Visited = FALSE;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Mandatory = Weight[M(Start,Index)];
Vertices[Index].Weight = Mandatory;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Mandatory != MAX_WEIGHT) {
Optional = IncludeOptional ? Weight[O(Start, Index)] : 0;
Vertices[Index].Weight += Optional;
ASSERT (Vertices[Index].Weight >= Optional);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MinI = Start;
MinWeight = 0;
while (!Vertices[Stop].Visited) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Update the weight from the shortest vertex to other unvisited vertices
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
for (Index = Start + 1; Index <= Stop; Index++) {
if (!Vertices[Index].Visited) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Mandatory = Weight[M(MinI, Index)];
if (Mandatory != MAX_WEIGHT) {
Optional = IncludeOptional ? Weight[O(MinI, Index)] : 0;
if (MinWeight + Mandatory + Optional <= Vertices[Index].Weight) {
Vertices[Index].Weight = MinWeight + Mandatory + Optional;
Vertices[Index].Previous = MinI; // Previous is Start based.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Find the shortest vertex from Start
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
MinI = VertexCount;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MinWeight = MAX_WEIGHT;
for (Index = Start + 1; Index <= Stop; Index++) {
if (!Vertices[Index].Visited && MinWeight > Vertices[Index].Weight) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MinI = Index;
MinWeight = Vertices[Index].Weight;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Mark the shortest vertex from Start as visited
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
Vertices[MinI].Visited = TRUE;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
/**
Append the MTRR setting to MTRR setting array.
@param Mtrrs Array holding all MTRR settings.
@param MtrrCapacity Capacity of the MTRR array.
@param MtrrCount The count of MTRR settings in array.
@param BaseAddress Base address.
@param Length Length.
@param Type Memory type.
@retval RETURN_SUCCESS MTRR setting is appended to array.
@retval RETURN_OUT_OF_RESOURCES Array is full.
**/
RETURN_STATUS
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibAppendVariableMtrr (
IN OUT MTRR_MEMORY_RANGE *Mtrrs,
IN UINT32 MtrrCapacity,
IN OUT UINT32 *MtrrCount,
IN UINT64 BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Type
)
{
if (*MtrrCount == MtrrCapacity) {
return RETURN_OUT_OF_RESOURCES;
}
Mtrrs[*MtrrCount].BaseAddress = BaseAddress;
Mtrrs[*MtrrCount].Length = Length;
Mtrrs[*MtrrCount].Type = Type;
(*MtrrCount)++;
return RETURN_SUCCESS;
}
/**
Return the memory type that has the least precedence.
@param TypeBits Bit mask of memory type.
@retval Memory type that has the least precedence.
**/
MTRR_MEMORY_CACHE_TYPE
MtrrLibLowestType (
IN UINT8 TypeBits
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
INT8 Type;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (TypeBits != 0);
for (Type = 7; (INT8)TypeBits > 0; Type--, TypeBits <<= 1);
return (MTRR_MEMORY_CACHE_TYPE)Type;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Return TRUE when the Operand is exactly power of 2.
@retval TRUE Operand is exactly power of 2.
@retval FALSE Operand is not power of 2.
**/
BOOLEAN
MtrrLibIsPowerOfTwo (
IN UINT64 Operand
)
{
ASSERT (Operand != 0);
return (BOOLEAN) ((Operand & (Operand - 1)) == 0);
}
/**
Calculate the subtractive path from vertex Start to Stop.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param DefaultType Default memory type.
@param A0 Alignment to use when base address is 0.
@param Ranges Array holding memory type settings for all memory regions.
@param RangeCount The count of memory ranges the array holds.
@param VertexCount The count of vertices in the graph.
@param Vertices Array holding all vertices.
@param Weight 2-dimention array holding weights between vertices.
@param Start Start vertex.
@param Stop Stop vertex.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param Types Type bit mask of memory range from Start to Stop.
@param TypeCount Number of different memory types from Start to Stop.
@param Mtrrs Array holding all MTRR settings.
@param MtrrCapacity Capacity of the MTRR array.
@param MtrrCount The count of MTRR settings in array.
@retval RETURN_SUCCESS The subtractive path is calculated successfully.
@retval RETURN_OUT_OF_RESOURCES The MTRR setting array is full.
**/
RETURN_STATUS
MtrrLibCalculateSubtractivePath (
IN MTRR_MEMORY_CACHE_TYPE DefaultType,
IN UINT64 A0,
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount,
IN UINT16 VertexCount,
IN MTRR_LIB_ADDRESS *Vertices,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
IN OUT UINT8 *Weight,
IN UINT16 Start,
IN UINT16 Stop,
IN UINT8 Types,
IN UINT8 TypeCount,
IN OUT MTRR_MEMORY_RANGE *Mtrrs, OPTIONAL
IN UINT32 MtrrCapacity, OPTIONAL
IN OUT UINT32 *MtrrCount OPTIONAL
)
{
RETURN_STATUS Status;
UINT64 Base;
UINT64 Length;
UINT8 PrecedentTypes;
UINTN Index;
UINT64 HBase;
UINT64 HLength;
UINT64 SubLength;
UINT16 SubStart;
UINT16 SubStop;
UINT16 Cur;
UINT16 Pre;
MTRR_MEMORY_CACHE_TYPE LowestType;
MTRR_MEMORY_CACHE_TYPE LowestPrecedentType;
Base = Vertices[Start].Address;
Length = Vertices[Stop].Address - Base;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
LowestType = MtrrLibLowestType (Types);
//
// Clear the lowest type (highest bit) to get the precedent types
//
PrecedentTypes = ~(1 << LowestType) & Types;
LowestPrecedentType = MtrrLibLowestType (PrecedentTypes);
if (Mtrrs == NULL) {
Weight[M(Start, Stop)] = ((LowestType == DefaultType) ? 0 : 1);
Weight[O(Start, Stop)] = ((LowestType == DefaultType) ? 1 : 0);
}
// Add all high level ranges
HBase = MAX_UINT64;
HLength = 0;
for (Index = 0; Index < RangeCount; Index++) {
if (Length == 0) {
break;
}
if ((Base < Ranges[Index].BaseAddress) || (Ranges[Index].BaseAddress + Ranges[Index].Length <= Base)) {
continue;
}
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// Base is in the Range[Index]
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Base + Length > Ranges[Index].BaseAddress + Ranges[Index].Length) {
SubLength = Ranges[Index].BaseAddress + Ranges[Index].Length - Base;
} else {
SubLength = Length;
}
if (((1 << Ranges[Index].Type) & PrecedentTypes) != 0) {
//
// Meet a range whose types take precedence.
// Update the [HBase, HBase + HLength) to include the range,
// [HBase, HBase + HLength) may contain sub ranges with 2 different types, and both take precedence.
//
if (HBase == MAX_UINT64) {
HBase = Base;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
HLength += SubLength;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Base += SubLength;
Length -= SubLength;
if (HLength == 0) {
continue;
}
if ((Ranges[Index].Type == LowestType) || (Length == 0)) { // meet low type or end
//
// Add the MTRRs for each high priority type range
// the range[HBase, HBase + HLength) contains only two types.
// We might use positive or subtractive, depending on which way uses less MTRR
//
for (SubStart = Start; SubStart <= Stop; SubStart++) {
if (Vertices[SubStart].Address == HBase) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
break;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
for (SubStop = SubStart; SubStop <= Stop; SubStop++) {
if (Vertices[SubStop].Address == HBase + HLength) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
break;
}
}
ASSERT (Vertices[SubStart].Address == HBase);
ASSERT (Vertices[SubStop].Address == HBase + HLength);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if ((TypeCount == 2) || (SubStart == SubStop - 1)) {
//
// add subtractive MTRRs for [HBase, HBase + HLength)
// [HBase, HBase + HLength) contains only one type.
// while - loop is to split the range to MTRR - compliant aligned range.
//
if (Mtrrs == NULL) {
Weight[M (Start, Stop)] += (UINT8)(SubStop - SubStart);
} else {
while (SubStart != SubStop) {
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
Vertices[SubStart].Address, Vertices[SubStart].Length, Vertices[SubStart].Type
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
);
if (RETURN_ERROR (Status)) {
return Status;
}
SubStart++;
}
}
} else {
ASSERT (TypeCount == 3);
MtrrLibCalculateLeastMtrrs (VertexCount, Vertices, Weight, SubStart, SubStop, TRUE);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Mtrrs == NULL) {
Weight[M (Start, Stop)] += Vertices[SubStop].Weight;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
} else {
// When we need to collect the optimal path from SubStart to SubStop
while (SubStop != SubStart) {
Cur = SubStop;
Pre = Vertices[Cur].Previous;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
SubStop = Pre;
if (Weight[M (Pre, Cur)] + Weight[O (Pre, Cur)] != 0) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
Vertices[Pre].Address, Vertices[Cur].Address - Vertices[Pre].Address,
(Pre != Cur - 1) ? LowestPrecedentType : Vertices[Pre].Type
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
);
if (RETURN_ERROR (Status)) {
return Status;
}
}
if (Pre != Cur - 1) {
Status = MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
VertexCount, Vertices, Weight,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Pre, Cur, PrecedentTypes, 2,
Mtrrs, MtrrCapacity, MtrrCount
);
if (RETURN_ERROR (Status)) {
return Status;
}
}
}
}
}
//
// Reset HBase, HLength
//
HBase = MAX_UINT64;
HLength = 0;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
return RETURN_SUCCESS;
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Calculate MTRR settings to cover the specified memory ranges.
@param DefaultType Default memory type.
@param A0 Alignment to use when base address is 0.
@param Ranges Memory range array holding the memory type
settings for all memory address.
@param RangeCount Count of memory ranges.
@param Scratch A temporary scratch buffer that is used to perform the calculation.
This is an optional parameter that may be NULL.
@param ScratchSize Pointer to the size in bytes of the scratch buffer.
It may be updated to the actual required size when the calculation
needs more scratch buffer.
@param Mtrrs Array holding all MTRR settings.
@param MtrrCapacity Capacity of the MTRR array.
@param MtrrCount The count of MTRR settings in array.
@retval RETURN_SUCCESS Variable MTRRs are allocated successfully.
@retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
**/
RETURN_STATUS
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibCalculateMtrrs (
IN MTRR_MEMORY_CACHE_TYPE DefaultType,
IN UINT64 A0,
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount,
IN VOID *Scratch,
IN OUT UINTN *ScratchSize,
IN OUT MTRR_MEMORY_RANGE *Mtrrs,
IN UINT32 MtrrCapacity,
IN OUT UINT32 *MtrrCount
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT64 Base0;
UINT64 Base1;
UINTN Index;
UINT64 Base;
UINT64 Length;
UINT64 Alignment;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT64 SubLength;
MTRR_LIB_ADDRESS *Vertices;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT8 *Weight;
UINT32 VertexIndex;
UINT32 VertexCount;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINTN RequiredScratchSize;
UINT8 TypeCount;
UINT16 Start;
UINT16 Stop;
UINT8 Type;
RETURN_STATUS Status;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Base0 = Ranges[0].BaseAddress;
Base1 = Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length;
MTRR_LIB_ASSERT_ALIGNED (Base0, Base1 - Base0);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Count the number of vertices.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
Vertices = (MTRR_LIB_ADDRESS*)Scratch;
for (VertexIndex = 0, Index = 0; Index < RangeCount; Index++) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Base = Ranges[Index].BaseAddress;
Length = Ranges[Index].Length;
while (Length != 0) {
Alignment = MtrrLibBiggestAlignment (Base, A0);
SubLength = Alignment;
if (SubLength > Length) {
SubLength = GetPowerOfTwo64 (Length);
}
if (VertexIndex < *ScratchSize / sizeof (*Vertices)) {
Vertices[VertexIndex].Address = Base;
Vertices[VertexIndex].Alignment = Alignment;
Vertices[VertexIndex].Type = Ranges[Index].Type;
Vertices[VertexIndex].Length = SubLength;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
Base += SubLength;
Length -= SubLength;
VertexIndex++;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Vertices[VertexIndex] = Base1, so whole vertex count is (VertexIndex + 1).
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
VertexCount = VertexIndex + 1;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
DEBUG ((
DEBUG_CACHE, " Count of vertices (%016llx - %016llx) = %d\n",
Ranges[0].BaseAddress, Ranges[RangeCount - 1].BaseAddress + Ranges[RangeCount - 1].Length, VertexCount
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
));
ASSERT (VertexCount < MAX_UINT16);
RequiredScratchSize = VertexCount * sizeof (*Vertices) + VertexCount * VertexCount * sizeof (*Weight);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (*ScratchSize < RequiredScratchSize) {
*ScratchSize = RequiredScratchSize;
return RETURN_BUFFER_TOO_SMALL;
}
Vertices[VertexCount - 1].Address = Base1;
Weight = (UINT8 *) &Vertices[VertexCount];
for (VertexIndex = 0; VertexIndex < VertexCount; VertexIndex++) {
//
// Set optional weight between vertices and self->self to 0
//
SetMem (&Weight[M(VertexIndex, 0)], VertexIndex + 1, 0);
//
// Set mandatory weight between vertices to MAX_WEIGHT
//
SetMem (&Weight[M (VertexIndex, VertexIndex + 1)], VertexCount - VertexIndex - 1, MAX_WEIGHT);
// Final result looks like:
// 00 FF FF FF
// 00 00 FF FF
// 00 00 00 FF
// 00 00 00 00
}
//
// Set mandatory weight and optional weight for adjacent vertices
//
for (VertexIndex = 0; VertexIndex < VertexCount - 1; VertexIndex++) {
if (Vertices[VertexIndex].Type != DefaultType) {
Weight[M (VertexIndex, VertexIndex + 1)] = 1;
Weight[O (VertexIndex, VertexIndex + 1)] = 0;
} else {
Weight[M (VertexIndex, VertexIndex + 1)] = 0;
Weight[O (VertexIndex, VertexIndex + 1)] = 1;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
for (TypeCount = 2; TypeCount <= 3; TypeCount++) {
for (Start = 0; Start < VertexCount; Start++) {
for (Stop = Start + 2; Stop < VertexCount; Stop++) {
ASSERT (Vertices[Stop].Address > Vertices[Start].Address);
Length = Vertices[Stop].Address - Vertices[Start].Address;
if (Length > Vertices[Start].Alignment) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Pickup a new Start when [Start, Stop) cannot be described by one MTRR.
//
break;
}
if ((Weight[M(Start, Stop)] == MAX_WEIGHT) && MtrrLibIsPowerOfTwo (Length)) {
if (MtrrLibGetNumberOfTypes (
Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
) == TypeCount) {
//
// Update the Weight[Start, Stop] using subtractive path.
//
MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
(UINT16)VertexCount, Vertices, Weight,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Start, Stop, Type, TypeCount,
NULL, 0, NULL
);
} else if (TypeCount == 2) {
//
// Pick up a new Start when we expect 2-type range, but 3-type range is met.
// Because no matter how Stop is increased, we always meet 3-type range.
//
break;
}
}
}
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = RETURN_SUCCESS;
MtrrLibCalculateLeastMtrrs ((UINT16) VertexCount, Vertices, Weight, 0, (UINT16) VertexCount - 1, FALSE);
Stop = (UINT16) VertexCount - 1;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
while (Stop != 0) {
Start = Vertices[Stop].Previous;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
TypeCount = MAX_UINT8;
Type = 0;
if (Weight[M(Start, Stop)] != 0) {
TypeCount = MtrrLibGetNumberOfTypes (Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibAppendVariableMtrr (
Mtrrs, MtrrCapacity, MtrrCount,
Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibLowestType (Type)
);
if (RETURN_ERROR (Status)) {
break;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Start != Stop - 1) {
//
// substractive path
//
if (TypeCount == MAX_UINT8) {
TypeCount = MtrrLibGetNumberOfTypes (
Ranges, RangeCount, Vertices[Start].Address, Vertices[Stop].Address - Vertices[Start].Address, &Type
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
);
}
Status = MtrrLibCalculateSubtractivePath (
DefaultType, A0,
Ranges, RangeCount,
(UINT16) VertexCount, Vertices, Weight, Start, Stop,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Type, TypeCount,
Mtrrs, MtrrCapacity, MtrrCount
);
if (RETURN_ERROR (Status)) {
break;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Stop = Start;
}
return Status;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Apply the fixed MTRR settings to memory range array.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param Fixed The fixed MTRR settings.
@param Ranges Return the memory range array holding memory type
settings for all memory address.
@param RangeCapacity The capacity of memory range array.
@param RangeCount Return the count of memory range.
@retval RETURN_SUCCESS The memory range array is returned successfully.
@retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
**/
RETURN_STATUS
MtrrLibApplyFixedMtrrs (
IN MTRR_FIXED_SETTINGS *Fixed,
IN OUT MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCapacity,
IN OUT UINTN *RangeCount
)
{
RETURN_STATUS Status;
UINTN MsrIndex;
UINTN Index;
MTRR_MEMORY_CACHE_TYPE MemoryType;
UINT64 Base;
Base = 0;
for (MsrIndex = 0; MsrIndex < ARRAY_SIZE (mMtrrLibFixedMtrrTable); MsrIndex++) {
ASSERT (Base == mMtrrLibFixedMtrrTable[MsrIndex].BaseAddress);
for (Index = 0; Index < sizeof (UINT64); Index++) {
MemoryType = (MTRR_MEMORY_CACHE_TYPE)((UINT8 *)(&Fixed->Mtrr[MsrIndex]))[Index];
Status = MtrrLibSetMemoryType (
Ranges, RangeCapacity, RangeCount, Base, mMtrrLibFixedMtrrTable[MsrIndex].Length, MemoryType
);
if (Status == RETURN_OUT_OF_RESOURCES) {
return Status;
}
Base += mMtrrLibFixedMtrrTable[MsrIndex].Length;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (Base == BASE_1MB);
return RETURN_SUCCESS;
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Apply the variable MTRR settings to memory range array.
@param VariableMtrr The variable MTRR array.
@param VariableMtrrCount The count of variable MTRRs.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param Ranges Return the memory range array with new MTRR settings applied.
@param RangeCapacity The capacity of memory range array.
@param RangeCount Return the count of memory range.
@retval RETURN_SUCCESS The memory range array is returned successfully.
@retval RETURN_OUT_OF_RESOURCES The count of memory ranges exceeds capacity.
**/
RETURN_STATUS
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibApplyVariableMtrrs (
IN CONST MTRR_MEMORY_RANGE *VariableMtrr,
IN UINT32 VariableMtrrCount,
IN OUT MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCapacity,
IN OUT UINTN *RangeCount
)
{
RETURN_STATUS Status;
UINTN Index;
//
// WT > WB
// UC > *
// UC > * (except WB, UC) > WB
//
//
// 1. Set WB
//
for (Index = 0; Index < VariableMtrrCount; Index++) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if ((VariableMtrr[Index].Length != 0) && (VariableMtrr[Index].Type == CacheWriteBack)) {
Status = MtrrLibSetMemoryType (
Ranges, RangeCapacity, RangeCount,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, VariableMtrr[Index].Type
);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Status == RETURN_OUT_OF_RESOURCES) {
return Status;
}
}
}
//
// 2. Set other types than WB or UC
//
for (Index = 0; Index < VariableMtrrCount; Index++) {
if ((VariableMtrr[Index].Length != 0) &&
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
(VariableMtrr[Index].Type != CacheWriteBack) && (VariableMtrr[Index].Type != CacheUncacheable)) {
Status = MtrrLibSetMemoryType (
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Ranges, RangeCapacity, RangeCount,
VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, VariableMtrr[Index].Type
);
if (Status == RETURN_OUT_OF_RESOURCES) {
return Status;
}
}
}
//
// 3. Set UC
//
for (Index = 0; Index < VariableMtrrCount; Index++) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (VariableMtrr[Index].Length != 0 && VariableMtrr[Index].Type == CacheUncacheable) {
Status = MtrrLibSetMemoryType (
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Ranges, RangeCapacity, RangeCount,
VariableMtrr[Index].BaseAddress, VariableMtrr[Index].Length, VariableMtrr[Index].Type
);
if (Status == RETURN_OUT_OF_RESOURCES) {
return Status;
}
}
}
return RETURN_SUCCESS;
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Return the memory type bit mask that's compatible to first type in the Ranges.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param Ranges Memory range array holding the memory type
settings for all memory address.
@param RangeCount Count of memory ranges.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@return Compatible memory type bit mask.
**/
UINT8
MtrrLibGetCompatibleTypes (
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount
)
{
ASSERT (RangeCount != 0);
switch (Ranges[0].Type) {
case CacheWriteBack:
case CacheWriteThrough:
return (1 << CacheWriteBack) | (1 << CacheWriteThrough) | (1 << CacheUncacheable);
break;
case CacheWriteCombining:
case CacheWriteProtected:
return (1 << Ranges[0].Type) | (1 << CacheUncacheable);
break;
case CacheUncacheable:
if (RangeCount == 1) {
return (1 << CacheUncacheable);
}
return MtrrLibGetCompatibleTypes (&Ranges[1], RangeCount - 1);
break;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
case CacheInvalid:
default:
ASSERT (FALSE);
break;
}
return 0;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Overwrite the destination MTRR settings with the source MTRR settings.
This routine is to make sure the modification to destination MTRR settings
is as small as possible.
@param DstMtrrs Destination MTRR settings.
@param DstMtrrCount Count of destination MTRR settings.
@param SrcMtrrs Source MTRR settings.
@param SrcMtrrCount Count of source MTRR settings.
@param Modified Flag array to indicate which destination MTRR setting is modified.
**/
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
VOID
MtrrLibMergeVariableMtrr (
MTRR_MEMORY_RANGE *DstMtrrs,
UINT32 DstMtrrCount,
MTRR_MEMORY_RANGE *SrcMtrrs,
UINT32 SrcMtrrCount,
BOOLEAN *Modified
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT32 DstIndex;
UINT32 SrcIndex;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (SrcMtrrCount <= DstMtrrCount);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
for (DstIndex = 0; DstIndex < DstMtrrCount; DstIndex++) {
Modified[DstIndex] = FALSE;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (DstMtrrs[DstIndex].Length == 0) {
continue;
}
for (SrcIndex = 0; SrcIndex < SrcMtrrCount; SrcIndex++) {
if (DstMtrrs[DstIndex].BaseAddress == SrcMtrrs[SrcIndex].BaseAddress &&
DstMtrrs[DstIndex].Length == SrcMtrrs[SrcIndex].Length &&
DstMtrrs[DstIndex].Type == SrcMtrrs[SrcIndex].Type) {
break;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (SrcIndex == SrcMtrrCount) {
//
// Remove the one from DstMtrrs which is not in SrcMtrrs
//
DstMtrrs[DstIndex].Length = 0;
Modified[DstIndex] = TRUE;
} else {
//
// Remove the one from SrcMtrrs which is also in DstMtrrs
//
SrcMtrrs[SrcIndex].Length = 0;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Now valid MTRR only exists in either DstMtrrs or SrcMtrrs.
// Merge MTRRs from SrcMtrrs to DstMtrrs
//
DstIndex = 0;
for (SrcIndex = 0; SrcIndex < SrcMtrrCount; SrcIndex++) {
if (SrcMtrrs[SrcIndex].Length != 0) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Find the empty slot in DstMtrrs
//
while (DstIndex < DstMtrrCount) {
if (DstMtrrs[DstIndex].Length == 0) {
break;
}
DstIndex++;
}
ASSERT (DstIndex < DstMtrrCount);
CopyMem (&DstMtrrs[DstIndex], &SrcMtrrs[SrcIndex], sizeof (SrcMtrrs[0]));
Modified[DstIndex] = TRUE;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
/**
Calculate the variable MTRR settings for all memory ranges.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param DefaultType Default memory type.
@param A0 Alignment to use when base address is 0.
@param Ranges Memory range array holding the memory type
settings for all memory address.
@param RangeCount Count of memory ranges.
@param Scratch Scratch buffer to be used in MTRR calculation.
@param ScratchSize Pointer to the size of scratch buffer.
@param VariableMtrr Array holding all MTRR settings.
@param VariableMtrrCapacity Capacity of the MTRR array.
@param VariableMtrrCount The count of MTRR settings in array.
@retval RETURN_SUCCESS Variable MTRRs are allocated successfully.
@retval RETURN_OUT_OF_RESOURCES Count of variable MTRRs exceeds capacity.
@retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
The required scratch buffer size is returned through ScratchSize.
**/
RETURN_STATUS
MtrrLibSetMemoryRanges (
IN MTRR_MEMORY_CACHE_TYPE DefaultType,
IN UINT64 A0,
IN MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount,
IN VOID *Scratch,
IN OUT UINTN *ScratchSize,
OUT MTRR_MEMORY_RANGE *VariableMtrr,
IN UINT32 VariableMtrrCapacity,
OUT UINT32 *VariableMtrrCount
)
{
RETURN_STATUS Status;
UINT32 Index;
UINT64 Base0;
UINT64 Base1;
UINT64 Alignment;
UINT8 CompatibleTypes;
UINT64 Length;
UINT32 End;
UINTN ActualScratchSize;
UINTN BiggestScratchSize;
*VariableMtrrCount = 0;
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// Since the whole ranges need multiple calls of MtrrLibCalculateMtrrs().
// Each call needs different scratch buffer size.
// When the provided scratch buffer size is not sufficient in any call,
// set the GetActualScratchSize to TRUE, and following calls will only
// calculate the actual scratch size for the caller.
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
BiggestScratchSize = 0;
for (Index = 0; Index < RangeCount;) {
Base0 = Ranges[Index].BaseAddress;
//
// Full step is optimal
//
while (Index < RangeCount) {
ASSERT (Ranges[Index].BaseAddress == Base0);
Alignment = MtrrLibBiggestAlignment (Base0, A0);
while (Base0 + Alignment <= Ranges[Index].BaseAddress + Ranges[Index].Length) {
if ((BiggestScratchSize <= *ScratchSize) && (Ranges[Index].Type != DefaultType)) {
Status = MtrrLibAppendVariableMtrr (
VariableMtrr, VariableMtrrCapacity, VariableMtrrCount,
Base0, Alignment, Ranges[Index].Type
);
if (RETURN_ERROR (Status)) {
return Status;
}
}
Base0 += Alignment;
Alignment = MtrrLibBiggestAlignment (Base0, A0);
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// Remove the above range from Ranges[Index]
//
Ranges[Index].Length -= Base0 - Ranges[Index].BaseAddress;
Ranges[Index].BaseAddress = Base0;
if (Ranges[Index].Length != 0) {
break;
} else {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Index++;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Index == RangeCount) {
break;
}
//
// Find continous ranges [Base0, Base1) which could be combined by MTRR.
// Per SDM, the compatible types between[B0, B1) are:
// UC, *
// WB, WT
// UC, WB, WT
//
CompatibleTypes = MtrrLibGetCompatibleTypes (&Ranges[Index], RangeCount - Index);
End = Index; // End points to last one that matches the CompatibleTypes.
while (End + 1 < RangeCount) {
if (((1 << Ranges[End + 1].Type) & CompatibleTypes) == 0) {
break;
}
End++;
}
Alignment = MtrrLibBiggestAlignment (Base0, A0);
Length = GetPowerOfTwo64 (Ranges[End].BaseAddress + Ranges[End].Length - Base0);
Base1 = Base0 + MIN (Alignment, Length);
//
// Base1 may not in Ranges[End]. Update End to the range Base1 belongs to.
//
End = Index;
while (End + 1 < RangeCount) {
if (Base1 <= Ranges[End + 1].BaseAddress) {
break;
}
End++;
}
Length = Ranges[End].Length;
Ranges[End].Length = Base1 - Ranges[End].BaseAddress;
ActualScratchSize = *ScratchSize;
Status = MtrrLibCalculateMtrrs (
DefaultType, A0,
&Ranges[Index], End + 1 - Index,
Scratch, &ActualScratchSize,
VariableMtrr, VariableMtrrCapacity, VariableMtrrCount
);
if (Status == RETURN_BUFFER_TOO_SMALL) {
BiggestScratchSize = MAX (BiggestScratchSize, ActualScratchSize);
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// Ignore this error, because we need to calculate the biggest
// scratch buffer size.
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = RETURN_SUCCESS;
}
if (RETURN_ERROR (Status)) {
return Status;
}
if (Length != Ranges[End].Length) {
Ranges[End].BaseAddress = Base1;
Ranges[End].Length = Length - Ranges[End].Length;
Index = End;
} else {
Index = End + 1;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (*ScratchSize < BiggestScratchSize) {
*ScratchSize = BiggestScratchSize;
return RETURN_BUFFER_TOO_SMALL;
}
return RETURN_SUCCESS;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Set the below-1MB memory attribute to fixed MTRR buffer.
Modified flag array indicates which fixed MTRR is modified.
@param [in, out] ClearMasks The bits (when set) to clear in the fixed MTRR MSR.
@param [in, out] OrMasks The bits to set in the fixed MTRR MSR.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param [in] BaseAddress Base address.
@param [in] Length Length.
@param [in] Type Memory type.
@retval RETURN_SUCCESS The memory attribute is set successfully.
@retval RETURN_UNSUPPORTED The requested range or cache type was invalid
for the fixed MTRRs.
**/
RETURN_STATUS
MtrrLibSetBelow1MBMemoryAttribute (
IN OUT UINT64 *ClearMasks,
IN OUT UINT64 *OrMasks,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
IN PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Type
)
{
RETURN_STATUS Status;
UINT32 MsrIndex;
UINT64 ClearMask;
UINT64 OrMask;
ASSERT (BaseAddress < BASE_1MB);
MsrIndex = (UINT32)-1;
while ((BaseAddress < BASE_1MB) && (Length != 0)) {
Status = MtrrLibProgramFixedMtrr (Type, &BaseAddress, &Length, &MsrIndex, &ClearMask, &OrMask);
if (RETURN_ERROR (Status)) {
return Status;
}
ClearMasks[MsrIndex] = ClearMasks[MsrIndex] | ClearMask;
OrMasks[MsrIndex] = (OrMasks[MsrIndex] & ~ClearMask) | OrMask;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
return RETURN_SUCCESS;
}
/**
This function attempts to set the attributes into MTRR setting buffer for multiple memory ranges.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param[in, out] MtrrSetting MTRR setting buffer to be set.
@param[in] Scratch A temporary scratch buffer that is used to perform the calculation.
@param[in, out] ScratchSize Pointer to the size in bytes of the scratch buffer.
It may be updated to the actual required size when the calculation
needs more scratch buffer.
@param[in] Ranges Pointer to an array of MTRR_MEMORY_RANGE.
When range overlap happens, the last one takes higher priority.
When the function returns, either all the attributes are set successfully,
or none of them is set.
@param[in] RangeCount Count of MTRR_MEMORY_RANGE.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval RETURN_SUCCESS The attributes were set for all the memory ranges.
@retval RETURN_INVALID_PARAMETER Length in any range is zero.
@retval RETURN_UNSUPPORTED The processor does not support one or more bytes of the
memory resource range specified by BaseAddress and Length in any range.
@retval RETURN_UNSUPPORTED The bit mask of attributes is not support for the memory resource
range specified by BaseAddress and Length in any range.
@retval RETURN_OUT_OF_RESOURCES There are not enough system resources to modify the attributes of
the memory resource ranges.
@retval RETURN_ACCESS_DENIED The attributes for the memory resource range specified by
BaseAddress and Length cannot be modified.
@retval RETURN_BUFFER_TOO_SMALL The scratch buffer is too small for MTRR calculation.
**/
RETURN_STATUS
EFIAPI
MtrrSetMemoryAttributesInMtrrSettings (
IN OUT MTRR_SETTINGS *MtrrSetting,
IN VOID *Scratch,
IN OUT UINTN *ScratchSize,
IN CONST MTRR_MEMORY_RANGE *Ranges,
IN UINTN RangeCount
)
{
RETURN_STATUS Status;
UINT32 Index;
UINT64 BaseAddress;
UINT64 Length;
BOOLEAN Above1MbExist;
UINT64 MtrrValidBitsMask;
UINT64 MtrrValidAddressMask;
MTRR_MEMORY_CACHE_TYPE DefaultType;
MTRR_VARIABLE_SETTINGS VariableSettings;
MTRR_MEMORY_RANGE WorkingRanges[2 * ARRAY_SIZE (MtrrSetting->Variables.Mtrr) + 2];
UINTN WorkingRangeCount;
BOOLEAN Modified;
MTRR_VARIABLE_SETTING VariableSetting;
UINT32 OriginalVariableMtrrCount;
UINT32 FirmwareVariableMtrrCount;
UINT32 WorkingVariableMtrrCount;
MTRR_MEMORY_RANGE OriginalVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
MTRR_MEMORY_RANGE WorkingVariableMtrr[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
BOOLEAN VariableSettingModified[ARRAY_SIZE (MtrrSetting->Variables.Mtrr)];
UINT64 ClearMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
UINT64 OrMasks[ARRAY_SIZE (mMtrrLibFixedMtrrTable)];
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MTRR_CONTEXT MtrrContext;
BOOLEAN MtrrContextValid;
Status = RETURN_SUCCESS;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// TRUE indicating the accordingly Variable setting needs modificaiton in OriginalVariableMtrr.
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
SetMem (VariableSettingModified, ARRAY_SIZE (VariableSettingModified), FALSE);
//
// TRUE indicating the caller requests to set variable MTRRs.
//
Above1MbExist = FALSE;
OriginalVariableMtrrCount = 0;
//
// 0. Dump the requests.
//
DEBUG_CODE (
DEBUG ((DEBUG_CACHE, "Mtrr: Set Mem Attribute to %a, ScratchSize = %x%a",
(MtrrSetting == NULL) ? "Hardware" : "Buffer", *ScratchSize,
(RangeCount <= 1) ? "," : "\n"
));
for (Index = 0; Index < RangeCount; Index++) {
DEBUG ((DEBUG_CACHE, " %a: [%016lx, %016lx)\n",
mMtrrMemoryCacheTypeShortName[MIN (Ranges[Index].Type, CacheInvalid)],
Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length
));
}
);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// 1. Validate the parameters.
//
if (!IsMtrrSupported ()) {
Status = RETURN_UNSUPPORTED;
goto Exit;
}
for (Index = 0; Index < RangeCount; Index++) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Ranges[Index].Length == 0) {
Status = RETURN_INVALID_PARAMETER;
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
if (((Ranges[Index].BaseAddress & ~MtrrValidAddressMask) != 0) ||
((((Ranges[Index].BaseAddress + Ranges[Index].Length) & ~MtrrValidAddressMask) != 0) &&
(Ranges[Index].BaseAddress + Ranges[Index].Length) != MtrrValidBitsMask + 1)
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
) {
//
// Either the BaseAddress or the Limit doesn't follow the alignment requirement.
// Note: It's still valid if Limit doesn't follow the alignment requirement but equals to MAX Address.
//
Status = RETURN_UNSUPPORTED;
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
if ((Ranges[Index].Type != CacheUncacheable) &&
(Ranges[Index].Type != CacheWriteCombining) &&
(Ranges[Index].Type != CacheWriteThrough) &&
(Ranges[Index].Type != CacheWriteProtected) &&
(Ranges[Index].Type != CacheWriteBack)) {
Status = RETURN_INVALID_PARAMETER;
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
if (Ranges[Index].BaseAddress + Ranges[Index].Length > BASE_1MB) {
Above1MbExist = TRUE;
}
}
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// 2. Apply the above-1MB memory attribute settings.
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Above1MbExist) {
//
// 2.1. Read all variable MTRRs and convert to Ranges.
//
OriginalVariableMtrrCount = GetVariableMtrrCountWorker ();
MtrrGetVariableMtrrWorker (MtrrSetting, OriginalVariableMtrrCount, &VariableSettings);
MtrrLibGetRawVariableRanges (
&VariableSettings, OriginalVariableMtrrCount,
MtrrValidBitsMask, MtrrValidAddressMask, OriginalVariableMtrr
);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
DefaultType = MtrrGetDefaultMemoryTypeWorker (MtrrSetting);
WorkingRangeCount = 1;
WorkingRanges[0].BaseAddress = 0;
WorkingRanges[0].Length = MtrrValidBitsMask + 1;
WorkingRanges[0].Type = DefaultType;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibApplyVariableMtrrs (
OriginalVariableMtrr, OriginalVariableMtrrCount,
WorkingRanges, ARRAY_SIZE (WorkingRanges), &WorkingRangeCount);
ASSERT_RETURN_ERROR (Status);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (OriginalVariableMtrrCount >= PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs));
FirmwareVariableMtrrCount = OriginalVariableMtrrCount - PcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
ASSERT (WorkingRangeCount <= 2 * FirmwareVariableMtrrCount + 1);
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// 2.2. Force [0, 1M) to UC, so that it doesn't impact subtraction algorithm.
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibSetMemoryType (
WorkingRanges, ARRAY_SIZE (WorkingRanges), &WorkingRangeCount,
0, SIZE_1MB, CacheUncacheable
);
ASSERT (Status != RETURN_OUT_OF_RESOURCES);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// 2.3. Apply the new memory attribute settings to Ranges.
//
Modified = FALSE;
for (Index = 0; Index < RangeCount; Index++) {
BaseAddress = Ranges[Index].BaseAddress;
Length = Ranges[Index].Length;
if (BaseAddress < BASE_1MB) {
if (Length <= BASE_1MB - BaseAddress) {
continue;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Length -= BASE_1MB - BaseAddress;
BaseAddress = BASE_1MB;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibSetMemoryType (
WorkingRanges, ARRAY_SIZE (WorkingRanges), &WorkingRangeCount,
BaseAddress, Length, Ranges[Index].Type
);
if (Status == RETURN_ALREADY_STARTED) {
Status = RETURN_SUCCESS;
} else if (Status == RETURN_OUT_OF_RESOURCES) {
goto Exit;
} else {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT_RETURN_ERROR (Status);
Modified = TRUE;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (Modified) {
//
// 2.4. Calculate the Variable MTRR settings based on the Ranges.
// Buffer Too Small may be returned if the scratch buffer size is insufficient.
//
Status = MtrrLibSetMemoryRanges (
DefaultType, LShiftU64 (1, (UINTN)HighBitSet64 (MtrrValidBitsMask)), WorkingRanges, WorkingRangeCount,
Scratch, ScratchSize,
WorkingVariableMtrr, FirmwareVariableMtrrCount + 1, &WorkingVariableMtrrCount
);
if (RETURN_ERROR (Status)) {
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// 2.5. Remove the [0, 1MB) MTRR if it still exists (not merged with other range)
//
for (Index = 0; Index < WorkingVariableMtrrCount; Index++) {
if (WorkingVariableMtrr[Index].BaseAddress == 0 && WorkingVariableMtrr[Index].Length == SIZE_1MB) {
ASSERT (WorkingVariableMtrr[Index].Type == CacheUncacheable);
WorkingVariableMtrrCount--;
CopyMem (
&WorkingVariableMtrr[Index], &WorkingVariableMtrr[Index + 1],
(WorkingVariableMtrrCount - Index) * sizeof (WorkingVariableMtrr[0])
);
break;
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (WorkingVariableMtrrCount > FirmwareVariableMtrrCount) {
Status = RETURN_OUT_OF_RESOURCES;
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
//
// 2.6. Merge the WorkingVariableMtrr to OriginalVariableMtrr
// Make sure least modification is made to OriginalVariableMtrr.
//
MtrrLibMergeVariableMtrr (
OriginalVariableMtrr, OriginalVariableMtrrCount,
WorkingVariableMtrr, WorkingVariableMtrrCount,
VariableSettingModified
);
}
}
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// 3. Apply the below-1MB memory attribute settings.
//
// (Value & ~0 | 0) still equals to (Value)
//
ZeroMem (ClearMasks, sizeof (ClearMasks));
ZeroMem (OrMasks, sizeof (OrMasks));
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
for (Index = 0; Index < RangeCount; Index++) {
if (Ranges[Index].BaseAddress >= BASE_1MB) {
continue;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Status = MtrrLibSetBelow1MBMemoryAttribute (
ClearMasks, OrMasks,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Type
);
if (RETURN_ERROR (Status)) {
goto Exit;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
MtrrContextValid = FALSE;
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// 4. Write fixed MTRRs that have been modified
//
for (Index = 0; Index < ARRAY_SIZE (ClearMasks); Index++) {
if (ClearMasks[Index] != 0) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (MtrrSetting != NULL) {
MtrrSetting->Fixed.Mtrr[Index] = (MtrrSetting->Fixed.Mtrr[Index] & ~ClearMasks[Index]) | OrMasks[Index];
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
} else {
if (!MtrrContextValid) {
MtrrLibPreMtrrChange (&MtrrContext);
MtrrContextValid = TRUE;
}
AsmMsrAndThenOr64 (mMtrrLibFixedMtrrTable[Index].Msr, ~ClearMasks[Index], OrMasks[Index]);
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
}
}
//
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
// 5. Write variable MTRRs that have been modified
//
for (Index = 0; Index < OriginalVariableMtrrCount; Index++) {
if (VariableSettingModified[Index]) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (OriginalVariableMtrr[Index].Length != 0) {
VariableSetting.Base = (OriginalVariableMtrr[Index].BaseAddress & MtrrValidAddressMask)
| (UINT8)OriginalVariableMtrr[Index].Type;
VariableSetting.Mask = ((~(OriginalVariableMtrr[Index].Length - 1)) & MtrrValidAddressMask) | BIT11;
} else {
VariableSetting.Base = 0;
VariableSetting.Mask = 0;
}
if (MtrrSetting != NULL) {
CopyMem (&MtrrSetting->Variables.Mtrr[Index], &VariableSetting, sizeof (VariableSetting));
} else {
if (!MtrrContextValid) {
MtrrLibPreMtrrChange (&MtrrContext);
MtrrContextValid = TRUE;
}
AsmWriteMsr64 (
MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),
VariableSetting.Base
);
AsmWriteMsr64 (
MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),
VariableSetting.Mask
);
}
}
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (MtrrSetting != NULL) {
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.E = 1;
((MSR_IA32_MTRR_DEF_TYPE_REGISTER *)&MtrrSetting->MtrrDefType)->Bits.FE = 1;
} else {
if (MtrrContextValid) {
MtrrLibPostMtrrChange (&MtrrContext);
}
}
Exit:
DEBUG ((DEBUG_CACHE, " Result = %r\n", Status));
if (!RETURN_ERROR (Status)) {
MtrrDebugPrintAllMtrrsWorker (MtrrSetting);
}
return Status;
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
This function attempts to set the attributes into MTRR setting buffer for a memory range.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param[in, out] MtrrSetting MTRR setting buffer to be set.
@param[in] BaseAddress The physical address that is the start address
of a memory range.
@param[in] Length The size in bytes of the memory range.
@param[in] Attribute The bit mask of attributes to set for the
memory range.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval RETURN_SUCCESS The attributes were set for the memory range.
@retval RETURN_INVALID_PARAMETER Length is zero.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@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.
Multiple memory range attributes setting by calling this API multiple
times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean
the number of CPU MTRRs are too small to set such memory attributes.
Pass the multiple memory range attributes to one call of
MtrrSetMemoryAttributesInMtrrSettings() may succeed.
@retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.
Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify
external scratch buffer.
**/
RETURN_STATUS
EFIAPI
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrSetMemoryAttributeInMtrrSettings (
IN OUT MTRR_SETTINGS *MtrrSetting,
IN PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Attribute
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
UINT8 Scratch[SCRATCH_BUFFER_SIZE];
UINTN ScratchSize;
MTRR_MEMORY_RANGE Range;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Range.BaseAddress = BaseAddress;
Range.Length = Length;
Range.Type = Attribute;
ScratchSize = sizeof (Scratch);
return MtrrSetMemoryAttributesInMtrrSettings (MtrrSetting, Scratch, &ScratchSize, &Range, 1);
}
/**
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
This function attempts to set the attributes for a memory range.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@param[in] BaseAddress The physical address that is the start
address of a memory range.
@param[in] Length The size in bytes of the memory range.
@param[in] Attributes The bit mask of attributes to set for the
memory range.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@retval RETURN_SUCCESS The attributes were set for the memory
range.
@retval RETURN_INVALID_PARAMETER Length is zero.
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
@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.
Multiple memory range attributes setting by calling this API multiple
times may fail with status RETURN_OUT_OF_RESOURCES. It may not mean
the number of CPU MTRRs are too small to set such memory attributes.
Pass the multiple memory range attributes to one call of
MtrrSetMemoryAttributesInMtrrSettings() may succeed.
@retval RETURN_BUFFER_TOO_SMALL The fixed internal scratch buffer is too small for MTRR calculation.
Caller should use MtrrSetMemoryAttributesInMtrrSettings() to specify
external scratch buffer.
**/
RETURN_STATUS
EFIAPI
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrSetMemoryAttribute (
IN PHYSICAL_ADDRESS BaseAddress,
IN UINT64 Length,
IN MTRR_MEMORY_CACHE_TYPE Attribute
)
{
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
return MtrrSetMemoryAttributeInMtrrSettings (NULL, BaseAddress, Length, Attribute);
}
/**
Worker function setting variable MTRRs
@param[in] VariableSettings A buffer to hold variable MTRRs content.
**/
VOID
MtrrSetVariableMtrrWorker (
IN MTRR_VARIABLE_SETTINGS *VariableSettings
)
{
UINT32 Index;
UINT32 VariableMtrrCount;
VariableMtrrCount = GetVariableMtrrCountWorker ();
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
ASSERT (VariableMtrrCount <= ARRAY_SIZE (VariableSettings->Mtrr));
for (Index = 0; Index < VariableMtrrCount; Index++) {
AsmWriteMsr64 (
MSR_IA32_MTRR_PHYSBASE0 + (Index << 1),
VariableSettings->Mtrr[Index].Base
);
AsmWriteMsr64 (
MSR_IA32_MTRR_PHYSMASK0 + (Index << 1),
VariableSettings->Mtrr[Index].Mask
);
}
}
/**
This function sets variable MTRRs
@param[in] VariableSettings A buffer to hold variable MTRRs content.
@return The pointer of VariableSettings
**/
MTRR_VARIABLE_SETTINGS*
EFIAPI
MtrrSetVariableMtrr (
IN MTRR_VARIABLE_SETTINGS *VariableSettings
)
{
MTRR_CONTEXT MtrrContext;
if (!IsMtrrSupported ()) {
return VariableSettings;
}
MtrrLibPreMtrrChange (&MtrrContext);
MtrrSetVariableMtrrWorker (VariableSettings);
MtrrLibPostMtrrChange (&MtrrContext);
MtrrDebugPrintAllMtrrs ();
return VariableSettings;
}
/**
Worker function setting fixed MTRRs
@param[in] FixedSettings A buffer to hold fixed MTRRs content.
**/
VOID
MtrrSetFixedMtrrWorker (
IN MTRR_FIXED_SETTINGS *FixedSettings
)
{
UINT32 Index;
for (Index = 0; Index < MTRR_NUMBER_OF_FIXED_MTRR; Index++) {
AsmWriteMsr64 (
mMtrrLibFixedMtrrTable[Index].Msr,
FixedSettings->Mtrr[Index]
);
}
}
/**
This function sets fixed MTRRs
@param[in] FixedSettings A buffer to hold fixed MTRRs content.
@retval The pointer of FixedSettings
**/
MTRR_FIXED_SETTINGS*
EFIAPI
MtrrSetFixedMtrr (
IN MTRR_FIXED_SETTINGS *FixedSettings
)
{
MTRR_CONTEXT MtrrContext;
if (!IsMtrrSupported ()) {
return FixedSettings;
}
MtrrLibPreMtrrChange (&MtrrContext);
MtrrSetFixedMtrrWorker (FixedSettings);
MtrrLibPostMtrrChange (&MtrrContext);
MtrrDebugPrintAllMtrrs ();
return FixedSettings;
}
/**
This function gets the content in all MTRRs (variable and fixed)
@param[out] MtrrSetting A buffer to hold all MTRRs content.
@retval the pointer of MtrrSetting
**/
MTRR_SETTINGS *
EFIAPI
MtrrGetAllMtrrs (
OUT MTRR_SETTINGS *MtrrSetting
)
{
if (!IsMtrrSupported ()) {
return MtrrSetting;
}
//
// Get fixed MTRRs
//
MtrrGetFixedMtrrWorker (&MtrrSetting->Fixed);
//
// Get variable MTRRs
//
MtrrGetVariableMtrrWorker (
NULL,
GetVariableMtrrCountWorker (),
&MtrrSetting->Variables
);
//
// Get MTRR_DEF_TYPE value
//
MtrrSetting->MtrrDefType = AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE);
return MtrrSetting;
}
/**
This function sets all MTRRs (variable and fixed)
@param[in] MtrrSetting A buffer holding all MTRRs content.
@retval The pointer of MtrrSetting
**/
MTRR_SETTINGS *
EFIAPI
MtrrSetAllMtrrs (
IN MTRR_SETTINGS *MtrrSetting
)
{
MTRR_CONTEXT MtrrContext;
if (!IsMtrrSupported ()) {
return MtrrSetting;
}
MtrrLibPreMtrrChange (&MtrrContext);
//
// Set fixed MTRRs
//
MtrrSetFixedMtrrWorker (&MtrrSetting->Fixed);
//
// Set variable MTRRs
//
MtrrSetVariableMtrrWorker (&MtrrSetting->Variables);
//
// Set MTRR_DEF_TYPE value
//
AsmWriteMsr64 (MSR_IA32_MTRR_DEF_TYPE, MtrrSetting->MtrrDefType);
MtrrLibPostMtrrChangeEnableCache (&MtrrContext);
return MtrrSetting;
}
/**
Checks if MTRR is supported.
@retval TRUE MTRR is supported.
@retval FALSE MTRR is not supported.
**/
BOOLEAN
EFIAPI
IsMtrrSupported (
VOID
)
{
CPUID_VERSION_INFO_EDX Edx;
MSR_IA32_MTRRCAP_REGISTER MtrrCap;
//
// Check CPUID(1).EDX[12] for MTRR capability
//
AsmCpuid (CPUID_VERSION_INFO, NULL, NULL, NULL, &Edx.Uint32);
if (Edx.Bits.MTRR == 0) {
return FALSE;
}
//
// Check number of variable MTRRs and fixed MTRRs existence.
// If number of variable MTRRs is zero, or fixed MTRRs do not
// exist, return false.
//
MtrrCap.Uint64 = AsmReadMsr64 (MSR_IA32_MTRRCAP);
if ((MtrrCap.Bits.VCNT == 0) || (MtrrCap.Bits.FIX == 0)) {
return FALSE;
}
return TRUE;
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
/**
Worker function prints all MTRRs for debugging.
If MtrrSetting is not NULL, print MTRR settings from input MTRR
settings buffer.
If MtrrSetting is NULL, print MTRR settings from MTRRs.
@param MtrrSetting A buffer holding all MTRRs content.
**/
VOID
MtrrDebugPrintAllMtrrsWorker (
IN MTRR_SETTINGS *MtrrSetting
)
{
DEBUG_CODE (
MTRR_SETTINGS LocalMtrrs;
MTRR_SETTINGS *Mtrrs;
UINTN Index;
UINTN RangeCount;
UINT64 MtrrValidBitsMask;
UINT64 MtrrValidAddressMask;
UINT32 VariableMtrrCount;
BOOLEAN ContainVariableMtrr;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MTRR_MEMORY_RANGE Ranges[
ARRAY_SIZE (mMtrrLibFixedMtrrTable) * sizeof (UINT64) + 2 * ARRAY_SIZE (Mtrrs->Variables.Mtrr) + 1
];
MTRR_MEMORY_RANGE RawVariableRanges[ARRAY_SIZE (Mtrrs->Variables.Mtrr)];
if (!IsMtrrSupported ()) {
return;
}
VariableMtrrCount = GetVariableMtrrCountWorker ();
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
if (MtrrSetting != NULL) {
Mtrrs = MtrrSetting;
} else {
MtrrGetAllMtrrs (&LocalMtrrs);
Mtrrs = &LocalMtrrs;
}
//
// Dump RAW MTRR contents
//
DEBUG ((DEBUG_CACHE, "MTRR Settings:\n"));
DEBUG ((DEBUG_CACHE, "=============\n"));
DEBUG ((DEBUG_CACHE, "MTRR Default Type: %016lx\n", Mtrrs->MtrrDefType));
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
for (Index = 0; Index < ARRAY_SIZE (mMtrrLibFixedMtrrTable); Index++) {
DEBUG ((DEBUG_CACHE, "Fixed MTRR[%02d] : %016lx\n", Index, Mtrrs->Fixed.Mtrr[Index]));
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
}
ContainVariableMtrr = FALSE;
for (Index = 0; Index < VariableMtrrCount; Index++) {
if ((Mtrrs->Variables.Mtrr[Index].Mask & BIT11) == 0) {
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
//
// If mask is not valid, then do not display range
//
continue;
}
ContainVariableMtrr = TRUE;
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
DEBUG ((DEBUG_CACHE, "Variable MTRR[%02d]: Base=%016lx Mask=%016lx\n",
Index,
Mtrrs->Variables.Mtrr[Index].Base,
Mtrrs->Variables.Mtrr[Index].Mask
));
}
if (!ContainVariableMtrr) {
DEBUG ((DEBUG_CACHE, "Variable MTRR : None.\n"));
}
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
DEBUG((DEBUG_CACHE, "\n"));
//
// Dump MTRR setting in ranges
//
DEBUG((DEBUG_CACHE, "Memory Ranges:\n"));
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
DEBUG((DEBUG_CACHE, "====================================\n"));
MtrrLibInitializeMtrrMask (&MtrrValidBitsMask, &MtrrValidAddressMask);
Ranges[0].BaseAddress = 0;
Ranges[0].Length = MtrrValidBitsMask + 1;
Ranges[0].Type = MtrrGetDefaultMemoryTypeWorker (Mtrrs);
RangeCount = 1;
MtrrLibGetRawVariableRanges (
&Mtrrs->Variables, VariableMtrrCount,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
MtrrValidBitsMask, MtrrValidAddressMask, RawVariableRanges
);
MtrrLibApplyVariableMtrrs (
RawVariableRanges, VariableMtrrCount,
UefiCpuPkg/MtrrLib: Update algorithm to calculate optimal settings The new algorithm converts the problem calculating optimal MTRR settings (using least MTRR registers) to the problem finding the shortest path in a graph. The memory required in extreme but rare case can be up to 256KB, so using local stack buffer is impossible considering current DxeIpl only allocates 128KB stack. The patch changes existing MtrrSetMemoryAttributeInMtrrSettings() and MtrrSetMemoryAttribute() to use the 4-page stack buffer for calculation. The two APIs return BUFFER_TOO_SMALL when the buffer is too small for calculation. The patch adds a new API MtrrSetMemoryAttribute*s*InMtrrSettings() to set multiple-range attributes in one function call. Since every call to MtrrSetMemoryAttributeInMtrrSettings (without-s) or MtrrSetMemoryAttribute() requires to calculate the MTRRs for the whole physical memory, combining multiple calls in one API can significantly reduce the calculation time. In theory, if N times of call to without-s API costs N seconds, the new API only costs 1 second. The new API uses the buffer supplied from caller to calculate MTRRs and returns BUFFER_TOO_SMALL when the buffer is too small for calculation. Test performed: 1. Random test a. Generate random memory settings, use the new algorithm to calculate the MTRRs. b. Read back the MTRRs and check the memory settings match the desired memory settings. c. Repeat the above #1 and #2 100000 times. 2. OVMF 32PEI + 64DXE boot to shell. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Eric Dong <eric.dong@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
2017-09-27 11:56:41 +02:00
Ranges, ARRAY_SIZE (Ranges), &RangeCount
);
MtrrLibApplyFixedMtrrs (&Mtrrs->Fixed, Ranges, ARRAY_SIZE (Ranges), &RangeCount);
for (Index = 0; Index < RangeCount; Index++) {
DEBUG ((DEBUG_CACHE, "%a:%016lx-%016lx\n",
mMtrrMemoryCacheTypeShortName[Ranges[Index].Type],
Ranges[Index].BaseAddress, Ranges[Index].BaseAddress + Ranges[Index].Length - 1
));
}
);
}
/**
This function prints all MTRRs for debugging.
**/
VOID
EFIAPI
MtrrDebugPrintAllMtrrs (
VOID
)
{
MtrrDebugPrintAllMtrrsWorker (NULL);
}