From nobody Sat May 18 21:45:20 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+95200+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+95200+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665739245; cv=none; d=zohomail.com; s=zohoarc; b=AkbY9gRPZO//g/aoa5s/kNSeDuMVLyj3Og4dImWo+WwhShecnmrZOocYdGrrlI2ch+KRmuNyHZ1X+J9KIw4n3gu468tjho53ayJf3gjCWTxTWV2Z7HDERF7BbrlYed08/zUcdWWVxh1r/Y2MZKo3QFSqDx8sHlEvsZEgq/aXR3k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665739245; 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=cgHuQB70Cbdd73zsthnwIeMeHBiJXmfXj09ca3dX4lg=; b=IpVKBKp+SbD7qh3Hje13Tu3GPwtLAXlUPgaltRM+JgOCSlrkV6CkmWR51Ix8fkaItswr/IYb8H385/iZpuI97UcZ7OZkDMpLZE7VALmm2XVupCN5LcDYheNiO2D9NWgEZ3XNh3nDg+DEcS39b8xAf42Bs32ywUX2SZU3THtNQVU= 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+95200+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 1665739245413482.1561481908112; Fri, 14 Oct 2022 02:20:45 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id DzzuYY1788612xqNbPuDgzhH; Fri, 14 Oct 2022 02:20:44 -0700 X-Received: from mga02.intel.com (mga02.intel.com [134.134.136.20]) by mx.groups.io with SMTP id smtpd.web11.5248.1665739243225774493 for ; Fri, 14 Oct 2022 02:20:43 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="292683786" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="292683786" X-Received: from orsmga002.jf.intel.com ([10.7.209.21]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:42 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="627510815" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="627510815" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:39 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [Patch V3 1/4] UefiCpuPkg: Add Unit tests for DxeCpuExceptionHandlerLib Date: Fri, 14 Oct 2022 17:19:28 +0800 Message-Id: <20221014091931.847-2-dun.tan@intel.com> In-Reply-To: <20221014091931.847-1-dun.tan@intel.com> References: <20221014091931.847-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: V2X7QIocHtu36IVuRsJ5UpJlx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665739244; bh=SI5uCM+TfstzbB5jzelrKNzERi2X0bMddJLXK3cWGDM=; h=Cc:Date:From:Reply-To:Subject:To; b=tRKJiFgH+27re4PJ7C12rmjfQTg9337cJosFyjCZyf6OqknxHrnF7T6/cJmVFjLDOZ3 yhCjA1IJM8/UGreYABu4kfWnyp5WzMtV2lqJ85bRt+/1NJVOaZ7xEM8auoJXdMjMJfKb+ GMI6AIFjzsc7V7tx18rAjshlGkNiD8rrgmk= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665739246816100003 Content-Type: text/plain; charset="utf-8" Add target based unit tests for the DxeCpuExceptionHandlerLib. A DXE driver is created to test DxeCpuExceptionHandlerLib. Four test cases are created in this Unit Test module: a.Test if exception handler can be registered/unregistered for no error code exception.In the test case, only no error code exception is triggered and tested by INTn instruction. b.Test if exception handler can be registered/unregistered for GP and PF. In the test case, GP exception is triggered and tested by setting CR4_RESERVED_BIT to 1. PF exception is triggered by writting to not-present or RO address. c.Test if CpuContext is consistent before and after exception. In this test case: 1.Set Cpu register to mExpectedContextInHandler before exception. 2.Trigger exception specified by ExceptionType. 3.Store SystemContext in mActualContextInHandler and set SystemContext to mExpectedContextAfterException in handler. 4.After return from exception, store Cpu registers in mActualContextAfterException. The expectation is: 1.Register values in mActualContextInHandler are the same with register values in mExpectedContextInHandler. 2.Register values in mActualContextAfterException are the same with register values mActualContextAfterException. d.Test if stack overflow can be captured by CpuStackGuard in both Bsp and AP. In this test case, stack overflow is triggered by a funtion which calls itself continuously. This test case triggers stack overflow in both BSP and AP. All AP use same Idt with Bsp. The expectation is: 1. PF exception is triggered (leading to a DF if sepereated stack is not prepared for PF) when Rsp<=3DStackBase+SIZE_4KB since [StackBase, StackBase + SIZE_4KB] is marked as not present in page table when PcdCpuStackGuard is TRUE. 2. Stack for PF/DF exception handler in both Bsp and AP is succussfully switched by InitializeSeparateExceptionStacks. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Reviewed-by: Ray Ni --- UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h = | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCommon.c = | 852 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerLibUnitTest.i= nf | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/DxeCpuExceptionHandlerUnitTest.c = | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTest.c = | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTestAsm.nas= m | 256 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++ 6 files changed, 1864 insertions(+) diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest= .h b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h new file mode 100644 index 0000000000..936098fde8 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h @@ -0,0 +1,336 @@ +/** @file + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + + Four test cases are created in this Unit Test module. + a.Test if exception handler can be registered/unregistered for no error = code exception + In this test case, only no error code exception is triggered and teste= d by INTn instruction. + The special hanlder for these exception will modify a global variable = for check. + + b.Test if exception handler can be registered/unregistered for GP and PF. + In this test case, GP exception is triggered and tested by setting CR4= _RESERVED_BIT to 1. + PF exception is triggered and tested by writting to not-present or RO = addres. + The special hanlder for these exceptions will set a global vartiable f= or check and adjust Rip to return from fault exception. + + c.Test if Cpu Context is consistent before and after exception. + In this test case: + 1. Set Cpu register to mExpectedContextInHandler before exception. + 2. Trigger exception specified by ExceptionType. + 3. Store SystemContext in mActualContextInHandler and set SystemCont= ext to mExpectedContextAfterException in handler. + 4. After return from exception, store Cpu registers in mActualContex= tAfterException. + The expectation is: + 1. Register values in mActualContextInHandler are the same with regi= ster values in mExpectedContextInHandler. + 2. Register values in mActualContextAfterException are the same with= register values mActualContextAfterException. + + d.Test if stack overflow can be captured by CpuStackGuard in both Bsp an= d AP. + In this test case, stack overflow is triggered by a funtion which call= s itself continuously. This test case triggers stack + overflow in both BSP and AP. All AP use same Idt with Bsp. The expecta= tion is: + 1. PF exception is triggered (leading to a DF if sepereated stack is= not prepared for PF) when Rsp <=3D StackBase + SIZE_4KB + since [StackBase, StackBase + SIZE_4KB] is marked as not present = in page table when PcdCpuStackGuard is TRUE. + 2. Stack for PF/DF exception handler in both Bsp and AP is succussfu= lly switched by InitializeSeparateExceptionStacks. + +**/ + +#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 + +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 Rbx; + UINT64 Rdx; + UINT64 Rcx; + UINT64 Rax; + UINT64 R8; + UINT64 R9; + UINT64 R10; + UINT64 R11; + UINT64 R12; + UINT64 R13; + UINT64 R14; + UINT64 R15; +} GENERAL_REGISTER; + +extern UINTN mFaultInstructionLength; +extern EFI_EXCEPTION_TYPE mExceptionType; +extern UINTN mRspAddress[]; + +/** + 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 by setting CR4_RESERVED_BIT to 1. + + @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. + This handler sets Rip/Eip in SystemContext to the instruction address af= ter the exception instruction. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +EFIAPI +AdjustRipForFaultHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ); + +/** + Test consistency of Cpu context. Four steps: + 1. Set Cpu register to mExpectedContextInHandler before exception. + 2. Trigger exception specified by ExceptionType. + 3. Store SystemContext in mActualContextInHandler and set SystemContext = to mExpectedContextAfterException in handler. + 4. After return from exception, store Cpu registers in mActualContextAft= erException. + + Rcx/Ecx in mExpectedContextInHandler is decided by different exception t= ype 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 to mExpectedContextInHandler 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 mActualContextInHandler with mExpectedContextInHandler. + 2.Compare mActualContextAfterException with mActualContextAfterException. + + @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 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 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 calling itself continuously. +**/ +VOID +EFIAPI +TriggerStackOverflow ( + 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..17afb592d3 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTestCommon.c @@ -0,0 +1,852 @@ +/** @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 exception triggered by INTn instruction. + This hanlder only modifies a global variable for check. + + @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 cpu original registers before exit 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 cpu original registers before exit 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 + ) +{ + UINTN Index; + EFI_STATUS Status; + + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { + if (Index =3D=3D BspProcessorNum) { + RestoreRegistersPerCpu ((VOID *)&CpuOriginalRegisterBuffer[Index]); + continue; + } + + ASSERT (MpServices !=3D NULL); + Status =3D MpServicesUnitTestStartupThisAP ( + *MpServices, + (EFI_AP_PROCEDURE)RestoreRegistersPerCpu, + Index, + 0, + (VOID *)&CpuOriginalRegisterBuffer[Index] + ); + ASSERT_EFI_ERROR (Status); + } +} + +/** + Store cpu registers before the test case starts. + + @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 cpu registers before the test case starts. + + @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; + 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) { + if (Index =3D=3D BspProcessorNum) { + SaveRegisterPerCpu ((VOID *)&CpuOriginalRegisterBuffer[Index]); + continue; + } + + ASSERT (MpServices !=3D NULL); + Status =3D MpServicesUnitTestStartupThisAP ( + *MpServices, + (EFI_AP_PROCEDURE)SaveRegisterPerCpu, + Index, + 0, + (VOID *)&CpuOriginalRegisterBuffer[Index] + ); + 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); +} + +/** + Get Ap stack base procedure. + + @param[out] ApStackBase Pointer to Ap stack base. +**/ +VOID +EFIAPI +GetStackBasePerAp ( + OUT VOID *ApStackBase + ) +{ + UINTN ApTopOfStack; + + ApTopOfStack =3D ALIGN_VALUE ((UINTN)&ApTopOfStack, (UINTN)PcdG= et32 (PcdCpuApStackSize)); + *(UINTN *)ApStackBase =3D ApTopOfStack - (UINTN)PcdGet32 (PcdCpuApStackS= ize); +} + +/** + Get all Cpu stack base. + + @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; + EFI_STATUS Status; + UINTN Index; + + CpuStackBaseBuffer =3D AllocateZeroPool (mNumberOfProcessors * sizeof (U= INTN)); + ASSERT (CpuStackBaseBuffer !=3D NULL); + + for (Index =3D 0; Index < mNumberOfProcessors; ++Index) { + if (Index =3D=3D BspProcessorNum) { + GetBspStackBase (&CpuStackBaseBuffer[Index]); + continue; + } + + ASSERT (MpServices !=3D NULL); + Status =3D MpServicesUnitTestStartupThisAP ( + *MpServices, + (EFI_AP_PROCEDURE)GetStackBasePerAp, + Index, + 0, + (VOID *)&CpuStackBaseBuffer[Index] + ); + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "AP[%d] StackBase =3D 0x%x\n", Index, CpuStackBase= Buffer[Index])); + } + + return CpuStackBaseBuffer; +} + +/** + Find not present or ReadOnly address in page table. + + @param[out] PFAddress Access to the address which is not permitted will= trigger PF exceptions. + + @retval TRUE Found not present or ReadOnly address in page table. + @retval FALSE Failed to found PFAddress in page table. +**/ +BOOLEAN +FindPFAddressInPageTable ( + OUT 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; + UINTN PreviousAddress; + + ASSERT (PFAddress !=3D NULL); + + Cr0.UintN =3D AsmReadCr0 (); + if (Cr0.Bits.PG =3D=3D 0) { + return FALSE; + } + + 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); + + PreviousAddress =3D 0; + 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 (Map[Index].LinearAddress > PreviousAddress) { + *PFAddress =3D PreviousAddress; + return TRUE; + } + + PreviousAddress =3D (UINTN)(Map[Index].LinearAddress + Map[Index].Leng= th); + + // + // 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 TRUE; + } + } + + return FALSE; +} + +/** + 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. + // + if (FindPFAddressInPageTable (&PFAddress)) { + 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) { + if (!FindPFAddressInPageTable (&FaultParameter)) { + 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; + 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) { + // + // 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 *)&SwitchStackDat= a[Index]); + continue; + } + + Status =3D MpServicesUnitTestStartupThisAP ( + MpServices, + InitializeExceptionStackSwitchHandlersPerAp, + Index, + 0, + (VOID *)&SwitchStackData[Index] + ); + 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) { + if (Index =3D=3D BspProcessorNum) { + InitializeExceptionStackSwitchHandlersPerAp ((VOID *)&SwitchStackD= ata[Index]); + continue; + } + + Status =3D MpServicesUnitTestStartupThisAP ( + MpServices, + InitializeExceptionStackSwitchHandlersPerAp, + Index, + 0, + (VOID *)&SwitchStackData[Index] + ); + 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 both 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) { + TriggerStackOverflow (); + } else { + MpServicesUnitTestStartupThisAP ( + MpServices, + (EFI_AP_PROCEDURE)TriggerStackOverflow, + 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..c0d962f26d --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTest.c @@ -0,0 +1,166 @@ +/** @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 mActualContextInHandler; +GENERAL_REGISTER mActualContextAfterException; + +// +// In TestCpuContextConsistency, Cpu registers will be set to mExpectedCon= textInHandler/mExpectedContextAfterException. +// Rcx in mExpectedContextInHandler is set runtime since Rcx is needed 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 mExpectedContextInHandler =3D { 1, 2, 3, 4, 5, 0, 7= , 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe }; +GENERAL_REGISTER mExpectedContextAfterException =3D { 0x11, 0x12, 0x13, 0= x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e }; + +/** + 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 + ) +{ + // + // Store SystemContext in mActualContextInHandler. + // + mActualContextInHandler.Rdi =3D SystemContext.SystemContextX64->Rdi; + mActualContextInHandler.Rsi =3D SystemContext.SystemContextX64->Rsi; + mActualContextInHandler.Rbx =3D SystemContext.SystemContextX64->Rbx; + mActualContextInHandler.Rdx =3D SystemContext.SystemContextX64->Rdx; + mActualContextInHandler.Rcx =3D SystemContext.SystemContextX64->Rcx; + mActualContextInHandler.Rax =3D SystemContext.SystemContextX64->Rax; + mActualContextInHandler.R8 =3D SystemContext.SystemContextX64->R8; + mActualContextInHandler.R9 =3D SystemContext.SystemContextX64->R9; + mActualContextInHandler.R10 =3D SystemContext.SystemContextX64->R10; + mActualContextInHandler.R11 =3D SystemContext.SystemContextX64->R11; + mActualContextInHandler.R12 =3D SystemContext.SystemContextX64->R12; + mActualContextInHandler.R13 =3D SystemContext.SystemContextX64->R13; + mActualContextInHandler.R14 =3D SystemContext.SystemContextX64->R14; + mActualContextInHandler.R15 =3D SystemContext.SystemContextX64->R15; + + // + // Modify cpu context. These registers will be stored in mActualContextA= fterException. + // Do not handle Rsp and Rbp. CpuExceptionHandlerLib doesn't set Rsp and= Rbp register + // to the value in SystemContext. + // + SystemContext.SystemContextX64->Rdi =3D mExpectedContextAfterException.R= di; + SystemContext.SystemContextX64->Rsi =3D mExpectedContextAfterException.R= si; + SystemContext.SystemContextX64->Rbx =3D mExpectedContextAfterException.R= bx; + SystemContext.SystemContextX64->Rdx =3D mExpectedContextAfterException.R= dx; + SystemContext.SystemContextX64->Rcx =3D mExpectedContextAfterException.R= cx; + SystemContext.SystemContextX64->Rax =3D mExpectedContextAfterException.R= ax; + SystemContext.SystemContextX64->R8 =3D mExpectedContextAfterException.R= 8; + SystemContext.SystemContextX64->R9 =3D mExpectedContextAfterException.R= 9; + SystemContext.SystemContextX64->R10 =3D mExpectedContextAfterException.R= 10; + SystemContext.SystemContextX64->R11 =3D mExpectedContextAfterException.R= 11; + SystemContext.SystemContextX64->R12 =3D mExpectedContextAfterException.R= 12; + SystemContext.SystemContextX64->R13 =3D mExpectedContextAfterException.R= 13; + SystemContext.SystemContextX64->R14 =3D mExpectedContextAfterException.R= 14; + SystemContext.SystemContextX64->R15 =3D mExpectedContextAfterException.R= 15; + + // + // 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 mActualContextInHandler with mExpectedContextInHandler. + 2.Compare mActualContextAfterException with mActualContextAfterException. + + @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 (mActualContextInHandler.Rdi, mExpectedContextInHandler.= Rdi); + UT_ASSERT_EQUAL (mActualContextInHandler.Rsi, mExpectedContextInHandler.= Rsi); + UT_ASSERT_EQUAL (mActualContextInHandler.Rbx, mExpectedContextInHandler.= Rbx); + UT_ASSERT_EQUAL (mActualContextInHandler.Rdx, mExpectedContextInHandler.= Rdx); + UT_ASSERT_EQUAL (mActualContextInHandler.Rcx, mExpectedContextInHandler.= Rcx); + UT_ASSERT_EQUAL (mActualContextInHandler.Rax, mExpectedContextInHandler.= Rax); + UT_ASSERT_EQUAL (mActualContextInHandler.R8, mExpectedContextInHandler.R= 8); + UT_ASSERT_EQUAL (mActualContextInHandler.R9, mExpectedContextInHandler.R= 9); + UT_ASSERT_EQUAL (mActualContextInHandler.R10, mExpectedContextInHandler.= R10); + UT_ASSERT_EQUAL (mActualContextInHandler.R11, mExpectedContextInHandler.= R11); + UT_ASSERT_EQUAL (mActualContextInHandler.R12, mExpectedContextInHandler.= R12); + UT_ASSERT_EQUAL (mActualContextInHandler.R13, mExpectedContextInHandler.= R13); + UT_ASSERT_EQUAL (mActualContextInHandler.R14, mExpectedContextInHandler.= R14); + UT_ASSERT_EQUAL (mActualContextInHandler.R15, mExpectedContextInHandler.= R15); + + UT_ASSERT_EQUAL (mActualContextAfterException.Rdi, mExpectedContextAfter= Exception.Rdi); + UT_ASSERT_EQUAL (mActualContextAfterException.Rsi, mExpectedContextAfter= Exception.Rsi); + UT_ASSERT_EQUAL (mActualContextAfterException.Rbx, mExpectedContextAfter= Exception.Rbx); + UT_ASSERT_EQUAL (mActualContextAfterException.Rdx, mExpectedContextAfter= Exception.Rdx); + UT_ASSERT_EQUAL (mActualContextAfterException.Rcx, mExpectedContextAfter= Exception.Rcx); + UT_ASSERT_EQUAL (mActualContextAfterException.Rax, mExpectedContextAfter= Exception.Rax); + UT_ASSERT_EQUAL (mActualContextAfterException.R8, mExpectedContextAfterE= xception.R8); + UT_ASSERT_EQUAL (mActualContextAfterException.R9, mExpectedContextAfterE= xception.R9); + UT_ASSERT_EQUAL (mActualContextAfterException.R10, mExpectedContextAfter= Exception.R10); + UT_ASSERT_EQUAL (mActualContextAfterException.R11, mExpectedContextAfter= Exception.R11); + UT_ASSERT_EQUAL (mActualContextAfterException.R12, mExpectedContextAfter= Exception.R12); + UT_ASSERT_EQUAL (mActualContextAfterException.R13, mExpectedContextAfter= Exception.R13); + UT_ASSERT_EQUAL (mActualContextAfterException.R14, mExpectedContextAfter= Exception.R14); + UT_ASSERT_EQUAL (mActualContextAfterException.R15, mExpectedContextAfter= Exception.R15); + 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..e229dbed00 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/X64/ArchExceptionHandlerTestAs= m.nasm @@ -0,0 +1,256 @@ +;-------------------------------------------------------------------------= ----- +; +; 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 + .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(mExpectedContextInHandler) +extern ASM_PFX(mActualContextAfterException) +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 + +;-------------------------------------------------------------------------= ----- +; ModifyRcxInGlobalBeforeException; +; This function is writed by assebly code because it's only called in this= file. +; It's used to set Rcx in mExpectedContextInHandler for different exceptio= n. +;-------------------------------------------------------------------------= ----- +global ASM_PFX(ModifyRcxInGlobalBeforeException) +ASM_PFX(ModifyRcxInGlobalBeforeException): + push rax + lea rax, [ASM_PFX(mExpectedContextInHandler)] + 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 + push rdx + + ; + ; Modify registers to mExpectedContextInHandler. Do not handle Rsp and= Rbp. + ; CpuExceptionHandlerLib doesn't set Rsp and Rsp register to the value= in SystemContext. + ; + lea r15, [ASM_PFX(mExpectedContextInHandler)] + 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 rcx ; Pop rdx(PFAddress) to= rcx. + call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextI= nHandler.Rcx to PFAddress. + call ASM_PFX(TriggerPFException) + jmp AfterException + +GPException: + pop rcx ; Pop rdx(Cr4ReservedBi= t) to rcx. + call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextI= nHandler.Rcx to Cr4ReservedBit. + call ASM_PFX(TriggerGPException) + jmp AfterException + +INTnException: + ; + ; Modify Rcx in mExpectedContextInHandler. + ; + add Rsp, 8 ; Discard the extra Rdx= in stack. Rcx is ExceptionType now. + call ASM_PFX(ModifyRcxInGlobalBeforeException) ; Set mExpectedContextI= nHandler.Rcx to ExceptionType. + call ASM_PFX(TriggerINTnException) + +AfterException: + ; + ; Save registers in mActualContextAfterException + ; + push rax + lea rax, [ASM_PFX(mActualContextAfterException)] + 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 +; TriggerStackOverflow ( +; VOID +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerStackOverflow) +ASM_PFX(TriggerStackOverflow): + 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 (#95200): https://edk2.groups.io/g/devel/message/95200 Mute This Topic: https://groups.io/mt/94323058/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 Sat May 18 21:45:20 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+95201+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+95201+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665739250; cv=none; d=zohomail.com; s=zohoarc; b=DdNMutZcypYtzJPC7GCz6fHKQ5gEalpoPH15Qy43cpQW76IBKHPskoIl0hOzp3pqfI6tEQYaJJp+9F5AFoOyDz3tpTdMmcAsmjFDfEcvnexe83TcDE/KeVYTJF3aZOEvhWceuFYLj8gC7dZM///xRkqI5vPjiZAd6zOhVtmdATs= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665739250; 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=/3SfOPHqGEvp/ETEZCRbPhJgXdfEKd9FsjTzjQXRLyM=; b=dwonsbeWz8FXJFrZB1AFrq8a4zrf6DcpWCZgo2fhm3fQaUzmHsQ3PG+0GZs5QP/nmcIYrPs9F4dOkItFTNMKXqktfDxsRH0SKXyDPThtKq8gHwxujjCymJE+CRL2c92D7ehBcU9UG9LYpCbOqKIYXSHlplVQJbEbACv9jj8kZWc= 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+95201+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 1665739250032980.9410902115249; Fri, 14 Oct 2022 02:20:50 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id zWbUYY1788612xwHZaGVgSwr; Fri, 14 Oct 2022 02:20:49 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web08.5230.1665739248923167542 for ; Fri, 14 Oct 2022 02:20:49 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="391639704" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="391639704" X-Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:48 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="627510862" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="627510862" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:46 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [Patch V3 2/4] UefiCpuPkg: Add Unit tests for PeiCpuExceptionHandlerLib Date: Fri, 14 Oct 2022 17:19:29 +0800 Message-Id: <20221014091931.847-3-dun.tan@intel.com> In-Reply-To: <20221014091931.847-1-dun.tan@intel.com> References: <20221014091931.847-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: kPNGrpgc5E1jAsMHQ0ZSktKCx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665739249; bh=akczfQtOow1dNhH5/+MTLVz2j09i3NrobtaIkTF3PQQ=; h=Cc:Date:From:Reply-To:Subject:To; b=WrVc/xDg3Lx29mFE9pBFlOSgnX6TAwUUCAJ6IhGJ0HureBo/TW9gwM9POSic6+9cn8T +/C628RFU+1Iy17Qk2p4Is5WTFWemG1UDQxoRQN+t80P+TUQDlfWeb1/PAlW0GOgkGzLp +0JlFFKsEsQrB2OU1JOSkKOeWCTeWbecRyo= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665739250893100001 Content-Type: text/plain; charset="utf-8" The previous change adds unit test for DxeCpuExeptionHandlerLib in 64bit mode. This change create a PEIM to add unit test for PeiCpuExceptionHandlerLib based on previous change.It can run in both 32bit and 64bit modes. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar Reviewed-by: Ray Ni --- UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h = | 9 +++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c = | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestAsm.na= sm | 208 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitTest.i= nf | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUnitTest.c = | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 617 insertions(+) diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest= .h b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h index 936098fde8..bad3387db5 100644 --- a/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h @@ -93,6 +93,15 @@ typedef struct { UINT64 R15; } GENERAL_REGISTER; =20 +typedef struct { + UINT32 Edi; + UINT32 Esi; + UINT32 Ebx; + UINT32 Edx; + UINT32 Ecx; + UINT32 Eax; +} GENERAL_REGISTER_IA32; + extern UINTN mFaultInstructionLength; extern EFI_EXCEPTION_TYPE mExceptionType; extern UINTN mRspAddress[]; diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandl= erTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandler= Test.c new file mode 100644 index 0000000000..8bb27249dc --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c @@ -0,0 +1,135 @@ +/** @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 mActualContextInHandler; +GENERAL_REGISTER_IA32 mActualContextAfterException; + +// +// In TestCpuContextConsistency, Cpu registers will be set to mExpectedCon= textInHandler/mExpectedContextAfterException. +// Ecx in mExpectedContextInHandler is set runtime since Ecx is needed 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 mExpectedContextInHandler =3D { 1, 2, 3, 4, 5,= 0 }; +GENERAL_REGISTER_IA32 mExpectedContextAfterException =3D { 11, 12, 13, 14= , 15, 16 }; + +/** + 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 + ) +{ + // + // Store SystemContext in exception handler. + // + mActualContextInHandler.Edi =3D SystemContext.SystemContextIa32->Edi; + mActualContextInHandler.Esi =3D SystemContext.SystemContextIa32->Esi; + mActualContextInHandler.Ebx =3D SystemContext.SystemContextIa32->Ebx; + mActualContextInHandler.Edx =3D SystemContext.SystemContextIa32->Edx; + mActualContextInHandler.Ecx =3D SystemContext.SystemContextIa32->Ecx; + mActualContextInHandler.Eax =3D SystemContext.SystemContextIa32->Eax; + + // + // Modify cpu context. These registers will be stored in mActualContextA= fterException. + // Do not handle Esp and Ebp in SystemContext. CpuExceptionHandlerLib do= esn't set Esp and + // Esp register to the value in SystemContext. + // + SystemContext.SystemContextIa32->Edi =3D mExpectedContextAfterException.= Edi; + SystemContext.SystemContextIa32->Esi =3D mExpectedContextAfterException.= Esi; + SystemContext.SystemContextIa32->Ebx =3D mExpectedContextAfterException.= Ebx; + SystemContext.SystemContextIa32->Edx =3D mExpectedContextAfterException.= Edx; + SystemContext.SystemContextIa32->Ecx =3D mExpectedContextAfterException.= Ecx; + SystemContext.SystemContextIa32->Eax =3D mExpectedContextAfterException.= 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 mActualContextInHandler with mExpectedContextInHandler. + 2.Compare mActualContextAfterException with mExpectedContextAfterExcepti= on. + + @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 (mActualContextInHandler.Edi, mExpectedContextInHandler.= Edi); + UT_ASSERT_EQUAL (mActualContextInHandler.Esi, mExpectedContextInHandler.= Esi); + UT_ASSERT_EQUAL (mActualContextInHandler.Ebx, mExpectedContextInHandler.= Ebx); + UT_ASSERT_EQUAL (mActualContextInHandler.Edx, mExpectedContextInHandler.= Edx); + UT_ASSERT_EQUAL (mActualContextInHandler.Ecx, mExpectedContextInHandler.= Ecx); + UT_ASSERT_EQUAL (mActualContextInHandler.Eax, mExpectedContextInHandler.= Eax); + + UT_ASSERT_EQUAL (mActualContextAfterException.Edi, mExpectedContextAfter= Exception.Edi); + UT_ASSERT_EQUAL (mActualContextAfterException.Esi, mExpectedContextAfter= Exception.Esi); + UT_ASSERT_EQUAL (mActualContextAfterException.Ebx, mExpectedContextAfter= Exception.Ebx); + UT_ASSERT_EQUAL (mActualContextAfterException.Edx, mExpectedContextAfter= Exception.Edx); + UT_ASSERT_EQUAL (mActualContextAfterException.Ecx, mExpectedContextAfter= Exception.Ecx); + UT_ASSERT_EQUAL (mActualContextAfterException.Eax, mExpectedContextAfter= 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..48031a5109 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestA= sm.nasm @@ -0,0 +1,208 @@ +;-------------------------------------------------------------------------= ----- +; +; 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 + .Ebx: resd 1 + .Edx: resd 1 + .Ecx: resd 1 + .Eax: resd 1 + +endstruc + +extern ASM_PFX(mExpectedContextInHandler) +extern ASM_PFX(mActualContextAfterException) +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 + +;-------------------------------------------------------------------------= ----- +; ModifyEcxInGlobalBeforeException; +; This function is writed by assebly code because it's only called in this= file. +; It's used to set Ecx in mExpectedContextInHandler for different exceptio= n. +;-------------------------------------------------------------------------= ----- +global ASM_PFX(ModifyEcxInGlobalBeforeException) +ASM_PFX(ModifyEcxInGlobalBeforeException): + push eax + lea eax, [ASM_PFX(mExpectedContextInHandler)] + 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 register to mExpectedContextInHandler. Do not handle Esp and = Ebp. + ; CpuExceptionHandlerLib doesn't set Esp and Esp register to the value= in SystemContext. + ; + lea eax, [ASM_PFX(mExpectedContextInHandler)] + 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: + mov ecx, dword [esp + 0x28] ; Set ecx to PFAddress. + call ASM_PFX(ModifyEcxInGlobalBeforeException) ; Set mExpectedContext= InHandler.Ecx to PFAddress. + push ecx ; Push PfAddress into = stack. + call ASM_PFX(TriggerPFException) + jmp AfterException + +GPException: + mov ecx, dword [esp + 0x28] ; Set ecx to CR4_RESER= VED_BIT. + call ASM_PFX(ModifyEcxInGlobalBeforeException) ; Set mExpectedContext= InHandler.Ecx to CR4_RESERVED_BIT. + push ecx ; Push CR4_RESERVED_BI= T into stack. + call ASM_PFX(TriggerGPException) + jmp AfterException + +INTnException: + call ASM_PFX(ModifyEcxInGlobalBeforeException) ; Set mExpectedContext= InHandler.Ecx to ExceptionType. + push ecx ; Push ExceptionType i= nto stack. + call ASM_PFX(TriggerINTnException) + +AfterException: + ; + ; Save register in mActualContextAfterException. + ; + push eax + lea eax, [ASM_PFX(mActualContextAfterException)] + 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 +; TriggerStackOverflow ( +; VOID +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerStackOverflow) +ASM_PFX(TriggerStackOverflow): + 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 (#95201): https://edk2.groups.io/g/devel/message/95201 Mute This Topic: https://groups.io/mt/94323060/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 Sat May 18 21:45:20 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+95202+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+95202+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665739253; cv=none; d=zohomail.com; s=zohoarc; b=bpvh/EBZksuqvQBauQ8jqZypor1EPjWSz888SJ3wm+oh4FUyTe/C3JvJ1aeId+vTQyahoEAX6tfIIZryVitJE+hs8HE4db2JPVsmM0WPkoq45inrdL/Xt2/miPh6URvKHJmwnxAk83GWBX0U7gtkNXTkG6bvYXmMqfrgGAAvqF0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665739253; 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=BMtHLLNVB/8cokNmNyUXMeK2GhClI6GVRq+KzSkd/TY=; b=llMzJ1FIiFh+AcMnqIHxefBpwMFDVOm/ICYOqt9bonNNv0OB3UquJj+bh3SfUo5ffUnoufy4n1PAp0FZGrFvCg2cW5e1gEut2TDKgx1lNOTm8SM6aCQFWfyllkr6p1o8n6HrZf0hzwc98kq6uZzUfB9Gz3ClwjP4PAzYEKT1lNU= 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+95202+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 1665739253674482.10882239493844; Fri, 14 Oct 2022 02:20:53 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id yB83YY1788612xBVAdGY2FiO; Fri, 14 Oct 2022 02:20:53 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web08.5230.1665739248923167542 for ; Fri, 14 Oct 2022 02:20:52 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="391639724" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="391639724" X-Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:52 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="627510874" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="627510874" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:50 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [Patch V3 3/4] UefiCpuPkg: Add Pei/DxeCpuExceptionHandlerLibUnitTest in dsc Date: Fri, 14 Oct 2022 17:19:30 +0800 Message-Id: <20221014091931.847-4-dun.tan@intel.com> In-Reply-To: <20221014091931.847-1-dun.tan@intel.com> References: <20221014091931.847-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: tf4igFUTrKrJyCDwAYNwCEbKx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665739253; bh=WCmV9bvUGslF2Ha08fVJVbDWyvXNw+qMhAz8ARsX+VY=; h=Cc:Date:From:Reply-To:Subject:To; b=nwAgLaD+WIJZTz/d1jzhUez2YUN7YdgSjBo2lAqXDQqLgBMcj8SaBhRCAy9sD3JPl7h 6++vlZT2fS1BXc9j6MbKHQe3RqjzlwEmG2fUdkC2RjqTTwe71Rz9tBqzpWukGBtBD3vgD PlpMJSFVX31knLYam99+YOmOx5Ujb58QRFg= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665739254862100001 Content-Type: text/plain; charset="utf-8" Add Pei/DxeCpuExceptionHandlerLibUnitTest module in UefiCpuPkg.dsc Signed-off-by: Dun Tan Cc: Eric Dong Reviewed-by: 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 (#95202): https://edk2.groups.io/g/devel/message/95202 Mute This Topic: https://groups.io/mt/94323061/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 Sat May 18 21:45:20 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+95203+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+95203+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665739258; cv=none; d=zohomail.com; s=zohoarc; b=R8LC5NgpQVxg0Y4vbuGjuheZp9Y0Cq6CLehRrDnDyZiJDrWaUhbo3KqOSquF3Rn9WhcjPRtFsPjdkI8h6KXuJnfmjKYEFHVNbldT1qhUC/kBNc3UOCtor6Ud8ThEwNsoYZNNB0dE/ueGGcV4j4pJnHKJrM7y2p+C9xsIg8VsK+0= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665739258; 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=jR/woK2za9rkgROgaZzaTJmJCIkjezo1eO6qBJaiH2o=; b=G7gxJJV6Xoo2hKUoKAwsja4yy27L5HX/pRw6Z7WQZ0V13Xml/WFM6I5JxnnxdnM1/ERmjnjEu20TxuBVyrVTmMG8ilnUVGAXkzMUG95ZcEbmqKqBF4tRiz3os3TXg/QT7fAkTmb0nPwA+FrIScPvyJ+FrrT0oSHeJsMSRv4WSP0= 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+95203+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 1665739258756645.6563324117626; Fri, 14 Oct 2022 02:20:58 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id aqyPYY1788612x4wiH8NZngP; Fri, 14 Oct 2022 02:20:56 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web08.5230.1665739248923167542 for ; Fri, 14 Oct 2022 02:20:56 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="391639752" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="391639752" X-Received: from orsmga002.jf.intel.com ([10.7.209.21]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:55 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10499"; a="627510896" X-IronPort-AV: E=Sophos;i="5.95,182,1661842800"; d="scan'208";a="627510896" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by orsmga002-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Oct 2022 02:20:54 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [Patch V3 4/4] UefiCpuPkg: Add CpuExceptionHandlerTest.h in ECC IgnoreFile Date: Fri, 14 Oct 2022 17:19:31 +0800 Message-Id: <20221014091931.847-5-dun.tan@intel.com> In-Reply-To: <20221014091931.847-1-dun.tan@intel.com> References: <20221014091931.847-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: iwzEBs3PLRCIZDBznw72CvcEx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665739256; bh=1vlsFQ0gkJ1nRnDfgXuQM/gDjnmPSLTMRdpL6yKduG0=; h=Cc:Date:From:Reply-To:Subject:To; b=FOewmOFtsPonLFjBLcac6Mct9wI8/wex/FzcIcheXPqGUJckwE/QNhyhUVl3DqPmtKl EcTtIBV7vUUWZaif5Z+tbXslGv17PZBmMktUSwSU+OTaQRXTnHAQwf6stfsgR/UMCiUPe +U1OFRiGE3agDZbGCmPwz0aiIWubbO3L2bs= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665739260887100003 Content-Type: text/plain; charset="utf-8" Add CpuExceptionHandlerTest.h in EccCheck IgnoreFiles of UefiCpuPkg/UefiCpuPkg.ci.yaml to pass ECC check. The GENERAL_REGISTER.R8 in this file triggers EccCheck failure since no lower case characters in R8/R9/R10. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar --- UefiCpuPkg/UefiCpuPkg.ci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/UefiCpuPkg/UefiCpuPkg.ci.yaml b/UefiCpuPkg/UefiCpuPkg.ci.yaml index bbdc44a45b..1acc6daa76 100644 --- a/UefiCpuPkg/UefiCpuPkg.ci.yaml +++ b/UefiCpuPkg/UefiCpuPkg.ci.yaml @@ -19,6 +19,7 @@ ], ## Both file path and directory path are accepted. "IgnoreFiles": [ + "CpuExceptionHandlerUnitTest/CpuExceptionHandlerTest.h" ] }, "CompilerPlugin": { --=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 (#95203): https://edk2.groups.io/g/devel/message/95203 Mute This Topic: https://groups.io/mt/94323062/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-