From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga14.intel.com (mga14.intel.com [192.55.52.115]) by mx.groups.io with SMTP id smtpd.web12.47803.1595818740766263786 for ; Sun, 26 Jul 2020 19:59:00 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@intel.onmicrosoft.com header.s=selector2-intel-onmicrosoft-com header.b=nk/8JaeH; spf=pass (domain: intel.com, ip: 192.55.52.115, mailfrom: eric.dong@intel.com) IronPort-SDR: QbPkB7AvNXZqL/JA8cXORuTuNngQZhcgZRqMXqqC7q8kC+Woda01rOVRFWoKus0MTPLuOZXo0g SJJWW83ACsaA== X-IronPort-AV: E=McAfee;i="6000,8403,9694"; a="150124705" X-IronPort-AV: E=Sophos;i="5.75,401,1589266800"; d="scan'208";a="150124705" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jul 2020 19:58:59 -0700 IronPort-SDR: Pr6XnrQIIp1w6xTRPVNP2aToPaCCt5Masqnzno716WDrNyQb1g00cmCK768V6R8Y8EgTHLjpWR CcsIh6OpBNAQ== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.75,401,1589266800"; d="scan'208";a="303292893" Received: from orsmsx601.amr.corp.intel.com ([10.22.229.14]) by orsmga002.jf.intel.com with ESMTP; 26 Jul 2020 19:58:58 -0700 Received: from orsmsx605.amr.corp.intel.com (10.22.229.18) by ORSMSX601.amr.corp.intel.com (10.22.229.14) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.1713.5; Sun, 26 Jul 2020 19:58:58 -0700 Received: from ORSEDG001.ED.cps.intel.com (10.7.248.4) by orsmsx605.amr.corp.intel.com (10.22.229.18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256) id 15.1.1713.5 via Frontend Transport; Sun, 26 Jul 2020 19:58:58 -0700 Received: from NAM10-BN7-obe.outbound.protection.outlook.com (104.47.70.109) by edgegateway.intel.com (134.134.137.100) with Microsoft SMTP Server (TLS) id 14.3.439.0; Sun, 26 Jul 2020 19:58:55 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=NdTGs/RM3A3p8zj7REYwJoGrOiy9aKJq+6UnKvlV1kqNxBnaMlp/DVs43+yn2vhrtLWX8Zz//Xoielt8pS2yzyIcQ9GbFW2OfAP+6Wce6/FO9pvWT20AZxoVWTOVoMR6vJ93/gUmCPd8PIyaPboCRvCHtehCF1uZvFarDols6VnkT6bV+CK6d3EnQrvE67R5E5BBqy5I4ksZYNojgv4k3iRQrhEew9SoXawJLtud22qweN4o4S4E2tLh/6jhjWF0H2MdXZSi8AdM+p+D3X5Ks6ZngBsURVFV+EZPEHRuk5Vst03h1cq3VnSC8kISgLOmKmkLQmR6Ka7fUMoty0d67g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+D13N77eP0FRiNzO5kuQ8IAetle8XOG43cqZWZJSBO8=; b=QgtuNLQq8ZRVRa1KzXyZ43lwRvfjpqKHiq2UcP9oQ/VUQoBqxlrrjHkIaJsnEPcbo9rquDkqO/Sz0SyK/ebkUdkkwdp8LrpKuLkb/TjoKa+FWqxx7rn8yNzCv2+v0ChPM8YgSDmjLsxeyckYo6u08wHCTLEOI7anD/hFMeABoXBu+47QcZLaDt0zoVpt2VZ/5UNj0/dOb7bRfrrRsZQwdaCnl5aO2jcvfRyk9RaETOaDbMmNFaVP5iP6MwidgquRb5gobXOYGBpU78nQU8JmeXGbwFZz+uIJkAWJfw3QSr7NZV6NCc3NUeA1TYYoVxD8eHJvw+1Tqi7FvGHctxAjdg== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=intel.com; dmarc=pass action=none header.from=intel.com; dkim=pass header.d=intel.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=intel.onmicrosoft.com; s=selector2-intel-onmicrosoft-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=+D13N77eP0FRiNzO5kuQ8IAetle8XOG43cqZWZJSBO8=; b=nk/8JaeHb1p1LwUaxKsWT6pm64Kp4DkHqQ6vkS58u6nn4FPnDMutGuK7GLQeFNLoFqo0NJSHu9jUggB3VKdA7lgy9WXyJ++9s3yckZPQJLdlkV+MP90AwphVdByVY5Y7qZw5T2+g/JewIqBP926lg136DsW9Kuug/1qIlYFwmDQ= Received: from DM6PR11MB3274.namprd11.prod.outlook.com (2603:10b6:5:b::26) by DM5PR11MB1625.namprd11.prod.outlook.com (2603:10b6:4:b::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3216.24; Mon, 27 Jul 2020 02:58:52 +0000 Received: from DM6PR11MB3274.namprd11.prod.outlook.com ([fe80::7173:fdb:cfda:5820]) by DM6PR11MB3274.namprd11.prod.outlook.com ([fe80::7173:fdb:cfda:5820%6]) with mapi id 15.20.3216.031; Mon, 27 Jul 2020 02:58:52 +0000 From: "Dong, Eric" To: "Ni, Ray" , "devel@edk2.groups.io" CC: "Kinney, Michael D" , "Shao, Ming" , Laszlo Ersek , Sean Brogan , Bret Barkelew , "Yao, Jiewen" Subject: Re: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Thread-Topic: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test Thread-Index: AQHWYYWqtyW1sOAS5UW4ErUG9myZhakawIhA Date: Mon, 27 Jul 2020 02:58:52 +0000 Message-ID: References: <20200724064148.1896-1-ray.ni@intel.com> In-Reply-To: <20200724064148.1896-1-ray.ni@intel.com> Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: authentication-results: intel.com; dkim=none (message not signed) header.d=none;intel.com; dmarc=none action=none header.from=intel.com; x-originating-ip: [192.102.204.45] x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: bde08de4-56a4-460d-cf9c-08d831d8feaa x-ms-traffictypediagnostic: DM5PR11MB1625: x-ld-processed: 46c98d88-e344-4ed4-8496-4ed7712e255d,ExtAddr x-ms-exchange-transport-forked: True x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:10000; x-ms-exchange-senderadcheck: 1 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: CjA6hsvOmfOzmk6MgjlEdRGDONnJuWmUgcBwctG3h3a8sYEt5JFlxvwQ3kmV5GUjElvAKWJboj4Eg9jFR/0M50goETICRyfFdfaURGXh2TqZJiokoPRwD3tKcqm5u9gmBCoBG/NKEm1f7yNKlajVXpyhpiqUjf+yQYdkUncHPBtoQR0Gp9h3BU1tedEjPO6NfK3c7s9v56Rt0SUoKru3fKrme0G2naBdQXku4hqGstNnd1/mmENpr56bfJtqCVw6QHhXU3d09GXTaFh6yvnkpzZrMgYE9AhOZMbCnUITiQxPkfx9SmPHJ35TFLY4bNOx x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:DM6PR11MB3274.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFTY:;SFS:(4636009)(366004)(376002)(396003)(346002)(39860400002)(136003)(6506007)(53546011)(66476007)(66556008)(64756008)(66446008)(2906002)(7696005)(30864003)(186003)(19627235002)(26005)(86362001)(66946007)(52536014)(76116006)(478600001)(107886003)(54906003)(9686003)(5660300002)(316002)(55016002)(8676002)(8936002)(110136005)(71200400001)(4326008)(33656002)(83380400001)(559001)(579004);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata: zorSiBjAXxuz+81NyyjPRfYjVTBPpAZsVM+FCAjhDHi3/zMOCP40t3FXy81ZPRZOHoHo/+x4dzQejLx5zGaUi6ipmQqj5J2I3SMmDJI31fpNOAXXTOvTyPGfbioFnUws3gEu3UJ6KPZfhfhVpb+ENRZxf9n6xwraBSIWyPQPg0anTzl5JbF+eJAMZMgtbDHABThvvSWt6SYte7bU1aN77u59QyEtp3Ijw2hS4tAsml+BQipTGY/WsdZoA0MihNngkDYfRf2/6paArVs0RJRxWVKu/JJwcHmr1vgjfEFjpX6ZFrmRDn9kN3+dXmxt4gywaF6zwytoXYUeC4j2u49kWlwuvY3vikavqrAHmuP4Ae4knCtoinIgUbdlJEouFlFthvi/FDrfdSRjUXTYCoz7v9/Sva1fmkUk6fqF0FGGF6xQ0bmZ7FYUndc7noeTdwknJlbT6CQthDS4NVPCgT1TtyE5gJJNUnGlnibx5ozjGYnt5ogA4V9hR7JEQMV7j/qI MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM6PR11MB3274.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: bde08de4-56a4-460d-cf9c-08d831d8feaa X-MS-Exchange-CrossTenant-originalarrivaltime: 27 Jul 2020 02:58:52.6280 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 46c98d88-e344-4ed4-8496-4ed7712e255d X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: BE8knEcG2cHmCrpCPhDckvot1Vg2ut6mrWnJQmscf/EShAhDtgOQRedBsWRGAcT0qts7CbEun4iwWgN5Wc6+BA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: DM5PR11MB1625 Return-Path: eric.dong@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Reviewed-by: Eric Dong > -----Original Message----- > From: Ni, Ray > Sent: Friday, July 24, 2020 2:42 PM > To: devel@edk2.groups.io > Cc: Kinney, Michael D ; Shao, Ming > ; Dong, Eric ; Laszlo Ersek > ; Sean Brogan ; Bret > Barkelew ; Yao, Jiewen > > Subject: [PATCH v2] UefiCpuPkg/MtrrLib/UnitTest: Add host based unit test >=20 > 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. >=20 > Test cases are developed for each of the API. >=20 > 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. >=20 > Signed-off-by: Ray Ni > Signed-off-by: Michael D Kinney > Signed-off-by: Ming Shao > Cc: Michael D Kinney > Cc: Ming Shao > Cc: Eric Dong > Cc: Ray Ni > Cc: Laszlo Ersek > Cc: Sean Brogan > Cc: Bret Barkelew > Cc: Jiewen Yao > --- > .../MtrrLib/UnitTest/MtrrLibUnitTest.c | 1140 +++++++++++++++++ > .../MtrrLib/UnitTest/MtrrLibUnitTest.h | 171 +++ > .../MtrrLib/UnitTest/MtrrLibUnitTestHost.inf | 39 + > UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c | 913 +++++++++++++ > UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc | 31 + > 5 files changed, 2294 insertions(+) > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > create mode 100644 > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > create mode 100644 > UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > create mode 100644 UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > create mode 100644 UefiCpuPkg/Test/UefiCpuPkgHostTest.dsc >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > new file mode 100644 > index 0000000000..2eac41fc74 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.c > @@ -0,0 +1,1140 @@ > +/** @file >=20 > + Unit tests of the MtrrLib instance of the MtrrLib class >=20 > + >=20 > + Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "MtrrLibUnitTest.h" >=20 > + >=20 > +STATIC CONST MTRR_LIB_SYSTEM_PARAMETER mDefaultSystemParameter > =3D { >=20 > + 42, TRUE, TRUE, CacheUncacheable, 12 >=20 > +}; >=20 > + >=20 > +STATIC MTRR_LIB_SYSTEM_PARAMETER mSystemParameters[] =3D { >=20 > + { 38, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 38, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > + >=20 > + { 42, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 42, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > + >=20 > + { 48, TRUE, TRUE, CacheUncacheable, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteBack, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteThrough, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteProtected, 12 }, >=20 > + { 48, TRUE, TRUE, CacheWriteCombining, 12 }, >=20 > +}; >=20 > + >=20 > +UINT32 mFixedMtrrsIndex[] =3D { >=20 > + MSR_IA32_MTRR_FIX64K_00000, >=20 > + MSR_IA32_MTRR_FIX16K_80000, >=20 > + MSR_IA32_MTRR_FIX16K_A0000, >=20 > + MSR_IA32_MTRR_FIX4K_C0000, >=20 > + MSR_IA32_MTRR_FIX4K_C8000, >=20 > + MSR_IA32_MTRR_FIX4K_D0000, >=20 > + MSR_IA32_MTRR_FIX4K_D8000, >=20 > + MSR_IA32_MTRR_FIX4K_E0000, >=20 > + MSR_IA32_MTRR_FIX4K_E8000, >=20 > + MSR_IA32_MTRR_FIX4K_F0000, >=20 > + MSR_IA32_MTRR_FIX4K_F8000 >=20 > +}; >=20 > +STATIC_ASSERT ( >=20 > + (ARRAY_SIZE (mFixedMtrrsIndex) =3D=3D MTRR_NUMBER_OF_FIXED_MTRR), >=20 > + "gFixedMtrrIndex does NOT contain all the fixed MTRRs!" >=20 > + ); >=20 > + >=20 > +// >=20 > +// Context structure to be used for most of the test cases. >=20 > +// >=20 > +typedef struct { >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > +} MTRR_LIB_TEST_CONTEXT; >=20 > + >=20 > +// >=20 > +// Context structure to be used for GetFirmwareVariableMtrrCount() test. >=20 > +// >=20 > +typedef struct { >=20 > + UINT32 NumberOfReservedVariableMtrrs; >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > +} MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT; >=20 > + >=20 > +STATIC CHAR8 *mCacheDescription[] =3D { "UC", "WC", "N/A", "N/A", "WT", > "WP", "WB" }; >=20 > + >=20 > +/** >=20 > + Compare the actual memory ranges against expected memory ranges and > return PASS when they match. >=20 > + >=20 > + @param ExpectedMemoryRanges Expected memory ranges. >=20 > + @param ExpectedMemoryRangeCount Count of expected memory ranges. >=20 > + @param ActualRanges Actual memory ranges. >=20 > + @param ActualRangeCount Count of actual memory ranges. >=20 > + >=20 > + @retval UNIT_TEST_PASSED Test passed. >=20 > + @retval others Test failed. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +VerifyMemoryRanges ( >=20 > + IN MTRR_MEMORY_RANGE *ExpectedMemoryRanges, >=20 > + IN UINTN ExpectedMemoryRangeCount, >=20 > + IN MTRR_MEMORY_RANGE *ActualRanges, >=20 > + IN UINTN ActualRangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRangeCount, ActualRangeCount); >=20 > + for (Index =3D 0; Index < ExpectedMemoryRangeCount; Index++) { >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].BaseAddress, > ActualRanges[Index].BaseAddress); >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Length, > ActualRanges[Index].Length); >=20 > + UT_ASSERT_EQUAL (ExpectedMemoryRanges[Index].Type, > ActualRanges[Index].Type); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Dump the memory ranges. >=20 > + >=20 > + @param Ranges Memory ranges to dump. >=20 > + @param RangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +DumpMemoryRanges ( >=20 > + MTRR_MEMORY_RANGE *Ranges, >=20 > + UINTN RangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + UT_LOG_INFO ("\t{ 0x%016llx, 0x%016llx, %a },\n", > Ranges[Index].BaseAddress, Ranges[Index].Length, > mCacheDescription[Ranges[Index].Type]); >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > +**/ >=20 > + >=20 > +/** >=20 > + Generate random count of MTRRs for each cache type. >=20 > + >=20 > + @param TotalCount Total MTRR count. >=20 > + @param UcCount Return count of Uncacheable type. >=20 > + @param WtCount Return count of Write Through type. >=20 > + @param WbCount Return count of Write Back type. >=20 > + @param WpCount Return count of Write Protected type. >=20 > + @param WcCount Return count of Write Combining type. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMemoryTypeCombination ( >=20 > + IN UINT32 TotalCount, >=20 > + OUT UINT32 *UcCount, >=20 > + OUT UINT32 *WtCount, >=20 > + OUT UINT32 *WbCount, >=20 > + OUT UINT32 *WpCount, >=20 > + OUT UINT32 *WcCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT32 TotalMtrrCount; >=20 > + UINT32 *CountPerType[5]; >=20 > + >=20 > + CountPerType[0] =3D UcCount; >=20 > + CountPerType[1] =3D WtCount; >=20 > + CountPerType[2] =3D WbCount; >=20 > + CountPerType[3] =3D WpCount; >=20 > + CountPerType[4] =3D WcCount; >=20 > + >=20 > + // >=20 > + // Initialize the count of each cache type to 0. >=20 > + // >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (CountPerType); Index++) { >=20 > + *(CountPerType[Index]) =3D 0; >=20 > + } >=20 > + >=20 > + // >=20 > + // Pick a random count of MTRRs >=20 > + // >=20 > + TotalMtrrCount =3D Random32 (1, TotalCount); >=20 > + for (Index =3D 0; Index < TotalMtrrCount; Index++) { >=20 > + // >=20 > + // For each of them, pick a random cache type. >=20 > + // >=20 > + (*(CountPerType[Random32 (0, ARRAY_SIZE (CountPerType) - 1)]))++; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetMemoryAttribute() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetMemoryAttributesInMtrrSettings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + RETURN_STATUS Status; >=20 > + UINT32 UcCount; >=20 > + UINT32 WtCount; >=20 > + UINT32 WbCount; >=20 > + UINT32 WpCount; >=20 > + UINT32 WcCount; >=20 > + >=20 > + UINT32 MtrrIndex; >=20 > + UINT8 *Scratch; >=20 > + UINTN ScratchSize; >=20 > + MTRR_SETTINGS LocalMtrrs; >=20 > + >=20 > + MTRR_MEMORY_RANGE > RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + MTRR_MEMORY_RANGE > ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ExpectedVariableMtrrUsage; >=20 > + UINTN ExpectedMemoryRangesCount; >=20 > + >=20 > + MTRR_MEMORY_RANGE > ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) > + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ActualVariableMtrrUsage; >=20 > + UINTN ActualMemoryRangesCount; >=20 > + >=20 > + MTRR_SETTINGS *Mtrrs[2]; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + GenerateRandomMemoryTypeCombination ( >=20 > + SystemParameter->VariableMtrrCount - PatchPcdGet32 > (PcdCpuNumberOfReservedVariableMtrrs), >=20 > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount >=20 > + ); >=20 > + GenerateValidAndConfigurableMtrrPairs ( >=20 > + SystemParameter->PhysicalAddressBits, RawMtrrRange, >=20 > + UcCount, WtCount, WbCount, WpCount, WcCount >=20 > + ); >=20 > + >=20 > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount > + WcCount; >=20 > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); >=20 > + GetEffectiveMemoryRanges ( >=20 > + SystemParameter->DefaultCacheType, >=20 > + SystemParameter->PhysicalAddressBits, >=20 > + RawMtrrRange, ExpectedVariableMtrrUsage, >=20 > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ( >=20 > + "Total MTRR [%d]: UC=3D%d, WT=3D%d, WB=3D%d, WP=3D%d, WC=3D%d\n", >=20 > + ExpectedVariableMtrrUsage, UcCount, WtCount, WbCount, WpCount, > WcCount >=20 > + ); >=20 > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", > ExpectedMemoryRangesCount); >=20 > + DumpMemoryRanges (ExpectedMemoryRanges, > ExpectedMemoryRangesCount); >=20 > + >=20 > + // >=20 > + // Default cache type is always an INPUT >=20 > + // >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); >=20 > + ScratchSize =3D SCRATCH_BUFFER_SIZE; >=20 > + Mtrrs[0] =3D &LocalMtrrs; >=20 > + Mtrrs[1] =3D NULL; >=20 > + >=20 > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { >=20 > + Scratch =3D calloc (ScratchSize, sizeof (UINT8)); >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex], > Scratch, &ScratchSize, ExpectedMemoryRanges, > ExpectedMemoryRangesCount); >=20 > + if (Status =3D=3D RETURN_BUFFER_TOO_SMALL) { >=20 > + Scratch =3D realloc (Scratch, ScratchSize); >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (Mtrrs[MtrrIndex]= , > Scratch, &ScratchSize, ExpectedMemoryRanges, > ExpectedMemoryRangesCount); >=20 > + } >=20 > + UT_ASSERT_STATUS_EQUAL (Status, RETURN_SUCCESS); >=20 > + >=20 > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + MtrrGetAllMtrrs (&LocalMtrrs); >=20 > + } >=20 > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); >=20 > + CollectTestResult ( >=20 > + SystemParameter->DefaultCacheType, SystemParameter- > >PhysicalAddressBits, SystemParameter->VariableMtrrCount, >=20 > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, > &ActualVariableMtrrUsage >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", > ActualMemoryRangesCount); >=20 > + DumpMemoryRanges (ActualMemoryRanges, > ActualMemoryRangesCount); >=20 > + VerifyMemoryRanges (ExpectedMemoryRanges, > ExpectedMemoryRangesCount, ActualMemoryRanges, > ActualMemoryRangesCount); >=20 > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D > ActualVariableMtrrUsage); >=20 > + >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + } >=20 > + >=20 > + free (Scratch); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Test routine to check whether invalid base/size can be rejected. >=20 > + >=20 > + @param Context Pointer to MTRR_LIB_SYSTEM_PARAMETER. >=20 > + >=20 > + @return Test status. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestInvalidMemoryLayouts ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + MTRR_MEMORY_RANGE > Ranges[MTRR_NUMBER_OF_VARIABLE_MTRR * 2 + 1]; >=20 > + UINTN RangeCount; >=20 > + UINT64 MaxAddress; >=20 > + UINT32 Index; >=20 > + UINT64 BaseAddress; >=20 > + UINT64 Length; >=20 > + RETURN_STATUS Status; >=20 > + UINTN ScratchSize; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + >=20 > + RangeCount =3D Random32 (1, ARRAY_SIZE (Ranges)); >=20 > + MaxAddress =3D 1ull << SystemParameter->PhysicalAddressBits; >=20 > + >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + do { >=20 > + BaseAddress =3D Random64 (0, MaxAddress); >=20 > + Length =3D Random64 (1, MaxAddress - BaseAddress); >=20 > + } while (((BaseAddress & 0xFFF) =3D=3D 0) || ((Length & 0xFFF) =3D= =3D 0)); >=20 > + >=20 > + Ranges[Index].BaseAddress =3D BaseAddress; >=20 > + Ranges[Index].Length =3D Length; >=20 > + Ranges[Index].Type =3D GenerateRandomCacheType (); >=20 > + >=20 > + Status =3D MtrrSetMemoryAttribute ( >=20 > + Ranges[Index].BaseAddress, Ranges[Index].Length, Ranges[Index].Typ= e >=20 > + ); >=20 > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); >=20 > + } >=20 > + >=20 > + ScratchSize =3D 0; >=20 > + Status =3D MtrrSetMemoryAttributesInMtrrSettings (NULL, NULL, > &ScratchSize, Ranges, RangeCount); >=20 > + UT_ASSERT_TRUE (RETURN_ERROR (Status)); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service IsMtrrSupported() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestIsMtrrSupported ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + // >=20 > + // MTRR capability off in CPUID leaf. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no variable or fixed MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no variable MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf, but no fixed MTRRs. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 7; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_FALSE (IsMtrrSupported ()); >=20 > + >=20 > + // >=20 > + // MTRR capability on in CPUID leaf with both variable and fixed MTRRs= . >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 7; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_ASSERT_TRUE (IsMtrrSupported ()); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service GetVariableMtrrCount() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestGetVariableMtrrCount ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + UINT32 Result; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + // >=20 > + // If MTRR capability off in CPUID leaf, then the count is always 0. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + for (SystemParameter.VariableMtrrCount =3D 1; > SystemParameter.VariableMtrrCount <=3D > MTRR_NUMBER_OF_VARIABLE_MTRR; > SystemParameter.VariableMtrrCount++) { >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D GetVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + } >=20 > + >=20 > + // >=20 > + // Try all supported variable MTRR counts. >=20 > + // If variable MTRR count is > MTRR_NUMBER_OF_VARIABLE_MTRR, then > an ASSERT() >=20 > + // is generated. >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + for (SystemParameter.VariableMtrrCount =3D 1; > SystemParameter.VariableMtrrCount <=3D > MTRR_NUMBER_OF_VARIABLE_MTRR; > SystemParameter.VariableMtrrCount++) { >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D GetVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); >=20 > + } >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > > MTRR_NUMBER_OF_VARIABLE_MTRR >=20 > + // >=20 > + SystemParameter.VariableMtrrCount =3D > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D MAX_UINT8; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetVariableMtrrCount (), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service GetFirmwareVariableMtrrCount() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestGetFirmwareVariableMtrrCount ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + UINT32 Result; >=20 > + UINT32 ReservedMtrrs; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT > *LocalContext; >=20 > + >=20 > + LocalContext =3D > (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) > Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + // >=20 > + // Positive test cases for VCNT =3D 10 and Reserved PCD in range 0..10 >=20 > + // >=20 > + for (ReservedMtrrs =3D 0; ReservedMtrrs <=3D > SystemParameter.VariableMtrrCount; ReservedMtrrs++) { >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > ReservedMtrrs); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount - > ReservedMtrrs); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test cases when Reserved PCD is larger than VCNT >=20 > + // >=20 > + for (ReservedMtrrs =3D SystemParameter.VariableMtrrCount + 1; > ReservedMtrrs <=3D 255; ReservedMtrrs++) { >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, > ReservedMtrrs); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test cases when Reserved PCD is larger than VCNT >=20 > + // >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, MAX_UINT32); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Negative test case when Fixed MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, 2); >=20 > + Result =3D GetFirmwareVariableMtrrCount (); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > > MTRR_NUMBER_OF_VARIABLE_MTRR >=20 > + // >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (GetFirmwareVariableMtrrCount (), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetMemoryAttribute() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetMemoryAttribute ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetFixedMtrr() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetFixedMtrr ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_FIXED_SETTINGS *Result; >=20 > + MTRR_FIXED_SETTINGS ExpectedFixedSettings; >=20 > + MTRR_FIXED_SETTINGS FixedSettings; >=20 > + UINTN Index; >=20 > + UINTN MsrIndex; >=20 > + UINTN ByteIndex; >=20 > + UINT64 MsrValue; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + // >=20 > + // Set random cache type to different ranges under 1MB and make sure >=20 > + // the fixed MTRR settings are expected. >=20 > + // Try 100 times. >=20 > + // >=20 > + for (Index =3D 0; Index < 100; Index++) { >=20 > + for (MsrIndex =3D 0; MsrIndex < ARRAY_SIZE (mFixedMtrrsIndex); > MsrIndex++) { >=20 > + MsrValue =3D 0; >=20 > + for (ByteIndex =3D 0; ByteIndex < sizeof (UINT64); ByteIndex++) { >=20 > + MsrValue =3D MsrValue | LShiftU64 (GenerateRandomCacheType (), > ByteIndex * 8); >=20 > + } >=20 > + ExpectedFixedSettings.Mtrr[MsrIndex] =3D MsrValue; >=20 > + AsmWriteMsr64 (mFixedMtrrsIndex[MsrIndex], MsrValue); >=20 > + } >=20 > + >=20 > + Result =3D MtrrGetFixedMtrr (&FixedSettings); >=20 > + UT_ASSERT_EQUAL (Result, &FixedSettings); >=20 > + UT_ASSERT_MEM_EQUAL (&FixedSettings, &ExpectedFixedSettings, > sizeof (FixedSettings)); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + ZeroMem (&FixedSettings, sizeof (FixedSettings)); >=20 > + ZeroMem (&ExpectedFixedSettings, sizeof (ExpectedFixedSettings)); >=20 > + Result =3D MtrrGetFixedMtrr (&FixedSettings); >=20 > + UT_ASSERT_EQUAL (Result, &FixedSettings); >=20 > + UT_ASSERT_MEM_EQUAL (&ExpectedFixedSettings, &FixedSettings, > sizeof (ExpectedFixedSettings)); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_SETTINGS *Result; >=20 > + MTRR_SETTINGS Mtrrs; >=20 > + MTRR_SETTINGS ExpectedMtrrs; >=20 > + MTRR_VARIABLE_SETTING > VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + UINT32 Index; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, > GenerateRandomCacheType (), &VariableMtrr[Index], NULL); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), > VariableMtrr[Index].Base); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), > VariableMtrr[Index].Mask); >=20 > + } >=20 > + Result =3D MtrrGetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + UT_ASSERT_MEM_EQUAL (Mtrrs.Variables.Mtrr, VariableMtrr, sizeof > (MTRR_VARIABLE_SETTING) * SystemParameter.VariableMtrrCount); >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + ZeroMem (&ExpectedMtrrs, sizeof (ExpectedMtrrs)); >=20 > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + UT_ASSERT_MEM_EQUAL (&ExpectedMtrrs, &Mtrrs, sizeof > (ExpectedMtrrs)); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > > MTRR_NUMBER_OF_VARIABLE_MTRR >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (MtrrGetAllMtrrs (&Mtrrs), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_SETTINGS *Result; >=20 > + MTRR_SETTINGS Mtrrs; >=20 > + UINT32 Index; >=20 > + MSR_IA32_MTRR_DEF_TYPE_REGISTER Default; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + Default.Uint64 =3D 0; >=20 > + Default.Bits.E =3D 1; >=20 > + Default.Bits.FE =3D 1; >=20 > + Default.Bits.Type =3D GenerateRandomCacheType (); >=20 > + >=20 > + ZeroMem (&Mtrrs, sizeof (Mtrrs)); >=20 > + Mtrrs.MtrrDefType =3D Default.Uint64; >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, > GenerateRandomCacheType (), &Mtrrs.Variables.Mtrr[Index], NULL); >=20 > + } >=20 > + Result =3D MtrrSetAllMtrrs (&Mtrrs); >=20 > + UT_ASSERT_EQUAL (Result, &Mtrrs); >=20 > + >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_DEF_TYPE), > Mtrrs.MtrrDefType); >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSBASE0 + > (Index << 1)), Mtrrs.Variables.Mtrr[Index].Base); >=20 > + UT_ASSERT_EQUAL (AsmReadMsr64 (MSR_IA32_MTRR_PHYSMASK0 + > (Index << 1)), Mtrrs.Variables.Mtrr[Index].Mask); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetMemoryAttributeInVariableMtrr() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetMemoryAttributeInVariableMtrr ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + UINT32 Result; >=20 > + MTRR_VARIABLE_SETTING > VariableSetting[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + VARIABLE_MTRR > VariableMtrr[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + UINT64 ValidMtrrBitsMask; >=20 > + UINT64 ValidMtrrAddressMask; >=20 > + UINT32 Index; >=20 > + MSR_IA32_MTRR_PHYSBASE_REGISTER Base; >=20 > + MSR_IA32_MTRR_PHYSMASK_REGISTER Mask; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + >=20 > + ValidMtrrBitsMask =3D (1ull << SystemParameter.PhysicalAddressBits)= - 1; >=20 > + ValidMtrrAddressMask =3D ValidMtrrBitsMask & 0xfffffffffffff000ULL; >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { >=20 > + GenerateRandomMtrrPair (SystemParameter.PhysicalAddressBits, > GenerateRandomCacheType (), &VariableSetting[Index], NULL); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSBASE0 + (Index << 1), > VariableSetting[Index].Base); >=20 > + AsmWriteMsr64 (MSR_IA32_MTRR_PHYSMASK0 + (Index << 1), > VariableSetting[Index].Mask); >=20 > + } >=20 > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, > ValidMtrrAddressMask, VariableMtrr); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.VariableMtrrCount); >=20 > + >=20 > + for (Index =3D 0; Index < SystemParameter.VariableMtrrCount; Index++) = { >=20 > + Base.Uint64 =3D VariableMtrr[Index].BaseAddress; >=20 > + Base.Bits.Type =3D (UINT32) VariableMtrr[Index].Type; >=20 > + UT_ASSERT_EQUAL (Base.Uint64, VariableSetting[Index].Base); >=20 > + >=20 > + Mask.Uint64 =3D ~(VariableMtrr[Index].Length - 1) & ValidMtrrBits= Mask; >=20 > + Mask.Bits.V =3D 1; >=20 > + UT_ASSERT_EQUAL (Mask.Uint64, VariableSetting[Index].Mask); >=20 > + } >=20 > + >=20 > + // >=20 > + // Negative test case when MTRRs are not supported >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetMemoryAttributeInVariableMtrr (ValidMtrrBitsMask, > ValidMtrrAddressMask, VariableMtrr); >=20 > + UT_ASSERT_EQUAL (Result, 0); >=20 > + >=20 > + // >=20 > + // Expect ASSERT() if variable MTRR count is > > MTRR_NUMBER_OF_VARIABLE_MTRR >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D > MTRR_NUMBER_OF_VARIABLE_MTRR + 1; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + UT_EXPECT_ASSERT_FAILURE (MtrrGetMemoryAttributeInVariableMtrr > (ValidMtrrBitsMask, ValidMtrrAddressMask, VariableMtrr), NULL); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrDebugPrintAllMtrrs() >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrDebugPrintAllMtrrs ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrGetDefaultMemoryType(). >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrGetDefaultMemoryType ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_TEST_CONTEXT *LocalContext; >=20 > + UINTN Index; >=20 > + MTRR_MEMORY_CACHE_TYPE Result; >=20 > + MTRR_LIB_SYSTEM_PARAMETER SystemParameter; >=20 > + MTRR_MEMORY_CACHE_TYPE CacheType[5]; >=20 > + >=20 > + CacheType[0] =3D CacheUncacheable; >=20 > + CacheType[1] =3D CacheWriteCombining; >=20 > + CacheType[2] =3D CacheWriteThrough; >=20 > + CacheType[3] =3D CacheWriteProtected; >=20 > + CacheType[4] =3D CacheWriteBack; >=20 > + >=20 > + LocalContext =3D (MTRR_LIB_TEST_CONTEXT *) Context; >=20 > + >=20 > + CopyMem (&SystemParameter, LocalContext->SystemParameter, sizeof > (SystemParameter)); >=20 > + // >=20 > + // If MTRRs are supported, then always return the cache type in the MS= R >=20 > + // MSR_IA32_MTRR_DEF_TYPE >=20 > + // >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (CacheType); Index++) { >=20 > + SystemParameter.DefaultCacheType =3D CacheType[Index]; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, SystemParameter.DefaultCacheType); >=20 > + } >=20 > + >=20 > + // >=20 > + // If MTRRs are not supported, then always return CacheUncacheable >=20 > + // >=20 > + SystemParameter.MtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D FALSE; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + SystemParameter.MtrrSupported =3D TRUE; >=20 > + SystemParameter.FixedMtrrSupported =3D TRUE; >=20 > + SystemParameter.VariableMtrrCount =3D 0; >=20 > + InitializeMtrrRegs (&SystemParameter); >=20 > + Result =3D MtrrGetDefaultMemoryType (); >=20 > + UT_ASSERT_EQUAL (Result, CacheUncacheable); >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Unit test of MtrrLib service MtrrSetMemoryAttributeInMtrrSettings(). >=20 > + >=20 > + @param[in] Context Ignored >=20 > + >=20 > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test >=20 > + case was successful. >=20 > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . >=20 > + >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +UnitTestMtrrSetMemoryAttributeInMtrrSettings ( >=20 > + IN UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + CONST MTRR_LIB_SYSTEM_PARAMETER *SystemParameter; >=20 > + RETURN_STATUS Status; >=20 > + UINT32 UcCount; >=20 > + UINT32 WtCount; >=20 > + UINT32 WbCount; >=20 > + UINT32 WpCount; >=20 > + UINT32 WcCount; >=20 > + >=20 > + UINTN MtrrIndex; >=20 > + UINTN Index; >=20 > + MTRR_SETTINGS LocalMtrrs; >=20 > + >=20 > + MTRR_MEMORY_RANGE > RawMtrrRange[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > + MTRR_MEMORY_RANGE > ExpectedMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof > (UINT64) + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ExpectedVariableMtrrUsage; >=20 > + UINTN ExpectedMemoryRangesCount; >=20 > + >=20 > + MTRR_MEMORY_RANGE > ActualMemoryRanges[MTRR_NUMBER_OF_FIXED_MTRR * sizeof (UINT64) > + 2 * MTRR_NUMBER_OF_VARIABLE_MTRR + 1]; >=20 > + UINT32 ActualVariableMtrrUsage; >=20 > + UINTN ActualMemoryRangesCount; >=20 > + >=20 > + MTRR_SETTINGS *Mtrrs[2]; >=20 > + >=20 > + SystemParameter =3D (MTRR_LIB_SYSTEM_PARAMETER *) Context; >=20 > + GenerateRandomMemoryTypeCombination ( >=20 > + SystemParameter->VariableMtrrCount - PatchPcdGet32 > (PcdCpuNumberOfReservedVariableMtrrs), >=20 > + &UcCount, &WtCount, &WbCount, &WpCount, &WcCount >=20 > + ); >=20 > + GenerateValidAndConfigurableMtrrPairs ( >=20 > + SystemParameter->PhysicalAddressBits, RawMtrrRange, >=20 > + UcCount, WtCount, WbCount, WpCount, WcCount >=20 > + ); >=20 > + >=20 > + ExpectedVariableMtrrUsage =3D UcCount + WtCount + WbCount + WpCount > + WcCount; >=20 > + ExpectedMemoryRangesCount =3D ARRAY_SIZE (ExpectedMemoryRanges); >=20 > + GetEffectiveMemoryRanges ( >=20 > + SystemParameter->DefaultCacheType, >=20 > + SystemParameter->PhysicalAddressBits, >=20 > + RawMtrrRange, ExpectedVariableMtrrUsage, >=20 > + ExpectedMemoryRanges, &ExpectedMemoryRangesCount >=20 > + ); >=20 > + >=20 > + UT_LOG_INFO ("--- Expected Memory Ranges [%d] ---\n", > ExpectedMemoryRangesCount); >=20 > + DumpMemoryRanges (ExpectedMemoryRanges, > ExpectedMemoryRangesCount); >=20 > + // >=20 > + // Default cache type is always an INPUT >=20 > + // >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + LocalMtrrs.MtrrDefType =3D MtrrGetDefaultMemoryType (); >=20 > + Mtrrs[0] =3D &LocalMtrrs; >=20 > + Mtrrs[1] =3D NULL; >=20 > + >=20 > + for (MtrrIndex =3D 0; MtrrIndex < ARRAY_SIZE (Mtrrs); MtrrIndex++) { >=20 > + for (Index =3D 0; Index < ExpectedMemoryRangesCount; Index++) { >=20 > + Status =3D MtrrSetMemoryAttributeInMtrrSettings ( >=20 > + Mtrrs[MtrrIndex], >=20 > + ExpectedMemoryRanges[Index].BaseAddress, >=20 > + ExpectedMemoryRanges[Index].Length, >=20 > + ExpectedMemoryRanges[Index].Type >=20 > + ); >=20 > + UT_ASSERT_TRUE (Status =3D=3D RETURN_SUCCESS || Status =3D=3D > RETURN_OUT_OF_RESOURCES || Status =3D=3D RETURN_BUFFER_TOO_SMALL); >=20 > + if (Status =3D=3D RETURN_OUT_OF_RESOURCES || Status =3D=3D > RETURN_BUFFER_TOO_SMALL) { >=20 > + return UNIT_TEST_SKIPPED; >=20 > + } >=20 > + } >=20 > + >=20 > + if (Mtrrs[MtrrIndex] =3D=3D NULL) { >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + MtrrGetAllMtrrs (&LocalMtrrs); >=20 > + } >=20 > + ActualMemoryRangesCount =3D ARRAY_SIZE (ActualMemoryRanges); >=20 > + CollectTestResult ( >=20 > + SystemParameter->DefaultCacheType, SystemParameter- > >PhysicalAddressBits, SystemParameter->VariableMtrrCount, >=20 > + &LocalMtrrs, ActualMemoryRanges, &ActualMemoryRangesCount, > &ActualVariableMtrrUsage >=20 > + ); >=20 > + UT_LOG_INFO ("--- Actual Memory Ranges [%d] ---\n", > ActualMemoryRangesCount); >=20 > + DumpMemoryRanges (ActualMemoryRanges, > ActualMemoryRangesCount); >=20 > + VerifyMemoryRanges (ExpectedMemoryRanges, > ExpectedMemoryRangesCount, ActualMemoryRanges, > ActualMemoryRangesCount); >=20 > + UT_ASSERT_TRUE (ExpectedVariableMtrrUsage >=3D > ActualVariableMtrrUsage); >=20 > + >=20 > + ZeroMem (&LocalMtrrs, sizeof (LocalMtrrs)); >=20 > + } >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Prep routine for UnitTestGetFirmwareVariableMtrrCount(). >=20 > + >=20 > + @param Context Point to a UINT32 data to save the > PcdCpuNumberOfReservedVariableMtrrs. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +SavePcdValue ( >=20 > + UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT > *LocalContext; >=20 > + >=20 > + LocalContext =3D > (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) > Context; >=20 > + LocalContext->NumberOfReservedVariableMtrrs =3D PatchPcdGet32 > (PcdCpuNumberOfReservedVariableMtrrs); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Clean up routine for UnitTestGetFirmwareVariableMtrrCount(). >=20 > + >=20 > + @param Context Point to a UINT32 data to save the > PcdCpuNumberOfReservedVariableMtrrs. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +RestorePcdValue ( >=20 > + UNIT_TEST_CONTEXT Context >=20 > + ) >=20 > +{ >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT > *LocalContext; >=20 > + >=20 > + LocalContext =3D > (MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT *) > Context; >=20 > + PatchPcdSet32 (PcdCpuNumberOfReservedVariableMtrrs, LocalContext- > >NumberOfReservedVariableMtrrs); >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Initialize the unit test framework, suite, and unit tests for the >=20 > + ResetSystemLib and run the ResetSystemLib unit test. >=20 > + >=20 > + @param Iteration Iteration of testing > MtrrSetMemoryAttributeInMtrrSettings >=20 > + and MtrrSetMemoryAttributesInMtrrSettin= gs using > random inputs. >=20 > + >=20 > + @retval EFI_SUCCESS All test cases were dispatched. >=20 > + @retval EFI_OUT_OF_RESOURCES There are not enough resources > available to >=20 > + initialize the unit tests. >=20 > +**/ >=20 > +STATIC >=20 > +EFI_STATUS >=20 > +EFIAPI >=20 > +UnitTestingEntry ( >=20 > + UINTN Iteration >=20 > + ) >=20 > +{ >=20 > + EFI_STATUS Status; >=20 > + UNIT_TEST_FRAMEWORK_HANDLE Framework; >=20 > + UNIT_TEST_SUITE_HANDLE MtrrApiTests; >=20 > + UINTN Index; >=20 > + UINTN SystemIndex; >=20 > + MTRR_LIB_TEST_CONTEXT Context; >=20 > + MTRR_LIB_GET_FIRMWARE_VARIABLE_MTRR_COUNT_CONTEXT > GetFirmwareVariableMtrrCountContext; >=20 > + >=20 > + Context.SystemParameter =3D &mDefaultSyste= mParameter; >=20 > + GetFirmwareVariableMtrrCountContext.SystemParameter =3D > &mDefaultSystemParameter; >=20 > + Framework =3D NULL; >=20 > + >=20 > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, > UNIT_TEST_APP_VERSION)); >=20 > + >=20 > + // >=20 > + // Setup the test framework for running the tests. >=20 > + // >=20 > + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, > gEfiCallerBaseName, UNIT_TEST_APP_VERSION); >=20 > + if (EFI_ERROR (Status)) { >=20 > + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status > =3D %r\n", Status)); >=20 > + goto EXIT; >=20 > + } >=20 > + >=20 > + // >=20 > + // --------------Suite-----------Description--------------Name--------= --Function- > -------Pre---Post-------------------Context----------- >=20 > + // >=20 > + >=20 > + // >=20 > + // Populate the MtrrLib API Unit Test Suite. >=20 > + // >=20 > + Status =3D CreateUnitTestSuite (&MtrrApiTests, Framework, "MtrrLib API > Tests", "MtrrLib.MtrrLib", NULL, NULL); >=20 > + if (EFI_ERROR (Status)) { >=20 > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MtrrLib API > Tests\n")); >=20 > + Status =3D EFI_OUT_OF_RESOURCES; >=20 > + goto EXIT; >=20 > + } >=20 > + AddTestCase (MtrrApiTests, "Test IsMtrrSupported", > "MtrrSupported", UnitTestIsMtrrSupported, = NULL, > NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test GetVariableMtrrCount", > "GetVariableMtrrCount", UnitTestGetVariableMtrrCount, > NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test GetFirmwareVariableMtrrCount", > "GetFirmwareVariableMtrrCount", > UnitTestGetFirmwareVariableMtrrCount, SavePcdValue, > RestorePcdValue, &GetFirmwareVariableMtrrCountContext); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetMemoryAttribute", > "MtrrGetMemoryAttribute", UnitTestMtrrGetMemoryAttribute, > NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetFixedMtrr", > "MtrrGetFixedMtrr", UnitTestMtrrGetFixedMtrr, = NULL, > NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetAllMtrrs", > "MtrrGetAllMtrrs", UnitTestMtrrGetAllMtrrs, = NULL, > NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrSetAllMtrrs", > "MtrrSetAllMtrrs", UnitTestMtrrSetAllMtrrs, = NULL, NULL, > &Context); >=20 > + AddTestCase (MtrrApiTests, "Test > MtrrGetMemoryAttributeInVariableMtrr", > "MtrrGetMemoryAttributeInVariableMtrr", > UnitTestMtrrGetMemoryAttributeInVariableMtrr, NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrDebugPrintAllMtrrs", > "MtrrDebugPrintAllMtrrs", UnitTestMtrrDebugPrintAllMtrrs, > NULL, NULL, &Context); >=20 > + AddTestCase (MtrrApiTests, "Test MtrrGetDefaultMemoryType", > "MtrrGetDefaultMemoryType", UnitTestMtrrGetDefaultMemoryType, > NULL, NULL, &Context); >=20 > + >=20 > + for (SystemIndex =3D 0; SystemIndex < ARRAY_SIZE (mSystemParameters); > SystemIndex++) { >=20 > + for (Index =3D 0; Index < Iteration; Index++) { >=20 > + AddTestCase (MtrrApiTests, "Test InvalidMemoryLayouts", > "InvalidMemoryLayouts", UnitTestInvalidMemoryLayouts, > InitializeMtrrRegs, NULL, &mSystemParameters[SystemIndex]); >=20 > + AddTestCase (MtrrApiTests, "Test > MtrrSetMemoryAttributeInMtrrSettings", > "MtrrSetMemoryAttributeInMtrrSettings", > UnitTestMtrrSetMemoryAttributeInMtrrSettings, InitializeMtrrRegs, NULL, > &mSystemParameters[SystemIndex]); >=20 > + AddTestCase (MtrrApiTests, "Test > MtrrSetMemoryAttributesInMtrrSettings", > "MtrrSetMemoryAttributesInMtrrSettings", > UnitTestMtrrSetMemoryAttributesInMtrrSettings, InitializeMtrrRegs, NULL, > &mSystemParameters[SystemIndex]); >=20 > + } >=20 > + } >=20 > + // >=20 > + // Execute the tests. >=20 > + // >=20 > + srand ((unsigned int) time (NULL)); >=20 > + Status =3D RunAllTestSuites (Framework); >=20 > + >=20 > +EXIT: >=20 > + if (Framework !=3D NULL) { >=20 > + FreeUnitTestFramework (Framework); >=20 > + } >=20 > + >=20 > + return Status; >=20 > +} >=20 > + >=20 > +/** >=20 > + Standard POSIX C entry point for host based unit test execution. >=20 > + >=20 > + @param Argc Number of arguments. >=20 > + @param Argv Array of arguments. >=20 > + >=20 > + @return Test application exit code. >=20 > +**/ >=20 > +INT32 >=20 > +main ( >=20 > + INT32 Argc, >=20 > + CHAR8 *Argv[] >=20 > + ) >=20 > +{ >=20 > + UINTN Iteration; >=20 > + >=20 > + // >=20 > + // First parameter specifies the test iterations. >=20 > + // Default is 10. >=20 > + // >=20 > + Iteration =3D 10; >=20 > + if (Argc =3D=3D 2) { >=20 > + Iteration =3D atoi (Argv[1]); >=20 > + } >=20 > + return UnitTestingEntry (Iteration); >=20 > +} >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > new file mode 100644 > index 0000000000..25d4269589 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTest.h > @@ -0,0 +1,171 @@ > +/** @file >=20 > + >=20 > + Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#ifndef _MTRR_SUPPORT_H_ >=20 > +#define _MTRR_SUPPORT_H_ >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#include >=20 > +#include >=20 > +#include >=20 > + >=20 > +#define UNIT_TEST_APP_NAME "MtrrLib Unit Tests" >=20 > +#define UNIT_TEST_APP_VERSION "1.0" >=20 > + >=20 > +#define SCRATCH_BUFFER_SIZE SIZE_16KB >=20 > + >=20 > +typedef struct { >=20 > + UINT8 PhysicalAddressBits; >=20 > + BOOLEAN MtrrSupported; >=20 > + BOOLEAN FixedMtrrSupported; >=20 > + MTRR_MEMORY_CACHE_TYPE DefaultCacheType; >=20 > + UINT32 VariableMtrrCount; >=20 > +} MTRR_LIB_SYSTEM_PARAMETER; >=20 > + >=20 > +extern UINT32 mFixedMtrrsIndex[]; >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param SystemParameter System parameter that controls the MTRR > registers initialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeMtrrRegs ( >=20 > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a random memory cache type. >=20 > +**/ >=20 > +MTRR_MEMORY_CACHE_TYPE >=20 > +GenerateRandomCacheType ( >=20 > + VOID >=20 > + ); >=20 > + >=20 > +/** >=20 > + Generate random MTRRs. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Return the randomly generated MTRRs. >=20 > + @param UcCount Count of Uncacheable MTRRs. >=20 > + @param WtCount Count of Write Through MTRRs. >=20 > + @param WbCount Count of Write Back MTRRs. >=20 > + @param WpCount Count of Write Protected MTRRs. >=20 > + @param WcCount Count of Write Combining MTRRs. >=20 > +**/ >=20 > +VOID >=20 > +GenerateValidAndConfigurableMtrrPairs ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 UcCount, >=20 > + IN UINT32 WtCount, >=20 > + IN UINT32 WbCount, >=20 > + IN UINT32 WpCount, >=20 > + IN UINT32 WcCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Convert the MTRR BASE/MASK array to memory ranges. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param MemoryRanges Memory ranges. >=20 > + @param MemoryRangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +GetEffectiveMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + OUT MTRR_MEMORY_RANGE *MemoryRanges, >=20 > + OUT UINTN *MemoryRangeCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Generate random MTRR BASE/MASK for a specified type. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param CacheType Cache type. >=20 > + @param MtrrPair Return the random MTRR. >=20 > + @param MtrrMemoryRange Return the random memory range. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMtrrPair ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_CACHE_TYPE CacheType, >=20 > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL >=20 > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL >=20 > + ); >=20 > + >=20 > +/** >=20 > + Collect the test result. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param VariableMtrrCount Count of variable MTRRs. >=20 > + @param Mtrrs MTRR settings to collect from. >=20 > + @param Ranges Return the memory ranges. >=20 > + @param RangeCount Return the count of memory ranges. >=20 > + @param MtrrCount Return the count of variable MTRRs being u= sed. >=20 > +**/ >=20 > +VOID >=20 > +CollectTestResult ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN UINT32 VariableMtrrCount, >=20 > + IN MTRR_SETTINGS *Mtrrs, >=20 > + OUT MTRR_MEMORY_RANGE *Ranges, >=20 > + IN OUT UINTN *RangeCount, >=20 > + OUT UINT32 *MtrrCount >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a 64bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 64bit random number >=20 > +**/ >=20 > +UINT64 >=20 > +Random64 ( >=20 > + UINT64 Start, >=20 > + UINT64 Limit >=20 > + ); >=20 > + >=20 > +/** >=20 > + Return a 32bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 32bit random number >=20 > +**/ >=20 > +UINT32 >=20 > +Random32 ( >=20 > + UINT32 Start, >=20 > + UINT32 Limit >=20 > + ); >=20 > +#endif >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > new file mode 100644 > index 0000000000..447238dc81 > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf > @@ -0,0 +1,39 @@ > +## @file >=20 > +# Unit tests of the MtrrLib instance of the MtrrLib class >=20 > +# >=20 > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + INF_VERSION =3D 0x00010006 >=20 > + BASE_NAME =3D MtrrLibUnitTestHost >=20 > + FILE_GUID =3D A1542D84-B64D-4847-885E-0509084376A= B >=20 > + MODULE_TYPE =3D HOST_APPLICATION >=20 > + VERSION_STRING =3D 1.0 >=20 > + >=20 > +# >=20 > +# The following information is for reference only and not required by th= e > build tools. >=20 > +# >=20 > +# VALID_ARCHITECTURES =3D IA32 X64 >=20 > +# >=20 > + >=20 > +[Sources] >=20 > + MtrrLibUnitTest.c >=20 > + MtrrLibUnitTest.h >=20 > + Support.c >=20 > + >=20 > +[Packages] >=20 > + MdePkg/MdePkg.dec >=20 > + UefiCpuPkg/UefiCpuPkg.dec >=20 > + UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec >=20 > + >=20 > +[LibraryClasses] >=20 > + BaseLib >=20 > + BaseMemoryLib >=20 > + DebugLib >=20 > + MtrrLib >=20 > + UnitTestLib >=20 > + >=20 > +[Pcd] >=20 > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs > ## SOMETIMES_CONSUMES >=20 > diff --git a/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > new file mode 100644 > index 0000000000..9fe4b0278e > --- /dev/null > +++ b/UefiCpuPkg/Library/MtrrLib/UnitTest/Support.c > @@ -0,0 +1,913 @@ > +/** @file >=20 > + Unit tests of the MtrrLib instance of the MtrrLib class >=20 > + >=20 > + Copyright (c) 2018 - 2020, Intel Corporation. All rights reserved.
>=20 > + SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > + >=20 > +**/ >=20 > + >=20 > +#include "MtrrLibUnitTest.h" >=20 > + >=20 > +MTRR_MEMORY_CACHE_TYPE mMemoryCacheTypes[] =3D { >=20 > + CacheUncacheable, CacheWriteCombining, CacheWriteThrough, > CacheWriteProtected, CacheWriteBack >=20 > + }; >=20 > + >=20 > +UINT64 mFixedMtrrsValue[MTRR_NUMBER_OF_FIXED_M= TRR]; >=20 > +MSR_IA32_MTRR_PHYSBASE_REGISTER > mVariableMtrrsPhysBase[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > +MSR_IA32_MTRR_PHYSMASK_REGISTER > mVariableMtrrsPhysMask[MTRR_NUMBER_OF_VARIABLE_MTRR]; >=20 > +MSR_IA32_MTRR_DEF_TYPE_REGISTER mDefTypeMsr; >=20 > +MSR_IA32_MTRRCAP_REGISTER mMtrrCapMsr; >=20 > +CPUID_VERSION_INFO_EDX mCpuidVersionInfoEdx; >=20 > +CPUID_VIR_PHY_ADDRESS_SIZE_EAX mCpuidVirPhyAddressSizeEax; >=20 > + >=20 > +/** >=20 > + Retrieves CPUID information. >=20 > + >=20 > + Executes the CPUID instruction with EAX set to the value specified by > Index. >=20 > + This function always returns Index. >=20 > + If Eax is not NULL, then the value of EAX after CPUID is returned in E= ax. >=20 > + If Ebx is not NULL, then the value of EBX after CPUID is returned in E= bx. >=20 > + If Ecx is not NULL, then the value of ECX after CPUID is returned in E= cx. >=20 > + If Edx is not NULL, then the value of EDX after CPUID is returned in E= dx. >=20 > + This function is only available on IA-32 and x64. >=20 > + >=20 > + @param Index The 32-bit value to load into EAX prior to invoking the > CPUID >=20 > + instruction. >=20 > + @param Eax The pointer to the 32-bit EAX value returned by the CPUI= D >=20 > + instruction. This is an optional parameter that may be N= ULL. >=20 > + @param Ebx The pointer to the 32-bit EBX value returned by the CPUI= D >=20 > + instruction. This is an optional parameter that may be N= ULL. >=20 > + @param Ecx The pointer to the 32-bit ECX value returned by the CPUI= D >=20 > + instruction. This is an optional parameter that may be N= ULL. >=20 > + @param Edx The pointer to the 32-bit EDX value returned by the CPUI= D >=20 > + instruction. This is an optional parameter that may be N= ULL. >=20 > + >=20 > + @return Index. >=20 > + >=20 > +**/ >=20 > +UINT32 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmCpuid ( >=20 > + IN UINT32 Index, >=20 > + OUT UINT32 *Eax, OPTIONAL >=20 > + OUT UINT32 *Ebx, OPTIONAL >=20 > + OUT UINT32 *Ecx, OPTIONAL >=20 > + OUT UINT32 *Edx OPTIONAL >=20 > + ) >=20 > +{ >=20 > + switch (Index) { >=20 > + case CPUID_VERSION_INFO: >=20 > + if (Edx !=3D NULL) { >=20 > + *Edx =3D mCpuidVersionInfoEdx.Uint32; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + case CPUID_EXTENDED_FUNCTION: >=20 > + if (Eax !=3D NULL) { >=20 > + *Eax =3D CPUID_VIR_PHY_ADDRESS_SIZE; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + case CPUID_VIR_PHY_ADDRESS_SIZE: >=20 > + if (Eax !=3D NULL) { >=20 > + *Eax =3D mCpuidVirPhyAddressSizeEax.Uint32; >=20 > + } >=20 > + return Index; >=20 > + break; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return Index; >=20 > +} >=20 > + >=20 > +/** >=20 > + Returns a 64-bit Machine Specific Register(MSR). >=20 > + >=20 > + Reads and returns the 64-bit MSR specified by Index. No parameter > checking is >=20 > + performed on Index, and some Index values may cause CPU exceptions. > The >=20 > + caller must either guarantee that Index is valid, or the caller must s= et up >=20 > + exception handlers to catch the exceptions. This function is only avai= lable >=20 > + on IA-32 and x64. >=20 > + >=20 > + @param MsrIndex The 32-bit MSR index to read. >=20 > + >=20 > + @return The value of the MSR identified by MsrIndex. >=20 > + >=20 > +**/ >=20 > +UINT64 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmReadMsr64( >=20 > + IN UINT32 MsrIndex >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { >=20 > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { >=20 > + return mFixedMtrrsValue[Index]; >=20 > + } >=20 > + } >=20 > + >=20 > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && >=20 > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + > (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) { >=20 > + if (MsrIndex % 2 =3D=3D 0) { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; >=20 > + return mVariableMtrrsPhysBase[Index].Uint64; >=20 > + } else { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; >=20 > + return mVariableMtrrsPhysMask[Index].Uint64; >=20 > + } >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { >=20 > + return mDefTypeMsr.Uint64; >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { >=20 > + return mMtrrCapMsr.Uint64; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return 0; >=20 > +} >=20 > + >=20 > +/** >=20 > + Writes a 64-bit value to a Machine Specific Register(MSR), and returns= the >=20 > + value. >=20 > + >=20 > + Writes the 64-bit value specified by Value to the MSR specified by Ind= ex. > The >=20 > + 64-bit value written to the MSR is returned. No parameter checking is >=20 > + performed on Index or Value, and some of these may cause CPU > exceptions. The >=20 > + caller must either guarantee that Index and Value are valid, or the ca= ller >=20 > + must establish proper exception handlers. This function is only availa= ble on >=20 > + IA-32 and x64. >=20 > + >=20 > + @param MsrIndex The 32-bit MSR index to write. >=20 > + @param Value The 64-bit value to write to the MSR. >=20 > + >=20 > + @return Value >=20 > + >=20 > +**/ >=20 > +UINT64 >=20 > +EFIAPI >=20 > +UnitTestMtrrLibAsmWriteMsr64( >=20 > + IN UINT32 MsrIndex, >=20 > + IN UINT64 Value >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mFixedMtrrsValue); Index++) { >=20 > + if (MsrIndex =3D=3D mFixedMtrrsIndex[Index]) { >=20 > + mFixedMtrrsValue[Index] =3D Value; >=20 > + return Value; >=20 > + } >=20 > + } >=20 > + >=20 > + if ((MsrIndex >=3D MSR_IA32_MTRR_PHYSBASE0) && >=20 > + (MsrIndex <=3D MSR_IA32_MTRR_PHYSMASK0 + > (MTRR_NUMBER_OF_VARIABLE_MTRR << 1))) { >=20 > + if (MsrIndex % 2 =3D=3D 0) { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSBASE0) >> 1; >=20 > + mVariableMtrrsPhysBase[Index].Uint64 =3D Value; >=20 > + return Value; >=20 > + } else { >=20 > + Index =3D (MsrIndex - MSR_IA32_MTRR_PHYSMASK0) >> 1; >=20 > + mVariableMtrrsPhysMask[Index].Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRR_DEF_TYPE) { >=20 > + mDefTypeMsr.Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + >=20 > + if (MsrIndex =3D=3D MSR_IA32_MTRRCAP) { >=20 > + mMtrrCapMsr.Uint64 =3D Value; >=20 > + return Value; >=20 > + } >=20 > + >=20 > + // >=20 > + // Should never fall through to here >=20 > + // >=20 > + ASSERT(FALSE); >=20 > + return 0; >=20 > +} >=20 > + >=20 > +/** >=20 > + Initialize MTRR registers. >=20 > +**/ >=20 > + >=20 > +/** >=20 > + Initialize the MTRR registers. >=20 > + >=20 > + @param SystemParameter System parameter that controls the MTRR > registers initialization. >=20 > +**/ >=20 > +UNIT_TEST_STATUS >=20 > +EFIAPI >=20 > +InitializeMtrrRegs ( >=20 > + IN MTRR_LIB_SYSTEM_PARAMETER *SystemParameter >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + SetMem (mFixedMtrrsValue, sizeof (mFixedMtrrsValue), > SystemParameter->DefaultCacheType); >=20 > + >=20 > + for (Index =3D 0; Index < ARRAY_SIZE (mVariableMtrrsPhysBase); Index++= ) { >=20 > + mVariableMtrrsPhysBase[Index].Uint64 =3D 0; >=20 > + mVariableMtrrsPhysBase[Index].Bits.Type =3D SystemParameter- > >DefaultCacheType; >=20 > + mVariableMtrrsPhysBase[Index].Bits.Reserved1 =3D 0; >=20 > + >=20 > + mVariableMtrrsPhysMask[Index].Uint64 =3D 0; >=20 > + mVariableMtrrsPhysMask[Index].Bits.V =3D 0; >=20 > + mVariableMtrrsPhysMask[Index].Bits.Reserved1 =3D 0; >=20 > + } >=20 > + >=20 > + mDefTypeMsr.Bits.E =3D 1; >=20 > + mDefTypeMsr.Bits.FE =3D 1; >=20 > + mDefTypeMsr.Bits.Type =3D SystemParameter->DefaultCacheType; >=20 > + mDefTypeMsr.Bits.Reserved1 =3D 0; >=20 > + mDefTypeMsr.Bits.Reserved2 =3D 0; >=20 > + mDefTypeMsr.Bits.Reserved3 =3D 0; >=20 > + >=20 > + mMtrrCapMsr.Bits.SMRR =3D 0; >=20 > + mMtrrCapMsr.Bits.WC =3D 0; >=20 > + mMtrrCapMsr.Bits.VCNT =3D SystemParameter->VariableMtrrCount; >=20 > + mMtrrCapMsr.Bits.FIX =3D SystemParameter->FixedMtrrSupported; >=20 > + mMtrrCapMsr.Bits.Reserved1 =3D 0; >=20 > + mMtrrCapMsr.Bits.Reserved2 =3D 0; >=20 > + mMtrrCapMsr.Bits.Reserved3 =3D 0; >=20 > + >=20 > + mCpuidVersionInfoEdx.Bits.MTRR =3D SystemParamete= r- > >MtrrSupported; >=20 > + mCpuidVirPhyAddressSizeEax.Bits.PhysicalAddressBits =3D > SystemParameter->PhysicalAddressBits; >=20 > + >=20 > + // >=20 > + // Hook BaseLib functions used by MtrrLib that require some emulation. >=20 > + // >=20 > + gUnitTestHostBaseLib.X86->AsmCpuid =3D UnitTestMtrrLibAsmCpuid; >=20 > + gUnitTestHostBaseLib.X86->AsmReadMsr64 =3D > UnitTestMtrrLibAsmReadMsr64; >=20 > + gUnitTestHostBaseLib.X86->AsmWriteMsr64 =3D > UnitTestMtrrLibAsmWriteMsr64; >=20 > + >=20 > + return UNIT_TEST_PASSED; >=20 > +} >=20 > + >=20 > +/** >=20 > + Collect the test result. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param VariableMtrrCount Count of variable MTRRs. >=20 > + @param Mtrrs MTRR settings to collect from. >=20 > + @param Ranges Return the memory ranges. >=20 > + @param RangeCount Return the count of memory ranges. >=20 > + @param MtrrCount Return the count of variable MTRRs being u= sed. >=20 > +**/ >=20 > +VOID >=20 > +CollectTestResult ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN UINT32 VariableMtrrCount, >=20 > + IN MTRR_SETTINGS *Mtrrs, >=20 > + OUT MTRR_MEMORY_RANGE *Ranges, >=20 > + IN OUT UINTN *RangeCount, >=20 > + OUT UINT32 *MtrrCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT64 MtrrValidBitsMask; >=20 > + UINT64 MtrrValidAddressMask; >=20 > + MTRR_MEMORY_RANGE RawMemoryRanges[ARRAY_SIZE (Mtrrs- > >Variables.Mtrr)]; >=20 > + >=20 > + ASSERT (Mtrrs !=3D NULL); >=20 > + ASSERT (VariableMtrrCount <=3D ARRAY_SIZE (Mtrrs->Variables.Mtrr)); >=20 > + >=20 > + MtrrValidBitsMask =3D (1ull << PhysicalAddressBits) - 1; >=20 > + MtrrValidAddressMask =3D MtrrValidBitsMask & ~0xFFFull; >=20 > + >=20 > + *MtrrCount =3D 0; >=20 > + for (Index =3D 0; Index < VariableMtrrCount; Index++) { >=20 > + if (((MSR_IA32_MTRR_PHYSMASK_REGISTER *) &Mtrrs- > >Variables.Mtrr[Index].Mask)->Bits.V =3D=3D 1) { >=20 > + RawMemoryRanges[*MtrrCount].BaseAddress =3D Mtrrs- > >Variables.Mtrr[Index].Base & MtrrValidAddressMask; >=20 > + RawMemoryRanges[*MtrrCount].Type =3D >=20 > + ((MSR_IA32_MTRR_PHYSBASE_REGISTER *) &Mtrrs- > >Variables.Mtrr[Index].Base)->Bits.Type; >=20 > + RawMemoryRanges[*MtrrCount].Length =3D >=20 > + ((~(Mtrrs->Variables.Mtrr[Index].Mask & MtrrValidAddressMask))= & > MtrrValidBitsMask) + 1; >=20 > + (*MtrrCount)++; >=20 > + } >=20 > + } >=20 > + >=20 > + GetEffectiveMemoryRanges (DefaultType, PhysicalAddressBits, > RawMemoryRanges, *MtrrCount, Ranges, RangeCount); >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a 32bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 32bit random number >=20 > +**/ >=20 > +UINT32 >=20 > +Random32 ( >=20 > + UINT32 Start, >=20 > + UINT32 Limit >=20 > + ) >=20 > +{ >=20 > + return (UINT32) (((double) rand () / RAND_MAX) * (Limit - Start)) + St= art; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a 64bit random number. >=20 > + >=20 > + @param Start Start of the random number range. >=20 > + @param Limit Limit of the random number range. >=20 > + @return 64bit random number >=20 > +**/ >=20 > +UINT64 >=20 > +Random64 ( >=20 > + UINT64 Start, >=20 > + UINT64 Limit >=20 > + ) >=20 > +{ >=20 > + return (UINT64) (((double) rand () / RAND_MAX) * (Limit - Start)) + St= art; >=20 > +} >=20 > + >=20 > +/** >=20 > + Generate random MTRR BASE/MASK for a specified type. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param CacheType Cache type. >=20 > + @param MtrrPair Return the random MTRR. >=20 > + @param MtrrMemoryRange Return the random memory range. >=20 > +**/ >=20 > +VOID >=20 > +GenerateRandomMtrrPair ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_CACHE_TYPE CacheType, >=20 > + OUT MTRR_VARIABLE_SETTING *MtrrPair, OPTIONAL >=20 > + OUT MTRR_MEMORY_RANGE *MtrrMemoryRange OPTIONAL >=20 > + ) >=20 > +{ >=20 > + MSR_IA32_MTRR_PHYSBASE_REGISTER PhysBase; >=20 > + MSR_IA32_MTRR_PHYSMASK_REGISTER PhysMask; >=20 > + UINT32 SizeShift; >=20 > + UINT32 BaseShift; >=20 > + UINT64 RandomBoundary; >=20 > + UINT64 MaxPhysicalAddress; >=20 > + UINT64 RangeSize; >=20 > + UINT64 RangeBase; >=20 > + UINT64 PhysBasePhyMaskValidBitsMask; >=20 > + >=20 > + MaxPhysicalAddress =3D 1ull << PhysicalAddressBits; >=20 > + do { >=20 > + SizeShift =3D Random32 (12, PhysicalAddressBits - 1); >=20 > + RangeSize =3D 1ull << SizeShift; >=20 > + >=20 > + BaseShift =3D Random32 (SizeShift, PhysicalAddressBits - 1); >=20 > + RandomBoundary =3D Random64 (0, 1ull << (PhysicalAddressBits - > BaseShift)); >=20 > + RangeBase =3D RandomBoundary << BaseShift; >=20 > + } while (RangeBase < SIZE_1MB || RangeBase > MaxPhysicalAddress - 1); >=20 > + >=20 > + PhysBasePhyMaskValidBitsMask =3D (MaxPhysicalAddress - 1) & > 0xfffffffffffff000ULL; >=20 > + >=20 > + PhysBase.Uint64 =3D 0; >=20 > + PhysBase.Bits.Type =3D CacheType; >=20 > + PhysBase.Uint64 |=3D RangeBase & PhysBasePhyMaskValidBitsMask; >=20 > + PhysMask.Uint64 =3D 0; >=20 > + PhysMask.Bits.V =3D 1; >=20 > + PhysMask.Uint64 |=3D ((~RangeSize) + 1) & > PhysBasePhyMaskValidBitsMask; >=20 > + >=20 > + if (MtrrPair !=3D NULL) { >=20 > + MtrrPair->Base =3D PhysBase.Uint64; >=20 > + MtrrPair->Mask =3D PhysMask.Uint64; >=20 > + } >=20 > + >=20 > + if (MtrrMemoryRange !=3D NULL) { >=20 > + MtrrMemoryRange->BaseAddress =3D RangeBase; >=20 > + MtrrMemoryRange->Length =3D RangeSize; >=20 > + MtrrMemoryRange->Type =3D CacheType; >=20 > + } >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Check whether the Range overlaps with any one in Ranges. >=20 > + >=20 > + @param Range The memory range to check. >=20 > + @param Ranges The memory ranges. >=20 > + @param Count Count of memory ranges. >=20 > + >=20 > + @return TRUE when overlap exists. >=20 > +**/ >=20 > +BOOLEAN >=20 > +RangesOverlap ( >=20 > + IN MTRR_MEMORY_RANGE *Range, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINTN Count >=20 > + ) >=20 > +{ >=20 > + while (Count-- !=3D 0) { >=20 > + // >=20 > + // Two ranges overlap when: >=20 > + // 1. range#2.base is in the middle of range#1 >=20 > + // 2. range#1.base is in the middle of range#2 >=20 > + // >=20 > + if ((Range->BaseAddress <=3D Ranges[Count].BaseAddress && > Ranges[Count].BaseAddress < Range->BaseAddress + Range->Length) >=20 > + || (Ranges[Count].BaseAddress <=3D Range->BaseAddress && Range- > >BaseAddress < Ranges[Count].BaseAddress + Ranges[Count].Length)) { >=20 > + return TRUE; >=20 > + } >=20 > + } >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > +/** >=20 > + Generate random MTRRs. >=20 > + >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Return the randomly generated MTRRs. >=20 > + @param UcCount Count of Uncacheable MTRRs. >=20 > + @param WtCount Count of Write Through MTRRs. >=20 > + @param WbCount Count of Write Back MTRRs. >=20 > + @param WpCount Count of Write Protected MTRRs. >=20 > + @param WcCount Count of Write Combine MTRRs. >=20 > +**/ >=20 > +VOID >=20 > +GenerateValidAndConfigurableMtrrPairs ( >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 UcCount, >=20 > + IN UINT32 WtCount, >=20 > + IN UINT32 WbCount, >=20 > + IN UINT32 WpCount, >=20 > + IN UINT32 WcCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + >=20 > + // >=20 > + // 1. Generate UC, WT, WB in order. >=20 > + // >=20 > + for (Index =3D 0; Index < UcCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheUncacheable, > NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + for (Index =3D UcCount; Index < UcCount + WtCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteThrough, > NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + for (Index =3D UcCount + WtCount; Index < UcCount + WtCount + WbCount; > Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteBack, NULL, > &RawMemoryRanges[Index]); >=20 > + } >=20 > + >=20 > + // >=20 > + // 2. Generate WP MTRR and DO NOT overlap with WT, WB. >=20 > + // >=20 > + for (Index =3D UcCount + WtCount + WbCount; Index < UcCount + WtCount > + WbCount + WpCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, > NULL, &RawMemoryRanges[Index]); >=20 > + while (RangesOverlap (&RawMemoryRanges[Index], > &RawMemoryRanges[UcCount], WtCount + WbCount)) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteProtected, > NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + } >=20 > + >=20 > + // >=20 > + // 3. Generate WC MTRR and DO NOT overlap with WT, WB, WP. >=20 > + // >=20 > + for (Index =3D UcCount + WtCount + WbCount + WpCount; Index < UcCount > + WtCount + WbCount + WpCount + WcCount; Index++) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, > NULL, &RawMemoryRanges[Index]); >=20 > + while (RangesOverlap (&RawMemoryRanges[Index], > &RawMemoryRanges[UcCount], WtCount + WbCount + WpCount)) { >=20 > + GenerateRandomMtrrPair (PhysicalAddressBits, CacheWriteCombining, > NULL, &RawMemoryRanges[Index]); >=20 > + } >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Return a random memory cache type. >=20 > +**/ >=20 > +MTRR_MEMORY_CACHE_TYPE >=20 > +GenerateRandomCacheType ( >=20 > + VOID >=20 > + ) >=20 > +{ >=20 > + return mMemoryCacheTypes[Random32 (0, ARRAY_SIZE > (mMemoryCacheTypes) - 1)]; >=20 > +} >=20 > + >=20 > +/** >=20 > + Compare function used by qsort(). >=20 > +**/ >=20 > + >=20 > +/** >=20 > + Compare function used by qsort(). >=20 > + >=20 > + @param Left Left operand to compare. >=20 > + @param Right Right operand to compare. >=20 > + >=20 > + @retval 0 Left =3D=3D Right >=20 > + @retval -1 Left < Right >=20 > + @retval 1 Left > Right >=20 > +**/ >=20 > +INT32 >=20 > +CompareFuncUint64 ( >=20 > + CONST VOID * Left, >=20 > + CONST VOID * Right >=20 > + ) >=20 > +{ >=20 > + INT64 Delta; >=20 > + Delta =3D (*(UINT64*)Left - *(UINT64*)Right); >=20 > + if (Delta > 0) { >=20 > + return 1; >=20 > + } else if (Delta =3D=3D 0) { >=20 > + return 0; >=20 > + } else { >=20 > + return -1; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Determin the memory cache type for the Range. >=20 > + >=20 > + @param DefaultType Default cache type. >=20 > + @param Range The memory range to determin the cache type. >=20 > + @param Ranges The entire memory ranges. >=20 > + @param RangeCount Count of the entire memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +DetermineMemoryCacheType ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN OUT MTRR_MEMORY_RANGE *Range, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINT32 RangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + Range->Type =3D CacheInvalid; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + if (RangesOverlap (Range, &Ranges[Index], 1)) { >=20 > + if (Ranges[Index].Type < Range->Type) { >=20 > + Range->Type =3D Ranges[Index].Type; >=20 > + } >=20 > + } >=20 > + } >=20 > + >=20 > + if (Range->Type =3D=3D CacheInvalid) { >=20 > + Range->Type =3D DefaultType; >=20 > + } >=20 > +} >=20 > + >=20 > +/** >=20 > + Get the index of the element that does NOT equals to Array[Index]. >=20 > + >=20 > + @param Index Current element. >=20 > + @param Array Array to scan. >=20 > + @param Count Count of the array. >=20 > + >=20 > + @return Next element that doesn't equal to current one. >=20 > +**/ >=20 > +UINT32 >=20 > +GetNextDifferentElementInSortedArray ( >=20 > + IN UINT32 Index, >=20 > + IN UINT64 *Array, >=20 > + IN UINT32 Count >=20 > + ) >=20 > +{ >=20 > + UINT64 CurrentElement; >=20 > + CurrentElement =3D Array[Index]; >=20 > + while (CurrentElement =3D=3D Array[Index] && Index < Count) { >=20 > + Index++; >=20 > + } >=20 > + return Index; >=20 > +} >=20 > + >=20 > +/** >=20 > + Remove the duplicates from the array. >=20 > + >=20 > + @param Array The array to operate on. >=20 > + @param Count Count of the array. >=20 > +**/ >=20 > +VOID >=20 > +RemoveDuplicatesInSortedArray ( >=20 > + IN OUT UINT64 *Array, >=20 > + IN OUT UINT32 *Count >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + UINT32 NewCount; >=20 > + >=20 > + Index =3D 0; >=20 > + NewCount =3D 0; >=20 > + while (Index < *Count) { >=20 > + Array[NewCount] =3D Array[Index]; >=20 > + NewCount++; >=20 > + Index =3D GetNextDifferentElementInSortedArray (Index, Array, *Count= ); >=20 > + } >=20 > + *Count =3D NewCount; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return TRUE when Address is in the Range. >=20 > + >=20 > + @param Address The address to check. >=20 > + @param Range The range to check. >=20 > + @return TRUE when Address is in the Range. >=20 > +**/ >=20 > +BOOLEAN >=20 > +AddressInRange ( >=20 > + IN UINT64 Address, >=20 > + IN MTRR_MEMORY_RANGE Range >=20 > + ) >=20 > +{ >=20 > + return (Address >=3D Range.BaseAddress) && (Address <=3D > Range.BaseAddress + Range.Length - 1); >=20 > +} >=20 > + >=20 > +/** >=20 > + Get the overlap bit flag. >=20 > + >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param Address The address to check. >=20 > +**/ >=20 > +UINT64 >=20 > +GetOverlapBitFlag ( >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + IN UINT64 Address >=20 > + ) >=20 > +{ >=20 > + UINT64 OverlapBitFlag; >=20 > + UINT32 Index; >=20 > + OverlapBitFlag =3D 0; >=20 > + for (Index =3D 0; Index < RawMemoryRangeCount; Index++) { >=20 > + if (AddressInRange (Address, RawMemoryRanges[Index])) { >=20 > + OverlapBitFlag |=3D (1ull << Index); >=20 > + } >=20 > + } >=20 > + >=20 > + return OverlapBitFlag; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return the relationship between flags. >=20 > + >=20 > + @param Flag1 Flag 1 >=20 > + @param Flag2 Flag 2 >=20 > + >=20 > + @retval 0 Flag1 =3D=3D Flag2 >=20 > + @retval 1 Flag1 is a subset of Flag2 >=20 > + @retval 2 Flag2 is a subset of Flag1 >=20 > + @retval 3 No subset relations between Flag1 and Flag2. >=20 > +**/ >=20 > +UINT32 >=20 > +CheckOverlapBitFlagsRelation ( >=20 > + IN UINT64 Flag1, >=20 > + IN UINT64 Flag2 >=20 > + ) >=20 > +{ >=20 > + if (Flag1 =3D=3D Flag2) return 0; >=20 > + if ((Flag1 | Flag2) =3D=3D Flag2) return 1; >=20 > + if ((Flag1 | Flag2) =3D=3D Flag1) return 2; >=20 > + return 3; >=20 > +} >=20 > + >=20 > +/** >=20 > + Return TRUE when the Endpoint is in any of the Ranges. >=20 > + >=20 > + @param Endpoint The endpoint to check. >=20 > + @param Ranges The memory ranges. >=20 > + @param RangeCount Count of memory ranges. >=20 > + >=20 > + @retval TRUE Endpoint is in one of the range. >=20 > + @retval FALSE Endpoint is not in any of the ranges. >=20 > +**/ >=20 > +BOOLEAN >=20 > +IsEndpointInRanges ( >=20 > + IN UINT64 Endpoint, >=20 > + IN MTRR_MEMORY_RANGE *Ranges, >=20 > + IN UINTN RangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + for (Index =3D 0; Index < RangeCount; Index++) { >=20 > + if (AddressInRange (Endpoint, Ranges[Index])) { >=20 > + return TRUE; >=20 > + } >=20 > + } >=20 > + return FALSE; >=20 > +} >=20 > + >=20 > + >=20 > +/** >=20 > + Compact adjacent ranges of the same type. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param EffectiveMtrrMemoryRanges Memory ranges to compact. >=20 > + @param EffectiveMtrrMemoryRangesCount Return the new count of > memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +CompactAndExtendEffectiveMtrrMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN OUT MTRR_MEMORY_RANGE **EffectiveMtrrMemoryRanges, >=20 > + IN OUT UINTN *EffectiveMtrrMemoryRangesCount >=20 > + ) >=20 > +{ >=20 > + UINT64 MaxAddress; >=20 > + UINTN NewRangesCountAtMost; >=20 > + MTRR_MEMORY_RANGE *NewRanges; >=20 > + UINTN NewRangesCountActual; >=20 > + MTRR_MEMORY_RANGE *CurrentRangeInNewRanges; >=20 > + MTRR_MEMORY_CACHE_TYPE CurrentRangeTypeInOldRanges; >=20 > + >=20 > + MTRR_MEMORY_RANGE *OldRanges; >=20 > + MTRR_MEMORY_RANGE OldLastRange; >=20 > + UINTN OldRangesIndex; >=20 > + >=20 > + NewRangesCountActual =3D 0; >=20 > + NewRangesCountAtMost =3D *EffectiveMtrrMemoryRangesCount + 2; // > At most with 2 more range entries. >=20 > + NewRanges =3D (MTRR_MEMORY_RANGE *) calloc > (NewRangesCountAtMost, sizeof (MTRR_MEMORY_RANGE)); >=20 > + OldRanges =3D *EffectiveMtrrMemoryRanges; >=20 > + if (OldRanges[0].BaseAddress > 0) { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D 0; >=20 > + NewRanges[NewRangesCountActual].Length =3D > OldRanges[0].BaseAddress; >=20 > + NewRanges[NewRangesCountActual].Type =3D DefaultType; >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + >=20 > + OldRangesIndex =3D 0; >=20 > + while (OldRangesIndex < *EffectiveMtrrMemoryRangesCount) { >=20 > + CurrentRangeTypeInOldRanges =3D OldRanges[OldRangesIndex].Type; >=20 > + CurrentRangeInNewRanges =3D NULL; >=20 > + if (NewRangesCountActual > 0) // We need to check CurrentNewRange > first before generate a new NewRange. >=20 > + { >=20 > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; >=20 > + } >=20 > + if (CurrentRangeInNewRanges !=3D NULL && CurrentRangeInNewRanges- > >Type =3D=3D CurrentRangeTypeInOldRanges) { >=20 > + CurrentRangeInNewRanges->Length +=3D > OldRanges[OldRangesIndex].Length; >=20 > + } else { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D > OldRanges[OldRangesIndex].BaseAddress; >=20 > + NewRanges[NewRangesCountActual].Length +=3D > OldRanges[OldRangesIndex].Length; >=20 > + NewRanges[NewRangesCountActual].Type =3D > CurrentRangeTypeInOldRanges; >=20 > + while (OldRangesIndex + 1 < *EffectiveMtrrMemoryRangesCount && > OldRanges[OldRangesIndex + 1].Type =3D=3D CurrentRangeTypeInOldRanges) >=20 > + { >=20 > + OldRangesIndex++; >=20 > + NewRanges[NewRangesCountActual].Length +=3D > OldRanges[OldRangesIndex].Length; >=20 > + } >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + >=20 > + OldRangesIndex++; >=20 > + } >=20 > + >=20 > + MaxAddress =3D (1ull << PhysicalAddressBits) - 1; >=20 > + OldLastRange =3D OldRanges[(*EffectiveMtrrMemoryRangesCount) - 1]; >=20 > + CurrentRangeInNewRanges =3D &NewRanges[NewRangesCountActual - 1]; >=20 > + if (OldLastRange.BaseAddress + OldLastRange.Length - 1 < MaxAddress) { >=20 > + if (CurrentRangeInNewRanges->Type =3D=3D DefaultType) { >=20 > + CurrentRangeInNewRanges->Length =3D MaxAddress - > CurrentRangeInNewRanges->BaseAddress + 1; >=20 > + } else { >=20 > + NewRanges[NewRangesCountActual].BaseAddress =3D > OldLastRange.BaseAddress + OldLastRange.Length; >=20 > + NewRanges[NewRangesCountActual].Length =3D MaxAddress - > NewRanges[NewRangesCountActual].BaseAddress + 1; >=20 > + NewRanges[NewRangesCountActual].Type =3D DefaultType; >=20 > + NewRangesCountActual++; >=20 > + } >=20 > + } >=20 > + >=20 > + free (*EffectiveMtrrMemoryRanges); >=20 > + *EffectiveMtrrMemoryRanges =3D NewRanges; >=20 > + *EffectiveMtrrMemoryRangesCount =3D NewRangesCountActual; >=20 > +} >=20 > + >=20 > +/** >=20 > + Collect all the endpoints in the raw memory ranges. >=20 > + >=20 > + @param Endpoints Return the collected endpoints. >=20 > + @param EndPointCount Return the count of endpoints. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +CollectEndpoints ( >=20 > + IN OUT UINT64 *Endpoints, >=20 > + IN OUT UINT32 *EndPointCount, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount >=20 > + ) >=20 > +{ >=20 > + UINT32 Index; >=20 > + UINT32 RawRangeIndex; >=20 > + >=20 > + ASSERT ((RawMemoryRangeCount << 1) =3D=3D *EndPointCount); >=20 > + >=20 > + for (Index =3D 0; Index < *EndPointCount; Index +=3D 2) { >=20 > + RawRangeIndex =3D Index >> 1; >=20 > + Endpoints[Index] =3D RawMemoryRanges[RawRangeIndex].BaseAddress; >=20 > + Endpoints[Index + 1] =3D > RawMemoryRanges[RawRangeIndex].BaseAddress + > RawMemoryRanges[RawRangeIndex].Length - 1; >=20 > + } >=20 > + >=20 > + qsort (Endpoints, *EndPointCount, sizeof (UINT64), CompareFuncUint64); >=20 > + RemoveDuplicatesInSortedArray (Endpoints, EndPointCount); >=20 > +} >=20 > + >=20 > +/** >=20 > + Convert the MTRR BASE/MASK array to memory ranges. >=20 > + >=20 > + @param DefaultType Default memory type. >=20 > + @param PhysicalAddressBits Physical address bits. >=20 > + @param RawMemoryRanges Raw memory ranges. >=20 > + @param RawMemoryRangeCount Count of raw memory ranges. >=20 > + @param MemoryRanges Memory ranges. >=20 > + @param MemoryRangeCount Count of memory ranges. >=20 > +**/ >=20 > +VOID >=20 > +GetEffectiveMemoryRanges ( >=20 > + IN MTRR_MEMORY_CACHE_TYPE DefaultType, >=20 > + IN UINT32 PhysicalAddressBits, >=20 > + IN MTRR_MEMORY_RANGE *RawMemoryRanges, >=20 > + IN UINT32 RawMemoryRangeCount, >=20 > + OUT MTRR_MEMORY_RANGE *MemoryRanges, >=20 > + OUT UINTN *MemoryRangeCount >=20 > + ) >=20 > +{ >=20 > + UINTN Index; >=20 > + UINT32 AllEndPointsCount; >=20 > + UINT64 *AllEndPointsInclusive; >=20 > + UINT32 AllRangePiecesCountMax; >=20 > + MTRR_MEMORY_RANGE *AllRangePieces; >=20 > + UINTN AllRangePiecesCountActual; >=20 > + UINT64 OverlapBitFlag1; >=20 > + UINT64 OverlapBitFlag2; >=20 > + INT32 OverlapFlagRelation; >=20 > + >=20 > + if (RawMemoryRangeCount =3D=3D 0) { >=20 > + MemoryRanges[0].BaseAddress =3D 0; >=20 > + MemoryRanges[0].Length =3D (1ull << PhysicalAddressBits); >=20 > + MemoryRanges[0].Type =3D DefaultType; >=20 > + *MemoryRangeCount =3D 1; >=20 > + return; >=20 > + } >=20 > + >=20 > + AllEndPointsCount =3D RawMemoryRangeCount << 1; >=20 > + AllEndPointsInclusive =3D calloc (AllEndPointsCount, sizeof (UINT6= 4)); >=20 > + AllRangePiecesCountMax =3D RawMemoryRangeCount * 3 + 1; >=20 > + AllRangePieces =3D calloc (AllRangePiecesCountMax, sizeof > (MTRR_MEMORY_RANGE)); >=20 > + CollectEndpoints (AllEndPointsInclusive, &AllEndPointsCount, > RawMemoryRanges, RawMemoryRangeCount); >=20 > + >=20 > + for (Index =3D 0, AllRangePiecesCountActual =3D 0; Index < AllEndPoint= sCount - > 1; Index++) { >=20 > + OverlapBitFlag1 =3D GetOverlapBitFlag (RawMemoryRanges, > RawMemoryRangeCount, AllEndPointsInclusive[Index]); >=20 > + OverlapBitFlag2 =3D GetOverlapBitFlag (RawMemoryRanges, > RawMemoryRangeCount, AllEndPointsInclusive[Index + 1]); >=20 > + OverlapFlagRelation =3D CheckOverlapBitFlagsRelation (OverlapBitFlag= 1, > OverlapBitFlag2); >=20 > + switch (OverlapFlagRelation) { >=20 > + case 0: // [1, 2] >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D > AllEndPointsInclusive[Index + 1] - AllEndPointsInclusive[Index] + 1; >=20 > + AllRangePiecesCountActual++; >=20 > + break; >=20 > + case 1: // [1, 2) >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D > (AllEndPointsInclusive[Index + 1] - 1) - AllEndPointsInclusive[Index] + 1= ; >=20 > + AllRangePiecesCountActual++; >=20 > + break; >=20 > + case 2: // (1, 2] >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index] + 1; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D > AllEndPointsInclusive[Index + 1] - (AllEndPointsInclusive[Index] + 1) + 1= ; >=20 > + AllRangePiecesCountActual++; >=20 > + >=20 > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangeP= ieces, > AllRangePiecesCountActual)) { >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; >=20 > + AllRangePiecesCountActual++; >=20 > + } >=20 > + break; >=20 > + case 3: // (1, 2) >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index] + 1; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D > (AllEndPointsInclusive[Index + 1] - 1) - (AllEndPointsInclusive[Index] + = 1) + 1; >=20 > + if (AllRangePieces[AllRangePiecesCountActual].Length =3D=3D 0) = // Only in > case 3 can exists Length=3D0, we should skip such "segment". >=20 > + break; >=20 > + AllRangePiecesCountActual++; >=20 > + if (!IsEndpointInRanges (AllEndPointsInclusive[Index], AllRangeP= ieces, > AllRangePiecesCountActual)) { >=20 > + AllRangePieces[AllRangePiecesCountActual].BaseAddress =3D > AllEndPointsInclusive[Index]; >=20 > + AllRangePieces[AllRangePiecesCountActual].Length =3D 1; >=20 > + AllRangePiecesCountActual++; >=20 > + } >=20 > + break; >=20 > + default: >=20 > + ASSERT (FALSE); >=20 > + } >=20 > + } >=20 > + >=20 > + for (Index =3D 0; Index < AllRangePiecesCountActual; Index++) { >=20 > + DetermineMemoryCacheType (DefaultType, &AllRangePieces[Index], > RawMemoryRanges, RawMemoryRangeCount); >=20 > + } >=20 > + >=20 > + CompactAndExtendEffectiveMtrrMemoryRanges (DefaultType, > PhysicalAddressBits, &AllRangePieces, &AllRangePiecesCountActual); >=20 > + ASSERT (*MemoryRangeCount >=3D AllRangePiecesCountActual); >=20 > + memcpy (MemoryRanges, AllRangePieces, AllRangePiecesCountActual * > sizeof (MTRR_MEMORY_RANGE)); >=20 > + *MemoryRangeCount =3D AllRangePiecesCountActual; >=20 > + >=20 > + free (AllEndPointsInclusive); >=20 > + free (AllRangePieces); >=20 > +} >=20 > 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 >=20 > +# UefiCpuPkg DSC file used to build host-based unit tests. >=20 > +# >=20 > +# Copyright (c) 2020, Intel Corporation. All rights reserved.
>=20 > +# SPDX-License-Identifier: BSD-2-Clause-Patent >=20 > +# >=20 > +## >=20 > + >=20 > +[Defines] >=20 > + PLATFORM_NAME =3D UefiCpuPkgHostTest >=20 > + PLATFORM_GUID =3D E00B9599-5B74-4FF7-AB9F-8183FB13B2F9 >=20 > + PLATFORM_VERSION =3D 0.1 >=20 > + DSC_SPECIFICATION =3D 0x00010005 >=20 > + OUTPUT_DIRECTORY =3D Build/UefiCpuPkg/HostTest >=20 > + SUPPORTED_ARCHITECTURES =3D IA32|X64 >=20 > + BUILD_TARGETS =3D NOOPT >=20 > + SKUID_IDENTIFIER =3D DEFAULT >=20 > + >=20 > +!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc >=20 > + >=20 > +[LibraryClasses] >=20 > + MtrrLib|UefiCpuPkg/Library/MtrrLib/MtrrLib.inf >=20 > + >=20 > +[PcdsPatchableInModule] >=20 > + gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs|0 >=20 > + >=20 > +[Components] >=20 > + # >=20 > + # Build HOST_APPLICATION that tests the MtrrLib >=20 > + # >=20 > + UefiCpuPkg/Library/MtrrLib/UnitTest/MtrrLibUnitTestHost.inf >=20 > -- > 2.27.0.windows.1