From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga01.intel.com (mga01.intel.com [192.55.52.88]) by mx.groups.io with SMTP id smtpd.web11.15471.1665538270452306225 for ; Tue, 11 Oct 2022 18:31:10 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=EumrOPDR; spf=pass (domain: intel.com, ip: 192.55.52.88, mailfrom: dun.tan@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1665538270; x=1697074270; h=from:to:cc:subject:date:message-id:references: in-reply-to:content-transfer-encoding:mime-version; bh=o58eg6ZEq1kDas511zw70p3A7ie2JFgrbnqp/J7Ld70=; b=EumrOPDRNrliqDTvPlHKmvO0pwIS2wGvkX6Gst54OlCaj2+WXI+t5oon 9GeKU6cnSKw/1bwp4G1J46Z44Guq8Axpx0FxomD4aA4HM+My7I7gmiBP8 w3/BtGOt/LFYTxw0KheN5jqdHemWgcrnr36OtuBUvVM/CilmHOHpUrBOR X3GxZcP9b+ATRK8/r4Ra7AH3LmkiZqPP44n7rrjf8b0SHazpasHheOOsq agXgc8wZnbc2QVCu8sAap1c3J0UM7QYWFr9pWwQiIPq7E2zV6H/UQyR1t 14mIjvskD2ruNkKoRDif7nWWi3aJ6kdrmzmTIdDDh3q3R4Ux4AEIHSD9S A==; X-IronPort-AV: E=McAfee;i="6500,9779,10497"; a="331157590" X-IronPort-AV: E=Sophos;i="5.95,177,1661842800"; d="scan'208";a="331157590" Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga101.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 11 Oct 2022 18:31:09 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10497"; a="626583291" X-IronPort-AV: E=Sophos;i="5.95,177,1661842800"; d="scan'208";a="626583291" Received: from fmsmsx603.amr.corp.intel.com ([10.18.126.83]) by orsmga002.jf.intel.com with ESMTP; 11 Oct 2022 18:31:09 -0700 Received: from fmsmsx611.amr.corp.intel.com (10.18.126.91) by fmsmsx603.amr.corp.intel.com (10.18.126.83) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Tue, 11 Oct 2022 18:31:08 -0700 Received: from fmsmsx611.amr.corp.intel.com (10.18.126.91) by fmsmsx611.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31; Tue, 11 Oct 2022 18:31:06 -0700 Received: from fmsedg602.ED.cps.intel.com (10.1.192.136) by fmsmsx611.amr.corp.intel.com (10.18.126.91) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.31 via Frontend Transport; Tue, 11 Oct 2022 18:31:06 -0700 Received: from NAM11-DM6-obe.outbound.protection.outlook.com (104.47.57.168) by edgegateway.intel.com (192.55.55.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.1.2375.31; Tue, 11 Oct 2022 18:31:06 -0700 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=kXWoSM9kvXz9SExHv8TGfAsfl9oKISihz1JVOjde3pQiX6jm3G3Ahk/KfV5AuS81r1sRy7iPErSDwy97SovskFxeMTDZ81+EZWMBE9H/W+lDoBEHzQEOsHYHwjdAkK2z0IpeuhMxPzSrv7pe7QqRkvGsOkZ1XVXDsex0wPeUaHYAj87S/7wqTSa9skTjq0iDGR1hj3fb8KMTOT+4GNzqmLXG9w4KGfWcchZ3+D60v3d1r2lG4eqM7Ac1zEYEwzDAwac5eQZw545AOdhhx4z383dbxJ5WcSYRCIWb9Qd+SNfFImPyQcDM1zDhTX1P4w43oZF+D8bdXRrmibMMIoa+kA== 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-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=NKgrCErB+FAOLAKF3x7rBLvdTxU6obmTFdEDuqNqHU8=; b=Lg6BH0nhvR/77b9B5yPeNvwamhXUhxbCYcCQA679AOw/t1GAI4hBowpHK9CXLIjVW4P0qiixW1c8w6oeaivprMe6CBnjFvJTP4vDud7k/MnnZ+wMEHNUbt18USCP03inYr4EDfGX4xMz3lJuBYinxDHqPbAyn0UtSApxe9qJTeyw+O7HGHeiClAfzUWQIiFXbWhZ7kM15UwHV2nAxjNE7jdEpy1ItzYYfGknj6Vdr9wlsnQRUGx4d9piDjHSHUf7QEd8il0WdzChqBpjb4aRxGsm8DZ+2kO47OfIfoF9ZTk78tJ2UkuymMMX9lQmSGQlMzLEbcpt/XnTQ46+QXp7ew== 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 Received: from BN9PR11MB5483.namprd11.prod.outlook.com (2603:10b6:408:104::10) by SJ0PR11MB6766.namprd11.prod.outlook.com (2603:10b6:a03:47c::12) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.5709.15; Wed, 12 Oct 2022 01:31:03 +0000 Received: from BN9PR11MB5483.namprd11.prod.outlook.com ([fe80::74ca:2692:fcb:1664]) by BN9PR11MB5483.namprd11.prod.outlook.com ([fe80::74ca:2692:fcb:1664%7]) with mapi id 15.20.5676.040; Wed, 12 Oct 2022 01:31:03 +0000 From: "duntan" To: "Ni, Ray" , "devel@edk2.groups.io" CC: "Dong, Eric" , "Kumar, Rahul R" Subject: Re: [PATCH 1/3] UefiCpuPkg: Add Unit tests for DxeCpuExceptionHandlerLib Thread-Topic: [PATCH 1/3] UefiCpuPkg: Add Unit tests for DxeCpuExceptionHandlerLib Thread-Index: AQHY3TdFp0jrtiaO3UKFDitD0Yn5Sq4I75GQgAEJz2A= Date: Wed, 12 Oct 2022 01:31:02 +0000 Message-ID: References: <20221011060335.575-1-dun.tan@intel.com> <20221011060335.575-2-dun.tan@intel.com> In-Reply-To: Accept-Language: zh-CN, en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: dlp-product: dlpe-windows dlp-version: 11.6.500.17 dlp-reaction: no-action authentication-results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=intel.com; x-ms-publictraffictype: Email x-ms-traffictypediagnostic: BN9PR11MB5483:EE_|SJ0PR11MB6766:EE_ x-ms-office365-filtering-correlation-id: 6ec2c776-ada5-405d-8274-08daabf16cef x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0; x-microsoft-antispam-message-info: d8eMEPuK7qpYMARyH4D9u7Enouvc0qmPQeA0Kh6LX5WI4GEppBppC8jwxLL16IwTj/QBUYpUDG5u+kq4HX1YjKEfXLg9MyKeX3wRGXF2xL/Pd7m7HPRmU7gGjfP83wdtdHQYVrVIjmzSm7t3h6aFMIjdD4hGBRLQc/AlMb67P7ojdb6iOH+Wx5vN1xH/3R9Aj4S8DjVvveOIyx8FDh+iiGSR10bkt+gzrRwzoeM8qAssdU0/sK3fVA3T/WQHLyJ+Lx+sOKGhmF6ElPupZi/w81ltKzbTprYB1KZjXFNornRjVw00SrSkVCA7flna7eRSffdsEJun5oLtIzcbkzYW3dWT+XjveXMuAKe6aJ+sqSeCtqsRKvI3MhTpnZm9KcwAnfq8+/0OJu0MOiOetgPaRpSpneZ5HOxYkenXIW2cYjhI/aJanz6GGLOvWc3jeE++fiZKByxitLlgdeset/jy3Q8gm56LBR+Ff7rAlo02RNahYFMmFwME8HLzyDPSf/qFCKFkjkPYtGpi6ZNa7+hhGRgRE8n4Tt8ouEp250DL4VfC85MDxEqE9XTltJkpNCXvp5LHV0UAAEVDei1/lTnKIqohAmDpJ1dDN+d6K5bLC3SXFzikMyaYcZR8bQsQHPaz4/t5g9bjas0akGQLhtM9dE2QhwWhfvzofnxcKM3Y7lmvHcHHRhj7cDhOdJvmHDQ78uPQvdV9T1xX0yL2qqbO05KpXOzQc/LVtAW3Auu/kuXN1kDLis9/w4eN7vAUHUecRSZyZakFr2/robGEaL2dgr8zRqmVnO8ObEvbuSg+Dsc= x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:BN9PR11MB5483.namprd11.prod.outlook.com;PTR:;CAT:NONE;SFS:(13230022)(376002)(346002)(136003)(366004)(39860400002)(396003)(451199015)(53546011)(8936002)(55016003)(86362001)(76116006)(66946007)(122000001)(316002)(38070700005)(19627235002)(8676002)(66446008)(64756008)(66476007)(33656002)(26005)(38100700002)(71200400001)(4326008)(54906003)(82960400001)(107886003)(478600001)(6506007)(110136005)(83380400001)(7696005)(9686003)(66556008)(41300700001)(52536014)(186003)(30864003)(2906002)(5660300002)(213903007)(579004)(559001);DIR:OUT;SFP:1102; x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?27b1LPguENxlu+vcHrbLrrv766hJOJXqwyBkPzbJy0CfWye2wYJzc2cnvwSL?= =?us-ascii?Q?jGrUqdzRxSL83PlSq4bX3L1x4B97wrIaPKXEiHM7121xt4Bc7YAohfpgnP1i?= =?us-ascii?Q?zaIp5buLMOiX8rzLsAlaex7DJ81FbZ7Y/XwQDJyOhXNQ8pgr6KdAmZWUtkoM?= =?us-ascii?Q?mkIR5NSfGAhPtQ2KerS+2qgdGME30qPZ82ZsmhMie17M2lGJMZ2LE49UfjdQ?= =?us-ascii?Q?YA1vScc/NEmfKhAIAXcum9wvxffYfM+8BFTa+CW7PypbtIuUq56Vqu2qyW1J?= =?us-ascii?Q?Cp9oGPDQIJ1aDlV9CTsCtvY0gwIYlsQOlkaO+rGwxX7YNgM2wvqEm7nH2sJb?= =?us-ascii?Q?tQau1yaD82gp4KLJVjHs1xNxM4gkUitLJ5Dap8hWubDtYzOZ5qYgiJtGvFXW?= =?us-ascii?Q?OtH/JHpEO6s3OmN3iBx4WrRa5fU0Hm2DYKAep8VW6UnF+mF2PBbYn7ltD5WS?= =?us-ascii?Q?BQB98syPGZZZ8PTTqPAeoxQ8vDR7dzk+vCFdjJg4ILkauYitco2Pl/xJQkFV?= =?us-ascii?Q?suh0tGQcUuDqM/xHlEoKjzmGUKdi1WM8Wovj1XYrm/xl2tiwOYK4/3qrcrfd?= =?us-ascii?Q?ngOT3bu3hyPcG1q2VOrsyJTr23sZGgs/lu7wxIdvqlgwhWypjUwNIM6EtpYh?= =?us-ascii?Q?38BqeIY2ATspS+tb3ozediuV4goVE5KPPM2L6TQySCz3+DOt1g3Pozt1F3Li?= =?us-ascii?Q?4a7xWgc9h+C6FuUPidVB3T2bojgooGO3GQxO+gnD/Lf9OUBOaXw5CFkrRgtB?= =?us-ascii?Q?YfheQhjMsZHmkDc4HYROOSSbDL2VC8W1ek2/71a/I/dUQrxC1So884NO9qt7?= =?us-ascii?Q?CA6/DYpWQ5FczVS2eAbdKQgZOr1cf5EyE4JvhJUsyQs0sugQz7ZV8WH/IAZ2?= =?us-ascii?Q?nFxl6k2qUBAGkuH0Av16YZZ49JC15Qbd1B24xPj97B2R3FwnfPqxB7KWApRd?= =?us-ascii?Q?EmXVGvEQA4ei6fmHxt+PSkgQupiaSqxKeBjBaBjMlc2yeM7acML///cVoQNb?= =?us-ascii?Q?ByEft4Tfrl0Tk/pdzo3uIgqHuvwn1QIUNYlF2Z8aIwp/ccNlilsBBO5TT9q/?= =?us-ascii?Q?5FJ2kSeXfp8cmLzi/8Pfn5u/cjJ5XrDpFRDpKBiv/MNgcb85rg8T3zZLjaPi?= =?us-ascii?Q?bQYPHyfrPGvC8H555wme4U87cDFAI6mKQZxt26Gv6WBXmMn9VKQ5dlc9r3qv?= =?us-ascii?Q?gcDp5Cvt7KzU7AlLiM088XKgL8gzIah4jXRlhTxf+xsfLL8ecdJjo/9iWaPb?= =?us-ascii?Q?W/vJhMh2kszQV7p7dr/kiolTFWAuNpG7l01dmXFjQ5OQKNPZjHx9hOuRMlxE?= =?us-ascii?Q?Bia8RZyXFYHJIWTjXweAU7I1OY3KEjQXhn/p6JD9kOmyFVze0JwOBAj7sHnl?= =?us-ascii?Q?+X1uj0++ud+UVicJFrq2JyF7LifrpbjcxpdH+33IyTzdJoq3Q5lRGOqXjmFy?= =?us-ascii?Q?Pvi/EGDbQ18G2pHM0Njb64pK4M+HPydZyE9QNGcs8AFcqxIs44vUQA7nmIVi?= =?us-ascii?Q?qpk0g3wL1TMBjDZx0+tP5hiUSmXbsZbUiUGwa6d93kMNOTf9PqqgNnlCgQt7?= =?us-ascii?Q?j8HG4TVw4799CjLVInE=3D?= MIME-Version: 1.0 X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: BN9PR11MB5483.namprd11.prod.outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: 6ec2c776-ada5-405d-8274-08daabf16cef X-MS-Exchange-CrossTenant-originalarrivaltime: 12 Oct 2022 01:31:02.9293 (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: LE8vTCGgJOsvaxslri8M3SmZIHKSpDj+qjcb7iQ15028/FjoVPMsAB/1vxGrOjfXPBBTF1iaaMs5Jyud3Vpnng== X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ0PR11MB6766 Return-Path: dun.tan@intel.com X-OriginatorOrg: intel.com Content-Language: en-US Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable Ok, I'll do this in V2 patch. Thanks for your comments. Thanks, Dun -----Original Message----- From: Ni, Ray =20 Sent: Tuesday, October 11, 2022 5:38 PM To: Tan, Dun ; devel@edk2.groups.io Cc: Dong, Eric ; Kumar, Rahul R Subject: RE: [PATCH 1/3] UefiCpuPkg: Add Unit tests for DxeCpuExceptionHand= lerLib Can you provide more details in the commit message? Especially explain what "consistent" means for #3 and what "CpuStackGuard i= n both BSP and AP" means in #4? Thanks, Ray > -----Original Message----- > From: Tan, Dun > Sent: Tuesday, October 11, 2022 2:04 PM > To: devel@edk2.groups.io > Cc: Dong, Eric ; Ni, Ray ; Kumar, > Rahul R > Subject: [PATCH 1/3] UefiCpuPkg: Add Unit tests for > DxeCpuExceptionHandlerLib >=20 > Add target based unit tests for the DxeCpuExceptionHandlerLib. > A DXE driver is created to test DxeCpuExceptionHandlerLib. Four > kinds of test cases are created in this module: > 1.Test if exception handler can be registered/unregistered for > no error code exception. 2.Test if exception handler can be > registered/unregistered for GP and PF. 3.Test if Cpu Context > is consistent before and after exception. 4.Test if stack > overflow can be captured by CpuStackGuard in both Bsp and AP. >=20 > Signed-off-by: Dun Tan > Cc: Eric Dong > Cc: Ray Ni > Cc: Rahul Kumar > --- > UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h > | 353 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++ >=20 > UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestComm > on.c | 856 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++ >=20 > UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibUnit > Test.inf | 58 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ >=20 > UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnitTe > st.c | 196 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++ >=20 > UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTest.c > | 167 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > +++++++++++++++++++++++++++++++++++++++++++++++++++ >=20 > UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTestA > sm.nasm | 260 > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > ++++++++++++++++++++++++++++ > 6 files changed, 1890 insertions(+) >=20 > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h > new file mode 100644 > index 0000000000..bfbc483075 > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h > @@ -0,0 +1,353 @@ > +/** @file > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#ifndef CPU_EXCEPTION_HANDLER_TEST_H_ > +#define CPU_EXCEPTION_HANDLER_TEST_H_ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +#define UNIT_TEST_APP_NAME "Cpu Exception Handler Lib Unit Tests" > +#define UNIT_TEST_APP_VERSION "1.0" > + > +#define CPU_INTERRUPT_NUM 256 > +#define SPEC_MAX_EXCEPTION_NUM 22 > +#define CR4_RESERVED_BIT BIT15 > + > +#pragma pack (1) > + > +typedef union { > + struct { > + UINT32 LimitLow : 16; > + UINT32 BaseLow : 16; > + UINT32 BaseMid : 8; > + UINT32 Type : 4; > + UINT32 System : 1; > + UINT32 Dpl : 2; > + UINT32 Present : 1; > + UINT32 LimitHigh : 4; > + UINT32 Software : 1; > + UINT32 Reserved : 1; > + UINT32 DefaultSize : 1; > + UINT32 Granularity : 1; > + UINT32 BaseHigh : 8; > + } Bits; > + UINT64 Uint64; > +} IA32_GDT; > + > +typedef struct { > + UINT32 InitialApicId; > + UINT32 ApicId; > + UINT32 Health; > + UINT64 ApTopOfStack; > +} CPU_INFO_IN_HOB; > +#pragma pack () > + > +typedef struct { > + IA32_DESCRIPTOR OriginalGdtr; > + IA32_DESCRIPTOR OriginalIdtr; > + UINT16 Tr; > +} CPU_REGISTER_BUFFER; > + > +typedef union { > + EDKII_PEI_MP_SERVICES2_PPI *Ppi; > + EFI_MP_SERVICES_PROTOCOL *Protocol; > +} MP_SERVICES; > + > +typedef struct { > + VOID *Buffer; > + UINTN BufferSize; > + EFI_STATUS Status; > +} EXCEPTION_STACK_SWITCH_CONTEXT; > + > +typedef struct { > + UINT64 Rdi; > + UINT64 Rsi; > + UINT64 Rbp; > + UINT64 Rbx; > + UINT64 Rdx; > + UINT64 Rcx; > + UINT64 Rax; > + UINT64 R8Register; > + UINT64 R9Register; > + UINT64 R10Register; > + UINT64 R11Register; > + UINT64 R12Register; > + UINT64 R13Register; > + UINT64 R14Register; > + UINT64 R15Register; > +} GENERAL_REGISTER; > + > +typedef struct { > + UINT32 Edi; > + UINT32 Esi; > + UINT32 Ebp; > + UINT32 Ebx; > + UINT32 Edx; > + UINT32 Ecx; > + UINT32 Eax; > +} GENERAL_REGISTER_IA32; > + > +extern UINTN mFaultInstructionLength; > +extern EFI_EXCEPTION_TYPE mExceptionType; > +extern UINTN mRspAddress[]; > +extern GENERAL_REGISTER mRegisterForCheck[]; > +extern GENERAL_REGISTER mAdjustRegisterBeforeException; > +extern GENERAL_REGISTER_IA32 mIa32RegisterForCheck[]; > +extern GENERAL_REGISTER_IA32 mAdjustIa32RegisterBeforeException; > + > +/** > + Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR > buffer. > + In PEIM, store original PeiServicePointer before new Idt table. > + > + @return Pointer to the allocated IA32_DESCRIPTOR buffer. > +**/ > +VOID * > +InitializeBspIdt ( > + VOID > + ); > + > +/** > + Trigger no error code exception by INT n instruction. > + > + @param[in] ExceptionType No error code exception type. > +**/ > +VOID > +EFIAPI > +TriggerINTnException ( > + IN EFI_EXCEPTION_TYPE ExceptionType > + ); > + > +/** > + Trigger GP exception. > + > + @param[in] Cr4ReservedBit Cr4 reserved bit. > +**/ > +VOID > +EFIAPI > +TriggerGPException ( > + UINTN Cr4ReservedBit > + ); > + > +/** > + Trigger PF exception by write to not present or ReadOnly address. > + > + @param[in] PFAddress Not present or ReadOnly address in page table. > +**/ > +VOID > +EFIAPI > +TriggerPFException ( > + UINTN PFAddress > + ); > + > +/** > + Special handler for fault exception. > + Rip/Eip in SystemContext will be modified to the instruction after the > exception instruction. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +AdjustRipForFaultHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ); > + > +/** > + Test consistency of Cpu context. Four steps: > + 1. Set Cpu register to mAdjustRegisterBeforeException before exception= . > + 2. Trigger exception specified by ExceptionType. > + 3. Store SystemContext in mRegisterForCheck[0] and set SystemContext > to mAdjustRegisterInsideException in handler. > + 4. Store the Cpu register in mRegisterForCheck[1] > + > + Rcx/Ecx in mAdjustRegisterInsideException is decided by different > exception type runtime since Rcx/Ecx is needed in assembly code. > + For GP and PF, Rcx/Ecx is set to FaultParameter. For other exception > triggered by INTn, Rcx/Ecx is set to ExceptionType. > + > + @param[in] ExceptionType Exception type. > + @param[in] FaultParameter Parameter for GP and PF. OPTIONAL > +**/ > +VOID > +EFIAPI > +AsmTestConsistencyOfCpuContext ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN UINTN FaultParameter OPTIONAL > + ); > + > +/** > + Special handler for ConsistencyOfCpuContext test case. General registe= r in > SystemContext > + is modified in this handler. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +AdjustCpuContextHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ); > + > +/** > + Compare cpu context in ConsistencyOfCpuContext test case. > + 1.Compare mRegisterForCheck[0] with mAdjustRegisterBeforeException. > + 2.Compare mRegisterForCheck[1] with mAdjustRegisterAfterException. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = it was > successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +CompareCpuContext ( > + VOID > + ); > + > +/** > + Get EFI_MP_SERVICES_PROTOCOL/EDKII_PEI_MP_SERVICES2_PPI pointer. > + > + @param[out] MpServices Pointer to the MP_SERVICES buffer > + > + @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL/PPI interface is > returned > + @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL/PPI interface is > not found > +**/ > +EFI_STATUS > +GetMpServices ( > + OUT MP_SERVICES *MpServices > + ); > + > +/** > + Create CpuExceptionLibUnitTestSuite and add test case. > + > + @param[in] FrameworkHandle Unit test framework. > + > + @return EFI_SUCCESS The unit test suite was created. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources > available to > + initialize the unit test suite. > +**/ > +EFI_STATUS > +AddCommonTestCase ( > + IN UNIT_TEST_FRAMEWORK_HANDLE Framework > + ); > + > +/** > + Execute a caller provided function on all enabled APs. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[in] Procedure Pointer to the function to be run on enabled= APs > of the system. > + @param[in] SingleThread If TRUE, then all the enabled APs execute th= e > function specified by Procedure > + one by one, in ascending order of processor = handle number. > + If FALSE, then all the enabled APs execute t= he function > specified by Procedure > + simultaneously. > + @param[in] TimeoutInMicroseconds Indicates the time limit in > microseconds for APs to return from Procedure, > + for blocking mode only. Zero means i= nfinity. > + @param[in] ProcedureArgument The parameter passed into Procedure > for all APs. > + > + @retval EFI_SUCCESS Execute a caller provided function on all en= abled > APs successfully > + @retval Others Execute a caller provided function on all en= abled APs > unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestStartupAllAPs ( > + IN MP_SERVICES MpServices, > + IN EFI_AP_PROCEDURE Procedure, > + IN BOOLEAN SingleThread, > + IN UINTN TimeoutInMicroSeconds, > + IN VOID *ProcedureArgument > + ); > + > +/** > + Caller gets one enabled AP to execute a caller-provided function. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[in] Procedure Pointer to the function to be run on enabled= APs > of the system. > + @param[in] ProcessorNumber The handle number of the AP. > + @param[in] TimeoutInMicroseconds Indicates the time limit in > microseconds for APs to return from Procedure, > + for blocking mode only. Zero means i= nfinity. > + @param[in] ProcedureArgument The parameter passed into Procedure > for all APs. > + > + > + @retval EFI_SUCCESS Caller gets one enabled AP to execute a call= er- > provided function successfully > + @retval Others Caller gets one enabled AP to execute a call= er- > provided function unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestStartupThisAP ( > + IN MP_SERVICES MpServices, > + IN EFI_AP_PROCEDURE Procedure, > + IN UINTN ProcessorNumber, > + IN UINTN TimeoutInMicroSeconds, > + IN VOID *ProcedureArgument > + ); > + > +/** > + Get the handle number for the calling processor. > + > + @param[in] MpServices Pointer to MP_SERVICES structure. > + @param[out] ProcessorNumber The handle number for the calling > processor. > + > + @retval EFI_SUCCESS Get the handle number for the calling proces= sor > successfully. > + @retval Others Get the handle number for the calling proces= sor > unsuccessfully. > +**/ > +EFI_STATUS > +MpServicesUnitTestWhoAmI ( > + IN MP_SERVICES MpServices, > + OUT UINTN *ProcessorNumber > + ); > + > +/** > + Retrieve the number of logical processor in the platform and the numbe= r > of those logical processors that > + are enabled on this boot. > + > + @param[in] MpServices Pointer to MP_SERVICES structure. > + @param[out] NumberOfProcessors Pointer to the total number of logical > processors in the system, including > + the BSP and disabled APs. > + @param[out] NumberOfEnabledProcessors Pointer to the number of > processors in the system that are enabled. > + > + @retval EFI_SUCCESS Retrieve the number of logical processor > successfully > + @retval Others Retrieve the number of logical processor > unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestGetNumberOfProcessors ( > + IN MP_SERVICES MpServices, > + OUT UINTN *NumberOfProcessors, > + OUT UINTN *NumberOfEnabledProcessors > + ); > + > +/** > + Trigger stack overflow by CpuStackGuard. > +**/ > +VOID > +EFIAPI > +TriggerStackOverflowbyCpuStackGuard ( > + VOID > + ); > + > +/** > + Special handler for CpuStackGuard test case. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +CpuStackGuardExceptionHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ); > + > +#endif > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCom > mon.c > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCom > mon.c > new file mode 100644 > index 0000000000..1c3d011c76 > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCom > mon.c > @@ -0,0 +1,856 @@ > +/** @file > + Unit tests of the CpuExceptionHandlerLib. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "CpuExceptionHandlerTest.h" > + > +// > +// Length of the assembly falut instruction. > +// > +UINTN mFaultInstructionLength =3D 0; > +EFI_EXCEPTION_TYPE mExceptionType =3D 256; > +UINTN mNumberOfProcessors =3D 1; > +UINTN mRspAddress[2] =3D { 0 }; > + > +// > +// Error code flag indicating whether or not an error code will be > +// pushed on the stack if an exception occurs. > +// > +// 1 means an error code will be pushed, otherwise 0 > +// > +CONST UINT32 mErrorCodeExceptionFlag =3D 0x20227d00; > + > +/** > + Special handler for trap exception. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +INTnExceptionHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + mExceptionType =3D ExceptionType; > +} > + > +/** > + Restore all cpu original register before test case. > + > + @param[in] Buffer Argument of the procedure. > +**/ > +VOID > +EFIAPI > +RestoreRegistersPerCpu ( > + IN VOID *Buffer > + ) > +{ > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + UINT16 Tr; > + IA32_TSS_DESCRIPTOR *Tss; > + > + CpuOriginalRegisterBuffer =3D (CPU_REGISTER_BUFFER *)Buffer; > + > + AsmWriteGdtr (&(CpuOriginalRegisterBuffer->OriginalGdtr)); > + AsmWriteIdtr (&(CpuOriginalRegisterBuffer->OriginalIdtr)); > + Tr =3D CpuOriginalRegisterBuffer->Tr; > + if ((Tr !=3D 0) && (Tr < CpuOriginalRegisterBuffer->OriginalGdtr.Limit= )) { > + Tss =3D (IA32_TSS_DESCRIPTOR *)(CpuOriginalRegisterBuffer- > >OriginalGdtr.Base + Tr); > + if (Tss->Bits.P =3D=3D 1) { > + // > + // Clear busy bit of TSS before write Tr > + // > + Tss->Bits.Type &=3D 0xD; > + AsmWriteTr (Tr); > + } > + } > +} > + > +/** > + Restore all cpu original register before test case. > + > + @param[in] MpServices MpServices. > + @param[in] CpuOriginalRegisterBuffer Address of > CpuOriginalRegisterBuffer. > + @param[in] BspProcessorNum Bsp processor number. > +**/ > +VOID > +RestoreAllCpuRegisters ( > + MP_SERVICES *MpServices, OPTIONAL > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer, > + UINTN BspProcessorNum > + ) > +{ > + CPU_REGISTER_BUFFER *AllCpuOriginalRegisterBuffer; > + UINTN Index; > + EFI_STATUS Status; > + > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + AllCpuOriginalRegisterBuffer =3D CpuOriginalRegisterBuffer + Index; > + if (Index =3D=3D BspProcessorNum) { > + RestoreRegistersPerCpu ((VOID *)AllCpuOriginalRegisterBuffer); > + continue; > + } > + > + ASSERT (MpServices !=3D NULL); > + Status =3D MpServicesUnitTestStartupThisAP ( > + *MpServices, > + (EFI_AP_PROCEDURE)RestoreRegistersPerCpu, > + Index, > + 0, > + (VOID *)AllCpuOriginalRegisterBuffer > + ); > + ASSERT_EFI_ERROR (Status); > + } > +} > + > +/** > + Store all cpu original register before test case. > + > + @param[in] Buffer Argument of the procedure. > +**/ > +VOID > +EFIAPI > +SaveRegisterPerCpu ( > + IN VOID *Buffer > + ) > +{ > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + IA32_DESCRIPTOR Gdtr; > + IA32_DESCRIPTOR Idtr; > + > + CpuOriginalRegisterBuffer =3D (CPU_REGISTER_BUFFER *)Buffer; > + > + AsmReadGdtr (&Gdtr); > + AsmReadIdtr (&Idtr); > + CpuOriginalRegisterBuffer->OriginalGdtr.Base =3D Gdtr.Base; > + CpuOriginalRegisterBuffer->OriginalGdtr.Limit =3D Gdtr.Limit; > + CpuOriginalRegisterBuffer->OriginalIdtr.Base =3D Idtr.Base; > + CpuOriginalRegisterBuffer->OriginalIdtr.Limit =3D Idtr.Limit; > + CpuOriginalRegisterBuffer->Tr =3D AsmReadTr (); > +} > + > +/** > + Store all cpu original register before test case. > + > + @param[in] MpServices MpServices. > + @param[in] BspProcessorNum Bsp processor number. > + > + @return Pointer to the allocated CPU_REGISTER_BUFFER. > +**/ > +CPU_REGISTER_BUFFER * > +SaveAllCpuRegisters ( > + MP_SERVICES *MpServices, OPTIONAL > + UINTN BspProcessorNum > + ) > +{ > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + CPU_REGISTER_BUFFER *AllCpuOriginalRegisterBuffer; > + EFI_STATUS Status; > + UINTN Index; > + > + CpuOriginalRegisterBuffer =3D AllocateZeroPool (mNumberOfProcessors * > sizeof (CPU_REGISTER_BUFFER)); > + ASSERT (CpuOriginalRegisterBuffer !=3D NULL); > + > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + AllCpuOriginalRegisterBuffer =3D CpuOriginalRegisterBuffer + Index; > + if (Index =3D=3D BspProcessorNum) { > + SaveRegisterPerCpu ((VOID *)AllCpuOriginalRegisterBuffer); > + continue; > + } > + > + ASSERT (MpServices !=3D NULL); > + Status =3D MpServicesUnitTestStartupThisAP ( > + *MpServices, > + (EFI_AP_PROCEDURE)SaveRegisterPerCpu, > + Index, > + 0, > + (VOID *)AllCpuOriginalRegisterBuffer > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + return CpuOriginalRegisterBuffer; > +} > + > +/** > + Initialize Ap Idt Procedure. > + > + @param[in] Buffer Argument of the procedure. > +**/ > +VOID > +EFIAPI > +InitializeIdtPerAp ( > + IN VOID *Buffer > + ) > +{ > + AsmWriteIdtr (Buffer); > +} > + > +/** > + Initialize all Ap Idt. > + > + @param[in] MpServices MpServices. > + @param[in] BspIdtr Pointer to IA32_DESCRIPTOR allocated by Bsp. > +**/ > +VOID > +InitializeApIdt ( > + MP_SERVICES MpServices, > + VOID *BspIdtr > + ) > +{ > + EFI_STATUS Status; > + > + Status =3D MpServicesUnitTestStartupAllAPs ( > + MpServices, > + (EFI_AP_PROCEDURE)InitializeIdtPerAp, > + FALSE, > + 0, > + BspIdtr > + ); > + ASSERT_EFI_ERROR (Status); > +} > + > +/** > + Check if exception handler can registered/unregistered for no error co= de > exception. > + > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = that may > + consume it. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test > + case was successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +EFIAPI > +TestRegisterHandlerForNoErrorCodeException ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + VOID *NewIdtr; > + > + CpuOriginalRegisterBuffer =3D SaveAllCpuRegisters (NULL, 0); > + NewIdtr =3D InitializeBspIdt (); > + Status =3D InitializeCpuExceptionHandlers (NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + for (Index =3D 0; Index < SPEC_MAX_EXCEPTION_NUM; Index++) { > + // > + // Only test no error code exception by INT n instruction. > + // > + if ((mErrorCodeExceptionFlag & (1 << Index)) !=3D 0) { > + continue; > + } > + > + DEBUG ((DEBUG_INFO, "TestCase1: ExceptionType is %d\n", Index)); > + Status =3D RegisterCpuInterruptHandler (Index, INTnExceptionHandler)= ; > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + TriggerINTnException (Index); > + UT_ASSERT_EQUAL (mExceptionType, Index); > + Status =3D RegisterCpuInterruptHandler (Index, NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + } > + > + RestoreAllCpuRegisters (NULL, CpuOriginalRegisterBuffer, 0); > + FreePool (CpuOriginalRegisterBuffer); > + FreePool (NewIdtr); > + return UNIT_TEST_PASSED; > +} > + > +/** > + Get Bsp stack base. > + > + @param[out] StackBase Pointer to stack base of BSP. > +**/ > +VOID > +GetBspStackBase ( > + OUT UINTN *StackBase > + ) > +{ > + EFI_PEI_HOB_POINTERS Hob; > + EFI_HOB_MEMORY_ALLOCATION *MemoryHob; > + > + // > + // Get the base of stack from Hob. > + // > + ASSERT (StackBase !=3D NULL); > + Hob.Raw =3D GetHobList (); > + while ((Hob.Raw =3D GetNextHob (EFI_HOB_TYPE_MEMORY_ALLOCATION, > Hob.Raw)) !=3D NULL) { > + MemoryHob =3D Hob.MemoryAllocation; > + if (CompareGuid (&gEfiHobMemoryAllocStackGuid, &MemoryHob- > >AllocDescriptor.Name)) { > + DEBUG (( > + DEBUG_INFO, > + "%a: Bsp StackBase =3D 0x%016lx StackSize =3D 0x%016lx\n", > + __FUNCTION__, > + MemoryHob->AllocDescriptor.MemoryBaseAddress, > + MemoryHob->AllocDescriptor.MemoryLength > + )); > + > + *StackBase =3D (UINTN)MemoryHob- > >AllocDescriptor.MemoryBaseAddress; > + // > + // Ensure the base of the stack is page-size aligned. > + // > + ASSERT ((*StackBase & EFI_PAGE_MASK) =3D=3D 0); > + break; > + } > + > + Hob.Raw =3D GET_NEXT_HOB (Hob); > + } > + > + ASSERT (*StackBase !=3D 0); > +} > + > +/** > + Initialize Ap Idt Procedure. > + > + @param[in] Buffer Argument of the procedure. > +**/ > +VOID > +EFIAPI > +GetStackBasePerAp ( > + IN VOID *Buffer > + ) > +{ > + UINTN ApTopOfStack; > + > + ApTopOfStack =3D ALIGN_VALUE ((UINTN)&ApTopOfStack, > (UINTN)PcdGet32 (PcdCpuApStackSize)); > + *(UINTN *)Buffer =3D ApTopOfStack - (UINTN)PcdGet32 > (PcdCpuApStackSize); > +} > + > +/** > + Get Ap stack Info. > + > + @param[in] MpServices MpServices. > + @param[in] BspProcessorNum Bsp processor number. > + > + @return Pointer to the allocated CpuStackBaseBuffer. > +**/ > +UINTN * > +GetAllCpuStackBase ( > + MP_SERVICES *MpServices, > + UINTN BspProcessorNum > + ) > +{ > + UINTN *CpuStackBaseBuffer; > + UINTN *AllCpuStackBaseBuffer; > + EFI_STATUS Status; > + UINTN Index; > + > + CpuStackBaseBuffer =3D AllocateZeroPool (mNumberOfProcessors * sizeof > (UINTN)); > + ASSERT (CpuStackBaseBuffer !=3D NULL); > + > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + AllCpuStackBaseBuffer =3D CpuStackBaseBuffer + Index; > + if (Index =3D=3D BspProcessorNum) { > + GetBspStackBase (AllCpuStackBaseBuffer); > + continue; > + } > + > + ASSERT (MpServices !=3D NULL); > + Status =3D MpServicesUnitTestStartupThisAP ( > + *MpServices, > + (EFI_AP_PROCEDURE)GetStackBasePerAp, > + Index, > + 0, > + (VOID *)AllCpuStackBaseBuffer > + ); > + ASSERT_EFI_ERROR (Status); > + DEBUG ((DEBUG_INFO, "AP[%d] StackBase =3D 0x%x\n", Index, > CpuStackBaseBuffer[Index])); > + } > + > + return CpuStackBaseBuffer; > +} > + > +/** > + Return not present or ReadOnly address in page table. > + > + @param[out] PFAddress Access to the address which is not permitted wi= ll > trigger PF exceptions. > +**/ > +VOID > +PageFaultAddressInPageTable ( > + UINTN *PFAddress > + ) > +{ > + IA32_CR0 Cr0; > + IA32_CR4 Cr4; > + UINTN PageTable; > + PAGING_MODE PagingMode; > + BOOLEAN Enable5LevelPaging; > + RETURN_STATUS Status; > + IA32_MAP_ENTRY *Map; > + UINTN MapCount; > + UINTN Index; > + > + ASSERT (PFAddress !=3D NULL); > + *PFAddress =3D 0; > + > + Cr0.UintN =3D AsmReadCr0 (); > + if (Cr0.Bits.PG =3D=3D 0) { > + return; > + } > + > + PageTable =3D AsmReadCr3 (); > + Cr4.UintN =3D AsmReadCr4 (); > + if (sizeof (UINTN) =3D=3D sizeof (UINT32)) { > + ASSERT (Cr4.Bits.PAE =3D=3D 1); > + PagingMode =3D PagingPae; > + } else { > + Enable5LevelPaging =3D (BOOLEAN)(Cr4.Bits.LA57 =3D=3D 1); > + PagingMode =3D Enable5LevelPaging ? Paging5Level : Paging4Le= vel; > + } > + > + MapCount =3D 0; > + Status =3D PageTableParse (PageTable, PagingMode, NULL, &MapCount); > + ASSERT (Status =3D=3D RETURN_BUFFER_TOO_SMALL); > + Map =3D AllocatePages (EFI_SIZE_TO_PAGES (MapCount * sizeof > (IA32_MAP_ENTRY))); > + Status =3D PageTableParse (PageTable, PagingMode, Map, &MapCount); > + ASSERT (Status =3D=3D RETURN_SUCCESS); > + > + for (Index =3D 0; Index < MapCount; Index++) { > + DEBUG (( > + DEBUG_ERROR, > + "%02d: %016lx - %016lx, %016lx\n", > + Index, > + Map[Index].LinearAddress, > + Map[Index].LinearAddress + Map[Index].Length, > + Map[Index].Attribute.Uint64 > + )); > + > + // > + // Not present address in page table. > + // > + if ((Index >=3D 1) && (Map[Index].LinearAddress > Map[Index - > 1].LinearAddress + Map[Index - 1].Length)) { > + *PFAddress =3D (UINTN)(Map[Index - 1].LinearAddress + Map[Index - > 1].Length); > + return; > + } > + > + // > + // ReadOnly address in page table. > + // > + if ((Cr0.Bits.WP !=3D 0) && (Map[Index].Attribute.Bits.ReadWrite =3D= =3D 0)) { > + *PFAddress =3D (UINTN)Map[Index].LinearAddress; > + return; > + } > + } > +} > + > +/** > + Test if exception handler can registered/unregistered for GP and PF. > + > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = that may > + consume it. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test > + case was successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +EFIAPI > +TestRegisterHandlerForGPAndPF ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + UINTN PFAddress; > + VOID *NewIdtr; > + > + PFAddress =3D 0; > + CpuOriginalRegisterBuffer =3D SaveAllCpuRegisters (NULL, 0); > + NewIdtr =3D InitializeBspIdt (); > + Status =3D InitializeCpuExceptionHandlers (NULL); > + > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + // > + // GP exception. > + // > + DEBUG ((DEBUG_INFO, "TestCase2: ExceptionType is %d\n", > EXCEPT_IA32_GP_FAULT)); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_GP_FAULT, > AdjustRipForFaultHandler); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + TriggerGPException (CR4_RESERVED_BIT); > + UT_ASSERT_EQUAL (mExceptionType, EXCEPT_IA32_GP_FAULT); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_GP_FAULT, NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + // > + // PF exception. > + // > + PageFaultAddressInPageTable (&PFAddress); > + > + if (PFAddress > 0) { > + DEBUG ((DEBUG_INFO, "TestCase2: ExceptionType is %d\n", > EXCEPT_IA32_PAGE_FAULT)); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, > AdjustRipForFaultHandler); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + TriggerPFException (PFAddress); > + > + UT_ASSERT_EQUAL (mExceptionType, EXCEPT_IA32_PAGE_FAULT); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, > NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + } > + > + RestoreAllCpuRegisters (NULL, CpuOriginalRegisterBuffer, 0); > + FreePool (CpuOriginalRegisterBuffer); > + FreePool (NewIdtr); > + return UNIT_TEST_PASSED; > +} > + > +/** > + Test if Cpu Context is consistent before and after exception. > + > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = that may > + consume it. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test > + case was successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +EFIAPI > +TestCpuContextConsistency ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + UINTN FaultParameter; > + VOID *NewIdtr; > + > + FaultParameter =3D 0; > + CpuOriginalRegisterBuffer =3D SaveAllCpuRegisters (NULL, 0); > + NewIdtr =3D InitializeBspIdt (); > + Status =3D InitializeCpuExceptionHandlers (NULL); > + > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + for (Index =3D 0; Index < 22; Index++) { > + if (Index =3D=3D EXCEPT_IA32_PAGE_FAULT) { > + PageFaultAddressInPageTable (&FaultParameter); > + if (FaultParameter =3D=3D 0) { > + continue; > + } > + } else if (Index =3D=3D EXCEPT_IA32_GP_FAULT) { > + FaultParameter =3D CR4_RESERVED_BIT; > + } else { > + if ((mErrorCodeExceptionFlag & (1 << Index)) !=3D 0) { > + continue; > + } > + } > + > + DEBUG ((DEBUG_INFO, "TestCase3: ExceptionType is %d\n", Index)); > + Status =3D RegisterCpuInterruptHandler (Index, AdjustCpuContextHandl= er); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + // > + // Trigger different type exception and compare different stage cpu > context. > + // > + AsmTestConsistencyOfCpuContext (Index, FaultParameter); > + CompareCpuContext (); > + Status =3D RegisterCpuInterruptHandler (Index, NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + } > + > + RestoreAllCpuRegisters (NULL, CpuOriginalRegisterBuffer, 0); > + FreePool (CpuOriginalRegisterBuffer); > + FreePool (NewIdtr); > + return UNIT_TEST_PASSED; > +} > + > +/** > + Initializes CPU exceptions handlers for the sake of stack switch > requirement. > + > + This function is a wrapper of InitializeSeparateExceptionStacks. It's = mainly > + for the sake of AP's init because of EFI_AP_PROCEDURE API requirement. > + > + @param[in,out] Buffer The pointer to private data buffer. > + > +**/ > +VOID > +EFIAPI > +InitializeExceptionStackSwitchHandlersPerAp ( > + IN OUT VOID *Buffer > + ) > +{ > + EXCEPTION_STACK_SWITCH_CONTEXT *CpuSwitchStackData; > + > + CpuSwitchStackData =3D (EXCEPTION_STACK_SWITCH_CONTEXT *)Buffer; > + > + // > + // This may be called twice for each Cpu. Only run > InitializeSeparateExceptionStacks > + // if this is the first call or the first call failed because of size = too small. > + // > + if ((CpuSwitchStackData->Status =3D=3D EFI_NOT_STARTED) || > (CpuSwitchStackData->Status =3D=3D EFI_BUFFER_TOO_SMALL)) { > + CpuSwitchStackData->Status =3D InitializeSeparateExceptionStacks > (CpuSwitchStackData->Buffer, &CpuSwitchStackData->BufferSize); > + } > +} > + > +/** > + Initializes MP exceptions handlers for the sake of stack switch requir= ement. > + > + This function will allocate required resources required to setup stack= switch > + and pass them through SwitchStackData to each logic processor. > + > + @param[in, out] MpServices MpServices. > + @param[in, out] BspProcessorNum Bsp processor number. > + > + @return Pointer to the allocated SwitchStackData. > +**/ > +EXCEPTION_STACK_SWITCH_CONTEXT * > +InitializeMpExceptionStackSwitchHandlers ( > + MP_SERVICES MpServices, > + UINTN BspProcessorNum > + ) > +{ > + UINTN Index; > + EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData; > + EXCEPTION_STACK_SWITCH_CONTEXT *CpuSwitchStackData; > + UINTN BufferSize; > + EFI_STATUS Status; > + UINT8 *Buffer; > + > + SwitchStackData =3D AllocateZeroPool (mNumberOfProcessors * sizeof > (EXCEPTION_STACK_SWITCH_CONTEXT)); > + ASSERT (SwitchStackData !=3D NULL); > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + CpuSwitchStackData =3D SwitchStackData + Index; > + // > + // Because the procedure may runs multiple times, use the status > EFI_NOT_STARTED > + // to indicate the procedure haven't been run yet. > + // > + SwitchStackData[Index].Status =3D EFI_NOT_STARTED; > + if (Index =3D=3D BspProcessorNum) { > + InitializeExceptionStackSwitchHandlersPerAp ((VOID > *)CpuSwitchStackData); > + continue; > + } > + > + Status =3D MpServicesUnitTestStartupThisAP ( > + MpServices, > + InitializeExceptionStackSwitchHandlersPerAp, > + Index, > + 0, > + (VOID *)CpuSwitchStackData > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + BufferSize =3D 0; > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + if (SwitchStackData[Index].Status =3D=3D EFI_BUFFER_TOO_SMALL) { > + ASSERT (SwitchStackData[Index].BufferSize !=3D 0); > + BufferSize +=3D SwitchStackData[Index].BufferSize; > + } else { > + ASSERT (SwitchStackData[Index].Status =3D=3D EFI_SUCCESS); > + ASSERT (SwitchStackData[Index].BufferSize =3D=3D 0); > + } > + } > + > + if (BufferSize !=3D 0) { > + Buffer =3D AllocateZeroPool (BufferSize); > + ASSERT (Buffer !=3D NULL); > + BufferSize =3D 0; > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + if (SwitchStackData[Index].Status =3D=3D EFI_BUFFER_TOO_SMALL) { > + SwitchStackData[Index].Buffer =3D (VOID *)(&Buffer[BufferSize]); > + BufferSize +=3D SwitchStackData[Index].BufferS= ize; > + DEBUG (( > + DEBUG_INFO, > + "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlersPerA= p: > 0x%lX with size 0x%lX\n", > + (UINT64)(UINTN)Index, > + (UINT64)(UINTN)SwitchStackData[Index].Buffer, > + (UINT64)(UINTN)SwitchStackData[Index].BufferSize > + )); > + } > + } > + > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + CpuSwitchStackData =3D SwitchStackData + Index; > + if (Index =3D=3D BspProcessorNum) { > + InitializeExceptionStackSwitchHandlersPerAp ((VOID > *)CpuSwitchStackData); > + continue; > + } > + > + Status =3D MpServicesUnitTestStartupThisAP ( > + MpServices, > + InitializeExceptionStackSwitchHandlersPerAp, > + Index, > + 0, > + (VOID *)CpuSwitchStackData > + ); > + ASSERT_EFI_ERROR (Status); > + } > + > + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { > + ASSERT (SwitchStackData[Index].Status =3D=3D EFI_SUCCESS); > + } > + } > + > + return SwitchStackData; > +} > + > +/** > + Test if stack overflow is captured by CpuStackGuard in Bsp and AP. > + > + @param[in] Context [Optional] An optional parameter that enables: > + 1) test-case reuse with varied parameters and > + 2) test-case re-entry for Target tests that nee= d a > + reboot. This parameter is a VOID* and it is th= e > + responsibility of the test author to ensure tha= t the > + contents are well understood by all test cases = that may > + consume it. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = the > test > + case was successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +EFIAPI > +TestCpuStackGuardInBspAndAp ( > + IN UNIT_TEST_CONTEXT Context > + ) > +{ > + EFI_STATUS Status; > + UINTN OriginalStackBase; > + UINTN NewStackTop; > + UINTN NewStackBase; > + EXCEPTION_STACK_SWITCH_CONTEXT *SwitchStackData; > + MP_SERVICES MpServices; > + UINTN ProcessorNumber; > + UINTN EnabledProcessorNum; > + CPU_REGISTER_BUFFER *CpuOriginalRegisterBuffer; > + UINTN Index; > + UINTN BspProcessorNum; > + VOID *NewIdtr; > + UINTN *CpuStackBaseBuffer; > + > + if (!PcdGetBool (PcdCpuStackGuard)) { > + return UNIT_TEST_PASSED; > + } > + > + // > + // Get MP Service Protocol > + // > + Status =3D GetMpServices (&MpServices); > + Status =3D MpServicesUnitTestGetNumberOfProcessors (MpServices, > &ProcessorNumber, &EnabledProcessorNum); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + Status =3D MpServicesUnitTestWhoAmI (MpServices, &BspProcessorNum); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + mNumberOfProcessors =3D ProcessorNumber; > + > + CpuOriginalRegisterBuffer =3D SaveAllCpuRegisters (&MpServices, > BspProcessorNum); > + > + // > + // Initialize Bsp and AP Idt. > + // Idt buffer should not be empty or it will hang in MP API. > + // > + NewIdtr =3D InitializeBspIdt (); > + Status =3D InitializeCpuExceptionHandlers (NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + InitializeApIdt (MpServices, NewIdtr); > + > + // > + // Get BSP and AP original stack base. > + // > + CpuStackBaseBuffer =3D GetAllCpuStackBase (&MpServices, > BspProcessorNum); > + > + // > + // InitializeMpExceptionStackSwitchHandlers and register exception > handler. > + // > + SwitchStackData =3D InitializeMpExceptionStackSwitchHandlers (MpServic= es, > BspProcessorNum); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAUL= T, > CpuStackGuardExceptionHandler); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_DOUBLE_FAULT, > AdjustRipForFaultHandler); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + > + for (Index =3D 0; Index < mNumberOfProcessors; Index++) { > + OriginalStackBase =3D CpuStackBaseBuffer[Index]; > + NewStackTop =3D (UINTN)(SwitchStackData[Index].Buffer) + > SwitchStackData[Index].BufferSize; > + NewStackBase =3D (UINTN)(SwitchStackData[Index].Buffer); > + if (Index =3D=3D BspProcessorNum) { > + TriggerStackOverflowbyCpuStackGuard (); > + } else { > + MpServicesUnitTestStartupThisAP ( > + MpServices, > + (EFI_AP_PROCEDURE)TriggerStackOverflowbyCpuStackGuard, > + Index, > + 0, > + NULL > + ); > + } > + > + DEBUG ((DEBUG_INFO, "TestCase4: mRspAddress[0] is 0x%x, > mRspAddress[1] is 0x%x\n", mRspAddress[0], mRspAddress[1])); > + UT_ASSERT_TRUE ((mRspAddress[0] >=3D OriginalStackBase) && > (mRspAddress[0] <=3D (OriginalStackBase + SIZE_4KB))); > + UT_ASSERT_TRUE ((mRspAddress[1] >=3D NewStackBase) && > (mRspAddress[1] < NewStackTop)); > + } > + > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_DOUBLE_FAULT, > NULL); > + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); > + RestoreAllCpuRegisters (&MpServices, CpuOriginalRegisterBuffer, > BspProcessorNum); > + FreePool (SwitchStackData); > + FreePool (CpuOriginalRegisterBuffer); > + FreePool (NewIdtr); > + > + return UNIT_TEST_PASSED; > +} > + > +/** > + Create CpuExceptionLibUnitTestSuite and add test case. > + > + @param[in] FrameworkHandle Unit test framework. > + > + @return EFI_SUCCESS The unit test suite was created. > + @retval EFI_OUT_OF_RESOURCES There are not enough resources > available to > + initialize the unit test suite. > +**/ > +EFI_STATUS > +AddCommonTestCase ( > + IN UNIT_TEST_FRAMEWORK_HANDLE Framework > + ) > +{ > + EFI_STATUS Status; > + UNIT_TEST_SUITE_HANDLE CpuExceptionLibUnitTestSuite; > + > + // > + // Populate the Manual Test Cases. > + // > + Status =3D CreateUnitTestSuite (&CpuExceptionLibUnitTestSuite, Framewo= rk, > "Test CpuExceptionHandlerLib", "CpuExceptionHandlerLib.Manual", NULL, > NULL); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for > CpuExceptionHandlerLib Test Cases\n")); > + Status =3D EFI_OUT_OF_RESOURCES; > + return Status; > + } > + > + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if exception handler > can be registered/unregistered for no error code exception", > "TestRegisterHandlerForNoErrorCodeException", > TestRegisterHandlerForNoErrorCodeException, NULL, NULL, NULL); > + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if exception handler > can be registered/unregistered for GP and PF", > "TestRegisterHandlerForGPAndPF", TestRegisterHandlerForGPAndPF, NULL, > NULL, NULL); > + > + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if Cpu Context is > consistent before and after exception.", "TestCpuContextConsistency", > TestCpuContextConsistency, NULL, NULL, NULL); > + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if stack overflow is > captured by CpuStackGuard in Bsp and AP", > "TestCpuStackGuardInBspAndAp", TestCpuStackGuardInBspAndAp, NULL, > NULL, NULL); > + > + return EFI_SUCCESS; > +} > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibU > nitTest.inf > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibU > nitTest.inf > new file mode 100644 > index 0000000000..e3dbe7b9ab > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibU > nitTest.inf > @@ -0,0 +1,58 @@ > +## @file > +# Unit tests of the DxeCpuExceptionHandlerLib instance. > +# > +# Copyright (c) 2022, Intel Corporation. All rights reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent > +## > + > +[Defines] > + INF_VERSION =3D 0x00010005 > + BASE_NAME =3D CpuExceptionHandlerDxeTest > + FILE_GUID =3D D76BFD9C-0B6D-46BD-AD66-2BBB6FA7031= A > + MODULE_TYPE =3D DXE_DRIVER > + VERSION_STRING =3D 1.0 > + ENTRY_POINT =3D CpuExceptionHandlerTestEntry > + > +# > +# The following information is for reference only and not required by th= e > build tools. > +# > +# VALID_ARCHITECTURES =3D X64 > +# > +[Sources.X64] > + X64/ArchExceptionHandlerTestAsm.nasm > + X64/ArchExceptionHandlerTest.c > + > +[Sources.common] > + CpuExceptionHandlerTest.h > + CpuExceptionHandlerTestCommon.c > + DxeCpuExceptionHandlerUnitTest.c > + > +[Packages] > + MdePkg/MdePkg.dec > + MdeModulePkg/MdeModulePkg.dec > + UefiCpuPkg/UefiCpuPkg.dec > + > +[LibraryClasses] > + BaseLib > + BaseMemoryLib > + DebugLib > + UnitTestLib > + MemoryAllocationLib > + CpuExceptionHandlerLib > + UefiDriverEntryPoint > + HobLib > + UefiBootServicesTableLib > + CpuPageTableLib > + > +[Guids] > + gEfiHobMemoryAllocStackGuid > + > +[Pcd] > + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES > + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES > + > +[Protocols] > + gEfiMpServiceProtocolGuid > + > +[Depex] > + gEfiMpServiceProtocolGuid > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnitT > est.c > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnit > Test.c > new file mode 100644 > index 0000000000..917fc549bf > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnit > Test.c > @@ -0,0 +1,196 @@ > +/** @file > + Unit tests of the CpuExceptionHandlerLib. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "CpuExceptionHandlerTest.h" > +#include > + > +/** > + Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR > buffer. > + In PEIM, store original PeiServicePointer before new Idt table. > + > + @return Pointer to the allocated IA32_DESCRIPTOR buffer. > +**/ > +VOID * > +InitializeBspIdt ( > + VOID > + ) > +{ > + UINTN *NewIdtTable; > + IA32_DESCRIPTOR *Idtr; > + > + Idtr =3D AllocateZeroPool (sizeof (IA32_DESCRIPTOR)); > + ASSERT (Idtr !=3D NULL); > + NewIdtTable =3D AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * > CPU_INTERRUPT_NUM); > + ASSERT (NewIdtTable !=3D NULL); > + Idtr->Base =3D (UINTN)NewIdtTable; > + Idtr->Limit =3D (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * > CPU_INTERRUPT_NUM - 1); > + > + AsmWriteIdtr (Idtr); > + return Idtr; > +} > + > +/** > + Retrieve the number of logical processor in the platform and the numbe= r > of those logical processors that > + are enabled on this boot. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[out] NumberOfProcessors Pointer to the total number of logical > processors in the system, including > + the BSP and disabled APs. > + @param[out] NumberOfEnabledProcessors Pointer to the number of > processors in the system that are enabled. > + > + @retval EFI_SUCCESS Retrieve the number of logical processor > successfully > + @retval Others Retrieve the number of logical processor > unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestGetNumberOfProcessors ( > + IN MP_SERVICES MpServices, > + OUT UINTN *NumberOfProcessors, > + OUT UINTN *NumberOfEnabledProcessors > + ) > +{ > + return MpServices.Protocol->GetNumberOfProcessors > (MpServices.Protocol, NumberOfProcessors, NumberOfEnabledProcessors); > +} > + > +/** > + Get the handle number for the calling processor. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[out] ProcessorNumber The handle number for the calling > processor. > + > + @retval EFI_SUCCESS Get the handle number for the calling proces= sor > successfully. > + @retval Others Get the handle number for the calling proces= sor > unsuccessfully. > +**/ > +EFI_STATUS > +MpServicesUnitTestWhoAmI ( > + IN MP_SERVICES MpServices, > + OUT UINTN *ProcessorNumber > + ) > +{ > + return MpServices.Protocol->WhoAmI (MpServices.Protocol, > ProcessorNumber); > +} > + > +/** > + Caller gets one enabled AP to execute a caller-provided function. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[in] Procedure Pointer to the function to be run on enabled= APs > of the system. > + @param[in] ProcessorNumber The handle number of the AP. > + @param[in] TimeoutInMicroSeconds Indicates the time limit in > microseconds for APs to return from Procedure, > + for blocking mode only. Zero means i= nfinity. > + @param[in] ProcedureArgument The parameter passed into Procedure > for all APs. > + > + > + @retval EFI_SUCCESS Caller gets one enabled AP to execute a call= er- > provided function successfully > + @retval Others Caller gets one enabled AP to execute a call= er- > provided function unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestStartupThisAP ( > + IN MP_SERVICES MpServices, > + IN EFI_AP_PROCEDURE Procedure, > + IN UINTN ProcessorNumber, > + IN UINTN TimeoutInMicroSeconds, > + IN VOID *ProcedureArgument > + ) > +{ > + return MpServices.Protocol->StartupThisAP (MpServices.Protocol, > Procedure, ProcessorNumber, NULL, TimeoutInMicroSeconds, > ProcedureArgument, NULL); > +} > + > +/** > + Execute a caller provided function on all enabled APs. > + > + @param[in] MpServices MP_SERVICES structure. > + @param[in] Procedure Pointer to the function to be run on enabled= APs > of the system. > + @param[in] SingleThread If TRUE, then all the enabled APs execute th= e > function specified by Procedure > + one by one, in ascending order of processor = handle number. > + If FALSE, then all the enabled APs execute t= he function > specified by Procedure > + simultaneously. > + @param[in] TimeoutInMicroSeconds Indicates the time limit in > microseconds for APs to return from Procedure, > + for blocking mode only. Zero means i= nfinity. > + @param[in] ProcedureArgument The parameter passed into Procedure > for all APs. > + > + @retval EFI_SUCCESS Execute a caller provided function on all en= abled > APs successfully > + @retval Others Execute a caller provided function on all en= abled APs > unsuccessfully > +**/ > +EFI_STATUS > +MpServicesUnitTestStartupAllAPs ( > + IN MP_SERVICES MpServices, > + IN EFI_AP_PROCEDURE Procedure, > + IN BOOLEAN SingleThread, > + IN UINTN TimeoutInMicroSeconds, > + IN VOID *ProcedureArgument > + ) > +{ > + return MpServices.Protocol->StartupAllAPs (MpServices.Protocol, > Procedure, SingleThread, NULL, TimeoutInMicroSeconds, > ProcedureArgument, NULL); > +} > + > +/** > + Get EFI_MP_SERVICES_PROTOCOL pointer. > + > + @param[out] MpServices Pointer to the buffer where > EFI_MP_SERVICES_PROTOCOL is stored > + > + @retval EFI_SUCCESS EFI_MP_SERVICES_PROTOCOL interface is > returned > + @retval EFI_NOT_FOUND EFI_MP_SERVICES_PROTOCOL interface is not > found > +**/ > +EFI_STATUS > +GetMpServices ( > + OUT MP_SERVICES *MpServices > + ) > +{ > + return gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID > **)&MpServices->Protocol); > +} > + > +/** > + Entry for CpuExceptionHandlerDxeTest driver. > + > + @param ImageHandle Image handle this driver. > + @param SystemTable Pointer to the System Table. > + > + @retval EFI_SUCCESS The driver executed normally. > + > +**/ > +EFI_STATUS > +EFIAPI > +CpuExceptionHandlerTestEntry ( > + IN EFI_HANDLE ImageHandle, > + IN EFI_SYSTEM_TABLE *SystemTable > + ) > +{ > + EFI_STATUS Status; > + UNIT_TEST_FRAMEWORK_HANDLE Framework; > + > + Framework =3D NULL; > + > + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, > UNIT_TEST_APP_VERSION)); > + > + // > + // Start setting up the test framework for running the tests. > + // > + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, > gEfiCallerBaseName, UNIT_TEST_APP_VERSION); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status > =3D %r\n", Status)); > + goto EXIT; > + } > + > + Status =3D AddCommonTestCase (Framework); > + if (EFI_ERROR (Status)) { > + DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status =3D %r\n", > Status)); > + goto EXIT; > + } > + > + // > + // Execute the tests. > + // > + Status =3D RunAllTestSuites (Framework); > + > +EXIT: > + if (Framework) { > + FreeUnitTestFramework (Framework); > + } > + > + return Status; > +} > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > t.c > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > t.c > new file mode 100644 > index 0000000000..9b086622f2 > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > t.c > @@ -0,0 +1,167 @@ > +/** @file > + Unit tests of the CpuExceptionHandlerLib. > + > + Copyright (c) 2022, Intel Corporation. All rights reserved.
> + SPDX-License-Identifier: BSD-2-Clause-Patent > + > +**/ > + > +#include "CpuExceptionHandlerTest.h" > + > +GENERAL_REGISTER mRegisterForCheck[2]; > + > +// > +// In TestCpuContextConsistency, Cpu registers will be set to > mAdjustRegisterBeforeException. > +// Rcx in mAdjustRegisterInsideException is set runtime since Rcx is nee= ded > in assembly code. > +// For GP and PF, Rcx is set to FaultParameter. For other exception > triggered by INTn, Rcx is set to ExceptionType. > +// > +GENERAL_REGISTER mAdjustRegisterBeforeException =3D { 1, 2, 3, 4, 5, 0,= 7, 8, > 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf }; > +GENERAL_REGISTER mAdjustRegisterInsideException =3D { 0x11, 0x12, 0x13, > 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; > + > +/** > + Special handler for fault exception. > + Rip/Eip in SystemContext will be modified to the instruction after the > exception instruction. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +AdjustRipForFaultHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + mExceptionType =3D ExceptionType; > + SystemContext.SystemContextX64->Rip +=3D mFaultInstructionLength; > +} > + > +/** > + Special handler for ConsistencyOfCpuContext test case. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > +**/ > +VOID > +EFIAPI > +AdjustCpuContextHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + // > + // Do not handle Esp and ebp. They will not be restored. > + // Store SystemContext in mRegisterForCheck[0] modified before > exception. > + // > + mRegisterForCheck[0].Rdi =3D SystemContext.SystemContextX64->R= di; > + mRegisterForCheck[0].Rsi =3D SystemContext.SystemContextX64->R= si; > + mRegisterForCheck[0].Rbx =3D SystemContext.SystemContextX64->R= bx; > + mRegisterForCheck[0].Rdx =3D SystemContext.SystemContextX64->R= dx; > + mRegisterForCheck[0].Rcx =3D SystemContext.SystemContextX64->R= cx; > + mRegisterForCheck[0].Rax =3D SystemContext.SystemContextX64->R= ax; > + mRegisterForCheck[0].R8Register =3D SystemContext.SystemContextX64- > >R8; > + mRegisterForCheck[0].R9Register =3D SystemContext.SystemContextX64- > >R9; > + mRegisterForCheck[0].R10Register =3D SystemContext.SystemContextX64- > >R10; > + mRegisterForCheck[0].R11Register =3D SystemContext.SystemContextX64- > >R11; > + mRegisterForCheck[0].R12Register =3D SystemContext.SystemContextX64- > >R12; > + mRegisterForCheck[0].R13Register =3D SystemContext.SystemContextX64- > >R13; > + mRegisterForCheck[0].R14Register =3D SystemContext.SystemContextX64- > >R14; > + mRegisterForCheck[0].R15Register =3D SystemContext.SystemContextX64- > >R15; > + > + // > + // Modify cpu context which will be stored in mRegisterForCheck[1]. > + // > + SystemContext.SystemContextX64->Rdi =3D > mAdjustRegisterInsideException.Rdi; > + SystemContext.SystemContextX64->Rsi =3D > mAdjustRegisterInsideException.Rsi; > + SystemContext.SystemContextX64->Rbx =3D > mAdjustRegisterInsideException.Rbx; > + SystemContext.SystemContextX64->Rdx =3D > mAdjustRegisterInsideException.Rdx; > + SystemContext.SystemContextX64->Rcx =3D > mAdjustRegisterInsideException.Rcx; > + SystemContext.SystemContextX64->Rax =3D > mAdjustRegisterInsideException.Rax; > + SystemContext.SystemContextX64->R8 =3D > mAdjustRegisterInsideException.R8Register; > + SystemContext.SystemContextX64->R9 =3D > mAdjustRegisterInsideException.R9Register; > + SystemContext.SystemContextX64->R10 =3D > mAdjustRegisterInsideException.R10Register; > + SystemContext.SystemContextX64->R11 =3D > mAdjustRegisterInsideException.R11Register; > + SystemContext.SystemContextX64->R12 =3D > mAdjustRegisterInsideException.R12Register; > + SystemContext.SystemContextX64->R13 =3D > mAdjustRegisterInsideException.R13Register; > + SystemContext.SystemContextX64->R14 =3D > mAdjustRegisterInsideException.R14Register; > + SystemContext.SystemContextX64->R15 =3D > mAdjustRegisterInsideException.R15Register; > + > + // > + // When fault exception happens, eip/rip points to the faulting instru= ction. > + // For now, olny GP and PF are tested in fault exception. > + // > + if ((ExceptionType =3D=3D EXCEPT_IA32_PAGE_FAULT) || (ExceptionType = =3D=3D > EXCEPT_IA32_GP_FAULT)) { > + AdjustRipForFaultHandler (ExceptionType, SystemContext); > + } > +} > + > +/** > + Compare cpu context in ConsistencyOfCpuContext test case. > + 1.Compare mRegisterForCheck[0] with mAdjustRegisterBeforeException. > + 2.Compare mRegisterForCheck[1] with mAdjustRegisterAfterException. > + > + @retval UNIT_TEST_PASSED The Unit test has completed and = it was > successful. > + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed= . > +**/ > +UNIT_TEST_STATUS > +CompareCpuContext ( > + VOID > + ) > +{ > + // > + // Do not handle Esp and ebp. They will not be restored. > + // > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rdi, > mAdjustRegisterBeforeException.Rdi); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rsi, > mAdjustRegisterBeforeException.Rsi); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rbx, > mAdjustRegisterBeforeException.Rbx); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rdx, > mAdjustRegisterBeforeException.Rdx); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rcx, > mAdjustRegisterBeforeException.Rcx); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rax, > mAdjustRegisterBeforeException.Rax); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R8Register, > mAdjustRegisterBeforeException.R8Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R9Register, > mAdjustRegisterBeforeException.R9Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R10Register, > mAdjustRegisterBeforeException.R10Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R11Register, > mAdjustRegisterBeforeException.R11Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R12Register, > mAdjustRegisterBeforeException.R12Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R13Register, > mAdjustRegisterBeforeException.R13Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R14Register, > mAdjustRegisterBeforeException.R14Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[0].R15Register, > mAdjustRegisterBeforeException.R15Register); > + > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rdi, > mAdjustRegisterInsideException.Rdi); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rsi, > mAdjustRegisterInsideException.Rsi); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rbx, > mAdjustRegisterInsideException.Rbx); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rdx, > mAdjustRegisterInsideException.Rdx); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rcx, > mAdjustRegisterInsideException.Rcx); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rax, > mAdjustRegisterInsideException.Rax); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R8Register, > mAdjustRegisterInsideException.R8Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R9Register, > mAdjustRegisterInsideException.R9Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R10Register, > mAdjustRegisterInsideException.R10Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R11Register, > mAdjustRegisterInsideException.R11Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R12Register, > mAdjustRegisterInsideException.R12Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R13Register, > mAdjustRegisterInsideException.R13Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R14Register, > mAdjustRegisterInsideException.R14Register); > + UT_ASSERT_EQUAL (mRegisterForCheck[1].R15Register, > mAdjustRegisterInsideException.R15Register); > + return UNIT_TEST_PASSED; > +} > + > +/** > + Special handler for CpuStackGuard test case. > + > + @param ExceptionType Exception type. > + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. > + > +**/ > +VOID > +EFIAPI > +CpuStackGuardExceptionHandler ( > + IN EFI_EXCEPTION_TYPE ExceptionType, > + IN EFI_SYSTEM_CONTEXT SystemContext > + ) > +{ > + UINTN LocalVariable; > + > + AdjustRipForFaultHandler (ExceptionType, SystemContext); > + mRspAddress[0] =3D (UINTN)SystemContext.SystemContextX64->Rsp; > + mRspAddress[1] =3D (UINTN)(&LocalVariable); > + > + return; > +} > diff --git > a/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > tAsm.nasm > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > tAsm.nasm > new file mode 100644 > index 0000000000..4838a12a67 > --- /dev/null > +++ > b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTes > tAsm.nasm > @@ -0,0 +1,260 @@ > +;-----------------------------------------------------------------------= ------- > +; > +; Copyright (c) 2022, Intel Corporation. All rights reserved.
> +; SPDX-License-Identifier: BSD-2-Clause-Patent > +; > +; Module Name: > +; > +; ArchExceptionHandlerTestAsm.nasm > +; > +; Abstract: > +; > +; x64 CPU Exception Handler Lib Unit test > +; > +;-----------------------------------------------------------------------= ------- > + > + DEFAULT REL > + SECTION .text > + > +struc GENERAL_REGISTER > + .Rdi: resq 1 > + .Rsi: resq 1 > + .Rbp: resq 1 > + .Rbx: resq 1 > + .Rdx: resq 1 > + .Rcx: resq 1 > + .Rax: resq 1 > + .R8: resq 1 > + .R9: resq 1 > + .R10: resq 1 > + .R11: resq 1 > + .R12: resq 1 > + .R13: resq 1 > + .R14: resq 1 > + .R15: resq 1 > + > +endstruc > + > +extern ASM_PFX(mRegisterForCheck) > +extern ASM_PFX(mAdjustRegisterBeforeException) > +extern ASM_PFX(mFaultInstructionLength) > + > +;-----------------------------------------------------------------------= ------- > +; VOID > +; EFIAPI > +; TriggerGPException ( > +; UINTN Cr4ReservedBit > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(TriggerGPException) > +ASM_PFX(TriggerGPException): > + ; > + ; Set reserved bit 15 of cr4 to 1 > + ; > + push rcx > + lea rcx, [ASM_PFX(mFaultInstructionLength)] > + mov qword[rcx], TriggerGPExceptionAfter - TriggerGPExceptionBefore > + pop rcx > +TriggerGPExceptionBefore: > + mov cr4, rcx > +TriggerGPExceptionAfter: > + ret > + > +;-----------------------------------------------------------------------= ------- > +; VOID > +; EFIAPI > +; TriggerPFException ( > +; UINTN PFAddress > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(TriggerPFException) > +ASM_PFX(TriggerPFException): > + push rcx > + lea rcx, [ASM_PFX(mFaultInstructionLength)] > + mov qword[rcx], TriggerPFExceptionAfter - TriggerPFExceptionBefore > + pop rcx > +TriggerPFExceptionBefore: > + mov qword[rcx], 0x1 > +TriggerPFExceptionAfter: > + ret > + > +global ASM_PFX(ModifyRcxInGlobalBeforeException) > +ASM_PFX(ModifyRcxInGlobalBeforeException): > + push rax > + lea rax, [ASM_PFX(mAdjustRegisterBeforeException)] > + mov [rax + GENERAL_REGISTER.Rcx], rcx > + pop rax > + ret > + > +;-----------------------------------------------------------------------= ------- > +;VOID > +;EFIAPI > +;AsmTestConsistencyOfCpuContext ( > +; IN EFI_EXCEPTION_TYPE ExceptionType > +; IN UINTN FaultParameter OPTIONAL > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(AsmTestConsistencyOfCpuContext) > +ASM_PFX(AsmTestConsistencyOfCpuContext): > + ; > + ; push original register > + ; > + push r15 > + push r14 > + push r13 > + push r12 > + push r11 > + push r10 > + push r9 > + push r8 > + push rax > + push rcx > + push rbx > + push rsi > + push rdi > + push rdx > + > + ; > + ; Modify register to mAdjustRegisterBeforeException > + ; > + lea r15, [ASM_PFX(mAdjustRegisterBeforeException)] > + mov rdi, [r15 + GENERAL_REGISTER.Rdi] > + mov rsi, [r15 + GENERAL_REGISTER.Rsi] > + mov rbx, [r15 + GENERAL_REGISTER.Rbx] > + mov rdx, [r15 + GENERAL_REGISTER.Rdx] > + mov rax, [r15 + GENERAL_REGISTER.Rax] > + mov r8, [r15 + GENERAL_REGISTER.R8] > + mov r9, [r15 + GENERAL_REGISTER.R9] > + mov r10, [r15 + GENERAL_REGISTER.R10] > + mov r11, [r15 + GENERAL_REGISTER.R11] > + mov r12, [r15 + GENERAL_REGISTER.R12] > + mov r13, [r15 + GENERAL_REGISTER.R13] > + mov r14, [r15 + GENERAL_REGISTER.R14] > + mov r15, [r15 + GENERAL_REGISTER.R15] > + > + cmp rcx, 0xd > + jz GPException > + cmp rcx, 0xe > + jz PFException > + jmp INTnException > + > +PFException: > + ; > + ; Pop rdx(Pei StackBase) to rcx and restore stack. > + ; Modify Rcx in mAdjustRegisterBeforeException. > + ; > + pop rcx > + push rcx > + call ASM_PFX(ModifyRcxInGlobalBeforeException) > + call ASM_PFX(TriggerPFException) > + jmp AfterException > + > +GPException: > + ; > + ; Prepare rcx value for GP. > + ; Modify Rcx in mAdjustRegisterBeforeException. > + ; > + pop rcx > + push rcx > + call ASM_PFX(ModifyRcxInGlobalBeforeException) > + call ASM_PFX(TriggerGPException) > + jmp AfterException > + > +INTnException: > + ; > + ; Modify Rcx in mAdjustRegisterBeforeException. > + ; > + call ASM_PFX(ModifyRcxInGlobalBeforeException) > + call ASM_PFX(TriggerINTnException) > + > +AfterException: > + ; > + ; Save register in mRegisterForCheck[1] > + ; > + push rax > + lea rax, [ASM_PFX(mRegisterForCheck)] > + add rax, GENERAL_REGISTER_size > + mov [rax + GENERAL_REGISTER.Rdi], rdi > + mov [rax + GENERAL_REGISTER.Rsi], rsi > + mov [rax + GENERAL_REGISTER.Rbx], rbx > + mov [rax + GENERAL_REGISTER.Rdx], rdx > + mov [rax + GENERAL_REGISTER.Rcx], rcx > + pop rcx > + mov [rax + GENERAL_REGISTER.Rax], rcx > + mov [rax + GENERAL_REGISTER.R8], r8 > + mov [rax + GENERAL_REGISTER.R9], r9 > + mov [rax + GENERAL_REGISTER.R10], r10 > + mov [rax + GENERAL_REGISTER.R11], r11 > + mov [rax + GENERAL_REGISTER.R12], r12 > + mov [rax + GENERAL_REGISTER.R13], r13 > + mov [rax + GENERAL_REGISTER.R14], r14 > + mov [rax + GENERAL_REGISTER.R15], r15 > + > + ; > + ; restore original register > + ; > + pop rdx > + pop rdi > + pop rsi > + pop rbx > + pop rcx > + pop rax > + pop r8 > + pop r9 > + pop r10 > + pop r11 > + pop r12 > + pop r13 > + pop r14 > + pop r15 > + > + ret > + > +;-----------------------------------------------------------------------= ------- > +; VOID > +; EFIAPI > +; TriggerStackOverflowbyCpuStackGuard ( > +; VOID > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(TriggerStackOverflowbyCpuStackGuard) > +ASM_PFX(TriggerStackOverflowbyCpuStackGuard): > + push rcx > + lea rcx, [ASM_PFX(mFaultInstructionLength)] > + mov qword[rcx], TriggerCpuStackGuardAfter - > TriggerCpuStackGuardBefore > + pop rcx > +TriggerCpuStackGuardBefore: > + call TriggerCpuStackGuardBefore > +TriggerCpuStackGuardAfter: > + ret > + > +;-----------------------------------------------------------------------= ------- > +; VOID > +; EFIAPI > +; TriggerINTnException ( > +; IN EFI_EXCEPTION_TYPE ExceptionType > +; ); > +;-----------------------------------------------------------------------= ------- > +global ASM_PFX(TriggerINTnException) > +ASM_PFX(TriggerINTnException): > + push rax > + push rdx > + push rcx > + lea rax, [AsmTriggerException1 - AsmTriggerException0] > + mul rcx > + mov rcx, AsmTriggerException0 > + add rax, rcx > + pop rcx > + pop rdx > + jmp rax > + ; > + ; rax =3D AsmTriggerException0 + (AsmTriggerException1 - > AsmTriggerException0) * rcx > + ; > +%assign Vector 0 > +%rep 22 > +AsmTriggerException %+ Vector: > + pop rax > + INT Vector > + ret > +%assign Vector Vector+1 > +%endrep > -- > 2.31.1.windows.1