From nobody Sat Feb 7 08:43:51 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+94972+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94972+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665468242; cv=none; d=zohomail.com; s=zohoarc; b=GGrCjd/v7tUH1fs8xxhKJR0KAYOSFkuKX+uYFT546XF91N2HzyhW9fA7f3qtxtsiu7h5f1vpvIWP3cq2v1tlbU2zu1Nl+bXx8Ld9ThDoFGWB2tAevJG7EvyC4uF9r6mcTUVcjJJKi2/KuELb+i/5Mwxd0YBRLbNCFHWTv85rNg8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665468242; h=Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=UqzrFV1mqFP9P+ZwEUxVU9ceTxOi637QT6SkQLhQiV8=; b=kAJ1Cud9KrDmVUyb5cbIS4zJyh95KA1oEtHPGDNGi/yeT+pFgZb7qjQeN3sf5rhYYtzGzwK1lnUuBlB5O4py2weD1/B1q1rWWIDmRHqsYsFp2BF42ZREx41Me3o0MrlrB2sUJ4fn6vEzMem0vt6EV2ovpm66SWJPLjuuceqmUAQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+94972+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 166546824216123.34460548663378; Mon, 10 Oct 2022 23:04:02 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id a9R4YY1788612xjKlWpBf7Mc; Mon, 10 Oct 2022 23:04:01 -0700 X-Received: from mga05.intel.com (mga05.intel.com [192.55.52.43]) by mx.groups.io with SMTP id smtpd.web11.4146.1665468237246285163 for ; Mon, 10 Oct 2022 23:04:01 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="390724537" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="390724537" X-Received: from fmsmga002.fm.intel.com ([10.253.24.26]) by fmsmga105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:04:00 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="730846938" X-IronPort-AV: E=Sophos;i="5.95,175,1661842800"; d="scan'208";a="730846938" X-Received: from shwdeopenlab702.ccr.corp.intel.com ([10.239.56.220]) by fmsmga002-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 23:03:59 -0700 From: "duntan" To: devel@edk2.groups.io Cc: Eric Dong , Ray Ni , Rahul Kumar Subject: [edk2-devel] [PATCH 2/3] UefiCpuPkg: Add Unit tests for PeiCpuExceptionHandlerLib Date: Tue, 11 Oct 2022 14:03:34 +0800 Message-Id: <20221011060335.575-3-dun.tan@intel.com> In-Reply-To: <20221011060335.575-1-dun.tan@intel.com> References: <20221011060335.575-1-dun.tan@intel.com> MIME-Version: 1.0 Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,dun.tan@intel.com X-Gm-Message-State: ZLK8aGwEnZn5CdK7JvNYk2BBx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665468241; bh=LJma1j+FO2QOhpdhIXZYB0V2y9BfL+NnB3oCqKh6eYk=; h=Cc:Date:From:Reply-To:Subject:To; b=A6GJdKKZnGFpt0ConAXGYg5vCD8LQrep0xIp1K06mK2TNoPm5nJiRgxKMzxELvGhLvD QKgnN2y/u2Ko3Lm+CdtstZaLHmrrvaDy1giDWRApHSdkLbpV5KMImUTI8GV+udTT+Oc/X 3T1pLRwuHB1M57B/xvbLTzoSTaPNAGH6dNc= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665468244078100002 Content-Type: text/plain; charset="utf-8" Add target based unit tests for the PeiCpuExceptionHandlerLib. A PEIM is created to test PeiCpuExceptionHandlerLib. Four kinds of test cases are created in this module: 1.Test if exception handler can be registered/unregistered for no error code exception. 2.Test if exception handler can be registered/unregistered for GP and PF. 3.Test if Cpu Context is consistent before and after exception. 4.Test if stack overflow can be captured by CpuStackGuard in both Bsp and AP. Signed-off-by: Dun Tan Cc: Eric Dong Cc: Ray Ni Cc: Rahul Kumar --- UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c = | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestAsm.na= sm | 217 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitTest.i= nf | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUnitTest.c = | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++= +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 615 insertions(+) diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandl= erTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandler= Test.c new file mode 100644 index 0000000000..32188b9a81 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTest.c @@ -0,0 +1,133 @@ +/** @file + Unit tests of the CpuExceptionHandlerLib. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CpuExceptionHandlerTest.h" + +GENERAL_REGISTER_IA32 mIa32RegisterForCheck[2]; + +// +// In TestCpuContextConsistency, Cpu registers will be set to mAdjustRegis= terBeforeException/mAdjustRegisterInsideException. +// Ecx in mAdjustRegisterInsideException is set runtime since Ecx is neede= d in assembly code. +// For GP and PF, Ecx is set to FaultParameter. For other exception trigge= red by INTn, Ecx is set to ExceptionType. +// +GENERAL_REGISTER_IA32 mAdjustIa32RegisterBeforeException =3D { 1, 2, 3, 4= , 5, 0, 7 }; +GENERAL_REGISTER_IA32 mAdjustIa32RegisterInsideException =3D { 11, 12, 13= , 14, 15, 16, 17 }; + +/** + Special handler for fault exception. + Rip/Eip in SystemContext will be modified to the instruction after the e= xception instruction. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + +**/ +VOID +EFIAPI +AdjustRipForFaultHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + mExceptionType =3D ExceptionType; + SystemContext.SystemContextIa32->Eip +=3D mFaultInstructionLength; +} + +/** + Special handler for ConsistencyOfCpuContext test case. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. +**/ +VOID +EFIAPI +AdjustCpuContextHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + // + // Do not handle Esp and ebp. They will not be restored. + // Store SystemContext modified before exception. + // + mIa32RegisterForCheck[0].Edi =3D SystemContext.SystemContextIa32->Edi; + mIa32RegisterForCheck[0].Esi =3D SystemContext.SystemContextIa32->Esi; + mIa32RegisterForCheck[0].Ebx =3D SystemContext.SystemContextIa32->Ebx; + mIa32RegisterForCheck[0].Edx =3D SystemContext.SystemContextIa32->Edx; + mIa32RegisterForCheck[0].Ecx =3D SystemContext.SystemContextIa32->Ecx; + mIa32RegisterForCheck[0].Eax =3D SystemContext.SystemContextIa32->Eax; + + // + // Modify cpu context which will be stored in mIa32RegisterForCheck[1]. + // + SystemContext.SystemContextIa32->Edi =3D mAdjustIa32RegisterInsideExcept= ion.Edi; + SystemContext.SystemContextIa32->Esi =3D mAdjustIa32RegisterInsideExcept= ion.Esi; + SystemContext.SystemContextIa32->Ebx =3D mAdjustIa32RegisterInsideExcept= ion.Ebx; + SystemContext.SystemContextIa32->Edx =3D mAdjustIa32RegisterInsideExcept= ion.Edx; + SystemContext.SystemContextIa32->Ecx =3D mAdjustIa32RegisterInsideExcept= ion.Ecx; + SystemContext.SystemContextIa32->Eax =3D mAdjustIa32RegisterInsideExcept= ion.Eax; + + // + // When fault exception happens, eip/rip points to the faulting instruct= ion. + // For now, olny GP and PF are tested in fault exception. + // + if ((ExceptionType =3D=3D EXCEPT_IA32_PAGE_FAULT) || (ExceptionType =3D= =3D EXCEPT_IA32_GP_FAULT)) { + AdjustRipForFaultHandler (ExceptionType, SystemContext); + } +} + +/** + Compare cpu context in ConsistencyOfCpuContext test case. + 1.Compare mRegisterForCheck[0] with mAdjustRegisterBeforeException. + 2.Compare mRegisterForCheck[1] with mAdjustRegisterAfterException. + + @retval UNIT_TEST_PASSED The Unit test has completed and it= was successful. + @retval UNIT_TEST_ERROR_TEST_FAILED A test case assertion has failed. +**/ +UNIT_TEST_STATUS +CompareCpuContext ( + VOID + ) +{ + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Edi, mAdjustIa32RegisterBefore= Exception.Edi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Esi, mAdjustIa32RegisterBefore= Exception.Esi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Ebx, mAdjustIa32RegisterBefore= Exception.Ebx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Edx, mAdjustIa32RegisterBefore= Exception.Edx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Ecx, mAdjustIa32RegisterBefore= Exception.Ecx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[0].Eax, mAdjustIa32RegisterBefore= Exception.Eax); + + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Edi, mAdjustIa32RegisterInside= Exception.Edi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Esi, mAdjustIa32RegisterInside= Exception.Esi); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Ebx, mAdjustIa32RegisterInside= Exception.Ebx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Edx, mAdjustIa32RegisterInside= Exception.Edx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Ecx, mAdjustIa32RegisterInside= Exception.Ecx); + UT_ASSERT_EQUAL (mIa32RegisterForCheck[1].Eax, mAdjustIa32RegisterInside= Exception.Eax); + return UNIT_TEST_PASSED; +} + +/** + Special handler for CpuStackGuard test case. + + @param ExceptionType Exception type. + @param SystemContext Pointer to EFI_SYSTEM_CONTEXT. + +**/ +VOID +EFIAPI +CpuStackGuardExceptionHandler ( + IN EFI_EXCEPTION_TYPE ExceptionType, + IN EFI_SYSTEM_CONTEXT SystemContext + ) +{ + UINTN LocalVariable; + + AdjustRipForFaultHandler (ExceptionType, SystemContext); + mRspAddress[0] =3D (UINTN)SystemContext.SystemContextIa32->Esp; + mRspAddress[1] =3D (UINTN)(&LocalVariable); + + return; +} diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandl= erTestAsm.nasm b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionH= andlerTestAsm.nasm new file mode 100644 index 0000000000..ccadd8765f --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/Ia32/ArchExceptionHandlerTestA= sm.nasm @@ -0,0 +1,217 @@ +;-------------------------------------------------------------------------= ----- +; +; Copyright (c) 2022, Intel Corporation. All rights reserved.
+; SPDX-License-Identifier: BSD-2-Clause-Patent +; +; Module Name: +; +; ArchExceptionHandlerTestAsm.nasm +; +; Abstract: +; +; ia32 CPU Exception Handler Lib Unit test +; +;-------------------------------------------------------------------------= ----- + + SECTION .text + +struc GENERAL_REGISTER_IA32 + .Edi: resd 1 + .Esi: resd 1 + .Ebp: resd 1 + .Ebx: resd 1 + .Edx: resd 1 + .Ecx: resd 1 + .Eax: resd 1 + +endstruc + +extern ASM_PFX(mIa32RegisterForCheck) +extern ASM_PFX(mAdjustIa32RegisterBeforeException) +extern ASM_PFX(mFaultInstructionLength) + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerGPException ( +; UINTN Cr4ReservedBit +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerGPException) +ASM_PFX(TriggerGPException): + ; + ; Set reserved bit 15 of cr4 to 1 + ; + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerGPExceptionAfter - TriggerGPExceptionBefore + mov ecx, dword [esp + 0x4] +TriggerGPExceptionBefore: + mov cr4, ecx +TriggerGPExceptionAfter: + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerPFException ( +; UINTN PfAddress +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerPFException) +ASM_PFX(TriggerPFException): + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerPFExceptionAfter - TriggerPFExceptionBefore + mov ecx, dword [esp + 0x4] +TriggerPFExceptionBefore: + mov dword[ecx], 0x1 +TriggerPFExceptionAfter: + ret + +global ASM_PFX(ModifyEcxInGlobalBeforeException) +ASM_PFX(ModifyEcxInGlobalBeforeException): + push eax + lea eax, [ASM_PFX(mAdjustIa32RegisterBeforeException)] + mov [eax + GENERAL_REGISTER_IA32.Ecx], ecx + pop eax + ret + +;-------------------------------------------------------------------------= ----- +;VOID +;EFIAPI +;AsmTestConsistencyOfCpuContext ( +; IN EFI_EXCEPTION_TYPE ExceptionType +; IN UINTN FaultParameter OPTIONAL +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(AsmTestConsistencyOfCpuContext) +ASM_PFX(AsmTestConsistencyOfCpuContext): + ; + ; push 7 general register plus 4 bytes + ; + pushad + + ; + ; modify Modify register to mAdjustRegisterBeforeException + ; + lea eax, [ASM_PFX(mAdjustIa32RegisterBeforeException)] + mov edi, [eax + GENERAL_REGISTER_IA32.Edi] + mov esi, [eax + GENERAL_REGISTER_IA32.Esi] + mov ebx, [eax + GENERAL_REGISTER_IA32.Ebx] + mov edx, [eax + GENERAL_REGISTER_IA32.Edx] + ; + ; Set ecx to ExceptionType + ; + mov ecx, dword [esp + 0x24] + mov eax, [eax + GENERAL_REGISTER_IA32.Eax] + + cmp ecx, 0xd + jz GPException + cmp ecx, 0xe + jz PFException + jmp INTnException + +PFException: + ; + ; Set ecx to PFAddress and Modify Ecx in mAdjustRegisterBeforeExceptio= n. + ; Push PfAddress into stack. + ; + mov ecx, dword [esp + 0x28] + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerPFException) + jmp AfterException + +GPException: + ; + ; Set ecx to CR4_RESERVED_BIT and Modify Ecx in mAdjustRegisterBeforeE= xception. + ; Push CR4_RESERVED_BIT into stack + ; + mov ecx, dword [esp + 0x28] + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerGPException) + jmp AfterException + +INTnException: + ; + ; Modify Ecx in mAdjustRegisterBeforeException. + ; Push exception index into stack + ; + call ASM_PFX(ModifyEcxInGlobalBeforeException) + push ecx + call ASM_PFX(TriggerINTnException) + +AfterException: + ; + ; Save register in mRegisterForCheck[1]. + ; Esp and ebp will not be synced to the value in SystemContext. Do not= test esp and ebp. + ; + push eax + lea eax, [ASM_PFX(mIa32RegisterForCheck)] + add eax, GENERAL_REGISTER_IA32_size + mov [eax + GENERAL_REGISTER_IA32.Edi], edi + mov [eax + GENERAL_REGISTER_IA32.Esi], esi + mov [eax + GENERAL_REGISTER_IA32.Ebx], ebx + mov [eax + GENERAL_REGISTER_IA32.Edx], edx + mov [eax + GENERAL_REGISTER_IA32.Ecx], ecx + pop ecx + mov [eax + GENERAL_REGISTER_IA32.Eax], ecx + add esp, 4 + + ; + ; restore original register + ; + popad + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerStackOverflowbyCpuStackGuard ( +; VOID +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerStackOverflowbyCpuStackGuard) +ASM_PFX(TriggerStackOverflowbyCpuStackGuard): + lea ecx, [ASM_PFX(mFaultInstructionLength)] + mov dword[ecx], TriggerCpuStackGuardAfter - TriggerCpuStackGuardBefore +TriggerCpuStackGuardBefore: + ; + ; Clear CR0.TS since it is set after return from a nested DF + ; + call TriggerCpuStackGuardBefore + clts +TriggerCpuStackGuardAfter: + ret + +;-------------------------------------------------------------------------= ----- +; VOID +; EFIAPI +; TriggerINTnException ( +; IN EFI_EXCEPTION_TYPE ExceptionType +; ); +;-------------------------------------------------------------------------= ----- +global ASM_PFX(TriggerINTnException) +ASM_PFX(TriggerINTnException): + push eax + push edx + lea eax, [AsmTriggerException1 - AsmTriggerException0] + mov ecx, dword [esp + 0xc] + push ecx + mul ecx + mov ecx, AsmTriggerException0 + add eax, ecx + pop ecx + pop edx + jmp eax + ; + ; eax =3D AsmTriggerException0 + (AsmTriggerException1 - AsmTriggerExc= eption0) * ecx + ; +%assign Vector 0 +%rep 22 +AsmTriggerException %+ Vector: + pop eax + INT Vector + ret +%assign Vector Vector+1 +%endrep diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerL= ibUnitTest.inf b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHand= lerLibUnitTest.inf new file mode 100644 index 0000000000..25f8f8dbe0 --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerLibUnitT= est.inf @@ -0,0 +1,61 @@ +## @file +# Unit tests of the PeiCpuExceptionHandlerLib instance. +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +## + +[Defines] + INF_VERSION =3D 0x00010006 + BASE_NAME =3D CpuExceptionHandlerPeiTest + FILE_GUID =3D 39A96CF7-F369-4357-9234-4B52F98A007F + MODULE_TYPE =3D PEIM + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D PeiEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# +[Sources.Ia32] + Ia32/ArchExceptionHandlerTestAsm.nasm + Ia32/ArchExceptionHandlerTest.c + +[Sources.X64] + X64/ArchExceptionHandlerTestAsm.nasm + X64/ArchExceptionHandlerTest.c + +[Sources.common] + CpuExceptionHandlerTest.h + CpuExceptionHandlerTestCommon.c + PeiCpuExceptionHandlerUnitTest.c + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + BaseMemoryLib + DebugLib + UnitTestLib + MemoryAllocationLib + CpuExceptionHandlerLib + PeimEntryPoint + HobLib + PeiServicesLib + CpuPageTableLib + PeiServicesTablePointerLib + +[Pcd] + gEfiMdeModulePkgTokenSpaceGuid.PcdCpuStackGuard ## CONSUMES + gUefiCpuPkgTokenSpaceGuid.PcdCpuApStackSize ## CONSUMES + +[Ppis] + gEdkiiPeiMpServices2PpiGuid ## CONSUMES + +[Depex] + gEdkiiPeiMpServices2PpiGuid AND + gEfiPeiMemoryDiscoveredPpiGuid diff --git a/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerU= nitTest.c b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUn= itTest.c new file mode 100644 index 0000000000..d9408d2f5e --- /dev/null +++ b/UefiCpuPkg/CpuExceptionHandlerUnitTest/PeiCpuExceptionHandlerUnitTest= .c @@ -0,0 +1,204 @@ +/** @file + Unit tests of the CpuExceptionHandlerLib. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "CpuExceptionHandlerTest.h" +#include +#include +#include + +/** + Initialize Bsp Idt with a new Idt table and return the IA32_DESCRIPTOR b= uffer. + In PEIM, store original PeiServicePointer before new Idt table. + + @return Pointer to the allocated IA32_DESCRIPTOR buffer. +**/ +VOID * +InitializeBspIdt ( + VOID + ) +{ + UINTN *NewIdtTable; + IA32_DESCRIPTOR *Idtr; + + Idtr =3D AllocateZeroPool (sizeof (IA32_DESCRIPTOR)); + ASSERT (Idtr !=3D NULL); + NewIdtTable =3D AllocateZeroPool (sizeof (IA32_IDT_GATE_DESCRIPTOR) * CP= U_INTERRUPT_NUM + sizeof (UINTN)); + ASSERT (NewIdtTable !=3D NULL); + // + // Store original PeiServicePointer before new Idt table + // + *NewIdtTable =3D (UINTN)GetPeiServicesTablePointer (); + NewIdtTable =3D (UINTN *)((UINTN)NewIdtTable + sizeof (UINTN)); + + Idtr->Base =3D (UINTN)NewIdtTable; + Idtr->Limit =3D (UINT16)(sizeof (IA32_IDT_GATE_DESCRIPTOR) * CPU_INTERRU= PT_NUM - 1); + + AsmWriteIdtr (Idtr); + return Idtr; +} + +/** + Retrieve the number of logical processor in the platform and the number = of those logical processors that + are enabled on this boot. + + @param[in] MpServices MP_SERVICES structure. + @param[out] NumberOfProcessors Pointer to the total number of logical p= rocessors in the system, including + the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of processor= s in the system that are enabled. + + @retval EFI_SUCCESS Retrieve the number of logical processor succe= ssfully + @retval Others Retrieve the number of logical processor unsuc= cessfully +**/ +EFI_STATUS +MpServicesUnitTestGetNumberOfProcessors ( + IN MP_SERVICES MpServices, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ) +{ + return MpServices.Ppi->GetNumberOfProcessors (MpServices.Ppi, NumberOfPr= ocessors, NumberOfEnabledProcessors); +} + +/** + Caller gets one enabled AP to execute a caller-provided function. + + @param[in] MpServices MP_SERVICES structure. + @param[in] Procedure Pointer to the function to be run on enabled A= Ps of the system. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + + @retval EFI_SUCCESS Caller gets one enabled AP to execute a caller= -provided function successfully + @retval Others Caller gets one enabled AP to execute a caller= -provided function unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestStartupThisAP ( + IN MP_SERVICES MpServices, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument + ) +{ + return MpServices.Ppi->StartupThisAP (MpServices.Ppi, Procedure, Process= orNumber, TimeoutInMicroSeconds, ProcedureArgument); +} + +/** + Execute a caller provided function on all enabled APs. + + @param[in] MpServices MP_SERVICES structure. + @param[in] Procedure Pointer to the function to be run on enabled A= Ps of the system. + @param[in] SingleThread If TRUE, then all the enabled APs execute the = function specified by Procedure + one by one, in ascending order of processor ha= ndle number. + If FALSE, then all the enabled APs execute the= function specified by Procedure + simultaneously. + @param[in] TimeoutInMicroSeconds Indicates the time limit in microsecon= ds for APs to return from Procedure, + for blocking mode only. Zero means inf= inity. + @param[in] ProcedureArgument The parameter passed into Procedure fo= r all APs. + + @retval EFI_SUCCESS Execute a caller provided function on all enab= led APs successfully + @retval Others Execute a caller provided function on all enab= led APs unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestStartupAllAPs ( + IN MP_SERVICES MpServices, + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument + ) +{ + return MpServices.Ppi->StartupAllAPs (MpServices.Ppi, Procedure, SingleT= hread, TimeoutInMicroSeconds, ProcedureArgument); +} + +/** + Get the handle number for the calling processor. + + @param[in] MpServices MP_SERVICES structure. + @param[out] ProcessorNumber The handle number for the calling processor. + + @retval EFI_SUCCESS Get the handle number for the calling processo= r successfully. + @retval Others Get the handle number for the calling processo= r unsuccessfully. +**/ +EFI_STATUS +MpServicesUnitTestWhoAmI ( + IN MP_SERVICES MpServices, + OUT UINTN *ProcessorNumber + ) +{ + return MpServices.Ppi->WhoAmI (MpServices.Ppi, ProcessorNumber); +} + +/** + Get EDKII_PEI_MP_SERVICES2_PPI pointer. + + @param[out] MpServices Pointer to the buffer where EDKII_PEI_MP_SERVI= CES2_PPI is stored + + @retval EFI_SUCCESS EDKII_PEI_MP_SERVICES2_PPI interface is return= ed + @retval EFI_NOT_FOUND EDKII_PEI_MP_SERVICES2_PPI interface is not fo= und +**/ +EFI_STATUS +GetMpServices ( + OUT MP_SERVICES *MpServices + ) +{ + return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOI= D **)&MpServices->Ppi); +} + +/** + Entry point of CpuExceptionHandlerPeiTest PEIM. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Describes the list of possible PEI Services. + + @retval EFI_SUCCESS The PEIM executed normally. + +**/ +EFI_STATUS +EFIAPI +PeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework; + + Framework =3D NULL; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSIO= N)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_APP_NAME, gEfiCa= llerBaseName, UNIT_TEST_APP_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n= ", Status)); + goto EXIT; + } + + Status =3D AddCommonTestCase (Framework); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in AddCommonTestCase. Status =3D %r\n", S= tatus)); + goto EXIT; + } + + // + // Execute the tests. + // + Status =3D RunAllTestSuites (Framework); + +EXIT: + if (Framework) { + FreeUnitTestFramework (Framework); + } + + return Status; +} --=20 2.31.1.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#94972): https://edk2.groups.io/g/devel/message/94972 Mute This Topic: https://groups.io/mt/94253442/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-