Mike, I resent V2 patch and reduced most of the global variable references.
Furtherly, I added more CONST modifier to avoid test case accidently modifies the system parameter structure. I submitted a Bugzilla https://bugzilla.tianocore.org/show_bug.cgi?id=2863 to capture what you suggested below. Thanks, Ray > -----Original Message----- > From: Kinney, Michael D <michael.d.kin...@intel.com> > Sent: Friday, July 24, 2020 9:34 AM > To: Ni, Ray <ray...@intel.com>; devel@edk2.groups.io; Kinney, Michael D > <michael.d.kin...@intel.com> > Cc: Shao, Ming <ming.s...@intel.com>; Dong, Eric <eric.d...@intel.com>; > Laszlo Ersek <ler...@redhat.com>; Sean Brogan > <sean.bro...@microsoft.com>; Bret Barkelew <bret.barke...@microsoft.com>; > Yao, Jiewen <jiewen....@intel.com> > Subject: RE: [PATCH] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test > > Hi Ray, > > In the following Unit Test Functions, I recommend passing in > mDefaultSystemParameter as the Context parameter to reduce the > use of a global variables. > > * UnitTestIsMtrrSupported() > * UnitTestGetVariableMtrrCount() > * UnitTestGetFirmwareVariableMtrrCount() > * UnitTestMtrrGetFixedMtrr() > * UnitTestMtrrGetAllMtrrs() > * UnitTestMtrrSetAllMtrrs() > * UnitTestMtrrGetMemoryAttributeInVariableMtrr() > * UnitTestMtrrGetDefaultMemoryType() > > The use of random memory maps is a good way to test complex > services like these. However, the issues with random test > vectors is that a test failure is difficult to reproduce. > You can also have cases where one run through CI fails and > the next run with different random values passes. > > I like the idea of using code that generates random test > vectors to generate a fixed set of test vectors that are > built into the unit test so we have the same test vectors > for every CI check. > > Then, we can split out the unit test that does random test > vectors into its own test that a developer can choose to > run with a high number of iterations when there is an algo > change or we are doing release testing. This unit test > would not be use for CI testing. > > I am ok with the first version using random, but please > enter a BZ to split it out. > > Thanks, > > Mike > > > -----Original Message----- > > From: Ni, Ray <ray...@intel.com> > > Sent: Friday, July 17, 2020 12:33 AM > > To: devel@edk2.groups.io > > Cc: Kinney, Michael D <michael.d.kin...@intel.com>; > > Shao, Ming <ming.s...@intel.com>; Dong, Eric > > <eric.d...@intel.com>; Laszlo Ersek > > <ler...@redhat.com>; Sean Brogan > > <sean.bro...@microsoft.com>; Bret Barkelew > > <bret.barke...@microsoft.com>; Yao, Jiewen > > <jiewen....@intel.com> > > Subject: [PATCH] UefiCpuPkg/MtrrLib/UnitTest: Add host > > based unit test > > > > Add host based unit tests for the MtrrLib services. > > The BaseLib services AsmCpuid(), AsmReadMsr64(), and > > AsmWriteMsr64() are hooked and provide simple emulation > > of the CPUID leafs and MSRs required by the MtrrLib to > > run as a host based unit test. > > > > Test cases are developed for each of the API. > > > > For the most important APIs > > MtrrSetMemoryAttributesInMtrrSettings() > > and MtrrSetMemoryAttributeInMtrrSettings(), random > > inputs are > > generated and fed to the APIs to make sure the > > implementation is > > good. The test application accepts an optional > > parameter which > > specifies how many iterations of feeding random inputs > > to the two > > APIs. The overall number of test cases increases when > > the iteration > > increases. Default iteration is 10 when no parameter is > > specified. > > > > Signed-off-by: Ray Ni <ray...@intel.com> > > Signed-off-by: Michael D Kinney > > <michael.d.kin...@intel.com> > > Signed-off-by: Ming Shao <ming.s...@intel.com> > > Cc: Michael D Kinney <michael.d.kin...@intel.com> > > Cc: Ming Shao <ming.s...@intel.com> > > Cc: Eric Dong <eric.d...@intel.com> > > Cc: Ray Ni <ray...@intel.com> > > Cc: Laszlo Ersek <ler...@redhat.com> > > Cc: Sean Brogan <sean.bro...@microsoft.com> > > Cc: Bret Barkelew <bret.barke...@microsoft.com> > > Cc: Jiewen Yao <jiewen....@intel.com> > > --- > > .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1094 > > +++++++++++++++++ > > .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171 > > +++ > > .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 + > > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913 > > ++++++++++++++ > > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 + > > 5 files changed, 2248 insertions(+) > > create mode 100644 > > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > > create mode 100644 > > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > > create mode 100644 > > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost > > .inf > > create mode 100644 > > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > > create mode 100644 > > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > > > > diff --git > > a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > > new file mode 100644 > > index 0000000000..b0623ddea7 > > --- /dev/null > > +++ > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > > @@ -0,0 +1,1094 @@ > > +/** @file > > > > + Unit tests of the MtrrLib instance of the MtrrLib > > class > > > > + > > > > + Copyright (c) 2020, Intel Corporation. All rights > > reserved.<BR> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > > > + > > > > +**/ > > > > + > > > > +#include "MtrrLibUnitTest.h" > > > > + > > > > +CONST MTRR_LIB_SYSTEM_PARAMETER > > mDefaultSystemParameter = { > > > > + 42, TRUE, TRUE, CacheUncacheable, 12 > > > > + }; > > > > + > > > > +MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] = { > > > > + { 38, TRUE, TRUE, CacheUncacheable, 12 }, > > > > + { 38, TRUE, TRUE, CacheWriteBack, 12 }, > > > > + { 38, TRUE, TRUE, CacheWriteThrough, 12 }, > > > > + { 38, TRUE, TRUE, CacheWriteProtected, 12 }, > > > > + { 38, TRUE, TRUE, CacheWriteCombining, 12 }, > > > > + > > > > + { 42, TRUE, TRUE, CacheUncacheable, 12 }, > > > > + { 42, TRUE, TRUE, CacheWriteBack, 12 }, > > > > + { 42, TRUE, TRUE, CacheWriteThrough, 12 }, > > > > + { 42, TRUE, TRUE, CacheWriteProtected, 12 }, > > > > + { 42, TRUE, TRUE, CacheWriteCombining, 12 }, > > > > + > > > > + { 48, TRUE, TRUE, CacheUncacheable, 12 }, > > > > + { 48, TRUE, TRUE, CacheWriteBack, 12 }, > > > > + { 48, TRUE, TRUE, CacheWriteThrough, 12 }, > > > > + { 48, TRUE, TRUE, CacheWriteProtected, 12 }, > > > > + { 48, TRUE, TRUE, CacheWriteCombining, 12 }, > > > > +}; > > > > + > > > > +UINT32 mFixedMtrrsIndex[] = { > > > > + MSR_IA32_MTRR_FIX64K_00000, > > > > + MSR_IA32_MTRR_FIX16K_80000, > > > > + MSR_IA32_MTRR_FIX16K_A0000, > > > > + MSR_IA32_MTRR_FIX4K_C0000, > > > > + MSR_IA32_MTRR_FIX4K_C8000, > > > > + MSR_IA32_MTRR_FIX4K_D0000, > > > > + MSR_IA32_MTRR_FIX4K_D8000, > > > > + MSR_IA32_MTRR_FIX4K_E0000, > > > > + MSR_IA32_MTRR_FIX4K_E8000, > > > > + MSR_IA32_MTRR_FIX4K_F0000, > > > > + MSR_IA32_MTRR_FIX4K_F8000 > > > > +}; > > > > +STATIC_ASSERT ( > > > > + (ARRAY_SIZE (mFixedMtrrsIndex) == > > MTRR_NUMBER_OF_FIXED_MTRR), > > > > + "gFixedMtrrIndex does NOT contain all the fixed > > MTRRs!" > > > > + ); > > > > + > > > > + > > > > +CHAR8 *mCacheDescription[] = { "UC", "WC", "N/A", > > "N/A", "WT", "WP", "WB" }; > > > > + > > > > +/** > > > > + Compare the actual memory ranges against expected > > memory ranges and return PASS when they match. > > > > + > > > > + @param ExpectedMemoryRanges Expected memory > > ranges. > > > > + @param ExpectedMemoryRangeCount Count of expected > > memory ranges. > > > > + @param ActualRanges Actual memory > > ranges. > > > > + @param ActualRangeCount Count of actual > > memory ranges. > > > > + > > > > + @retval UNIT_TEST_PASSED Test passed. > > > > + @retval others Test failed. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +VerifyMemoryRanges ( > > > > + IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges, > > > > + IN UINTN ExpectedMemoryRangeCount, > > > > + IN MTRR_MEMORY_RANGE *ActualRanges, > > > > + IN UINTN ActualRangeCount > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, > > ActualRangeCount); > > > > + for (Index = 0; Index < ExpectedMemoryRangeCount; > > Index++) { > > > > + UT_ASSERT_EQUAL > > (ExpectedMemoryRanges[Index].BaseAddress, > > ActualRanges[Index].BaseAddress); > > > > + UT_ASSERT_EQUAL > > (ExpectedMemoryRanges[Index].Length, > > ActualRanges[Index].Length); > > > > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, > > ActualRanges[Index].Type); > > > > + } > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Dump the memory ranges. > > > > + > > > > + @param Ranges Memory ranges to dump. > > > > + @param RangeCount Count of memory ranges. > > > > +**/ > > > > +VOID > > > > +DumpMemoryRanges ( > > > > + MTRR_MEMORY_RANGE *Ranges, > > > > + UINTN RangeCount > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + for (Index = 0; Index < RangeCount; Index++) { > > > > + UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", > > Ranges[Index].BaseAddress, Ranges[Index].Length, > > mCacheDescription[Ranges[Index].Type]); > > > > + } > > > > +} > > > > + > > > > +/** > > > > +**/ > > > > + > > > > +/** > > > > + Generate random count of MTRRs for each cache type. > > > > + > > > > + @param TotalCount Total MTRR count. > > > > + @param UcCount Return count of Uncacheable type. > > > > + @param WtCount Return count of Write Through > > type. > > > > + @param WbCount Return count of Write Back type. > > > > + @param WpCount Return count of Write Protected > > type. > > > > + @param WcCount Return count of Write Combining > > type. > > > > +**/ > > > > +VOID > > > > +GenerateRandomMemoryTypeCombination ( > > > > + IN UINT32 TotalCount, > > > > + OUT UINT32 *UcCount, > > > > + OUT UINT32 *WtCount, > > > > + OUT UINT32 *WbCount, > > > > + OUT UINT32 *WpCount, > > > > + OUT UINT32 *WcCount > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + UINT32 TotalMtrrCount; > > > > + UINT32 *CountPerType[5]; > > > > + > > > > + CountPerType[0] = UcCount; > > > > + CountPerType[1] = WtCount; > > > > + CountPerType[2] = WbCount; > > > > + CountPerType[3] = WpCount; > > > > + CountPerType[4] = WcCount; > > > > + > > > > + // > > > > + // Initialize the count of each cache type to 0. > > > > + // > > > > + for (Index = 0; Index < ARRAY_SIZE (CountPerType); > > Index++) { > > > > + *(CountPerType[Index]) = 0; > > > > + } > > > > + > > > > + // > > > > + // Pick a random count of MTRRs > > > > + // > > > > + TotalMtrrCount = Random32 (1, TotalCount); > > > > + for (Index = 0; Index < TotalMtrrCount; Index++) { > > > > + // > > > > + // For each of them, pick a random cache type. > > > > + // > > > > + (*(CountPerType[Random32 (0, ARRAY_SIZE > > (CountPerType) - 1)]))++; > > > > + } > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrSetMemoryAttribute() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrSetMemoryAttributesInMtrrSettings ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > > > + RETURN_STATUS Status; > > > > + UINT32 UcCount; > > > > + UINT32 WtCount; > > > > + UINT32 WbCount; > > > > + UINT32 WpCount; > > > > + UINT32 WcCount; > > > > + > > > > + UINT32 MtrrIndex; > > > > + UINT8 *Scratch; > > > > + UINTN ScratchSize; > > > > + MTRR_SETTINGS LocalMtrrs; > > > > + > > > > + MTRR_MEMORY_RANGE > > RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > + MTRR_MEMORY_RANGE > > ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > > > + UINT32 ExpectedVariableMtrrUsage; > > > > + UINTN ExpectedMemoryRangesCount; > > > > + > > > > + MTRR_MEMORY_RANGE > > ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > > > + UINT32 ActualVariableMtrrUsage; > > > > + UINTN ActualMemoryRangesCount; > > > > + > > > > + MTRR_SETTINGS *Mtrrs[2]; > > > > + > > > > + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) > > Context; > > > > + GenerateRandomMemoryTypeCombination ( > > > > + SystemParameter->VariableMtrrCount - PatchPcdGet32 > > (PcdCpuNumberOfReservedVariableMtrrs), > > > > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount > > > > + ); > > > > + GenerateValidAndConfigurableMtrrPairs ( > > > > + SystemParameter->PhysicalAddressBits, > > RawMtrrRange, > > > > + UcCount, WtCount, WbCount, WpCount, WcCount > > > > + ); > > > > + > > > > + ExpectedVariableMtrrUsage = UcCount + WtCount + > > WbCount + WpCount + WcCount; > > > > + ExpectedMemoryRangesCount = ARRAY_SIZE > > (ExpectedMemoryRanges); > > > > + GetEffectiveMemoryRanges ( > > > > + SystemParameter->DefaultCacheType, > > > > + SystemParameter->PhysicalAddressBits, > > > > + RawMtrrRange, ExpectedVariableMtrrUsage, > > > > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount > > > > + ); > > > > + > > > > + UT_LOG_INFO ( > > > > + "Total MTRR [%d]: UC=%d, WT=%d, WB=%d, WP=%d, > > WC=%d\n", > > > > + ExpectedVariableMtrrUsage, UcCount, WtCount, > > WbCount, WpCount, WcCount > > > > + ); > > > > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] --- > > \n", ExpectedMemoryRangesCount); > > > > + DumpMemoryRanges (ExpectedMemoryRanges, > > ExpectedMemoryRangesCount); > > > > + > > > > + // > > > > + // Default cache type is always an INPUT > > > > + // > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType > > (); > > > > + ScratchSize = SCRATCH_BUFFER_SIZE; > > > > + Mtrrs[0] = &LocalMtrrs; > > > > + Mtrrs[1] = NULL; > > > > + > > > > + for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); > > MtrrIndex++) { > > > > + Scratch = calloc (ScratchSize, sizeof (UINT8)); > > > > + Status = MtrrSetMemoryAttributesInMtrrSettings > > (Mtrrs[MtrrIndex], Scratch, &ScratchSize, > > ExpectedMemoryRanges, ExpectedMemoryRangesCount); > > > > + if (Status == RETURN_BUFFER_TOO_SMALL) { > > > > + Scratch = realloc (Scratch, ScratchSize); > > > > + Status = MtrrSetMemoryAttributesInMtrrSettings > > (Mtrrs[MtrrIndex], Scratch, &ScratchSize, > > ExpectedMemoryRanges, ExpectedMemoryRangesCount); > > > > + } > > > > + UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS); > > > > + > > > > + if (Mtrrs[MtrrIndex] == NULL) { > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + MtrrGetAllMtrrs (&LocalMtrrs); > > > > + } > > > > + ActualMemoryRangesCount = ARRAY_SIZE > > (ActualMemoryRanges); > > > > + CollectTestResult ( > > > > + SystemParameter->DefaultCacheType, > > SystemParameter->PhysicalAddressBits, SystemParameter- > > >VariableMtrrCount, > > > > + &LocalMtrrs, ActualMemoryRanges, > > &ActualMemoryRangesCount, &ActualVariableMtrrUsage > > > > + ); > > > > + > > > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] --- > > \n", ActualMemoryRangesCount); > > > > + DumpMemoryRanges (ActualMemoryRanges, > > ActualMemoryRangesCount); > > > > + VerifyMemoryRanges (ExpectedMemoryRanges, > > ExpectedMemoryRangesCount, ActualMemoryRanges, > > ActualMemoryRangesCount); > > > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= > > ActualVariableMtrrUsage); > > > > + > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + } > > > > + > > > > + free (Scratch); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Test routine to check whether invalid base/size can > > be rejected. > > > > + > > > > + @param Context Pointer to > > MTRR_LIB_SYSTEM_PARAMETER. > > > > + > > > > + @return Test status. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestInvalidMemoryLayouts ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > > > + MTRR_MEMORY_RANGE > > Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1]; > > > > + UINTN RangeCount; > > > > + UINT64 MaxAddress; > > > > + UINT32 Index; > > > > + UINT64 BaseAddress; > > > > + UINT64 Length; > > > > + RETURN_STATUS Status; > > > > + UINTN ScratchSize; > > > > + > > > > + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) > > Context; > > > > + > > > > + RangeCount = Random32 (1, ARRAY_SIZE (Ranges)); > > > > + MaxAddress = 1ull << SystemParameter- > > >PhysicalAddressBits; > > > > + > > > > + for (Index = 0; Index < RangeCount; Index++) { > > > > + do { > > > > + BaseAddress = Random64 (0, MaxAddress); > > > > + Length = Random64 (1, MaxAddress - > > BaseAddress); > > > > + } while (((BaseAddress & 0xFFF) == 0) || ((Length > > & 0xFFF) == 0)); > > > > + > > > > + Ranges[Index].BaseAddress = BaseAddress; > > > > + Ranges[Index].Length = Length; > > > > + Ranges[Index].Type = > > GenerateRandomCacheType (); > > > > + > > > > + Status = MtrrSetMemoryAttribute ( > > > > + Ranges[Index].BaseAddress, Ranges[Index].Length, > > Ranges[Index].Type > > > > + ); > > > > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); > > > > + } > > > > + > > > > + ScratchSize = 0; > > > > + Status = MtrrSetMemoryAttributesInMtrrSettings > > (NULL, NULL, &ScratchSize, Ranges, RangeCount); > > > > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service IsMtrrSupported() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestIsMtrrSupported ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + // > > > > + // MTRR capability off in CPUID leaf. > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > > > + > > > > + // > > > > + // MTRR capability on in CPUID leaf, but no variable > > or fixed MTRRs. > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = 0; > > > > + SystemParameter.FixedMtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > > > + > > > > + // > > > > + // MTRR capability on in CPUID leaf, but no variable > > MTRRs. > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = 0; > > > > + SystemParameter.FixedMtrrSupported = TRUE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > > > + > > > > + // > > > > + // MTRR capability on in CPUID leaf, but no fixed > > MTRRs. > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = 7; > > > > + SystemParameter.FixedMtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_ASSERT_FALSE (IsMtrrSupported ()); > > > > + > > > > + // > > > > + // MTRR capability on in CPUID leaf with both > > variable and fixed MTRRs. > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = 7; > > > > + SystemParameter.FixedMtrrSupported = TRUE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_ASSERT_TRUE (IsMtrrSupported ()); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service GetVariableMtrrCount() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestGetVariableMtrrCount ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + UINT32 Result; > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + // > > > > + // If MTRR capability off in CPUID leaf, then the > > count is always 0. > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + for (SystemParameter.VariableMtrrCount = 1; > > SystemParameter.VariableMtrrCount <= > > MTRR_NUMBER_OF_VARIABLE_MTRR; > > SystemParameter.VariableMtrrCount++) { > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = GetVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + } > > > > + > > > > + // > > > > + // Try all supported variable MTRR counts. > > > > + // If variable MTRR count is > > > MTRR_NUMBER_OF_VARIABLE_MTRR, then an ASSERT() > > > > + // is generated. > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + for (SystemParameter.VariableMtrrCount = 1; > > SystemParameter.VariableMtrrCount <= > > MTRR_NUMBER_OF_VARIABLE_MTRR; > > SystemParameter.VariableMtrrCount++) { > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = GetVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, > > SystemParameter.VariableMtrrCount); > > > > + } > > > > + > > > > + // > > > > + // Expect ASSERT() if variable MTRR count is > > > MTRR_NUMBER_OF_VARIABLE_MTRR > > > > + // > > > > + SystemParameter.VariableMtrrCount = > > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), > > NULL); > > > > + > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = MAX_UINT8; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), > > NULL); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > GetFirmwareVariableMtrrCount() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestGetFirmwareVariableMtrrCount ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + UINT32 Result; > > > > + UINT32 ReservedMtrrs; > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + // > > > > + // Positive test cases for VCNT = 10 and Reserved > > PCD in range 0..10 > > > > + // > > > > + for (ReservedMtrrs = 0; ReservedMtrrs <= > > SystemParameter.VariableMtrrCount; ReservedMtrrs++) { > > > > + PatchPcdSet32 > > (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); > > > > + Result = GetFirmwareVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, > > SystemParameter.VariableMtrrCount - ReservedMtrrs); > > > > + } > > > > + > > > > + // > > > > + // Negative test cases when Reserved PCD is larger > > than VCNT > > > > + // > > > > + for (ReservedMtrrs = > > SystemParameter.VariableMtrrCount + 1; ReservedMtrrs <= > > 255; ReservedMtrrs++) { > > > > + PatchPcdSet32 > > (PcdCpuNumberOfReservedVariableMtrrs, ReservedMtrrs); > > > > + Result = GetFirmwareVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + } > > > > + > > > > + // > > > > + // Negative test cases when Reserved PCD is larger > > than VCNT > > > > + // > > > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > > MAX_UINT32); > > > > + Result = GetFirmwareVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + > > > > + // > > > > + // Negative test case when MTRRs are not supported > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > > 2); > > > > + Result = GetFirmwareVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + > > > > + // > > > > + // Negative test case when Fixed MTRRs are not > > supported > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.FixedMtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > > 2); > > > > + Result = GetFirmwareVariableMtrrCount (); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + > > > > + // > > > > + // Expect ASSERT() if variable MTRR count is > > > MTRR_NUMBER_OF_VARIABLE_MTRR > > > > + // > > > > + SystemParameter.FixedMtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = > > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_EXPECT_ASSERT_FAILURE > > (GetFirmwareVariableMtrrCount (), NULL); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrGetMemoryAttribute() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrGetMemoryAttribute ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service MtrrGetFixedMtrr() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrGetFixedMtrr ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_FIXED_SETTINGS *Result; > > > > + MTRR_FIXED_SETTINGS ExpectedFixedSettings; > > > > + MTRR_FIXED_SETTINGS FixedSettings; > > > > + UINTN Index; > > > > + UINTN MsrIndex; > > > > + UINTN ByteIndex; > > > > + UINT64 MsrValue; > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + // > > > > + // Set random cache type to different ranges under > > 1MB and make sure > > > > + // the fixed MTRR settings are expected. > > > > + // Try 100 times. > > > > + // > > > > + for (Index = 0; Index < 100; Index++) { > > > > + for (MsrIndex = 0; MsrIndex < ARRAY_SIZE > > (mFixedMtrrsIndex); MsrIndex++) { > > > > + MsrValue = 0; > > > > + for (ByteIndex = 0; ByteIndex < sizeof (UINT64); > > ByteIndex++) { > > > > + MsrValue = MsrValue | LShiftU64 > > (GenerateRandomCacheType (), ByteIndex * 8); > > > > + } > > > > + ExpectedFixedSettings.Mtrr[MsrIndex] = MsrValue; > > > > + AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], > > MsrValue); > > > > + } > > > > + > > > > + Result = MtrrGetFixedMtrr (&FixedSettings); > > > > + UT_ASSERT_EQUAL (Result, &FixedSettings); > > > > + UT_ASSERT_MEM_EQUAL (&FixedSettings, > > &ExpectedFixedSettings, sizeof (FixedSettings)); > > > > + } > > > > + > > > > + // > > > > + // Negative test case when MTRRs are not supported > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + > > > > + ZeroMem (&FixedSettings, sizeof (FixedSettings)); > > > > + ZeroMem (&ExpectedFixedSettings, sizeof > > (ExpectedFixedSettings)); > > > > + Result = MtrrGetFixedMtrr (&FixedSettings); > > > > + UT_ASSERT_EQUAL (Result, &FixedSettings); > > > > + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, > > &FixedSettings, sizeof (ExpectedFixedSettings)); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service MtrrGetAllMtrrs() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrGetAllMtrrs ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_SETTINGS *Result; > > > > + MTRR_SETTINGS Mtrrs; > > > > + MTRR_SETTINGS ExpectedMtrrs; > > > > + MTRR_VARIABLE_SETTING > > VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > + UINT32 Index; > > > > + > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + > > > > + for (Index = 0; Index < > > SystemParameter.VariableMtrrCount; Index++) { > > > > + GenerateRandomMtrrPair > > (SystemParameter.PhysicalAddressBits, > > GenerateRandomCacheType (), &VariableMtrr[Index], > > NULL); > > > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << > > 1), VariableMtrr[Index].Base); > > > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << > > 1), VariableMtrr[Index].Mask); > > > > + } > > > > + Result = MtrrGetAllMtrrs (&Mtrrs); > > > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > > > + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, > > VariableMtrr, sizeof (MTRR_VARIABLE_SETTING) * > > SystemParameter.VariableMtrrCount); > > > > + > > > > + // > > > > + // Negative test case when MTRRs are not supported > > > > + // > > > > + ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs)); > > > > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); > > > > + > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetAllMtrrs (&Mtrrs); > > > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > > > + UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof > > (ExpectedMtrrs)); > > > > + > > > > + // > > > > + // Expect ASSERT() if variable MTRR count is > > > MTRR_NUMBER_OF_VARIABLE_MTRR > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = > > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), > > NULL); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service MtrrSetAllMtrrs() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrSetAllMtrrs ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_SETTINGS *Result; > > > > + MTRR_SETTINGS Mtrrs; > > > > + UINT32 Index; > > > > + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default; > > > > + > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + > > > > + Default.Uint64 = 0; > > > > + Default.Bits.E = 1; > > > > + Default.Bits.FE = 1; > > > > + Default.Bits.Type = GenerateRandomCacheType (); > > > > + > > > > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); > > > > + Mtrrs.MtrrDefType = Default.Uint64; > > > > + for (Index = 0; Index < > > SystemParameter.VariableMtrrCount; Index++) { > > > > + GenerateRandomMtrrPair > > (SystemParameter.PhysicalAddressBits, > > GenerateRandomCacheType (), > > &Mtrrs.Variables.Mtrr[Index], NULL); > > > > + } > > > > + Result = MtrrSetAllMtrrs (&Mtrrs); > > > > + UT_ASSERT_EQUAL (Result, &Mtrrs); > > > > + > > > > + UT_ASSERT_EQUAL (AsmReadMsr64 > > (MSR_IA32_MTRR_DEF_TYPE), Mtrrs.MtrrDefType); > > > > + for (Index = 0; Index < > > SystemParameter.VariableMtrrCount; Index++) { > > > > + UT_ASSERT_EQUAL (AsmReadMsr64 > > (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1)), > > Mtrrs.Variables.Mtrr[Index].Base); > > > > + UT_ASSERT_EQUAL (AsmReadMsr64 > > (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1)), > > Mtrrs.Variables.Mtrr[Index].Mask); > > > > + } > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrGetMemoryAttributeInVariableMtrr() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrGetMemoryAttributeInVariableMtrr ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + UINT32 Result; > > > > + MTRR_VARIABLE_SETTING > > VariableSetting[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > + VARIABLE_MTRR > > VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > + UINT64 ValidMtrrBitsMask; > > > > + UINT64 > > ValidMtrrAddressMask; > > > > + UINT32 Index; > > > > + MSR_IA32_MTRR_PHYSBASE_REGISTER Base; > > > > + MSR_IA32_MTRR_PHYSMASK_REGISTER Mask; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + > > > > + ValidMtrrBitsMask = (1ull << > > SystemParameter.PhysicalAddressBits) - 1; > > > > + ValidMtrrAddressMask = ValidMtrrBitsMask & > > 0xfffffffffffff000ULL; > > > > + > > > > + for (Index = 0; Index < > > SystemParameter.VariableMtrrCount; Index++) { > > > > + GenerateRandomMtrrPair > > (SystemParameter.PhysicalAddressBits, > > GenerateRandomCacheType (), &VariableSetting[Index], > > NULL); > > > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << > > 1), VariableSetting[Index].Base); > > > > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << > > 1), VariableSetting[Index].Mask); > > > > + } > > > > + Result = MtrrGetMemoryAttributeInVariableMtrr > > (ValidMtrrBitsMask, ValidMtrrAddressMask, > > VariableMtrr); > > > > + UT_ASSERT_EQUAL (Result, > > SystemParameter.VariableMtrrCount); > > > > + > > > > + for (Index = 0; Index < > > SystemParameter.VariableMtrrCount; Index++) { > > > > + Base.Uint64 = VariableMtrr[Index].BaseAddress; > > > > + Base.Bits.Type = (UINT32) > > VariableMtrr[Index].Type; > > > > + UT_ASSERT_EQUAL (Base.Uint64, > > VariableSetting[Index].Base); > > > > + > > > > + Mask.Uint64 = ~(VariableMtrr[Index].Length - 1) > > & ValidMtrrBitsMask; > > > > + Mask.Bits.V = 1; > > > > + UT_ASSERT_EQUAL (Mask.Uint64, > > VariableSetting[Index].Mask); > > > > + } > > > > + > > > > + // > > > > + // Negative test case when MTRRs are not supported > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetMemoryAttributeInVariableMtrr > > (ValidMtrrBitsMask, ValidMtrrAddressMask, > > VariableMtrr); > > > > + UT_ASSERT_EQUAL (Result, 0); > > > > + > > > > + // > > > > + // Expect ASSERT() if variable MTRR count is > > > MTRR_NUMBER_OF_VARIABLE_MTRR > > > > + // > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = > > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + UT_EXPECT_ASSERT_FAILURE > > (MtrrGetMemoryAttributeInVariableMtrr > > (ValidMtrrBitsMask, ValidMtrrAddressMask, > > VariableMtrr), NULL); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrDebugPrintAllMtrrs() > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrDebugPrintAllMtrrs ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrGetDefaultMemoryType(). > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrGetDefaultMemoryType ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + MTRR_MEMORY_CACHE_TYPE Result; > > > > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; > > > > + MTRR_MEMORY_CACHE_TYPE CacheType[5]; > > > > + > > > > + CacheType[0] = CacheUncacheable; > > > > + CacheType[1] = CacheWriteCombining; > > > > + CacheType[2] = CacheWriteThrough; > > > > + CacheType[3] = CacheWriteProtected; > > > > + CacheType[4] = CacheWriteBack; > > > > + > > > > + CopyMem (&SystemParameter, &mDefaultSystemParameter, > > sizeof (SystemParameter)); > > > > + // > > > > + // If MTRRs are supported, then always return the > > cache type in the MSR > > > > + // MSR_IA32_MTRR_DEF_TYPE > > > > + // > > > > + for (Index = 0; Index < ARRAY_SIZE (CacheType); > > Index++) { > > > > + SystemParameter.DefaultCacheType = > > CacheType[Index]; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetDefaultMemoryType (); > > > > + UT_ASSERT_EQUAL (Result, > > SystemParameter.DefaultCacheType); > > > > + } > > > > + > > > > + // > > > > + // If MTRRs are not supported, then always return > > CacheUncacheable > > > > + // > > > > + SystemParameter.MtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetDefaultMemoryType (); > > > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > > > + > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.FixedMtrrSupported = FALSE; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetDefaultMemoryType (); > > > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > > > + > > > > + SystemParameter.MtrrSupported = TRUE; > > > > + SystemParameter.FixedMtrrSupported = TRUE; > > > > + SystemParameter.VariableMtrrCount = 0; > > > > + InitializeMtrrRegs (&SystemParameter); > > > > + Result = MtrrGetDefaultMemoryType (); > > > > + UT_ASSERT_EQUAL (Result, CacheUncacheable); > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Unit test of MtrrLib service > > MtrrSetMemoryAttributeInMtrrSettings(). > > > > + > > > > + @param[in] Context Ignored > > > > + > > > > + @retval UNIT_TEST_PASSED The Unit test > > has completed and the test > > > > + case was > > successful. > > > > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case > > assertion has failed. > > > > + > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +UnitTestMtrrSetMemoryAttributeInMtrrSettings ( > > > > + IN UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; > > > > + RETURN_STATUS Status; > > > > + UINT32 UcCount; > > > > + UINT32 WtCount; > > > > + UINT32 WbCount; > > > > + UINT32 WpCount; > > > > + UINT32 WcCount; > > > > + > > > > + UINTN MtrrIndex; > > > > + UINTN Index; > > > > + MTRR_SETTINGS LocalMtrrs; > > > > + > > > > + MTRR_MEMORY_RANGE > > RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > + MTRR_MEMORY_RANGE > > ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > > > + UINT32 ExpectedVariableMtrrUsage; > > > > + UINTN ExpectedMemoryRangesCount; > > > > + > > > > + MTRR_MEMORY_RANGE > > ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; > > > > + UINT32 ActualVariableMtrrUsage; > > > > + UINTN ActualMemoryRangesCount; > > > > + > > > > + MTRR_SETTINGS *Mtrrs[2]; > > > > + > > > > + SystemParameter = (MTRR_LIB_SYSTEM_PARAMETER *) > > Context; > > > > + GenerateRandomMemoryTypeCombination ( > > > > + SystemParameter->VariableMtrrCount - PatchPcdGet32 > > (PcdCpuNumberOfReservedVariableMtrrs), > > > > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount > > > > + ); > > > > + GenerateValidAndConfigurableMtrrPairs ( > > > > + SystemParameter->PhysicalAddressBits, > > RawMtrrRange, > > > > + UcCount, WtCount, WbCount, WpCount, WcCount > > > > + ); > > > > + > > > > + ExpectedVariableMtrrUsage = UcCount + WtCount + > > WbCount + WpCount + WcCount; > > > > + ExpectedMemoryRangesCount = ARRAY_SIZE > > (ExpectedMemoryRanges); > > > > + GetEffectiveMemoryRanges ( > > > > + SystemParameter->DefaultCacheType, > > > > + SystemParameter->PhysicalAddressBits, > > > > + RawMtrrRange, ExpectedVariableMtrrUsage, > > > > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount > > > > + ); > > > > + > > > > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] --- > > \n", ExpectedMemoryRangesCount); > > > > + DumpMemoryRanges (ExpectedMemoryRanges, > > ExpectedMemoryRangesCount); > > > > + // > > > > + // Default cache type is always an INPUT > > > > + // > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + LocalMtrrs.MtrrDefType = MtrrGetDefaultMemoryType > > (); > > > > + Mtrrs[0] = &LocalMtrrs; > > > > + Mtrrs[1] = NULL; > > > > + > > > > + for (MtrrIndex = 0; MtrrIndex < ARRAY_SIZE (Mtrrs); > > MtrrIndex++) { > > > > + for (Index = 0; Index < ExpectedMemoryRangesCount; > > Index++) { > > > > + Status = MtrrSetMemoryAttributeInMtrrSettings ( > > > > + Mtrrs[MtrrIndex], > > > > + > > ExpectedMemoryRanges[Index].BaseAddress, > > > > + ExpectedMemoryRanges[Index].Length, > > > > + ExpectedMemoryRanges[Index].Type > > > > + ); > > > > + UT_ASSERT_TRUE (Status == RETURN_SUCCESS || > > Status == RETURN_OUT_OF_RESOURCES || Status == > > RETURN_BUFFER_TOO_SMALL); > > > > + if (Status == RETURN_OUT_OF_RESOURCES || Status > > == RETURN_BUFFER_TOO_SMALL) { > > > > + return UNIT_TEST_SKIPPED; > > > > + } > > > > + } > > > > + > > > > + if (Mtrrs[MtrrIndex] == NULL) { > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + MtrrGetAllMtrrs (&LocalMtrrs); > > > > + } > > > > + ActualMemoryRangesCount = ARRAY_SIZE > > (ActualMemoryRanges); > > > > + CollectTestResult ( > > > > + SystemParameter->DefaultCacheType, > > SystemParameter->PhysicalAddressBits, SystemParameter- > > >VariableMtrrCount, > > > > + &LocalMtrrs, ActualMemoryRanges, > > &ActualMemoryRangesCount, &ActualVariableMtrrUsage > > > > + ); > > > > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] --- > > \n", ActualMemoryRangesCount); > > > > + DumpMemoryRanges (ActualMemoryRanges, > > ActualMemoryRangesCount); > > > > + VerifyMemoryRanges (ExpectedMemoryRanges, > > ExpectedMemoryRangesCount, ActualMemoryRanges, > > ActualMemoryRangesCount); > > > > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >= > > ActualVariableMtrrUsage); > > > > + > > > > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); > > > > + } > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Prep routine for > > UnitTestGetFirmwareVariableMtrrCount(). > > > > + > > > > + @param Context Point to a UINT32 data to save the > > PcdCpuNumberOfReservedVariableMtrrs. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +SavePcdValue ( > > > > + UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + *(UINT32 *) Context = PatchPcdGet32 > > (PcdCpuNumberOfReservedVariableMtrrs); > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Clean up routine for > > UnitTestGetFirmwareVariableMtrrCount(). > > > > + > > > > + @param Context Point to a UINT32 data to save the > > PcdCpuNumberOfReservedVariableMtrrs. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +RestorePcdValue ( > > > > + UNIT_TEST_CONTEXT Context > > > > + ) > > > > +{ > > > > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > > *(UINT32 *) Context); > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Initialize the unit test framework, suite, and unit > > tests for the > > > > + ResetSystemLib and run the ResetSystemLib unit test. > > > > + > > > > + @param Iteration Iteration of testing > > MtrrSetMemoryAttributeInMtrrSettings > > > > + and > > MtrrSetMemoryAttributesInMtrrSettings using random > > inputs. > > > > + > > > > + @retval EFI_SUCCESS All test cases were > > dispatched. > > > > + @retval EFI_OUT_OF_RESOURCES There are not enough > > resources available to > > > > + initialize the unit > > tests. > > > > +**/ > > > > +STATIC > > > > +EFI_STATUS > > > > +EFIAPI > > > > +UnitTestingEntry ( > > > > + UINTN Iteration > > > > + ) > > > > +{ > > > > + EFI_STATUS Status; > > > > + UNIT_TEST_FRAMEWORK_HANDLE Framework; > > > > + UNIT_TEST_SUITE_HANDLE MtrrApiTests; > > > > + UINTN Index; > > > > + UINTN SystemIndex; > > > > + UINT32 OriginalPcdValue; > > > > + > > > > + Framework = NULL; > > > > + > > > > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, > > UNIT_TEST_APP_VERSION)); > > > > + > > > > + // > > > > + // Setup the test framework for running the tests. > > > > + // > > > > + Status = InitUnitTestFramework (&Framework, > > UNIT_TEST_APP_NAME, gEfiCallerBaseName, > > UNIT_TEST_APP_VERSION); > > > > + if (EFI_ERROR (Status)) { > > > > + DEBUG ((DEBUG_ERROR, "Failed in > > InitUnitTestFramework. Status = %r\n", Status)); > > > > + goto EXIT; > > > > + } > > > > + > > > > + // > > > > + // --------------Suite-----------Description-------- > > ------Name----------Function--------Pre---Post--------- > > ----------Context----------- > > > > + // > > > > + > > > > + // > > > > + // Populate the MtrrLib API Unit Test Suite. > > > > + // > > > > + Status = CreateUnitTestSuite (&MtrrApiTests, > > Framework, "MtrrLib API Tests", "MtrrLib.MtrrLib", > > NULL, NULL); > > > > + if (EFI_ERROR (Status)) { > > > > + DEBUG ((DEBUG_ERROR, "Failed in > > CreateUnitTestSuite for MtrrLib API Tests\n")); > > > > + Status = EFI_OUT_OF_RESOURCES; > > > > + goto EXIT; > > > > + } > > > > + AddTestCase (MtrrApiTests, "Test IsMtrrSupported", > > "MtrrSupported", > > UnitTestIsMtrrSupported, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test > > GetVariableMtrrCount", > > "GetVariableMtrrCount", > > UnitTestGetVariableMtrrCount, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test > > GetFirmwareVariableMtrrCount", > > "GetFirmwareVariableMtrrCount", > > UnitTestGetFirmwareVariableMtrrCount, > > SavePcdValue, RestorePcdValue, &OriginalPcdValue); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrGetMemoryAttribute", > > "MtrrGetMemoryAttribute", > > UnitTestMtrrGetMemoryAttribute, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", > > "MtrrGetFixedMtrr", > > UnitTestMtrrGetFixedMtrr, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", > > "MtrrGetAllMtrrs", > > UnitTestMtrrGetAllMtrrs, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", > > "MtrrSetAllMtrrs", > > UnitTestMtrrSetAllMtrrs, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrGetMemoryAttributeInVariableMtrr", > > "MtrrGetMemoryAttributeInVariableMtrr", > > UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrDebugPrintAllMtrrs", > > "MtrrDebugPrintAllMtrrs", > > UnitTestMtrrDebugPrintAllMtrrs, NULL, > > NULL, NULL); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrGetDefaultMemoryType", > > "MtrrGetDefaultMemoryType", > > UnitTestMtrrGetDefaultMemoryType, NULL, > > NULL, NULL); > > > > + > > > > + for (SystemIndex = 0; SystemIndex < ARRAY_SIZE > > (mSystemParameters); SystemIndex++) { > > > > + for (Index = 0; Index < Iteration; Index++) { > > > > + AddTestCase (MtrrApiTests, "Test > > InvalidMemoryLayouts", > > "InvalidMemoryLayouts", > > UnitTestInvalidMemoryLayouts, > > InitializeMtrrRegs, NULL, > > &mSystemParameters[SystemIndex]); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrSetMemoryAttributeInMtrrSettings", > > "MtrrSetMemoryAttributeInMtrrSettings", > > UnitTestMtrrSetMemoryAttributeInMtrrSettings, > > InitializeMtrrRegs, NULL, > > &mSystemParameters[SystemIndex]); > > > > + AddTestCase (MtrrApiTests, "Test > > MtrrSetMemoryAttributesInMtrrSettings", > > "MtrrSetMemoryAttributesInMtrrSettings", > > UnitTestMtrrSetMemoryAttributesInMtrrSettings, > > InitializeMtrrRegs, NULL, > > &mSystemParameters[SystemIndex]); > > > > + } > > > > + } > > > > + // > > > > + // Execute the tests. > > > > + // > > > > + srand ((unsigned int) time (NULL)); > > > > + Status = RunAllTestSuites (Framework); > > > > + > > > > +EXIT: > > > > + if (Framework != NULL) { > > > > + FreeUnitTestFramework (Framework); > > > > + } > > > > + > > > > + return Status; > > > > +} > > > > + > > > > +/** > > > > + Standard POSIX C entry point for host based unit > > test execution. > > > > + > > > > + @param Argc Number of arguments. > > > > + @param Argv Array of arguments. > > > > + > > > > + @return Test application exit code. > > > > +**/ > > > > +INT32 > > > > +main ( > > > > + INT32 Argc, > > > > + CHAR8 *Argv[] > > > > + ) > > > > +{ > > > > + UINTN Iteration; > > > > + > > > > + // > > > > + // First parameter specifies the test iterations. > > > > + // Default is 10. > > > > + // > > > > + Iteration = 10; > > > > + if (Argc == 2) { > > > > + Iteration = atoi (Argv[1]); > > > > + } > > > > + return UnitTestingEntry (Iteration); > > > > +} > > > > diff --git > > a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > > new file mode 100644 > > index 0000000000..25d4269589 > > --- /dev/null > > +++ > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > > @@ -0,0 +1,171 @@ > > +/** @file > > > > + > > > > + Copyright (c) 2020, Intel Corporation. All rights > > reserved.<BR> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > > > + > > > > +**/ > > > > + > > > > +#ifndef _MTRR_SUPPORT_H_ > > > > +#define _MTRR_SUPPORT_H_ > > > > + > > > > +#include <stdio.h> > > > > +#include <stdlib.h> > > > > +#include <string.h> > > > > +#include <stdarg.h> > > > > +#include <stddef.h> > > > > +#include <setjmp.h> > > > > +#include <cmocka.h> > > > > +#include <time.h> > > > > + > > > > +#include <Uefi.h> > > > > +#include <Library/BaseLib.h> > > > > +#include <Library/BaseMemoryLib.h> > > > > +#include <Library/DebugLib.h> > > > > +#include <Library/UnitTestLib.h> > > > > +#include <Library/MtrrLib.h> > > > > +#include <Library/UnitTestHostBaseLib.h> > > > > + > > > > +#include <Register/ArchitecturalMsr.h> > > > > +#include <Register/Cpuid.h> > > > > +#include <Register/Msr.h> > > > > + > > > > +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests" > > > > +#define UNIT_TEST_APP_VERSION "1.0" > > > > + > > > > +#define SCRATCH_BUFFER_SIZE SIZE_16KB > > > > + > > > > +typedef struct { > > > > + UINT8 PhysicalAddressBits; > > > > + BOOLEAN MtrrSupported; > > > > + BOOLEAN FixedMtrrSupported; > > > > + MTRR_MEMORY_CACHE_TYPE DefaultCacheType; > > > > + UINT32 VariableMtrrCount; > > > > +} MTRR_LIB_SYSTEM_PARAMETER; > > > > + > > > > +extern UINT32 > > mFixedMtrrsIndex[]; > > > > + > > > > +/** > > > > + Initialize the MTRR registers. > > > > + > > > > + @param SystemParameter System parameter that > > controls the MTRR registers initialization. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +InitializeMtrrRegs ( > > > > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter > > > > + ); > > > > + > > > > +/** > > > > + Return a random memory cache type. > > > > +**/ > > > > +MTRR_MEMORY_CACHE_TYPE > > > > +GenerateRandomCacheType ( > > > > + VOID > > > > + ); > > > > + > > > > +/** > > > > + Generate random MTRRs. > > > > + > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param RawMemoryRanges Return the randomly > > generated MTRRs. > > > > + @param UcCount Count of Uncacheable > > MTRRs. > > > > + @param WtCount Count of Write Through > > MTRRs. > > > > + @param WbCount Count of Write Back > > MTRRs. > > > > + @param WpCount Count of Write Protected > > MTRRs. > > > > + @param WcCount Count of Write Combining > > MTRRs. > > > > +**/ > > > > +VOID > > > > +GenerateValidAndConfigurableMtrrPairs ( > > > > + IN UINT32 > > PhysicalAddressBits, > > > > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 UcCount, > > > > + IN UINT32 WtCount, > > > > + IN UINT32 WbCount, > > > > + IN UINT32 WpCount, > > > > + IN UINT32 WcCount > > > > + ); > > > > + > > > > +/** > > > > + Convert the MTRR BASE/MASK array to memory ranges. > > > > + > > > > + @param DefaultType Default memory type. > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param RawMemoryRanges Raw memory ranges. > > > > + @param RawMemoryRangeCount Count of raw memory > > ranges. > > > > + @param MemoryRanges Memory ranges. > > > > + @param MemoryRangeCount Count of memory ranges. > > > > +**/ > > > > +VOID > > > > +GetEffectiveMemoryRanges ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 RawMemoryRangeCount, > > > > + OUT MTRR_MEMORY_RANGE *MemoryRanges, > > > > + OUT UINTN *MemoryRangeCount > > > > + ); > > > > + > > > > +/** > > > > + Generate random MTRR BASE/MASK for a specified type. > > > > + > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param CacheType Cache type. > > > > + @param MtrrPair Return the random MTRR. > > > > + @param MtrrMemoryRange Return the random memory > > range. > > > > +**/ > > > > +VOID > > > > +GenerateRandomMtrrPair ( > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN MTRR_MEMORY_CACHE_TYPE CacheType, > > > > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL > > > > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL > > > > + ); > > > > + > > > > +/** > > > > + Collect the test result. > > > > + > > > > + @param DefaultType Default memory type. > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param VariableMtrrCount Count of variable MTRRs. > > > > + @param Mtrrs MTRR settings to collect > > from. > > > > + @param Ranges Return the memory > > ranges. > > > > + @param RangeCount Return the count of > > memory ranges. > > > > + @param MtrrCount Return the count of > > variable MTRRs being used. > > > > +**/ > > > > +VOID > > > > +CollectTestResult ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN UINT32 VariableMtrrCount, > > > > + IN MTRR_SETTINGS *Mtrrs, > > > > + OUT MTRR_MEMORY_RANGE *Ranges, > > > > + IN OUT UINTN *RangeCount, > > > > + OUT UINT32 *MtrrCount > > > > + ); > > > > + > > > > +/** > > > > + Return a 64bit random number. > > > > + > > > > + @param Start Start of the random number range. > > > > + @param Limit Limit of the random number range. > > > > + @return 64bit random number > > > > +**/ > > > > +UINT64 > > > > +Random64 ( > > > > + UINT64 Start, > > > > + UINT64 Limit > > > > + ); > > > > + > > > > +/** > > > > + Return a 32bit random number. > > > > + > > > > + @param Start Start of the random number range. > > > > + @param Limit Limit of the random number range. > > > > + @return 32bit random number > > > > +**/ > > > > +UINT32 > > > > +Random32 ( > > > > + UINT32 Start, > > > > + UINT32 Limit > > > > + ); > > > > +#endif > > > > diff --git > > a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo > > st.inf > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo > > st.inf > > new file mode 100644 > > index 0000000000..447238dc81 > > --- /dev/null > > +++ > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHo > > st.inf > > @@ -0,0 +1,39 @@ > > +## @file > > > > +# Unit tests of the MtrrLib instance of the MtrrLib > > class > > > > +# > > > > +# Copyright (c) 2020, Intel Corporation. All rights > > reserved.<BR> > > > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > > > +## > > > > + > > > > +[Defines] > > > > + INF_VERSION = 0x00010006 > > > > + BASE_NAME = MtrrLibUnitTestHost > > > > + FILE_GUID = A1542D84-B64D-4847- > > 885E-0509084376AB > > > > + MODULE_TYPE = HOST_APPLICATION > > > > + VERSION_STRING = 1.0 > > > > + > > > > +# > > > > +# The following information is for reference only and > > not required by the build tools. > > > > +# > > > > +# VALID_ARCHITECTURES = IA32 X64 > > > > +# > > > > + > > > > +[Sources] > > > > + MtrrLibUnitTest.c > > > > + MtrrLibUnitTest.h > > > > + Support.c > > > > + > > > > +[Packages] > > > > + MdePkg/MdePkg.dec > > > > + UefiCpuPkg/UefiCpuPkg.dec > > > > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec > > > > + > > > > +[LibraryClasses] > > > > + BaseLib > > > > + BaseMemoryLib > > > > + DebugLib > > > > + MtrrLib > > > > + UnitTestLib > > > > + > > > > +[Pcd] > > > > + > > gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariabl > > eMtrrs ## SOMETIMES_CONSUMES > > > > diff --git > > a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > > b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > > new file mode 100644 > > index 0000000000..9fe4b0278e > > --- /dev/null > > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > > @@ -0,0 +1,913 @@ > > +/** @file > > > > + Unit tests of the MtrrLib instance of the MtrrLib > > class > > > > + > > > > + Copyright (c) 2018 - 2020, Intel Corporation. All > > rights reserved.<BR> > > > > + SPDX-License-Identifier: BSD-2-Clause-Patent > > > > + > > > > +**/ > > > > + > > > > +#include "MtrrLibUnitTest.h" > > > > + > > > > +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] = { > > > > + CacheUncacheable, CacheWriteCombining, > > CacheWriteThrough, CacheWriteProtected, CacheWriteBack > > > > + }; > > > > + > > > > +UINT64 > > mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_MTRR]; > > > > +MSR_IA32_MTRR_PHYSBASE_REGISTER > > mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > +MSR_IA32_MTRR_PHYSMASK_REGISTER > > mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR]; > > > > +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; > > > > +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; > > > > +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; > > > > +CPUID_VIR_PHY_ADDRESS_SIZE_EAX > > mCpuidVirPhyAddressSizeEax; > > > > + > > > > +/** > > > > + Retrieves CPUID information. > > > > + > > > > + Executes the CPUID instruction with EAX set to the > > value specified by Index. > > > > + This function always returns Index. > > > > + If Eax is not NULL, then the value of EAX after > > CPUID is returned in Eax. > > > > + If Ebx is not NULL, then the value of EBX after > > CPUID is returned in Ebx. > > > > + If Ecx is not NULL, then the value of ECX after > > CPUID is returned in Ecx. > > > > + If Edx is not NULL, then the value of EDX after > > CPUID is returned in Edx. > > > > + This function is only available on IA-32 and x64. > > > > + > > > > + @param Index The 32-bit value to load into EAX > > prior to invoking the CPUID > > > > + instruction. > > > > + @param Eax The pointer to the 32-bit EAX value > > returned by the CPUID > > > > + instruction. This is an optional > > parameter that may be NULL. > > > > + @param Ebx The pointer to the 32-bit EBX value > > returned by the CPUID > > > > + instruction. This is an optional > > parameter that may be NULL. > > > > + @param Ecx The pointer to the 32-bit ECX value > > returned by the CPUID > > > > + instruction. This is an optional > > parameter that may be NULL. > > > > + @param Edx The pointer to the 32-bit EDX value > > returned by the CPUID > > > > + instruction. This is an optional > > parameter that may be NULL. > > > > + > > > > + @return Index. > > > > + > > > > +**/ > > > > +UINT32 > > > > +EFIAPI > > > > +UnitTestMtrrLibAsmCpuid ( > > > > + IN UINT32 Index, > > > > + OUT UINT32 *Eax, OPTIONAL > > > > + OUT UINT32 *Ebx, OPTIONAL > > > > + OUT UINT32 *Ecx, OPTIONAL > > > > + OUT UINT32 *Edx OPTIONAL > > > > + ) > > > > +{ > > > > + switch (Index) { > > > > + case CPUID_VERSION_INFO: > > > > + if (Edx != NULL) { > > > > + *Edx = mCpuidVersionInfoEdx.Uint32; > > > > + } > > > > + return Index; > > > > + break; > > > > + case CPUID_EXTENDED_FUNCTION: > > > > + if (Eax != NULL) { > > > > + *Eax = CPUID_VIR_PHY_ADDRESS_SIZE; > > > > + } > > > > + return Index; > > > > + break; > > > > + case CPUID_VIR_PHY_ADDRESS_SIZE: > > > > + if (Eax != NULL) { > > > > + *Eax = mCpuidVirPhyAddressSizeEax.Uint32; > > > > + } > > > > + return Index; > > > > + break; > > > > + } > > > > + > > > > + // > > > > + // Should never fall through to here > > > > + // > > > > + ASSERT(FALSE); > > > > + return Index; > > > > +} > > > > + > > > > +/** > > > > + Returns a 64-bit Machine Specific Register(MSR). > > > > + > > > > + Reads and returns the 64-bit MSR specified by Index. > > No parameter checking is > > > > + performed on Index, and some Index values may cause > > CPU exceptions. The > > > > + caller must either guarantee that Index is valid, or > > the caller must set up > > > > + exception handlers to catch the exceptions. This > > function is only available > > > > + on IA-32 and x64. > > > > + > > > > + @param MsrIndex The 32-bit MSR index to read. > > > > + > > > > + @return The value of the MSR identified by MsrIndex. > > > > + > > > > +**/ > > > > +UINT64 > > > > +EFIAPI > > > > +UnitTestMtrrLibAsmReadMsr64( > > > > + IN UINT32 MsrIndex > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + > > > > + for (Index = 0; Index < ARRAY_SIZE > > (mFixedMtrrsValue); Index++) { > > > > + if (MsrIndex == mFixedMtrrsIndex[Index]) { > > > > + return mFixedMtrrsValue[Index]; > > > > + } > > > > + } > > > > + > > > > + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) && > > > > + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + > > (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) { > > > > + if (MsrIndex % 2 == 0) { > > > > + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> > > 1; > > > > + return mVariableMtrrsPhysBase[Index].Uint64; > > > > + } else { > > > > + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> > > 1; > > > > + return mVariableMtrrsPhysMask[Index].Uint64; > > > > + } > > > > + } > > > > + > > > > + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) { > > > > + return mDefTypeMsr.Uint64; > > > > + } > > > > + > > > > + if (MsrIndex == MSR_IA32_MTRRCAP) { > > > > + return mMtrrCapMsr.Uint64; > > > > + } > > > > + > > > > + // > > > > + // Should never fall through to here > > > > + // > > > > + ASSERT(FALSE); > > > > + return 0; > > > > +} > > > > + > > > > +/** > > > > + Writes a 64-bit value to a Machine Specific > > Register(MSR), and returns the > > > > + value. > > > > + > > > > + Writes the 64-bit value specified by Value to the > > MSR specified by Index. The > > > > + 64-bit value written to the MSR is returned. No > > parameter checking is > > > > + performed on Index or Value, and some of these may > > cause CPU exceptions. The > > > > + caller must either guarantee that Index and Value > > are valid, or the caller > > > > + must establish proper exception handlers. This > > function is only available on > > > > + IA-32 and x64. > > > > + > > > > + @param MsrIndex The 32-bit MSR index to write. > > > > + @param Value The 64-bit value to write to the MSR. > > > > + > > > > + @return Value > > > > + > > > > +**/ > > > > +UINT64 > > > > +EFIAPI > > > > +UnitTestMtrrLibAsmWriteMsr64( > > > > + IN UINT32 MsrIndex, > > > > + IN UINT64 Value > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + > > > > + for (Index = 0; Index < ARRAY_SIZE > > (mFixedMtrrsValue); Index++) { > > > > + if (MsrIndex == mFixedMtrrsIndex[Index]) { > > > > + mFixedMtrrsValue[Index] = Value; > > > > + return Value; > > > > + } > > > > + } > > > > + > > > > + if ((MsrIndex >= MSR_IA32_MTRR_PHYSBASE0) && > > > > + (MsrIndex <= MSR_IA32_MTRR_PHYSMASK0 + > > (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) { > > > > + if (MsrIndex % 2 == 0) { > > > > + Index = (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> > > 1; > > > > + mVariableMtrrsPhysBase[Index].Uint64 = Value; > > > > + return Value; > > > > + } else { > > > > + Index = (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> > > 1; > > > > + mVariableMtrrsPhysMask[Index].Uint64 = Value; > > > > + return Value; > > > > + } > > > > + } > > > > + > > > > + if (MsrIndex == MSR_IA32_MTRR_DEF_TYPE) { > > > > + mDefTypeMsr.Uint64 = Value; > > > > + return Value; > > > > + } > > > > + > > > > + if (MsrIndex == MSR_IA32_MTRRCAP) { > > > > + mMtrrCapMsr.Uint64 = Value; > > > > + return Value; > > > > + } > > > > + > > > > + // > > > > + // Should never fall through to here > > > > + // > > > > + ASSERT(FALSE); > > > > + return 0; > > > > +} > > > > + > > > > +/** > > > > + Initialize MTRR registers. > > > > +**/ > > > > + > > > > +/** > > > > + Initialize the MTRR registers. > > > > + > > > > + @param SystemParameter System parameter that > > controls the MTRR registers initialization. > > > > +**/ > > > > +UNIT_TEST_STATUS > > > > +EFIAPI > > > > +InitializeMtrrRegs ( > > > > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + > > > > + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), > > SystemParameter->DefaultCacheType); > > > > + > > > > + for (Index = 0; Index < ARRAY_SIZE > > (mVariableMtrrsPhysBase); Index++) { > > > > + mVariableMtrrsPhysBase[Index].Uint64 = 0; > > > > + mVariableMtrrsPhysBase[Index].Bits.Type = > > SystemParameter->DefaultCacheType; > > > > + mVariableMtrrsPhysBase[Index].Bits.Reserved1 = 0; > > > > + > > > > + mVariableMtrrsPhysMask[Index].Uint64 = 0; > > > > + mVariableMtrrsPhysMask[Index].Bits.V = 0; > > > > + mVariableMtrrsPhysMask[Index].Bits.Reserved1 = 0; > > > > + } > > > > + > > > > + mDefTypeMsr.Bits.E = 1; > > > > + mDefTypeMsr.Bits.FE = 1; > > > > + mDefTypeMsr.Bits.Type = SystemParameter- > > >DefaultCacheType; > > > > + mDefTypeMsr.Bits.Reserved1 = 0; > > > > + mDefTypeMsr.Bits.Reserved2 = 0; > > > > + mDefTypeMsr.Bits.Reserved3 = 0; > > > > + > > > > + mMtrrCapMsr.Bits.SMRR = 0; > > > > + mMtrrCapMsr.Bits.WC = 0; > > > > + mMtrrCapMsr.Bits.VCNT = SystemParameter- > > >VariableMtrrCount; > > > > + mMtrrCapMsr.Bits.FIX = SystemParameter- > > >FixedMtrrSupported; > > > > + mMtrrCapMsr.Bits.Reserved1 = 0; > > > > + mMtrrCapMsr.Bits.Reserved2 = 0; > > > > + mMtrrCapMsr.Bits.Reserved3 = 0; > > > > + > > > > + mCpuidVersionInfoEdx.Bits.MTRR > > = SystemParameter->MtrrSupported; > > > > + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits > > = SystemParameter->PhysicalAddressBits; > > > > + > > > > + // > > > > + // Hook BaseLib functions used by MtrrLib that > > require some emulation. > > > > + // > > > > + gUnitTestHostBaseLib.X86->AsmCpuid = > > UnitTestMtrrLibAsmCpuid; > > > > + gUnitTestHostBaseLib.X86->AsmReadMsr64 = > > UnitTestMtrrLibAsmReadMsr64; > > > > + gUnitTestHostBaseLib.X86->AsmWriteMsr64 = > > UnitTestMtrrLibAsmWriteMsr64; > > > > + > > > > + return UNIT_TEST_PASSED; > > > > +} > > > > + > > > > +/** > > > > + Collect the test result. > > > > + > > > > + @param DefaultType Default memory type. > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param VariableMtrrCount Count of variable MTRRs. > > > > + @param Mtrrs MTRR settings to collect > > from. > > > > + @param Ranges Return the memory > > ranges. > > > > + @param RangeCount Return the count of > > memory ranges. > > > > + @param MtrrCount Return the count of > > variable MTRRs being used. > > > > +**/ > > > > +VOID > > > > +CollectTestResult ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN UINT32 VariableMtrrCount, > > > > + IN MTRR_SETTINGS *Mtrrs, > > > > + OUT MTRR_MEMORY_RANGE *Ranges, > > > > + IN OUT UINTN *RangeCount, > > > > + OUT UINT32 *MtrrCount > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + UINT64 MtrrValidBitsMask; > > > > + UINT64 MtrrValidAddressMask; > > > > + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs- > > >Variables.Mtrr)]; > > > > + > > > > + ASSERT (Mtrrs != NULL); > > > > + ASSERT (VariableMtrrCount <= ARRAY_SIZE (Mtrrs- > > >Variables.Mtrr)); > > > > + > > > > + MtrrValidBitsMask = (1ull << PhysicalAddressBits) - > > 1; > > > > + MtrrValidAddressMask = MtrrValidBitsMask & > > ~0xFFFull; > > > > + > > > > + *MtrrCount = 0; > > > > + for (Index = 0; Index < VariableMtrrCount; Index++) > > { > > > > + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs- > > >Variables.Mtrr[Index].Mask)->Bits.V == 1) { > > > > + RawMemoryRanges[*MtrrCount].BaseAddress = Mtrrs- > > >Variables.Mtrr[Index].Base & MtrrValidAddressMask; > > > > + RawMemoryRanges[*MtrrCount].Type = > > > > + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs- > > >Variables.Mtrr[Index].Base)->Bits.Type; > > > > + RawMemoryRanges[*MtrrCount].Length = > > > > + ((~(Mtrrs->Variables.Mtrr[Index].Mask & > > MtrrValidAddressMask)) & MtrrValidBitsMask) + 1; > > > > + (*MtrrCount)++; > > > > + } > > > > + } > > > > + > > > > + GetEffectiveMemoryRanges (DefaultType, > > PhysicalAddressBits, RawMemoryRanges, *MtrrCount, > > Ranges, RangeCount); > > > > +} > > > > + > > > > +/** > > > > + Return a 32bit random number. > > > > + > > > > + @param Start Start of the random number range. > > > > + @param Limit Limit of the random number range. > > > > + @return 32bit random number > > > > +**/ > > > > +UINT32 > > > > +Random32 ( > > > > + UINT32 Start, > > > > + UINT32 Limit > > > > + ) > > > > +{ > > > > + return (UINT32) (((double) rand () / RAND_MAX) * > > (Limit - Start)) + Start; > > > > +} > > > > + > > > > +/** > > > > + Return a 64bit random number. > > > > + > > > > + @param Start Start of the random number range. > > > > + @param Limit Limit of the random number range. > > > > + @return 64bit random number > > > > +**/ > > > > +UINT64 > > > > +Random64 ( > > > > + UINT64 Start, > > > > + UINT64 Limit > > > > + ) > > > > +{ > > > > + return (UINT64) (((double) rand () / RAND_MAX) * > > (Limit - Start)) + Start; > > > > +} > > > > + > > > > +/** > > > > + Generate random MTRR BASE/MASK for a specified type. > > > > + > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param CacheType Cache type. > > > > + @param MtrrPair Return the random MTRR. > > > > + @param MtrrMemoryRange Return the random memory > > range. > > > > +**/ > > > > +VOID > > > > +GenerateRandomMtrrPair ( > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN MTRR_MEMORY_CACHE_TYPE CacheType, > > > > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL > > > > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL > > > > + ) > > > > +{ > > > > + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase; > > > > + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask; > > > > + UINT32 SizeShift; > > > > + UINT32 BaseShift; > > > > + UINT64 RandomBoundary; > > > > + UINT64 MaxPhysicalAddress; > > > > + UINT64 RangeSize; > > > > + UINT64 RangeBase; > > > > + UINT64 > > PhysBasePhyMaskValidBitsMask; > > > > + > > > > + MaxPhysicalAddress = 1ull << PhysicalAddressBits; > > > > + do { > > > > + SizeShift = Random32 (12, PhysicalAddressBits - > > 1); > > > > + RangeSize = 1ull << SizeShift; > > > > + > > > > + BaseShift = Random32 (SizeShift, > > PhysicalAddressBits - 1); > > > > + RandomBoundary = Random64 (0, 1ull << > > (PhysicalAddressBits - BaseShift)); > > > > + RangeBase = RandomBoundary << BaseShift; > > > > + } while (RangeBase < SIZE_1MB || RangeBase > > > MaxPhysicalAddress - 1); > > > > + > > > > + PhysBasePhyMaskValidBitsMask = (MaxPhysicalAddress - > > 1) & 0xfffffffffffff000ULL; > > > > + > > > > + PhysBase.Uint64 = 0; > > > > + PhysBase.Bits.Type = CacheType; > > > > + PhysBase.Uint64 |= RangeBase & > > PhysBasePhyMaskValidBitsMask; > > > > + PhysMask.Uint64 = 0; > > > > + PhysMask.Bits.V = 1; > > > > + PhysMask.Uint64 |= ((~RangeSize) + 1) & > > PhysBasePhyMaskValidBitsMask; > > > > + > > > > + if (MtrrPair != NULL) { > > > > + MtrrPair->Base = PhysBase.Uint64; > > > > + MtrrPair->Mask = PhysMask.Uint64; > > > > + } > > > > + > > > > + if (MtrrMemoryRange != NULL) { > > > > + MtrrMemoryRange->BaseAddress = RangeBase; > > > > + MtrrMemoryRange->Length = RangeSize; > > > > + MtrrMemoryRange->Type = CacheType; > > > > + } > > > > +} > > > > + > > > > + > > > > +/** > > > > + Check whether the Range overlaps with any one in > > Ranges. > > > > + > > > > + @param Range The memory range to check. > > > > + @param Ranges The memory ranges. > > > > + @param Count Count of memory ranges. > > > > + > > > > + @return TRUE when overlap exists. > > > > +**/ > > > > +BOOLEAN > > > > +RangesOverlap ( > > > > + IN MTRR_MEMORY_RANGE *Range, > > > > + IN MTRR_MEMORY_RANGE *Ranges, > > > > + IN UINTN Count > > > > + ) > > > > +{ > > > > + while (Count-- != 0) { > > > > + // > > > > + // Two ranges overlap when: > > > > + // 1. range#2.base is in the middle of range#1 > > > > + // 2. range#1.base is in the middle of range#2 > > > > + // > > > > + if ((Range->BaseAddress <= > > Ranges[Count].BaseAddress && Ranges[Count].BaseAddress > > < Range->BaseAddress + Range->Length) > > > > + || (Ranges[Count].BaseAddress <= Range- > > >BaseAddress && Range->BaseAddress < > > Ranges[Count].BaseAddress + Ranges[Count].Length)) { > > > > + return TRUE; > > > > + } > > > > + } > > > > + return FALSE; > > > > +} > > > > + > > > > +/** > > > > + Generate random MTRRs. > > > > + > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param RawMemoryRanges Return the randomly > > generated MTRRs. > > > > + @param UcCount Count of Uncacheable > > MTRRs. > > > > + @param WtCount Count of Write Through > > MTRRs. > > > > + @param WbCount Count of Write Back > > MTRRs. > > > > + @param WpCount Count of Write Protected > > MTRRs. > > > > + @param WcCount Count of Write Combine > > MTRRs. > > > > +**/ > > > > +VOID > > > > +GenerateValidAndConfigurableMtrrPairs ( > > > > + IN UINT32 > > PhysicalAddressBits, > > > > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 UcCount, > > > > + IN UINT32 WtCount, > > > > + IN UINT32 WbCount, > > > > + IN UINT32 WpCount, > > > > + IN UINT32 WcCount > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + > > > > + // > > > > + // 1. Generate UC, WT, WB in order. > > > > + // > > > > + for (Index = 0; Index < UcCount; Index++) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheUncacheable, NULL, &RawMemoryRanges[Index]); > > > > + } > > > > + > > > > + for (Index = UcCount; Index < UcCount + WtCount; > > Index++) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteThrough, NULL, &RawMemoryRanges[Index]); > > > > + } > > > > + > > > > + for (Index = UcCount + WtCount; Index < UcCount + > > WtCount + WbCount; Index++) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteBack, NULL, &RawMemoryRanges[Index]); > > > > + } > > > > + > > > > + // > > > > + // 2. Generate WP MTRR and DO NOT overlap with WT, > > WB. > > > > + // > > > > + for (Index = UcCount + WtCount + WbCount; Index < > > UcCount + WtCount + WbCount + WpCount; Index++) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteProtected, NULL, &RawMemoryRanges[Index]); > > > > + while (RangesOverlap (&RawMemoryRanges[Index], > > &RawMemoryRanges[UcCount], WtCount + WbCount)) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteProtected, NULL, &RawMemoryRanges[Index]); > > > > + } > > > > + } > > > > + > > > > + // > > > > + // 3. Generate WC MTRR and DO NOT overlap with WT, > > WB, WP. > > > > + // > > > > + for (Index = UcCount + WtCount + WbCount + WpCount; > > Index < UcCount + WtCount + WbCount + WpCount + > > WcCount; Index++) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteCombining, NULL, &RawMemoryRanges[Index]); > > > > + while (RangesOverlap (&RawMemoryRanges[Index], > > &RawMemoryRanges[UcCount], WtCount + WbCount + > > WpCount)) { > > > > + GenerateRandomMtrrPair (PhysicalAddressBits, > > CacheWriteCombining, NULL, &RawMemoryRanges[Index]); > > > > + } > > > > + } > > > > +} > > > > + > > > > +/** > > > > + Return a random memory cache type. > > > > +**/ > > > > +MTRR_MEMORY_CACHE_TYPE > > > > +GenerateRandomCacheType ( > > > > + VOID > > > > + ) > > > > +{ > > > > + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE > > (mMemoryCacheTypes) - 1)]; > > > > +} > > > > + > > > > +/** > > > > + Compare function used by qsort(). > > > > +**/ > > > > + > > > > +/** > > > > + Compare function used by qsort(). > > > > + > > > > + @param Left Left operand to compare. > > > > + @param Right Right operand to compare. > > > > + > > > > + @retval 0 Left == Right > > > > + @retval -1 Left < Right > > > > + @retval 1 Left > Right > > > > +**/ > > > > +INT32 > > > > +CompareFuncUint64 ( > > > > + CONST VOID * Left, > > > > + CONST VOID * Right > > > > + ) > > > > +{ > > > > + INT64 Delta; > > > > + Delta = (*(UINT64*)Left - *(UINT64*)Right); > > > > + if (Delta > 0) { > > > > + return 1; > > > > + } else if (Delta == 0) { > > > > + return 0; > > > > + } else { > > > > + return -1; > > > > + } > > > > +} > > > > + > > > > +/** > > > > + Determin the memory cache type for the Range. > > > > + > > > > + @param DefaultType Default cache type. > > > > + @param Range The memory range to determin the > > cache type. > > > > + @param Ranges The entire memory ranges. > > > > + @param RangeCount Count of the entire memory > > ranges. > > > > +**/ > > > > +VOID > > > > +DetermineMemoryCacheType ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN OUT MTRR_MEMORY_RANGE *Range, > > > > + IN MTRR_MEMORY_RANGE *Ranges, > > > > + IN UINT32 RangeCount > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + Range->Type = CacheInvalid; > > > > + for (Index = 0; Index < RangeCount; Index++) { > > > > + if (RangesOverlap (Range, &Ranges[Index], 1)) { > > > > + if (Ranges[Index].Type < Range->Type) { > > > > + Range->Type = Ranges[Index].Type; > > > > + } > > > > + } > > > > + } > > > > + > > > > + if (Range->Type == CacheInvalid) { > > > > + Range->Type = DefaultType; > > > > + } > > > > +} > > > > + > > > > +/** > > > > + Get the index of the element that does NOT equals to > > Array[Index]. > > > > + > > > > + @param Index Current element. > > > > + @param Array Array to scan. > > > > + @param Count Count of the array. > > > > + > > > > + @return Next element that doesn't equal to current > > one. > > > > +**/ > > > > +UINT32 > > > > +GetNextDifferentElementInSortedArray ( > > > > + IN UINT32 Index, > > > > + IN UINT64 *Array, > > > > + IN UINT32 Count > > > > + ) > > > > +{ > > > > + UINT64 CurrentElement; > > > > + CurrentElement = Array[Index]; > > > > + while (CurrentElement == Array[Index] && Index < > > Count) { > > > > + Index++; > > > > + } > > > > + return Index; > > > > +} > > > > + > > > > +/** > > > > + Remove the duplicates from the array. > > > > + > > > > + @param Array The array to operate on. > > > > + @param Count Count of the array. > > > > +**/ > > > > +VOID > > > > +RemoveDuplicatesInSortedArray ( > > > > + IN OUT UINT64 *Array, > > > > + IN OUT UINT32 *Count > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + UINT32 NewCount; > > > > + > > > > + Index = 0; > > > > + NewCount = 0; > > > > + while (Index < *Count) { > > > > + Array[NewCount] = Array[Index]; > > > > + NewCount++; > > > > + Index = GetNextDifferentElementInSortedArray > > (Index, Array, *Count); > > > > + } > > > > + *Count = NewCount; > > > > +} > > > > + > > > > +/** > > > > + Return TRUE when Address is in the Range. > > > > + > > > > + @param Address The address to check. > > > > + @param Range The range to check. > > > > + @return TRUE when Address is in the Range. > > > > +**/ > > > > +BOOLEAN > > > > +AddressInRange ( > > > > + IN UINT64 Address, > > > > + IN MTRR_MEMORY_RANGE Range > > > > + ) > > > > +{ > > > > + return (Address >= Range.BaseAddress) && (Address > > <= Range.BaseAddress + Range.Length - 1); > > > > +} > > > > + > > > > +/** > > > > + Get the overlap bit flag. > > > > + > > > > + @param RawMemoryRanges Raw memory ranges. > > > > + @param RawMemoryRangeCount Count of raw memory > > ranges. > > > > + @param Address The address to check. > > > > +**/ > > > > +UINT64 > > > > +GetOverlapBitFlag ( > > > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 RawMemoryRangeCount, > > > > + IN UINT64 Address > > > > + ) > > > > +{ > > > > + UINT64 OverlapBitFlag; > > > > + UINT32 Index; > > > > + OverlapBitFlag = 0; > > > > + for (Index = 0; Index < RawMemoryRangeCount; > > Index++) { > > > > + if (AddressInRange (Address, > > RawMemoryRanges[Index])) { > > > > + OverlapBitFlag |= (1ull << Index); > > > > + } > > > > + } > > > > + > > > > + return OverlapBitFlag; > > > > +} > > > > + > > > > +/** > > > > + Return the relationship between flags. > > > > + > > > > + @param Flag1 Flag 1 > > > > + @param Flag2 Flag 2 > > > > + > > > > + @retval 0 Flag1 == Flag2 > > > > + @retval 1 Flag1 is a subset of Flag2 > > > > + @retval 2 Flag2 is a subset of Flag1 > > > > + @retval 3 No subset relations between Flag1 and > > Flag2. > > > > +**/ > > > > +UINT32 > > > > +CheckOverlapBitFlagsRelation ( > > > > + IN UINT64 Flag1, > > > > + IN UINT64 Flag2 > > > > + ) > > > > +{ > > > > + if (Flag1 == Flag2) return 0; > > > > + if ((Flag1 | Flag2) == Flag2) return 1; > > > > + if ((Flag1 | Flag2) == Flag1) return 2; > > > > + return 3; > > > > +} > > > > + > > > > +/** > > > > + Return TRUE when the Endpoint is in any of the > > Ranges. > > > > + > > > > + @param Endpoint The endpoint to check. > > > > + @param Ranges The memory ranges. > > > > + @param RangeCount Count of memory ranges. > > > > + > > > > + @retval TRUE Endpoint is in one of the range. > > > > + @retval FALSE Endpoint is not in any of the ranges. > > > > +**/ > > > > +BOOLEAN > > > > +IsEndpointInRanges ( > > > > + IN UINT64 Endpoint, > > > > + IN MTRR_MEMORY_RANGE *Ranges, > > > > + IN UINTN RangeCount > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + for (Index = 0; Index < RangeCount; Index++) { > > > > + if (AddressInRange (Endpoint, Ranges[Index])) { > > > > + return TRUE; > > > > + } > > > > + } > > > > + return FALSE; > > > > +} > > > > + > > > > + > > > > +/** > > > > + Compact adjacent ranges of the same type. > > > > + > > > > + @param DefaultType Default memory > > type. > > > > + @param PhysicalAddressBits Physical > > address bits. > > > > + @param EffectiveMtrrMemoryRanges Memory ranges > > to compact. > > > > + @param EffectiveMtrrMemoryRangesCount Return the new > > count of memory ranges. > > > > +**/ > > > > +VOID > > > > +CompactAndExtendEffectiveMtrrMemoryRanges ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN OUT MTRR_MEMORY_RANGE > > **EffectiveMtrrMemoryRanges, > > > > + IN OUT UINTN > > *EffectiveMtrrMemoryRangesCount > > > > + ) > > > > +{ > > > > + UINT64 MaxAddress; > > > > + UINTN NewRangesCountAtMost; > > > > + MTRR_MEMORY_RANGE *NewRanges; > > > > + UINTN NewRangesCountActual; > > > > + MTRR_MEMORY_RANGE > > *CurrentRangeInNewRanges; > > > > + MTRR_MEMORY_CACHE_TYPE > > CurrentRangeTypeInOldRanges; > > > > + > > > > + MTRR_MEMORY_RANGE *OldRanges; > > > > + MTRR_MEMORY_RANGE OldLastRange; > > > > + UINTN OldRangesIndex; > > > > + > > > > + NewRangesCountActual = 0; > > > > + NewRangesCountAtMost = > > *EffectiveMtrrMemoryRangesCount + 2; // At most with > > 2 more range entries. > > > > + NewRanges = (MTRR_MEMORY_RANGE *) calloc > > (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE)); > > > > + OldRanges = *EffectiveMtrrMemoryRanges; > > > > + if (OldRanges[0].BaseAddress > 0) { > > > > + NewRanges[NewRangesCountActual].BaseAddress = 0; > > > > + NewRanges[NewRangesCountActual].Length = > > OldRanges[0].BaseAddress; > > > > + NewRanges[NewRangesCountActual].Type = > > DefaultType; > > > > + NewRangesCountActual++; > > > > + } > > > > + > > > > + OldRangesIndex = 0; > > > > + while (OldRangesIndex < > > *EffectiveMtrrMemoryRangesCount) { > > > > + CurrentRangeTypeInOldRanges = > > OldRanges[OldRangesIndex].Type; > > > > + CurrentRangeInNewRanges = NULL; > > > > + if (NewRangesCountActual > 0) // We need to > > check CurrentNewRange first before generate a new > > NewRange. > > > > + { > > > > + CurrentRangeInNewRanges = > > &NewRanges[NewRangesCountActual - 1]; > > > > + } > > > > + if (CurrentRangeInNewRanges != NULL && > > CurrentRangeInNewRanges->Type == > > CurrentRangeTypeInOldRanges) { > > > > + CurrentRangeInNewRanges->Length += > > OldRanges[OldRangesIndex].Length; > > > > + } else { > > > > + NewRanges[NewRangesCountActual].BaseAddress = > > OldRanges[OldRangesIndex].BaseAddress; > > > > + NewRanges[NewRangesCountActual].Length += > > OldRanges[OldRangesIndex].Length; > > > > + NewRanges[NewRangesCountActual].Type = > > CurrentRangeTypeInOldRanges; > > > > + while (OldRangesIndex + 1 < > > *EffectiveMtrrMemoryRangesCount && > > OldRanges[OldRangesIndex + 1].Type == > > CurrentRangeTypeInOldRanges) > > > > + { > > > > + OldRangesIndex++; > > > > + NewRanges[NewRangesCountActual].Length += > > OldRanges[OldRangesIndex].Length; > > > > + } > > > > + NewRangesCountActual++; > > > > + } > > > > + > > > > + OldRangesIndex++; > > > > + } > > > > + > > > > + MaxAddress = (1ull << PhysicalAddressBits) - 1; > > > > + OldLastRange = > > OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1]; > > > > + CurrentRangeInNewRanges = > > &NewRanges[NewRangesCountActual - 1]; > > > > + if (OldLastRange.BaseAddress + OldLastRange.Length - > > 1 < MaxAddress) { > > > > + if (CurrentRangeInNewRanges->Type == DefaultType) > > { > > > > + CurrentRangeInNewRanges->Length = MaxAddress - > > CurrentRangeInNewRanges->BaseAddress + 1; > > > > + } else { > > > > + NewRanges[NewRangesCountActual].BaseAddress = > > OldLastRange.BaseAddress + OldLastRange.Length; > > > > + NewRanges[NewRangesCountActual].Length = > > MaxAddress - > > NewRanges[NewRangesCountActual].BaseAddress + 1; > > > > + NewRanges[NewRangesCountActual].Type = > > DefaultType; > > > > + NewRangesCountActual++; > > > > + } > > > > + } > > > > + > > > > + free (*EffectiveMtrrMemoryRanges); > > > > + *EffectiveMtrrMemoryRanges = NewRanges; > > > > + *EffectiveMtrrMemoryRangesCount = > > NewRangesCountActual; > > > > +} > > > > + > > > > +/** > > > > + Collect all the endpoints in the raw memory ranges. > > > > + > > > > + @param Endpoints Return the collected > > endpoints. > > > > + @param EndPointCount Return the count of > > endpoints. > > > > + @param RawMemoryRanges Raw memory ranges. > > > > + @param RawMemoryRangeCount Count of raw memory > > ranges. > > > > +**/ > > > > +VOID > > > > +CollectEndpoints ( > > > > + IN OUT UINT64 *Endpoints, > > > > + IN OUT UINT32 *EndPointCount, > > > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 RawMemoryRangeCount > > > > + ) > > > > +{ > > > > + UINT32 Index; > > > > + UINT32 RawRangeIndex; > > > > + > > > > + ASSERT ((RawMemoryRangeCount << 1) == > > *EndPointCount); > > > > + > > > > + for (Index = 0; Index < *EndPointCount; Index += 2) > > { > > > > + RawRangeIndex = Index >> 1; > > > > + Endpoints[Index] = > > RawMemoryRanges[RawRangeIndex].BaseAddress; > > > > + Endpoints[Index + 1] = > > RawMemoryRanges[RawRangeIndex].BaseAddress + > > RawMemoryRanges[RawRangeIndex].Length - 1; > > > > + } > > > > + > > > > + qsort (Endpoints, *EndPointCount, sizeof (UINT64), > > CompareFuncUint64); > > > > + RemoveDuplicatesInSortedArray (Endpoints, > > EndPointCount); > > > > +} > > > > + > > > > +/** > > > > + Convert the MTRR BASE/MASK array to memory ranges. > > > > + > > > > + @param DefaultType Default memory type. > > > > + @param PhysicalAddressBits Physical address bits. > > > > + @param RawMemoryRanges Raw memory ranges. > > > > + @param RawMemoryRangeCount Count of raw memory > > ranges. > > > > + @param MemoryRanges Memory ranges. > > > > + @param MemoryRangeCount Count of memory ranges. > > > > +**/ > > > > +VOID > > > > +GetEffectiveMemoryRanges ( > > > > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, > > > > + IN UINT32 PhysicalAddressBits, > > > > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, > > > > + IN UINT32 RawMemoryRangeCount, > > > > + OUT MTRR_MEMORY_RANGE *MemoryRanges, > > > > + OUT UINTN *MemoryRangeCount > > > > + ) > > > > +{ > > > > + UINTN Index; > > > > + UINT32 AllEndPointsCount; > > > > + UINT64 *AllEndPointsInclusive; > > > > + UINT32 AllRangePiecesCountMax; > > > > + MTRR_MEMORY_RANGE *AllRangePieces; > > > > + UINTN AllRangePiecesCountActual; > > > > + UINT64 OverlapBitFlag1; > > > > + UINT64 OverlapBitFlag2; > > > > + INT32 OverlapFlagRelation; > > > > + > > > > + if (RawMemoryRangeCount == 0) { > > > > + MemoryRanges[0].BaseAddress = 0; > > > > + MemoryRanges[0].Length = (1ull << > > PhysicalAddressBits); > > > > + MemoryRanges[0].Type = DefaultType; > > > > + *MemoryRangeCount = 1; > > > > + return; > > > > + } > > > > + > > > > + AllEndPointsCount = RawMemoryRangeCount << > > 1; > > > > + AllEndPointsInclusive = calloc > > (AllEndPointsCount, sizeof (UINT64)); > > > > + AllRangePiecesCountMax = RawMemoryRangeCount * 3 > > + 1; > > > > + AllRangePieces = calloc > > (AllRangePiecesCountMax, sizeof (MTRR_MEMORY_RANGE)); > > > > + CollectEndpoints (AllEndPointsInclusive, > > &AllEndPointsCount, RawMemoryRanges, > > RawMemoryRangeCount); > > > > + > > > > + for (Index = 0, AllRangePiecesCountActual = 0; Index > > < AllEndPointsCount - 1; Index++) { > > > > + OverlapBitFlag1 = GetOverlapBitFlag > > (RawMemoryRanges, RawMemoryRangeCount, > > AllEndPointsInclusive[Index]); > > > > + OverlapBitFlag2 = GetOverlapBitFlag > > (RawMemoryRanges, RawMemoryRangeCount, > > AllEndPointsInclusive[Index + 1]); > > > > + OverlapFlagRelation = CheckOverlapBitFlagsRelation > > (OverlapBitFlag1, OverlapBitFlag2); > > > > + switch (OverlapFlagRelation) { > > > > + case 0: // [1, 2] > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index]; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > AllEndPointsInclusive[Index + 1] - > > AllEndPointsInclusive[Index] + 1; > > > > + AllRangePiecesCountActual++; > > > > + break; > > > > + case 1: // [1, 2) > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index]; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > (AllEndPointsInclusive[Index + 1] - 1) - > > AllEndPointsInclusive[Index] + 1; > > > > + AllRangePiecesCountActual++; > > > > + break; > > > > + case 2: // (1, 2] > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index] + 1; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > AllEndPointsInclusive[Index + 1] - > > (AllEndPointsInclusive[Index] + 1) + 1; > > > > + AllRangePiecesCountActual++; > > > > + > > > > + if (!IsEndpointInRanges > > (AllEndPointsInclusive[Index], AllRangePieces, > > AllRangePiecesCountActual)) { > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index]; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > 1; > > > > + AllRangePiecesCountActual++; > > > > + } > > > > + break; > > > > + case 3: // (1, 2) > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index] + 1; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > (AllEndPointsInclusive[Index + 1] - 1) - > > (AllEndPointsInclusive[Index] + 1) + 1; > > > > + if > > (AllRangePieces[AllRangePiecesCountActual].Length == 0) > > // Only in case 3 can exists Length=0, we should skip > > such "segment". > > > > + break; > > > > + AllRangePiecesCountActual++; > > > > + if (!IsEndpointInRanges > > (AllEndPointsInclusive[Index], AllRangePieces, > > AllRangePiecesCountActual)) { > > > > + > > AllRangePieces[AllRangePiecesCountActual].BaseAddress = > > AllEndPointsInclusive[Index]; > > > > + > > AllRangePieces[AllRangePiecesCountActual].Length = > > 1; > > > > + AllRangePiecesCountActual++; > > > > + } > > > > + break; > > > > + default: > > > > + ASSERT (FALSE); > > > > + } > > > > + } > > > > + > > > > + for (Index = 0; Index < AllRangePiecesCountActual; > > Index++) { > > > > + DetermineMemoryCacheType (DefaultType, > > &AllRangePieces[Index], RawMemoryRanges, > > RawMemoryRangeCount); > > > > + } > > > > + > > > > + CompactAndExtendEffectiveMtrrMemoryRanges > > (DefaultType, PhysicalAddressBits, &AllRangePieces, > > &AllRangePiecesCountActual); > > > > + ASSERT (*MemoryRangeCount >= > > AllRangePiecesCountActual); > > > > + memcpy (MemoryRanges, AllRangePieces, > > AllRangePiecesCountActual * sizeof > > (MTRR_MEMORY_RANGE)); > > > > + *MemoryRangeCount = AllRangePiecesCountActual; > > > > + > > > > + free (AllEndPointsInclusive); > > > > + free (AllRangePieces); > > > > +} > > > > diff --git a/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > > b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > > new file mode 100644 > > index 0000000000..8a5c456830 > > --- /dev/null > > +++ b/UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc > > @@ -0,0 +1,31 @@ > > +## @file > > > > +# UefiCpuPkg DSC file used to build host-based unit > > tests. > > > > +# > > > > +# Copyright (c) 2020, Intel Corporation. All rights > > reserved.<BR> > > > > +# SPDX-License-Identifier: BSD-2-Clause-Patent > > > > +# > > > > +## > > > > + > > > > +[Defines] > > > > + PLATFORM_NAME = UefiCpuPkgHostTest > > > > + PLATFORM_GUID = E00B9599-5B74-4FF7-AB9F- > > 8183FB13B2F9 > > > > + PLATFORM_VERSION = 0.1 > > > > + DSC_SPECIFICATION = 0x00010005 > > > > + OUTPUT_DIRECTORY = Build/UefiCpuPkg/HostTest > > > > + SUPPORTED_ARCHITECTURES = IA32|X64 > > > > + BUILD_TARGETS = NOOPT > > > > + SKUID_IDENTIFIER = DEFAULT > > > > + > > > > +!include > > UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc > > > > + > > > > +[LibraryClasses] > > > > + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf > > > > + > > > > +[PcdsPatchableInModule] > > > > + > > gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariabl > > eMtrrs|0 > > > > + > > > > +[Components] > > > > + # > > > > + # Build HOST_APPLICATION that tests the MtrrLib > > > > + # > > > > + > > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost > > .inf > > > > -- > > 2.27.0.windows.1 > -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#63228): https://edk2.groups.io/g/devel/message/63228 Mute This Topic: https://groups.io/mt/75607707/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-