From nobody Wed May 8 12:53:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94971+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94971+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665468238; cv=none; d=zohomail.com; s=zohoarc; b=R1tbCOGCFEW9HUikbZ6/pxEbdVSvGqDTccwlwPWb+wRcb6qf8prDfjgSvRLmJPp/cWwHBhAFlHEXJn2Ggdgs5+pwEIqrvbAuHAziwToLVSUurgKezxxq0aCGBSirrww78dJZBDpDxnuLGbSE5hJA2QtQUVcLVse+wtdT4FWHByU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665468238; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=aU8PnzTaEpqwWeffSXBTQ2knlFTr3TGss1IZHob5y4U=; b=LTny4LKTw7fdNRonkoyfv9AOeLMi3UrBgQ2ZtQ+Ox8TVkApi6vAEaSLPUxlnY00pKw8gMGDf6qca0CxDAMpirgkgZkwrRAHUft/m5C4E+5Q66nvHSqa5R221kubOdvCbR+KnDvMnbVcmlSk4fpn02aeTyJfV1PgrQQm4KF5Uayw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94971+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 16654682384281002.4632578049795; Mon, 10 Oct 2022 23:03:58 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id NBjCYY1788612xPHl1Q26a7E; Mon, 10 Oct 2022 23:03:58 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web11.4146.1665468237246285163 for ; Mon, 10 Oct 2022 23:03:57 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="390724512" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="390724512" X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:03:56 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="730846920" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="730846920" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:03:55 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH 1/3] UefiCpuPkg: Add Unit tests for DxeCpuExceptionHandlerLib Date: Tue, 11 Oct 2022 14:03:33 +0800 Message-Id: <20221011060335.575-2-dun.tan@intel.com> In-Reply-To: <20221011060335.575-1-dun.tan@intel.com> References: <20221011060335.575-1-dun.tan@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,dun.tan@intel.com X-Gm-Message-State: CfMrsTxadRZntWld8RtZyMkrx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665468238; bh=LGqAEf399oPMPnxFLKjyO6HNIhEnJU36HQgoJdOVSxQ=; h=Cc:Date:From:Reply-To:Subject:To; b=iEViOGIZhSnCUIeEr7fuZmclwg2dJV5QDyIBpDFBWHzz+qB+9RvzKDTKHyFj1oxMvEq d67jxgdF/3BHnPoOgWuKr0Oo/J28qTnGF9fiRfsRAH4trLPNcBGzPKHJmYH05P/+exJBZ 59u4wXRUtdvhzT8tU2WRX1jYrBi01mph06o= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665468240060100001 Content-Type: text/plain; charset="utf-8" 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. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar --- UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h = | 353 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCommon.c = | 856 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibUnitTest.i= nf | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnitTest.c = | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTest.c = | 167 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTestAsm.nas= m | 260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1890 insertions(+) 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 b= uffer. + 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 e= xception 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 except= ion type runtime since Rcx/Ecx is needed in assembly code. + For GP and PF, Rcx/Ecx is set to FaultParameter. For other exception tri= ggered 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 register = 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 retu= rned + @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 A= Ps of the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute the = function specified by Procedure + one by one, in ascending order of processor ha= ndle number. + If FALSE, then all the enabled APs execute the= function specified by Procedure + simultaneously. + @param[in] TimeoutInMicroseconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + @retval EFI_SUCCESS Execute a caller provided function on all enab= led APs successfully + @retval Others Execute a caller provided function on all enab= led 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 A= Ps of the system. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] TimeoutInMicroseconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller= -provided function successfully + @retval Others Caller gets one enabled AP to execute a caller= -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 processo= r successfully. + @retval Others Get the handle number for the calling processo= r unsuccessfully. +**/ +EFI_STATUS +MpServicesUnitTestWhoAmI ( + IN MP_SERVICES MpServices, + OUT UINTN *ProcessorNumber + ); + +/** + Retrieve the number of logical processor in the platform and the number = 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 p= rocessors in the system, including + the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of processor= s in the system that are enabled. + + @retval EFI_SUCCESS Retrieve the number of logical processor succe= ssfully + @retval Others Retrieve the number of logical processor unsuc= cessfully +**/ +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/CpuExceptionHandlerTest= Common.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCo= mmon.c new file mode 100644 index 0000000000..1c3d011c76 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCommon.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->OriginalGdt= r.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 CpuOriginalRegisterBuff= er. + @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 * si= zeof (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 code= 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 need a + reboot. This parameter is a VOID* and it is the + responsibility of the test author to ensure that = the + contents are well understood by all test cases th= at may + consume it. + + @retval UNIT_TEST_PASSED The Unit test has completed and th= e 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->AllocDescri= ptor.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 (U= INTN)); + 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, CpuStackBase= Buffer[Index])); + } + + return CpuStackBaseBuffer; +} + +/** + Return not present or ReadOnly address in page table. + + @param[out] PFAddress Access to the address which is not permitted will= 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 : Paging4Leve= l; + } + + 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].Linea= rAddress + 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 need a + reboot. This parameter is a VOID* and it is the + responsibility of the test author to ensure that = the + contents are well understood by all test cases th= at may + consume it. + + @retval UNIT_TEST_PASSED The Unit test has completed and th= e 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_F= AULT)); + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_GP_FAULT, AdjustRipF= orFaultHandler); + 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_PA= GE_FAULT)); + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT, Adjust= RipForFaultHandler); + 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 need a + reboot. This parameter is a VOID* and it is the + responsibility of the test author to ensure that = the + contents are well understood by all test cases th= at may + consume it. + + @retval UNIT_TEST_PASSED The Unit test has completed and th= e 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, AdjustCpuContextHandler= ); + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); + + // + // Trigger different type exception and compare different stage cpu co= ntext. + // + 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 require= ment. + + This function is a wrapper of InitializeSeparateExceptionStacks. It's ma= inly + 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 InitializeSeparateExc= eptionStacks + // if this is the first call or the first call failed because of size to= o small. + // + if ((CpuSwitchStackData->Status =3D=3D EFI_NOT_STARTED) || (CpuSwitchSta= ckData->Status =3D=3D EFI_BUFFER_TOO_SMALL)) { + CpuSwitchStackData->Status =3D InitializeSeparateExceptionStacks (CpuS= witchStackData->Buffer, &CpuSwitchStackData->BufferSize); + } +} + +/** + Initializes MP exceptions handlers for the sake of stack switch requirem= ent. + + This function will allocate required resources required to setup stack s= witch + 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 (EXCE= PTION_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_N= OT_STARTED + // to indicate the procedure haven't been run yet. + // + SwitchStackData[Index].Status =3D EFI_NOT_STARTED; + if (Index =3D=3D BspProcessorNum) { + InitializeExceptionStackSwitchHandlersPerAp ((VOID *)CpuSwitchStackD= ata); + 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].BufferSiz= e; + DEBUG (( + DEBUG_INFO, + "Buffer[cpu%lu] for InitializeExceptionStackSwitchHandlersPerAp:= 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 *)CpuSwitchStac= kData); + 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 need a + reboot. This parameter is a VOID* and it is the + responsibility of the test author to ensure that = the + contents are well understood by all test cases th= at may + consume it. + + @retval UNIT_TEST_PASSED The Unit test has completed and th= e 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, &Process= orNumber, &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, BspProce= ssorNum); + + // + // 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 handl= er. + // + SwitchStackData =3D InitializeMpExceptionStackSwitchHandlers (MpServices= , BspProcessorNum); + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_PAGE_FAULT,= CpuStackGuardExceptionHandler); + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); + Status =3D RegisterCpuInterruptHandler (EXCEPT_IA32_DOUBLE_FAULT, Adjust= RipForFaultHandler); + UT_ASSERT_EQUAL (Status, EFI_SUCCESS); + + for (Index =3D 0; Index < mNumberOfProcessors; Index++) { + OriginalStackBase =3D CpuStackBaseBuffer[Index]; + NewStackTop =3D (UINTN)(SwitchStackData[Index].Buffer) + SwitchS= tackData[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) && (mRspAddres= s[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, BspProce= ssorNum); + 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, Framework= , "Test CpuExceptionHandlerLib", "CpuExceptionHandlerLib.Manual", NULL, NUL= L); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for CpuExceptionHa= ndlerLib Test Cases\n")); + Status =3D EFI_OUT_OF_RESOURCES; + return Status; + } + + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if exception handler c= an be registered/unregistered for no error code exception", "TestRegisterHa= ndlerForNoErrorCodeException", TestRegisterHandlerForNoErrorCodeException, = NULL, NULL, NULL); + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if exception handler c= an be registered/unregistered for GP and PF", "TestRegisterHandlerForGPAndP= F", TestRegisterHandlerForGPAndPF, NULL, NULL, NULL); + + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if Cpu Context is cons= istent before and after exception.", "TestCpuContextConsistency", TestCpuCo= ntextConsistency, NULL, NULL, NULL); + AddTestCase (CpuExceptionLibUnitTestSuite, "Check if stack overflow is c= aptured by CpuStackGuard in Bsp and AP", "TestCpuStackGuardInBspAndAp", Tes= tCpuStackGuardInBspAndAp, NULL, NULL, NULL); + + return EFI_SUCCESS; +} diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerL= ibUnitTest.inf b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHand= lerLibUnitTest.inf new file mode 100644 index 0000000000..e3dbe7b9ab --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibUnitT= est.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-2BBB6FA7031A + 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 the = 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/DxeCpuExceptionHandlerU= nitTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUn= itTest.c new file mode 100644 index 0000000000..917fc549bf --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnitTest= .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 b= uffer. + 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) * CP= U_INTERRUPT_NUM); + ASSERT (NewIdtTable !=3D NULL); + Idtr->Base =3D (UINTN)NewIdtTable; + Idtr->Limit =3D (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRU= PT_NUM - 1); + + AsmWriteIdtr (Idtr); + return Idtr; +} + +/** + Retrieve the number of logical processor in the platform and the number = 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 p= rocessors in the system, including + the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of processor= s in the system that are enabled. + + @retval EFI_SUCCESS Retrieve the number of logical processor succe= ssfully + @retval Others Retrieve the number of logical processor unsuc= cessfully +**/ +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 processo= r successfully. + @retval Others Get the handle number for the calling processo= r 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 A= Ps of the system. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller= -provided function successfully + @retval Others Caller gets one enabled AP to execute a caller= -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, Procedur= e, 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 A= Ps of the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute the = function specified by Procedure + one by one, in ascending order of processor ha= ndle number. + If FALSE, then all the enabled APs execute the= function specified by Procedure + simultaneously. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + @retval EFI_SUCCESS Execute a caller provided function on all enab= led APs successfully + @retval Others Execute a caller provided function on all enab= led 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, Procedur= e, SingleThread, NULL, TimeoutInMicroSeconds, ProcedureArgument, NULL); +} + +/** + Get EFI_MP_SERVICES_PROTOCOL pointer. + + @param[out] MpServices Pointer to the buffer where EFI_MP_SERVICES_PR= OTOCOL 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_VERSIO= N)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCa= llerBaseName, 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", S= tatus)); + goto EXIT; + } + + // + // Execute the tests. + // + Status =3D RunAllTestSuites (Framework); + +EXIT: + if (Framework) { + FreeUnitTestFramework (Framework); + } + + return Status; +} diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandle= rTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTe= st.c new file mode 100644 index 0000000000..9b086622f2 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTest.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 mAdjustRegis= terBeforeException. +// Rcx in mAdjustRegisterInsideException is set runtime since Rcx is neede= d in assembly code. +// For GP and PF, Rcx is set to FaultParameter. For other exception trigge= red 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, 0= x14, 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 e= xception 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->Rdi; + mRegisterForCheck[0].Rsi =3D SystemContext.SystemContextX64->Rsi; + mRegisterForCheck[0].Rbx =3D SystemContext.SystemContextX64->Rbx; + mRegisterForCheck[0].Rdx =3D SystemContext.SystemContextX64->Rdx; + mRegisterForCheck[0].Rcx =3D SystemContext.SystemContextX64->Rcx; + mRegisterForCheck[0].Rax =3D SystemContext.SystemContextX64->Rax; + 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.R= di; + SystemContext.SystemContextX64->Rsi =3D mAdjustRegisterInsideException.R= si; + SystemContext.SystemContextX64->Rbx =3D mAdjustRegisterInsideException.R= bx; + SystemContext.SystemContextX64->Rdx =3D mAdjustRegisterInsideException.R= dx; + SystemContext.SystemContextX64->Rcx =3D mAdjustRegisterInsideException.R= cx; + SystemContext.SystemContextX64->Rax =3D mAdjustRegisterInsideException.R= ax; + SystemContext.SystemContextX64->R8 =3D mAdjustRegisterInsideException.R= 8Register; + SystemContext.SystemContextX64->R9 =3D mAdjustRegisterInsideException.R= 9Register; + SystemContext.SystemContextX64->R10 =3D mAdjustRegisterInsideException.R= 10Register; + SystemContext.SystemContextX64->R11 =3D mAdjustRegisterInsideException.R= 11Register; + SystemContext.SystemContextX64->R12 =3D mAdjustRegisterInsideException.R= 12Register; + SystemContext.SystemContextX64->R13 =3D mAdjustRegisterInsideException.R= 13Register; + SystemContext.SystemContextX64->R14 =3D mAdjustRegisterInsideException.R= 14Register; + SystemContext.SystemContextX64->R15 =3D mAdjustRegisterInsideException.R= 15Register; + + // + // When fault exception happens, eip/rip points to the faulting instruct= ion. + // 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, mAdjustRegisterBeforeExceptio= n.Rdi); + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rsi, mAdjustRegisterBeforeExceptio= n.Rsi); + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rbx, mAdjustRegisterBeforeExceptio= n.Rbx); + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rdx, mAdjustRegisterBeforeExceptio= n.Rdx); + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rcx, mAdjustRegisterBeforeExceptio= n.Rcx); + UT_ASSERT_EQUAL (mRegisterForCheck[0].Rax, mAdjustRegisterBeforeExceptio= n.Rax); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R8Register, mAdjustRegisterBeforeE= xception.R8Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R9Register, mAdjustRegisterBeforeE= xception.R9Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R10Register, mAdjustRegisterBefore= Exception.R10Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R11Register, mAdjustRegisterBefore= Exception.R11Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R12Register, mAdjustRegisterBefore= Exception.R12Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R13Register, mAdjustRegisterBefore= Exception.R13Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R14Register, mAdjustRegisterBefore= Exception.R14Register); + UT_ASSERT_EQUAL (mRegisterForCheck[0].R15Register, mAdjustRegisterBefore= Exception.R15Register); + + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rdi, mAdjustRegisterInsideExceptio= n.Rdi); + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rsi, mAdjustRegisterInsideExceptio= n.Rsi); + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rbx, mAdjustRegisterInsideExceptio= n.Rbx); + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rdx, mAdjustRegisterInsideExceptio= n.Rdx); + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rcx, mAdjustRegisterInsideExceptio= n.Rcx); + UT_ASSERT_EQUAL (mRegisterForCheck[1].Rax, mAdjustRegisterInsideExceptio= n.Rax); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R8Register, mAdjustRegisterInsideE= xception.R8Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R9Register, mAdjustRegisterInsideE= xception.R9Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R10Register, mAdjustRegisterInside= Exception.R10Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R11Register, mAdjustRegisterInside= Exception.R11Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R12Register, mAdjustRegisterInside= Exception.R12Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R13Register, mAdjustRegisterInside= Exception.R13Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R14Register, mAdjustRegisterInside= Exception.R14Register); + UT_ASSERT_EQUAL (mRegisterForCheck[1].R15Register, mAdjustRegisterInside= Exception.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/ArchExceptionHandle= rTestAsm.nasm b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHan= dlerTestAsm.nasm new file mode 100644 index 0000000000..4838a12a67 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTestAs= m.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 - AsmTriggerExc= eption0) * rcx + ; +%assign Vector 0 +%rep 22 +AsmTriggerException %+ Vector: + pop rax + INT Vector + ret +%assign Vector Vector+1 +%endrep --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94971): https://edk2.groups.io/g/devel/message/94971 Mute This Topic: https://groups.io/mt/94253439/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 12:53:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94972+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94972+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665468242; cv=none; d=zohomail.com; s=zohoarc; b=GGrCjd/v7tUH1fs8xxhKJR0KAYOSFkuKX+uYFT546XF91N2HzyhW9fA7f3qtxtsiu7h5f1vpvIWP3cq2v1tlbU2zu1Nl+bXx8Ld9ThDoFGWB2tAevJG7EvyC4uF9r6mcTUVcjJJKi2/KuELb+i/5Mwxd0YBRLbNCFHWTv85rNg8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665468242; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=UqzrFV1mqFP9P+ZwEUxVU9ceTxOi637QT6SkQLhQiV8=; b=kAJ1Cud9KrDmVUyb5cbIS4zJyh95KA1oEtHPGDNGi/yeT+pFgZb7qjQeN3sf5rhYYtzGzwK1lnUuBlB5O4py2weD1/B1q1rWWIDmRHqsYsFp2BF42ZREx41Me3o0MrlrB2sUJ4fn6vEzMem0vt6EV2ovpm66SWJPLjuuceqmUAQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94972+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 166546824216123.34460548663378; Mon, 10 Oct 2022 23:04:02 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id a9R4YY1788612xjKlWpBf7Mc; Mon, 10 Oct 2022 23:04:01 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web11.4146.1665468237246285163 for ; Mon, 10 Oct 2022 23:04:01 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="390724537" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="390724537" X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:04:00 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="730846938" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="730846938" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:03:59 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH 2/3] UefiCpuPkg: Add Unit tests for PeiCpuExceptionHandlerLib Date: Tue, 11 Oct 2022 14:03:34 +0800 Message-Id: <20221011060335.575-3-dun.tan@intel.com> In-Reply-To: <20221011060335.575-1-dun.tan@intel.com> References: <20221011060335.575-1-dun.tan@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,dun.tan@intel.com X-Gm-Message-State: ZLK8aGwEnZn5CdK7JvNYk2BBx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665468241; bh=LJma1j+FO2QOhpdhIXZYB0V2y9BfL+NnB3oCqKh6eYk=; h=Cc:Date:From:Reply-To:Subject:To; b=A6GJdKKZnGFpt0ConAXGYg5vCD8LQrep0xIp1K06mK2TNoPm5nJiRgxKMzxELvGhLvD QKgnN2y/u2Ko3Lm+CdtstZaLHmrrvaDy1giDWRApHSdkLbpV5KMImUTI8GV+udTT+Oc/X 3T1pLRwuHB1M57B/xvbLTzoSTaPNAGH6dNc= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665468244078100002 Content-Type: text/plain; charset="utf-8" Add target based unit tests for the PeiCpuExceptionHandlerLib. A PEIM is created to test PeiCpuExceptionHandlerLib. 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. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar --- UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c = | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestAsm.na= sm | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitTest.i= nf | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUnitTest.c = | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 615 insertions(+) diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandl= erTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandler= Test.c new file mode 100644 index 0000000000..32188b9a81 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c @@ -0,0 +1,133 @@ +/** @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_IA32 mIa32RegisterForCheck[2]; + +// +// In TestCpuContextConsistency, Cpu registers will be set to mAdjustRegis= terBeforeException/mAdjustRegisterInsideException. +// Ecx in mAdjustRegisterInsideException is set runtime since Ecx is neede= d in assembly code. +// For GP and PF, Ecx is set to FaultParameter. For other exception trigge= red by INTn, Ecx is set to ExceptionType. +// +GENERAL_REGISTER_IA32 mAdjustIa32RegisterBeforeException =3D { 1, 2, 3, 4= , 5, 0, 7 }; +GENERAL_REGISTER_IA32 mAdjustIa32RegisterInsideException =3D { 11, 12, 13= , 14, 15, 16, 17 }; + +/** + Special handler for fault exception. + Rip/Eip in SystemContext will be modified to the instruction after the e= xception 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.SystemContextIa32->Eip +=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 modified before exception. + // + mIa32RegisterForCheck[0].Edi =3D SystemContext.SystemContextIa32->Edi; + mIa32RegisterForCheck[0].Esi =3D SystemContext.SystemContextIa32->Esi; + mIa32RegisterForCheck[0].Ebx =3D SystemContext.SystemContextIa32->Ebx; + mIa32RegisterForCheck[0].Edx =3D SystemContext.SystemContextIa32->Edx; + mIa32RegisterForCheck[0].Ecx =3D SystemContext.SystemContextIa32->Ecx; + mIa32RegisterForCheck[0].Eax =3D SystemContext.SystemContextIa32->Eax; + + // + // Modify cpu context which will be stored in mIa32RegisterForCheck[1]. + // + SystemContext.SystemContextIa32->Edi =3D mAdjustIa32RegisterInsideExcept= ion.Edi; + SystemContext.SystemContextIa32->Esi =3D mAdjustIa32RegisterInsideExcept= ion.Esi; + SystemContext.SystemContextIa32->Ebx =3D mAdjustIa32RegisterInsideExcept= ion.Ebx; + SystemContext.SystemContextIa32->Edx =3D mAdjustIa32RegisterInsideExcept= ion.Edx; + SystemContext.SystemContextIa32->Ecx =3D mAdjustIa32RegisterInsideExcept= ion.Ecx; + SystemContext.SystemContextIa32->Eax =3D mAdjustIa32RegisterInsideExcept= ion.Eax; + + // + // When fault exception happens, eip/rip points to the faulting instruct= ion. + // 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 + ) +{ + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Edi, mAdjustIa32RegisterBefore= Exception.Edi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Esi, mAdjustIa32RegisterBefore= Exception.Esi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Ebx, mAdjustIa32RegisterBefore= Exception.Ebx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Edx, mAdjustIa32RegisterBefore= Exception.Edx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Ecx, mAdjustIa32RegisterBefore= Exception.Ecx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Eax, mAdjustIa32RegisterBefore= Exception.Eax); + + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Edi, mAdjustIa32RegisterInside= Exception.Edi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Esi, mAdjustIa32RegisterInside= Exception.Esi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Ebx, mAdjustIa32RegisterInside= Exception.Ebx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Edx, mAdjustIa32RegisterInside= Exception.Edx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Ecx, mAdjustIa32RegisterInside= Exception.Ecx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Eax, mAdjustIa32RegisterInside= Exception.Eax); + 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.SystemContextIa32->Esp; + mRspAddress[1] =3D (UINTN)(&LocalVariable); + + return; +} diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandl= erTestAsm.nasm b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionH= andlerTestAsm.nasm new file mode 100644 index 0000000000..ccadd8765f --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestA= sm.nasm @@ -0,0 +1,217 @@ +;-------------------------------------------------------------------------= ----- +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ArchExceptionHandlerTestAsm.nasm +; +; Abstract: +; +; ia32 CPU Exception Handler Lib Unit test +; +;-------------------------------------------------------------------------= ----- + + SECTION .text + +struc GENERAL_REGISTER_IA32 + .Edi: resd 1 + .Esi: resd 1 + .Ebp: resd 1 + .Ebx: resd 1 + .Edx: resd 1 + .Ecx: resd 1 + .Eax: resd 1 + +endstruc + +extern ASM_PFX(mIa32RegisterForCheck) +extern ASM_PFX(mAdjustIa32RegisterBeforeException) +extern ASM_PFX(mFaultInstructionLength) + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerGPException ( +; UINTN Cr4ReservedBit +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerGPException) +ASM_PFX(TriggerGPException): + ; + ; Set reserved bit 15 of cr4 to 1 + ; + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerGPExceptionAfter - TriggerGPExceptionBefore + mov ecx, dword [esp + 0x4] +TriggerGPExceptionBefore: + mov cr4, ecx +TriggerGPExceptionAfter: + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerPFException ( +; UINTN PfAddress +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerPFException) +ASM_PFX(TriggerPFException): + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerPFExceptionAfter - TriggerPFExceptionBefore + mov ecx, dword [esp + 0x4] +TriggerPFExceptionBefore: + mov dword[ecx], 0x1 +TriggerPFExceptionAfter: + ret + +global ASM_PFX(ModifyEcxInGlobalBeforeException) +ASM_PFX(ModifyEcxInGlobalBeforeException): + push eax + lea eax, [ASM_PFX(mAdjustIa32RegisterBeforeException)] + mov [eax + GENERAL_REGISTER_IA32.Ecx], ecx + pop eax + ret + +;-------------------------------------------------------------------------= ----- +;VOID +;EFIAPI +;AsmTestConsistencyOfCpuContext ( +; IN EFI_EXCEPTION_TYPE ExceptionType +; IN UINTN FaultParameter OPTIONAL +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(AsmTestConsistencyOfCpuContext) +ASM_PFX(AsmTestConsistencyOfCpuContext): + ; + ; push 7 general register plus 4 bytes + ; + pushad + + ; + ; modify Modify register to mAdjustRegisterBeforeException + ; + lea eax, [ASM_PFX(mAdjustIa32RegisterBeforeException)] + mov edi, [eax + GENERAL_REGISTER_IA32.Edi] + mov esi, [eax + GENERAL_REGISTER_IA32.Esi] + mov ebx, [eax + GENERAL_REGISTER_IA32.Ebx] + mov edx, [eax + GENERAL_REGISTER_IA32.Edx] + ; + ; Set ecx to ExceptionType + ; + mov ecx, dword [esp + 0x24] + mov eax, [eax + GENERAL_REGISTER_IA32.Eax] + + cmp ecx, 0xd + jz GPException + cmp ecx, 0xe + jz PFException + jmp INTnException + +PFException: + ; + ; Set ecx to PFAddress and Modify Ecx in mAdjustRegisterBeforeExceptio= n. + ; Push PfAddress into stack. + ; + mov ecx, dword [esp + 0x28] + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerPFException) + jmp AfterException + +GPException: + ; + ; Set ecx to CR4_RESERVED_BIT and Modify Ecx in mAdjustRegisterBeforeE= xception. + ; Push CR4_RESERVED_BIT into stack + ; + mov ecx, dword [esp + 0x28] + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerGPException) + jmp AfterException + +INTnException: + ; + ; Modify Ecx in mAdjustRegisterBeforeException. + ; Push exception index into stack + ; + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerINTnException) + +AfterException: + ; + ; Save register in mRegisterForCheck[1]. + ; Esp and ebp will not be synced to the value in SystemContext. Do not= test esp and ebp. + ; + push eax + lea eax, [ASM_PFX(mIa32RegisterForCheck)] + add eax, GENERAL_REGISTER_IA32_size + mov [eax + GENERAL_REGISTER_IA32.Edi], edi + mov [eax + GENERAL_REGISTER_IA32.Esi], esi + mov [eax + GENERAL_REGISTER_IA32.Ebx], ebx + mov [eax + GENERAL_REGISTER_IA32.Edx], edx + mov [eax + GENERAL_REGISTER_IA32.Ecx], ecx + pop ecx + mov [eax + GENERAL_REGISTER_IA32.Eax], ecx + add esp, 4 + + ; + ; restore original register + ; + popad + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerStackOverflowbyCpuStackGuard ( +; VOID +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerStackOverflowbyCpuStackGuard) +ASM_PFX(TriggerStackOverflowbyCpuStackGuard): + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerCpuStackGuardAfter - TriggerCpuStackGuardBefore +TriggerCpuStackGuardBefore: + ; + ; Clear CR0.TS since it is set after return from a nested DF + ; + call TriggerCpuStackGuardBefore + clts +TriggerCpuStackGuardAfter: + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerINTnException ( +; IN EFI_EXCEPTION_TYPE ExceptionType +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerINTnException) +ASM_PFX(TriggerINTnException): + push eax + push edx + lea eax, [AsmTriggerException1 - AsmTriggerException0] + mov ecx, dword [esp + 0xc] + push ecx + mul ecx + mov ecx, AsmTriggerException0 + add eax, ecx + pop ecx + pop edx + jmp eax + ; + ; eax =3D AsmTriggerException0 + (AsmTriggerException1 - AsmTriggerExc= eption0) * ecx + ; +%assign Vector 0 +%rep 22 +AsmTriggerException %+ Vector: + pop eax + INT Vector + ret +%assign Vector Vector+1 +%endrep diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerL= ibUnitTest.inf b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHand= lerLibUnitTest.inf new file mode 100644 index 0000000000..25f8f8dbe0 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitT= est.inf @@ -0,0 +1,61 @@ +## @file +# Unit tests of the PeiCpuExceptionHandlerLib instance. +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x00010006 + BASE_NAME =3D CpuExceptionHandlerPeiTest + FILE_GUID =3D 39A96CF7-F369-4357-9234-4B52F98A007F + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PeiEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# +[Sources.Ia32] + Ia32/ArchExceptionHandlerTestAsm.nasm + Ia32/ArchExceptionHandlerTest.c + +[Sources.X64] + X64/ArchExceptionHandlerTestAsm.nasm + X64/ArchExceptionHandlerTest.c + +[Sources.common] + CpuExceptionHandlerTest.h + CpuExceptionHandlerTestCommon.c + PeiCpuExceptionHandlerUnitTest.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UnitTestLib + MemoryAllocationLib + CpuExceptionHandlerLib + PeimEntryPoint + HobLib + PeiServicesLib + CpuPageTableLib + PeiServicesTablePointerLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES + +[Ppis] + gEdkiiPeiMpServices2PpiGuid ## CONSUMES + +[Depex] + gEdkiiPeiMpServices2PpiGuid AND + gEfiPeiMemoryDiscoveredPpiGuid diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerU= nitTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUn= itTest.c new file mode 100644 index 0000000000..d9408d2f5e --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUnitTest= .c @@ -0,0 +1,204 @@ +/** @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 +#include +#include + +/** + Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR b= uffer. + 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) * CP= U_INTERRUPT_NUM + sizeof (UINTN)); + ASSERT (NewIdtTable !=3D NULL); + // + // Store original PeiServicePointer before new Idt table + // + *NewIdtTable =3D (UINTN)GetPeiServicesTablePointer (); + NewIdtTable =3D (UINTN *)((UINTN)NewIdtTable + sizeof (UINTN)); + + Idtr->Base =3D (UINTN)NewIdtTable; + Idtr->Limit =3D (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRU= PT_NUM - 1); + + AsmWriteIdtr (Idtr); + return Idtr; +} + +/** + Retrieve the number of logical processor in the platform and the number = 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 p= rocessors in the system, including + the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of processor= s in the system that are enabled. + + @retval EFI_SUCCESS Retrieve the number of logical processor succe= ssfully + @retval Others Retrieve the number of logical processor unsuc= cessfully +**/ +EFI_STATUS +MpServicesUnitTestGetNumberOfProcessors ( + IN MP_SERVICES MpServices, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ) +{ + return MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, NumberOfPr= ocessors, NumberOfEnabledProcessors); +} + +/** + 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 A= Ps of the system. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller= -provided function successfully + @retval Others Caller gets one enabled AP to execute a caller= -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.Ppi->StartupThisAP (MpServices.Ppi, Procedure, Process= orNumber, TimeoutInMicroSeconds, ProcedureArgument); +} + +/** + 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 A= Ps of the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute the = function specified by Procedure + one by one, in ascending order of processor ha= ndle number. + If FALSE, then all the enabled APs execute the= function specified by Procedure + simultaneously. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + @retval EFI_SUCCESS Execute a caller provided function on all enab= led APs successfully + @retval Others Execute a caller provided function on all enab= led 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.Ppi->StartupAllAPs (MpServices.Ppi, Procedure, SingleT= hread, TimeoutInMicroSeconds, ProcedureArgument); +} + +/** + 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 processo= r successfully. + @retval Others Get the handle number for the calling processo= r unsuccessfully. +**/ +EFI_STATUS +MpServicesUnitTestWhoAmI ( + IN MP_SERVICES MpServices, + OUT UINTN *ProcessorNumber + ) +{ + return MpServices.Ppi->WhoAmI (MpServices.Ppi, ProcessorNumber); +} + +/** + Get EDKII_PEI_MP_SERVICES2_PPI pointer. + + @param[out] MpServices Pointer to the buffer where EDKII_PEI_MP_SERVI= CES2_PPI is stored + + @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is return= ed + @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not fo= und +**/ +EFI_STATUS +GetMpServices ( + OUT MP_SERVICES *MpServices + ) +{ + return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOI= D **)&MpServices->Ppi); +} + +/** + Entry point of CpuExceptionHandlerPeiTest PEIM. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEIM executed normally. + +**/ +EFI_STATUS +EFIAPI +PeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + 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_VERSIO= N)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCa= llerBaseName, 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", S= tatus)); + goto EXIT; + } + + // + // Execute the tests. + // + Status =3D RunAllTestSuites (Framework); + +EXIT: + if (Framework) { + FreeUnitTestFramework (Framework); + } + + return Status; +} --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94972): https://edk2.groups.io/g/devel/message/94972 Mute This Topic: https://groups.io/mt/94253442/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Wed May 8 12:53:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+94973+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94973+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665468246; cv=none; d=zohomail.com; s=zohoarc; b=fB7vFdgZZw20KnhPcxqbhZ4IEan4fTw2uuubcyUbDhX2XrspCJAriPUm2T7iYbsCPs5+lrmB23wM6SCkTdY0YHAe0IIuBNVKXwHfGXJn0DGgg+p55LSh0i6L9e4c8dzFglCVuLN8e6Z46nN5xsEN8iFQcs+h805ijQosuLdnYLM= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665468246; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=TLYNiPhhP8aAEZAvC+dRxI7cpfjErkdtOEU7SzwkG7s=; b=JmWs9sI/KZ/dIHGdbJXKxD9wfyFMvrRcE+9yjjM2417Iss+/kn5xwhemtMFTOnF8AeijUBCR7V0hr+J3/nZzl+Z9NBeZ/3wLqVNxWb11jENPKywkIzGwZo3PvxPes6+0yjL01tmpCHifLAcDCB0+GqFAVGFMtZnGsQrrxpyAq0M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94973+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1665468246034113.02562654154167; Mon, 10 Oct 2022 23:04:06 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id AkM5YY1788612xL0V1q8h3Gv; Mon, 10 Oct 2022 23:04:04 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web11.4146.1665468237246285163 for ; Mon, 10 Oct 2022 23:04:04 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="390724561" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="390724561" X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:04:04 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="730846965" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="730846965" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:04:02 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH 3/3] UefiCpuPkg: Add Pei/DxeCpuExceptionHandlerLibUnitTest in dsc Date: Tue, 11 Oct 2022 14:03:35 +0800 Message-Id: <20221011060335.575-4-dun.tan@intel.com> In-Reply-To: <20221011060335.575-1-dun.tan@intel.com> References: <20221011060335.575-1-dun.tan@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,dun.tan@intel.com X-Gm-Message-State: zjfrAYKfJOJ2THtOMXfXN1FQx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665468244; bh=/A9aJmw4R47DyXLsDPgY9VWeTf8/+3hN6W9Y27sVoYY=; h=Cc:Date:From:Reply-To:Subject:To; b=q2o9eFJpk+XkwhPskgAhqli7RtSIdOQumPFab9JuObGhqgadaP/GXZlU32jPMQxAhkr EGYPPQQLcWzwh4/MAkBfQOhXivVpMOOWSiZBj7J4b9DsiJZVemtfdohcbBSN3SnOFE45H HBbSAd2LE20fROclpxyA+ZzQGzna7JKjX0I= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665468247959100002 Content-Type: text/plain; charset="utf-8" Add Pei/DxeCpuExceptionHandlerLibUnitTest module in UefiCpuPkg.dsc Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar --- UefiCpuPkg/UefiCpuPkg.dsc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index f694b3a77c..31145dbe7e 100644 --- a/UefiCpuPkg/UefiCpuPkg.dsc +++ b/UefiCpuPkg/UefiCpuPkg.dsc @@ -63,6 +63,9 @@ MicrocodeLib|UefiCpuPkg/Library/MicrocodeLib/MicrocodeLib.inf SmmCpuRendezvousLib|UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezv= ousLib.inf CpuPageTableLib|UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf + UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf + UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceL= ibNull/UnitTestPersistenceLibNull.inf + UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultRepor= tLib/UnitTestResultReportLibDebugLib.inf =20 [LibraryClasses.common.SEC] PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.= inf @@ -177,6 +180,10 @@ UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf + UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitTest= .inf + +[Components.X64] + UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibUnitTest= .inf =20 [BuildOptions] *_*_*_CC_FLAGS =3D -D DISABLE_NEW_DEPRECATED_INTERFACES --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94973): https://edk2.groups.io/g/devel/message/94973 Mute This Topic: https://groups.io/mt/94253445/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-