From nobody Sat Feb 7 10:14:54 2026 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-