From: "Michael D Kinney" <michael.d.kinney@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
"tim.lewis@insyde.com" <tim.lewis@insyde.com>,
"spbrogan@outlook.com" <spbrogan@outlook.com>,
"Ni, Ray" <ray.ni@intel.com>,
"Kinney, Michael D" <michael.d.kinney@intel.com>
Cc: "Shao, Ming" <ming.shao@intel.com>,
"Dong, Eric" <eric.dong@intel.com>,
'Laszlo Ersek' <lersek@redhat.com>,
'Sean Brogan' <sean.brogan@microsoft.com>,
'Bret Barkelew' <Bret.Barkelew@microsoft.com>,
"Yao, Jiewen" <jiewen.yao@intel.com>
Subject: Re: [edk2-devel] [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
Date: Tue, 28 Jul 2020 17:19:40 +0000 [thread overview]
Message-ID: <MN2PR11MB44619DEF262A1985AC1187BED2730@MN2PR11MB4461.namprd11.prod.outlook.com> (raw)
In-Reply-To: <04ae01d66502$67338d20$359aa760$@insyde.com>
Sean and Tim,
Ray has already opened a BZ to work on this topic.
https://bugzilla.tianocore.org/show_bug.cgi?id=2863
I like the idea if the static seed. That may be a simpler
way to reuse a smaller set of random test vectors in CI
and still provide a way for developers and release testing
to run a much larger set of random test vectors.
Mike
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On
> Behalf Of Tim Lewis
> Sent: Tuesday, July 28, 2020 10:13 AM
> To: devel@edk2.groups.io; spbrogan@outlook.com; Ni, Ray
> <ray.ni@intel.com>
> Cc: Kinney, Michael D <michael.d.kinney@intel.com>;
> Shao, Ming <ming.shao@intel.com>; Dong, Eric
> <eric.dong@intel.com>; 'Laszlo Ersek'
> <lersek@redhat.com>; 'Sean Brogan'
> <sean.brogan@microsoft.com>; 'Bret Barkelew'
> <Bret.Barkelew@microsoft.com>; Yao, Jiewen
> <jiewen.yao@intel.com>
> Subject: Re: [edk2-devel] [PATCH v4]
> UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
>
> Sean --
>
> What I have seen done for fuzz testing is to (a) report
> the seed used to initialize the RNG in the log and then
> (b) provide an option to force the seed to that value.
> Using a static seed might actually be the default for CI
> runs, but stand-alone runs could use a random value.
>
> Just a thought.
>
> Tim
>
> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On
> Behalf Of Sean
> Sent: Tuesday, July 28, 2020 9:38 AM
> To: devel@edk2.groups.io; ray.ni@intel.com
> Cc: Michael D Kinney <michael.d.kinney@intel.com>; Ming
> Shao <ming.shao@intel.com>; Eric Dong
> <eric.dong@intel.com>; Laszlo Ersek <lersek@redhat.com>;
> Sean Brogan <sean.brogan@microsoft.com>; Bret Barkelew
> <Bret.Barkelew@microsoft.com>; Jiewen Yao
> <jiewen.yao@intel.com>
> Subject: Re: [edk2-devel] [PATCH v4]
> UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test
>
> Ray,
>
> I worry that this style of testing will lead to
> inconsistant results.
> Generating random test cases means that the test cases
> on any given run
> could find a bug in this code without this code
> changing. I think this
> type of testing (fuzz testing like) is great but I think
> we might want
> to consider this a different test type and treat it
> differently.
>
> For unit testing the mtrr lib it would make more sense
> to identify a few
> unique passing and failing tests and statically add
> those. If there are
> edge cases or more cases needed to get full code
> coverage then
> developing those would be great.
>
> Another point is once we start tracking code coverage
> your random test
> generation will lead to different results which will
> make it hard to
> track the metrics reliably.
>
> Finally, if edk2 community wants to support fuzz testing
> (which i think
> is good) we should add details about how to add fuzz
> testing to edk2 and
> how to exclude it from PR/CI test runs.
>
> Thoughts?
>
> Thanks
> Sean
>
>
>
>
> On 7/28/2020 1:43 AM, Ni, Ray wrote:
> > 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.ni@intel.com>
> > Signed-off-by: Michael D Kinney
> <michael.d.kinney@intel.com>
> > Signed-off-by: Ming Shao <ming.shao@intel.com>
> > Cc: Michael D Kinney <michael.d.kinney@intel.com>
> > Cc: Eric Dong <eric.dong@intel.com>
> > Cc: Laszlo Ersek <lersek@redhat.com>
> > Cc: Ming Shao <ming.shao@intel.com>
> > Cc: Sean Brogan <sean.brogan@microsoft.com>
> > Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > ---
> > .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1139
> +++++++++++++++++
> > .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 182
> +++
> > .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39
> +
> > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 923
> +++++++++++++
> > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31
> +
> > UefiCpuPkg/UefiCpuPkg.ci.yaml | 12
> +-
> > 6 files changed, 2325 insertions(+), 1 deletion(-)
> > 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..123e1c741a
> > --- /dev/null
> > +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c
> > @@ -0,0 +1,1139 @@
> > +/** @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"
> >
> > +
> >
> > +STATIC CONST MTRR_LIB_SYSTEM_PARAMETER
> mDefaultSystemParameter = {
> >
> > + 42, TRUE, TRUE, CacheUncacheable, 12
> >
> > +};
> >
> > +
> >
> > +STATIC 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!"
> >
> > + );
> >
> > +
> >
> > +//
> >
> > +// Context structure to be used for most of the test
> cases.
> >
> > +//
> >
> > +typedef struct {
> >
> > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
> >
> > +} MTRR_LIB_TEST_CONTEXT;
> >
> > +
> >
> > +//
> >
> > +// Context structure to be used for
> GetFirmwareVariableMtrrCount() test.
> >
> > +//
> >
> > +typedef struct {
> >
> > + UINT32
> NumberOfReservedVariableMtrrs;
> >
> > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter;
> >
> > +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT;
> >
> > +
> >
> > +STATIC 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
> >
> > + )
> >
> > +{
> >
> > + CONST 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
> >
> > + )
> >
> > +{
> >
> > + CONST 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;
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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;
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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;
> >
> > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT
> *LocalContext;
> >
> > +
> >
> > + LocalContext =
> (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)
> Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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;
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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;
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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;
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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_TEST_CONTEXT *LocalContext;
> >
> > + 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;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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
> >
> > + )
> >
> > +{
> >
> > + MTRR_LIB_TEST_CONTEXT *LocalContext;
> >
> > + 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;
> >
> > +
> >
> > + LocalContext = (MTRR_LIB_TEST_CONTEXT *) Context;
> >
> > +
> >
> > + CopyMem (&SystemParameter, LocalContext-
> >SystemParameter, 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
> >
> > + )
> >
> > +{
> >
> > + CONST 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
> >
> > + )
> >
> > +{
> >
> > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT
> *LocalContext;
> >
> > +
> >
> > + LocalContext =
> (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)
> Context;
> >
> > + LocalContext->NumberOfReservedVariableMtrrs =
> PatchPcdGet32 (PcdCpuNumberOfReservedVariableMtrrs);
> >
> > + return UNIT_TEST_PASSED;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > + Clean up routine for
> UnitTestGetFirmwareVariableMtrrCount().
> >
> > +
> >
> > + @param Context Point to a UINT32 data to save the
> PcdCpuNumberOfReservedVariableMtrrs.
> >
> > +**/
> >
> > +VOID
> >
> > +EFIAPI
> >
> > +RestorePcdValue (
> >
> > + UNIT_TEST_CONTEXT Context
> >
> > + )
> >
> > +{
> >
> > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT
> *LocalContext;
> >
> > +
> >
> > + LocalContext =
> (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *)
> Context;
> >
> > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs,
> LocalContext->NumberOfReservedVariableMtrrs);
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > + 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;
> >
> > + MTRR_LIB_TEST_CONTEXT
> Context;
> >
> > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT
> GetFirmwareVariableMtrrCountContext;
> >
> > +
> >
> > + Context.SystemParameter
> = &mDefaultSystemParameter;
> >
> > + GetFirmwareVariableMtrrCountContext.SystemParameter
> = &mDefaultSystemParameter;
> >
> > + 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, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test
> GetVariableMtrrCount",
> "GetVariableMtrrCount",
> UnitTestGetVariableMtrrCount, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test
> GetFirmwareVariableMtrrCount",
> "GetFirmwareVariableMtrrCount",
> UnitTestGetFirmwareVariableMtrrCount,
> SavePcdValue, RestorePcdValue,
> &GetFirmwareVariableMtrrCountContext);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrGetMemoryAttribute",
> "MtrrGetMemoryAttribute",
> UnitTestMtrrGetMemoryAttribute, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr",
> "MtrrGetFixedMtrr",
> UnitTestMtrrGetFixedMtrr, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs",
> "MtrrGetAllMtrrs",
> UnitTestMtrrGetAllMtrrs, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs",
> "MtrrSetAllMtrrs",
> UnitTestMtrrSetAllMtrrs, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrGetMemoryAttributeInVariableMtrr",
> "MtrrGetMemoryAttributeInVariableMtrr",
> UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrDebugPrintAllMtrrs",
> "MtrrDebugPrintAllMtrrs",
> UnitTestMtrrDebugPrintAllMtrrs, NULL,
> NULL, &Context);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrGetDefaultMemoryType",
> "MtrrGetDefaultMemoryType",
> UnitTestMtrrGetDefaultMemoryType, NULL,
> NULL, &Context);
> >
> > +
> >
> > + for (SystemIndex = 0; SystemIndex < ARRAY_SIZE
> (mSystemParameters); SystemIndex++) {
> >
> > + for (Index = 0; Index < Iteration; Index++) {
> >
> > + AddTestCase (MtrrApiTests, "Test
> InvalidMemoryLayouts",
> "InvalidMemoryLayouts",
> UnitTestInvalidMemoryLayouts,
> InitializeSystem, NULL,
> &mSystemParameters[SystemIndex]);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributeInMtrrSettings",
> "MtrrSetMemoryAttributeInMtrrSettings",
> UnitTestMtrrSetMemoryAttributeInMtrrSettings,
> InitializeSystem, NULL,
> &mSystemParameters[SystemIndex]);
> >
> > + AddTestCase (MtrrApiTests, "Test
> MtrrSetMemoryAttributesInMtrrSettings",
> "MtrrSetMemoryAttributesInMtrrSettings",
> UnitTestMtrrSetMemoryAttributesInMtrrSettings,
> InitializeSystem, 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..9750523133
> > --- /dev/null
> > +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h
> > @@ -0,0 +1,182 @@
> > +/** @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
> >
> > + );
> >
> > +
> >
> > +/**
> >
> > + Initialize the MTRR registers.
> >
> > +
> >
> > + @param Context System parameter that controls the
> MTRR registers initialization.
> >
> > +**/
> >
> > +UNIT_TEST_STATUS
> >
> > +EFIAPI
> >
> > +InitializeSystem (
> >
> > + IN UNIT_TEST_CONTEXT Context
> >
> > + );
> >
> > +
> >
> > +/**
> >
> > + 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/MtrrLibUnitTestHos
> t.inf
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHos
> t.inf
> > new file mode 100644
> > index 0000000000..447238dc81
> > --- /dev/null
> > +++
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHos
> t.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.PcdCpuNumberOfReservedVariable
> Mtrrs ## SOMETIMES_CONSUMES
> >
> > diff --git
> a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> > new file mode 100644
> > index 0000000000..a7eed45940
> > --- /dev/null
> > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c
> > @@ -0,0 +1,923 @@
> > +/** @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 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;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > + Initialize the MTRR registers.
> >
> > +
> >
> > + @param Context System parameter that controls the
> MTRR registers initialization.
> >
> > +**/
> >
> > +UNIT_TEST_STATUS
> >
> > +EFIAPI
> >
> > +InitializeSystem (
> >
> > + IN UNIT_TEST_CONTEXT Context
> >
> > + )
> >
> > +{
> >
> > + return InitializeMtrrRegs
> ((MTRR_LIB_SYSTEM_PARAMETER *) Context);
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > + 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.PcdCpuNumberOfReservedVariable
> Mtrrs|0
> >
> > +
> >
> > +[Components]
> >
> > + #
> >
> > + # Build HOST_APPLICATION that tests the MtrrLib
> >
> > + #
> >
> > +
> UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.
> inf
> >
> > diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml
> b/UefiCpuPkg/UefiCpuPkg.ci.yaml
> > index 99e460a8b0..4559b40105 100644
> > --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml
> > +++ b/UefiCpuPkg/UefiCpuPkg.ci.yaml
> > @@ -8,6 +8,10 @@
> > "CompilerPlugin": {
> >
> > "DscPath": "UefiCpuPkg.dsc"
> >
> > },
> >
> > + ## options defined
> ci/Plugin/HostUnitTestCompilerPlugin
> >
> > + "HostUnitTestCompilerPlugin": {
> >
> > + "DscPath": "Test/UefiCpuPkgHostTest.dsc"
> >
> > + },
> >
> > "CharEncodingCheck": {
> >
> > "IgnoreFiles": []
> >
> > },
> >
> > @@ -18,7 +22,9 @@
> > "UefiCpuPkg/UefiCpuPkg.dec"
> >
> > ],
> >
> > # For host based unit tests
> >
> > - "AcceptableDependencies-HOST_APPLICATION":[],
> >
> > + "AcceptableDependencies-HOST_APPLICATION":[
> >
> > +
> "UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec"
> >
> > + ],
> >
> > # For UEFI shell based apps
> >
> > "AcceptableDependencies-
> UEFI_APPLICATION":[],
> >
> > "IgnoreInf": []
> >
> > @@ -30,6 +36,10 @@
> > "UefiCpuPkg/ResetVector/Vtf0/Vtf0.inf"
> >
> > ]
> >
> > },
> >
> > + "HostUnitTestDscCompleteCheck": {
> >
> > + "IgnoreInf": [""],
> >
> > + "DscPath": "Test/UefiCpuPkgHostTest.dsc"
> >
> > + },
> >
> > "GuidCheck": {
> >
> > "IgnoreGuidName": ["SecCore",
> "ResetVector"], # Expected duplication for
> gEfiFirmwareVolumeTopFileGuid
> >
> > "IgnoreGuidValue": [],
> >
>
>
>
>
>
>
next prev parent reply other threads:[~2020-07-28 17:20 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-07-28 8:43 [PATCH v4] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Ni, Ray
2020-07-28 12:09 ` [edk2-devel] " Laszlo Ersek
2020-07-28 16:37 ` Sean
2020-07-28 17:13 ` Tim Lewis
2020-07-28 17:19 ` Michael D Kinney [this message]
2020-07-28 17:53 ` [EXTERNAL] " Bret Barkelew
2020-07-28 18:59 ` [EXTERNAL] " Andrew Fish
2020-07-28 20:08 ` Tim Lewis
2020-07-28 22:07 ` Michael D Kinney
2020-08-10 8:45 ` Ni, Ray
[not found] ` <1629DBB4A876976B.23512@groups.io>
2020-08-12 14:22 ` Ni, Ray
2020-08-12 17:40 ` Laszlo Ersek
[not found] <1625DE1EFA10C00D.10080@groups.io>
2020-07-28 8:46 ` Ni, Ray
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=MN2PR11MB44619DEF262A1985AC1187BED2730@MN2PR11MB4461.namprd11.prod.outlook.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox