From nobody Thu May 9 03:28:41 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+94940+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+94940+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1665409973; cv=none; d=zohomail.com; s=zohoarc; b=QV4sc9MT6Qop/wUuPp+6D4i3icYx+4Xgaq2TFwAW8LXEfu+JxwgAf2G7frZlT4zCvMMA1VFrb3oHH79LObALPa1qFaG/hAqjdgEwKEMtXEZP81VhZ5pCx4DJAjwGMlpmXlTrjkfkxaj2AaZHwg2zsJrYxbXQhw8uxkRSft7ibRw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1665409973; h=Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Sender:Subject:To; bh=Rsv75iWVOCuP9YW/lUWuKmfQVBE0TZ4HkfeBYvvwtUs=; b=THX6AVMTb+pcJ9miYmrw0AMnH0wT/li5xIiVIaM3iZxqvwSrYDOKYgbGGOgYN9RCZ/YTEzr7/Rwi8M6rQm2uZeg+E7zCi6laW196jlUEnh21ej3KqHD4lkdxLnT9H0rZTTThmW4fDwYw4hjto9WDFCRMMtsqK+Cj5SpaDxjvWKs= 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+94940+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 1665409973736841.7885189527136; Mon, 10 Oct 2022 06:52:53 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id 1C0zYY1788612x7iaaIAJ37i; Mon, 10 Oct 2022 06:52:52 -0700 X-Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mx.groups.io with SMTP id smtpd.web12.6489.1665409970924307550 for ; Mon, 10 Oct 2022 06:52:51 -0700 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="302967259" X-IronPort-AV: E=Sophos;i="5.95,173,1661842800"; d="scan'208";a="302967259" X-Received: from orsmga006.jf.intel.com ([10.7.209.51]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 10 Oct 2022 06:52:49 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=McAfee;i="6500,9779,10496"; a="603728963" X-IronPort-AV: E=Sophos;i="5.95,173,1661842800"; d="scan'208";a="603728963" X-Received: from shwdeopenlab102.ccr.corp.intel.com ([10.239.56.236]) by orsmga006.jf.intel.com with ESMTP; 10 Oct 2022 06:52:46 -0700 From: "Jason Lou" To: devel@edk2.groups.io Cc: Jason Lou , Ray Ni , Eric Dong , Laszlo Ersek , Rahul Kumar Subject: [edk2-devel] [PATCH v2] UefiCpuPkg/Test: Add unit tests for MP service PPI and Protocol Date: Mon, 10 Oct 2022 21:52:42 +0800 Message-Id: <20221010135242.5587-1-yun.lou@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,yun.lou@intel.com X-Gm-Message-State: mouf4bL8gdOtGRnluwPdKToEx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1665409972; bh=YjKQRyQZq53ZzO1MjCeP6mTuSL/RgYbQqhHigrIrG/A=; h=Cc:Date:From:Reply-To:Subject:To; b=LJ/p7AX8ux0KaPZgsnzwX96zUAKtOKSfuoviZDZ49SQk0Iuxd1hW5//MVJDRSRwDd+K A9eyu0zx7AwZdYNmIlOZOlNRWqEXs8Oex1EzUgkSwpdTTjeOUmmsOY1OMvSx/pdVj9xRI NlltB6Thf+p3c1R4I26Q4IkC0TI3FbuqBhM= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1665409976020100001 Content-Type: text/plain; charset="utf-8" From: Jason Lou The code changes add unit tests based on current UnitTestFramework. EdkiiPeiMpServices2PpiPeiUnitTest PEI module is used to test EdkiiPeiMpServices2Ppi and EfiMpServiceProtocolDxeUnitTest DXE driver is used to test EfiMpServiceProtocol. Signed-off-by: Jason Lou Cc: Ray Ni Cc: Eric Dong Cc: Laszlo Ersek Cc: Rahul Kumar Reviewed-by: Ray Ni --- UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiUn= itTest.c | 477 ++++++ UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolUnit= Test.c | 244 +++ UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCom= mom.c | 1776 ++++++++++++++++++++ UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2PpiPe= iUnitTest.inf | 46 + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDxeU= nitTest.inf | 46 + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTestCom= mom.h | 627 +++++++ UefiCpuPkg/UefiCpuPkg.dsc = | 5 + 7 files changed, 3221 insertions(+) diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpSe= rvices2PpiUnitTest.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/Ed= kiiPeiMpServices2PpiUnitTest.c new file mode 100644 index 0000000000..5c42a81d29 --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2= PpiUnitTest.c @@ -0,0 +1,477 @@ +/** @file + PEI Module to test APIs defined in EdkiiPeiMpServices2Ppi. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include "EfiMpServicesUnitTestCommom.h" + +#define UNIT_TEST_NAME "EdkiiPeiMpServices2Ppi Unit Test" +#define UNIT_TEST_VERSION "0.1" + +/** + 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 +MpServicesUnitTestGetMpServices ( + OUT MP_SERVICES *MpServices + ) +{ + return PeiServicesLocatePpi (&gEdkiiPeiMpServices2PpiGuid, 0, NULL, (VOI= D **)&MpServices->Ppi); +} + +/** + 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); +} + +/** + Get detailed information on the requested logical processor. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the processor. + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processo= r information is stored. + + @retval EFI_SUCCESS Get information on the requested logical proce= ssor successfully + @retval Others Get information on the requested logical proce= ssor unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestGetProcessorInfo ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ) +{ + return MpServices.Ppi->GetProcessorInfo (MpServices.Ppi, ProcessorNumber= , ProcessorInfoBuffer); +} + +/** + 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); +} + +/** + 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); +} + +/** + Switch the requested AP to be the BSP from that point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of AP that is to become th= e new BSP. + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enab= led AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS Switch the requested AP to be the BSP successf= ully + @retval Others Switch the requested AP to be the BSP unsucces= sfully +**/ +EFI_STATUS +MpServicesUnitTestSwitchBSP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ) +{ + return MpServices.Ppi->SwitchBSP (MpServices.Ppi, ProcessorNumber, Enabl= eOldBSP); +} + +/** + Caller enables or disables an AP from this point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] EnableAP Specifies the new state for the processor for = enabled, FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifi= es the new health status of the AP. + + @retval EFI_SUCCESS Caller enables or disables an AP successfully. + @retval Others Caller enables or disables an AP unsuccessfull= y. +**/ +EFI_STATUS +MpServicesUnitTestEnableDisableAP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag + ) +{ + return MpServices.Ppi->EnableDisableAP (MpServices.Ppi, ProcessorNumber,= EnableAP, HealthFlag); +} + +/** + 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); +} + +/** + Execute a caller provided function on all enabled CPUs. + + @param[in] MpServices MP_SERVICES structure. + @param[in] Procedure Pointer to the function to be run on enabled C= PUs of the system. + @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 enabled CPUs. + + @retval EFI_SUCCESS Execute a caller provided function on all enab= led CPUs successfully + @retval Others Execute a caller provided function on all enab= led CPUs unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestStartupAllCPUs ( + IN MP_SERVICES MpServices, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument + ) +{ + return MpServices.Ppi->StartupAllCPUs (MpServices.Ppi, Procedure, Timeou= tInMicroSeconds, ProcedureArgument); +} + +/** + Infinite loop procedure to be run on specified AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +ApInfiniteLoopProcedure ( + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + volatile BOOLEAN InfiniteLoop; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + Status =3D MpServicesUnitTestWhoAmI (LocalContext->MpServices, &Processo= rNumber); + ASSERT_EFI_ERROR (Status); + + if (ProcessorNumber =3D=3D LocalContext->BspNumber) { + InfiniteLoop =3D FALSE; + } else { + InfiniteLoop =3D TRUE; + } + + while (InfiniteLoop) { + } +} + +/** + Procedure to run MP service StartupAllCPUs on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceStartupAllCPUsOnAp ( + IN OUT VOID *Buffer + ) +{ + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestStartupAllCP= Us ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedu= re, + 0, + NULL + ); +} + +/** + Unit test of PEI MP service StartupAllCPU. + All CPUs should execute the Procedure. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllCPUs1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * s= izeof (*LocalContext->CommonBuffer), 0xFF); + Status =3D MpServicesUnitTestStartupAllCPUs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreCpuNumbers, + 0, + (VOID *)LocalContext + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfProces= sors; ProcessorIndex++) { + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] =3D=3D Proc= essorIndex); + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of PEI MP service StartupAllCPU. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllCPUs2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceStartupAllCPU= sOnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of PEI MP service StartupAllCPU. + When called with all CPUs timeout, the return status should be EFI_TIMEO= UT. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllCPUs3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + Status =3D MpServicesUnitTestStartupAllCPUs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)ApInfiniteLoopProcedure, + RUN_PROCEDURE_TIMEOUT_VALUE, + (VOID *)LocalContext + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); + + return UNIT_TEST_PASSED; +} + +/** + Create test suite and unit tests only for EdkiiPeiMpServices2Ppi. + + @param[in] Framework A pointer to the framework that is being persi= sted. + @param[in] Context A pointer to the private data buffer. + + @retval EFI_SUCCESS Create test suite and unit tests successfully. + @retval Others Create test suite and unit tests unsuccessfull= y. +**/ +EFI_STATUS +AddTestCaseOnlyForEdkiiPeiMpServices2Ppi ( + IN UNIT_TEST_FRAMEWORK_HANDLE Framework, + IN MP_SERVICE_UT_CONTEXT *Context + ) +{ + EFI_STATUS Status; + UNIT_TEST_SUITE_HANDLE MpServiceStartupAllCPUsTestSuite; + + MpServiceStartupAllCPUsTestSuite =3D NULL; + + // + // Test StartupAllCPUs function + // + Status =3D CreateUnitTestSuite (&MpServiceStartupAllCPUsTestSuite, Frame= work, "Execute a caller provided function on all enabled CPUs", "MpServices= .StartupAllCPUs", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStart= upAllCPUs Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 1", = "TestStartupAllCPUs1", TestStartupAllCPUs1, InitUTContext, CheckUTContext, = Context); + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 2", = "TestStartupAllCPUs2", TestStartupAllCPUs2, InitUTContext, CheckUTContext, = Context); + AddTestCase (MpServiceStartupAllCPUsTestSuite, "Test StartupAllCPUs 3", = "TestStartupAllCPUs3", TestStartupAllCPUs3, InitUTContext, CheckUTContext, = Context); + + return EFI_SUCCESS; +} + +/** + Standard PEIM entry point for unit test execution from PEI. + Initialize the unit test framework, suite, and unit tests for the EdkiiP= eiMpServices2Ppi and run the unit test. + + @param[in] FileHandle Handle of the file being invoked. + @param[in] PeiServices Pointer to PEI Services table. + +**/ +EFI_STATUS +EFIAPI +PeiEntryPoint ( + IN EFI_PEI_FILE_HANDLE FileHandle, + IN CONST EFI_PEI_SERVICES **PeiServices + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework; + MP_SERVICE_UT_CONTEXT Context; + + Framework =3D NULL; + Context.MpServices.Ppi =3D NULL; + Context.CommonBuffer =3D NULL; + Context.DisabledApNumber =3D NULL; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCaller= BaseName, UNIT_TEST_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n= ", Status)); + goto EXIT; + } + + // + // Create test suite and unit tests only for EdkiiPeiMpServices2Ppi. + // + Status =3D AddTestCaseOnlyForEdkiiPeiMpServices2Ppi (Framework, &Context= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in AddTestCaseOnlyForEdkiiPeiMpServices2P= pi. Status =3D %r\n", Status)); + goto EXIT; + } + + // + // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and = EfiMpServiceProtocol. + // + Status =3D AddCommonTestCase (Framework, &Context); + 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 !=3D NULL) { + FreeUnitTestFramework (Framework); + } + + return Status; +} diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpService= ProtocolUnitTest.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiM= pServiceProtocolUnitTest.c new file mode 100644 index 0000000000..57f8ba3c06 --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtoco= lUnitTest.c @@ -0,0 +1,244 @@ +/** @file + PEI Module to test EfiMpServiceProtocol. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include "EfiMpServicesUnitTestCommom.h" + +#define UNIT_TEST_NAME "EfiMpServiceProtocol Unit Test" +#define UNIT_TEST_VERSION "0.1" + +/** + 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 +MpServicesUnitTestGetMpServices ( + OUT MP_SERVICES *MpServices + ) +{ + return gBS->LocateProtocol (&gEfiMpServiceProtocolGuid, NULL, (VOID **)&= MpServices->Protocol); +} + +/** + 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 detailed information on the requested logical processor. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the processor. + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processo= r information is stored. + + @retval EFI_SUCCESS Get information on the requested logical proce= ssor successfully + @retval Others Get information on the requested logical proce= ssor unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestGetProcessorInfo ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ) +{ + return MpServices.Protocol->GetProcessorInfo (MpServices.Protocol, Proce= ssorNumber, ProcessorInfoBuffer); +} + +/** + 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); +} + +/** + 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); +} + +/** + Switch the requested AP to be the BSP from that point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of AP that is to become th= e new BSP. + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enab= led AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS Switch the requested AP to be the BSP successf= ully + @retval Others Switch the requested AP to be the BSP unsucces= sfully +**/ +EFI_STATUS +MpServicesUnitTestSwitchBSP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ) +{ + return MpServices.Protocol->SwitchBSP (MpServices.Protocol, ProcessorNum= ber, EnableOldBSP); +} + +/** + Caller enables or disables an AP from this point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] EnableAP Specifies the new state for the processor for = enabled, FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifi= es the new health status of the AP. + + @retval EFI_SUCCESS Caller enables or disables an AP successfully. + @retval Others Caller enables or disables an AP unsuccessfull= y. +**/ +EFI_STATUS +MpServicesUnitTestEnableDisableAP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag + ) +{ + return MpServices.Protocol->EnableDisableAP (MpServices.Protocol, Proces= sorNumber, EnableAP, HealthFlag); +} + +/** + 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= ); +} + +/** + Standard DXE driver or UEFI application entry point for unit test execut= ion from DXE or UEFI Shell. + Initialize the unit test framework, suite, and unit tests for the EfiMpS= erviceProtocol and run the unit test. + + @param[in] ImageHandle The firmware allocated handle for the EFI ima= ge. + @param[in] SystemTable A pointer to the EFI System Table. + +**/ +EFI_STATUS +EFIAPI +DxeEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + EFI_STATUS Status; + UNIT_TEST_FRAMEWORK_HANDLE Framework; + MP_SERVICE_UT_CONTEXT Context; + + Framework =3D NULL; + Context.MpServices.Ppi =3D NULL; + Context.CommonBuffer =3D NULL; + Context.DisabledApNumber =3D NULL; + + DEBUG ((DEBUG_INFO, "%a v%a\n", UNIT_TEST_NAME, UNIT_TEST_VERSION)); + + // + // Start setting up the test framework for running the tests. + // + Status =3D InitUnitTestFramework (&Framework, UNIT_TEST_NAME, gEfiCaller= BaseName, UNIT_TEST_VERSION); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in InitUnitTestFramework. Status =3D %r\n= ", Status)); + goto EXIT; + } + + // + // Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and = EfiMpServiceProtocol. + // + Status =3D AddCommonTestCase (Framework, &Context); + 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 !=3D NULL) { + FreeUnitTestFramework (Framework); + } + + return Status; +} diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpService= sUnitTestCommom.c b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMp= ServicesUnitTestCommom.c new file mode 100644 index 0000000000..ff79c5e8d4 --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTe= stCommom.c @@ -0,0 +1,1776 @@ +/** @file + Common code to test EdkiiPeiMpServices2Ppi and EfiMpServiceProtocol. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "EfiMpServicesUnitTestCommom.h" + +/** + Prep routine for Unit test function. + To save the ProcessorNumber of disabled AP and temporarily enable it. + + @param[in] Context Context pointer for this test. + + @retval UNIT_TEST_PASSED Prep routine runs successful. + @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful. +**/ +UNIT_TEST_STATUS +EFIAPI +InitUTContext ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + UINTN NumberOfDisabledAPs; + UINTN IndexOfDisabledAPs; + UINTN BspNumber; + UINTN ProcessorNumber; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + if (LocalContext->MpServices.Ppi !=3D NULL) { + return UNIT_TEST_PASSED; + } + + Status =3D MpServicesUnitTestGetMpServices (&LocalContext->MpServices); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumbe= r); + UT_ASSERT_NOT_EFI_ERROR (Status); + DEBUG ((DEBUG_INFO, "%a: BspNumber =3D 0x%x\n", __FUNCTION__, BspNumber)= ); + + Status =3D MpServicesUnitTestGetNumberOfProcessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + DEBUG (( + DEBUG_INFO, + "%a: NumberOfProcessors =3D 0x%x, NumberOfEnabledProcessors =3D 0x%x\n= ", + __FUNCTION__, + NumberOfProcessors, + NumberOfEnabledProcessors + )); + + LocalContext->BspNumber =3D BspNumber; + LocalContext->NumberOfProcessors =3D NumberOfProcessors; + LocalContext->NumberOfEnabledProcessors =3D NumberOfEnabledProcessors; + + LocalContext->CommonBuffer =3D AllocatePages (EFI_SIZE_TO_PAGES (NumberO= fProcessors * sizeof (*LocalContext->CommonBuffer))); + UT_ASSERT_NOT_NULL (LocalContext->CommonBuffer); + + NumberOfDisabledAPs =3D NumberOfProcessors - NumberOfEnabledProcessors; + if ((NumberOfDisabledAPs > 0) && (LocalContext->DisabledApNumber =3D=3D = NULL)) { + LocalContext->DisabledApNumber =3D AllocatePages (EFI_SIZE_TO_PAGES (N= umberOfDisabledAPs * sizeof (*LocalContext->DisabledApNumber))); + UT_ASSERT_NOT_NULL (LocalContext->DisabledApNumber); + ZeroMem (LocalContext->DisabledApNumber, NumberOfDisabledAPs * sizeof = (*LocalContext->DisabledApNumber)); + + for (ProcessorNumber =3D 0, IndexOfDisabledAPs =3D 0; ProcessorNumber = < LocalContext->NumberOfProcessors; ProcessorNumber++) { + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + ProcessorNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) { + // + // Save ProcessorNumber of disabled AP. + // + LocalContext->DisabledApNumber[IndexOfDisabledAPs] =3D ProcessorNu= mber; + IndexOfDisabledAPs++; + + DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled and temporarily enab= le it.\n", __FUNCTION__, ProcessorNumber)); + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ProcessorNumber, + TRUE, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + UT_ASSERT_TRUE (IndexOfDisabledAPs =3D=3D NumberOfDisabledAPs); + } + + return UNIT_TEST_PASSED; +} + +/** + Cleanup routine for Unit test function. + If any processor is disabled unexpectedly then reenable it. + + @param[in] Context Context pointer for this test. +**/ +VOID +EFIAPI +CheckUTContext ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + UINTN BspNumber; + UINTN ProcessorNumber; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + ASSERT (LocalContext->MpServices.Ppi !=3D NULL); + + Status =3D MpServicesUnitTestWhoAmI (LocalContext->MpServices, &BspNumbe= r); + ASSERT_EFI_ERROR (Status); + + if (BspNumber !=3D LocalContext->BspNumber) { + LocalContext->BspNumber =3D BspNumber; + DEBUG ((DEBUG_INFO, "%a: New BspNumber =3D 0x%x\n", __FUNCTION__, BspN= umber)); + } + + ASSERT (BspNumber =3D=3D LocalContext->BspNumber); + + Status =3D MpServicesUnitTestGetNumberOfProcessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + ASSERT_EFI_ERROR (Status); + + if (NumberOfProcessors !=3D LocalContext->NumberOfProcessors) { + LocalContext->NumberOfProcessors =3D NumberOfProcessors; + DEBUG ((DEBUG_INFO, "%a: New NumberOfProcessors =3D 0x%x\n", __FUNCTIO= N__, NumberOfProcessors)); + } + + if (NumberOfEnabledProcessors !=3D LocalContext->NumberOfProcessors) { + DEBUG ((DEBUG_INFO, "%a: New NumberOfEnabledProcessors =3D 0x%x\n", __= FUNCTION__, NumberOfEnabledProcessors)); + + for (ProcessorNumber =3D 0; ProcessorNumber < LocalContext->NumberOfPr= ocessors; ProcessorNumber++) { + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + ProcessorNumber, + &ProcessorInfoBuffer + ); + ASSERT_EFI_ERROR (Status); + + if (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)) { + DEBUG ((DEBUG_INFO, "%a: AP(0x%x) is disabled unexpectedly and ree= nable it.\n", __FUNCTION__, ProcessorNumber)); + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ProcessorNumber, + TRUE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + } + } +} + +/** + Cleanup routine for Unit test function. + It will be called by the last "AddTestCase" to restore AP state and free= pointer. + + @param[in] Context Context pointer for this test. +**/ +VOID +EFIAPI +FreeUTContext ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NumberOfDisabledAPs; + UINTN IndexOfDisabledAPs; + MP_SERVICE_UT_CONTEXT *LocalContext; + + CheckUTContext (Context); + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + ASSERT (LocalContext->MpServices.Ppi !=3D NULL); + + if (LocalContext->DisabledApNumber !=3D NULL) { + NumberOfDisabledAPs =3D LocalContext->NumberOfProcessors - LocalContex= t->NumberOfEnabledProcessors; + for (IndexOfDisabledAPs =3D 0; IndexOfDisabledAPs < NumberOfDisabledAP= s; IndexOfDisabledAPs++) { + DEBUG (( + DEBUG_INFO, + "%a: Disable AP(0x%x) to restore its state.\n", + __FUNCTION__, + LocalContext->DisabledApNumber[IndexOfDisabledAPs] + )); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + LocalContext->DisabledApNumber[IndexOfDisabledAPs], + FALSE, + NULL + ); + ASSERT_EFI_ERROR (Status); + } + + FreePages (LocalContext->DisabledApNumber, EFI_SIZE_TO_PAGES (NumberOf= DisabledAPs * sizeof (*LocalContext->DisabledApNumber))); + } + + if (LocalContext->CommonBuffer !=3D NULL) { + FreePages (LocalContext->CommonBuffer, EFI_SIZE_TO_PAGES (LocalContext= ->NumberOfProcessors * sizeof (*LocalContext->CommonBuffer))); + } +} + +/** + Produce to store ProcessorNumber in the corresponding location of Common= Buffer. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +StoreCpuNumbers ( + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + Status =3D MpServicesUnitTestWhoAmI (LocalContext->MpServices, &Processo= rNumber); + ASSERT_EFI_ERROR (Status); + + // + // The layout of CommonBuffer (E.g. BspNumber =3D 2 and NumberOfProcesso= rs =3D 6) + // Index 00 01 02 03 04 05 + // Value 00 01 02 03 04 05 + // + if (ProcessorNumber < LocalContext->NumberOfProcessors) { + LocalContext->CommonBuffer[ProcessorNumber] =3D ProcessorNumber; + } +} + +/** + Produce to store the ProcessorNumber of AP execution order in CommonBuff= er. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +StoreAPsExecutionOrder ( + IN OUT VOID *Buffer + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + UINTN *ApCounter; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + Status =3D MpServicesUnitTestWhoAmI (LocalContext->MpServices, &Processo= rNumber); + ASSERT_EFI_ERROR (Status); + + // + // The layout of CommonBuffer (E.g. BspNumber =3D 2 and NumberOfProcesso= rs =3D 6) + // Index 00 01 02 03 04 05 + // Value 00 01 03 04 05 ApCounter(5) + // + ApCounter =3D &(LocalContext->CommonBuffer[= LocalContext->NumberOfProcessors - 1]); + LocalContext->CommonBuffer[*ApCounter] =3D ProcessorNumber; + (*ApCounter)++; +} + +/** + Infinite loop procedure to be run on specified CPU. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +InfiniteLoopProcedure ( + IN OUT VOID *Buffer + ) +{ + volatile BOOLEAN InfiniteLoop; + + InfiniteLoop =3D TRUE; + + while (InfiniteLoop) { + } +} + +/** + Empty procedure to be run on specified CPU. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +EmptyProcedure ( + IN OUT VOID *Buffer + ) +{ +} + +/** + Procedure to run MP service GetNumberOfProcessors on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceGetNumberOfProcessorsOnAp ( + IN OUT VOID *Buffer + ) +{ + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestGetNumberOfP= rocessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); +} + +/** + Procedure to run MP service GetProcessorInfo on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceGetProcessorInfoOnAp ( + IN OUT VOID *Buffer + ) +{ + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestGetProcessor= Info ( + LocalContext->MpServices, + LocalContext->ApNumber, + &ProcessorInfoBuffer + ); +} + +/** + Procedure to run MP service EnableDisableAP on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceEnableDisableAPOnAp ( + IN OUT VOID *Buffer + ) +{ + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestEnableDisabl= eAP ( + LocalContext->MpServices, + LocalContext->ApNumber, + FALSE, + NULL + ); +} + +/** + Procedure to run MP service StartupThisAP on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceStartupThisAPOnAp ( + IN OUT VOID *Buffer + ) +{ + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestStartupThisA= P ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedu= re, + LocalContext->ApNumber, + 0, + NULL + ); +} + +/** + Procedure to run MP service StartupAllAPs on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceStartupAllAPsOnAp ( + IN OUT VOID *Buffer + ) +{ + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestStartupAllAP= s ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedu= re, + FALSE, + 0, + NULL + ); +} + +/** + Procedure to run MP service SwitchBSP on AP. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +RunMpServiceSwitchBSPOnAp ( + IN OUT VOID *Buffer + ) +{ + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Buffer; + + LocalContext->ApProcedureReturnStatus =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + LocalContext->ApNumber, + TRUE + ); +} + +/** + Unit test of MP service WhoAmI. + The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1. + The ProcessorNumbers of all CPUs are unique. + + @param[in] Context Context pointer for this test. + + @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 +TestWhoAmI1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + Status =3D MpServicesUnitTestWhoAmI ( + LocalContext->MpServices, + &ProcessorNumber + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE (ProcessorNumber < LocalContext->NumberOfProcessors); + + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * s= izeof (*LocalContext->CommonBuffer), 0xFF); + LocalContext->CommonBuffer[ProcessorNumber] =3D ProcessorNumber; + + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreCpuNumbers, + FALSE, + 0, + (VOID *)LocalContext + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // The layout of CommonBuffer (E.g. BspNumber =3D 2 and NumberOfProcesso= rs =3D 6) + // Index 00 01 02 03 04 05 + // Value 00 01 02 03 04 05 + // + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfProces= sors; ProcessorIndex++) { + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] =3D=3D Proc= essorIndex); + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service GetNumberOfProcessors. + NumberOfProcessors should be greater that 0 and not less than NumberOfEn= abledProcessors. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + Status =3D MpServicesUnitTestGetNumberOfProcessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE (NumberOfProcessors > 0 && NumberOfProcessors >=3D Number= OfEnabledProcessors); + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service GetNumberOfProcessors. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceGetNumberOfPr= ocessorsOnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service GetNumberOfProcessors. + Call EnableDisableAP() to change the number of enabled AP. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + FALSE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestGetNumberOfProcessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE (NumberOfProcessors =3D=3D LocalContext->NumberOfProc= essors); + + if (ApNumber < LocalContext->BspNumber) { + UT_ASSERT_TRUE (NumberOfEnabledProcessors =3D=3D LocalContext->Num= berOfProcessors - (ApNumber + 1)); + } else { + UT_ASSERT_TRUE (NumberOfEnabledProcessors =3D=3D LocalContext->Num= berOfProcessors - ApNumber); + } + } + } + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestGetNumberOfProcessors ( + LocalContext->MpServices, + &NumberOfProcessors, + &NumberOfEnabledProcessors + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE (NumberOfProcessors =3D=3D LocalContext->NumberOfProc= essors); + + if (ApNumber < LocalContext->BspNumber) { + UT_ASSERT_TRUE (NumberOfEnabledProcessors =3D=3D ApNumber + 2); + } else { + UT_ASSERT_TRUE (NumberOfEnabledProcessors =3D=3D ApNumber + 1); + } + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service GetProcessorInfo. + When all the parameters are valid, all reserved bits of StatusFlag in Pr= ocessorInfoBuffer should be set to zero. + When all the parameters are valid, the StatusFlag should not have an inv= alid value (The BSP can never be in the disabled state.). + When called with nonexistent processor handle, the return status should = be EFI_NOT_FOUND. + + @param[in] Context Context pointer for this test. + + @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 +TestGetProcessorInfo1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ProcessorNumber; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ProcessorNumber =3D 0; ProcessorNumber <=3D LocalContext->NumberOfP= rocessors; ProcessorNumber++) { + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + ProcessorNumber, + &ProcessorInfoBuffer + ); + + if (ProcessorNumber =3D=3D LocalContext->NumberOfProcessors) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & (UINT32) ~(PROCESS= OR_AS_BSP_BIT|PROCESSOR_ENABLED_BIT|PROCESSOR_HEALTH_STATUS_BIT)) =3D=3D 0); + + if (ProcessorNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP= _BIT) && (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT)); + } else { + UT_ASSERT_TRUE (!(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BS= P_BIT)); + } + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service GetProcessorInfo. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestGetProcessorInfo2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceGetProcessorI= nfoOnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service EnableDisableAP. + When called with BSP number, the return status should be EFI_INVALID_PAR= AMETER. + When called with a nonexistent processor handle, the return status shoul= d be EFI_NOT_FOUND. + The AP should be really Enable/Disabled. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber <=3D LocalContext->NumberOfProcessors; ApN= umber++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + FALSE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else if (ApNumber =3D=3D LocalContext->NumberOfProcessors) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedure, + ApNumber, + 0, + NULL + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedure, + ApNumber, + 0, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service EnableDisableAP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceEnableDisable= APOnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service EnableDisableAP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + UINT32 OldHealthFlag; + UINT32 NewHealthFlag; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + ApNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + OldHealthFlag =3D ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_ST= ATUS_BIT; + NewHealthFlag =3D OldHealthFlag ^ PROCESSOR_HEALTH_STATUS_BIT; + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + &NewHealthFlag + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + ApNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ((ProcessorInfoBuffer.StatusFlag & PROCESSOR_HEALTH_S= TATUS_BIT) =3D=3D NewHealthFlag); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + &OldHealthFlag + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupThisAP. + When called to startup a BSP, the return status should be EFI_INVALID_PA= RAMETER. + When called with a nonexistent processor handle, the return status shoul= d be EFI_NOT_FOUND. + The requested AP should execute the Procedure when called by StartupThis= AP. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber <=3D LocalContext->NumberOfProcessors; ApN= umber++) { + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors *= sizeof (*LocalContext->CommonBuffer), 0xFF); + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreCpuNumbers, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else if (ApNumber =3D=3D LocalContext->NumberOfProcessors) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfPr= ocessors; ProcessorIndex++) { + UT_ASSERT_TRUE ( + ((ProcessorIndex =3D=3D ApNumber) && (LocalContext->CommonBuffer= [ProcessorIndex] =3D=3D ProcessorIndex)) || + ((ProcessorIndex !=3D ApNumber) && (LocalContext->CommonBuffer[P= rocessorIndex] =3D=3D (UINTN) ~0)) + ); + } + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupThisAP. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceStartupThisAP= OnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupThisAP. + When timeout expired before the requested AP has finished, the return st= atus should be EFI_TIMEOUT. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)InfiniteLoopProcedure, + ApNumber, + RUN_PROCEDURE_TIMEOUT_VALUE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupThisAP. + When called with disabled AP, the return status should be EFI_INVALID_PA= RAMETER. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP4 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + FALSE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedure, + ApNumber, + 0, + NULL + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedure, + ApNumber, + 0, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupAllAPs. + All APs should execute the Procedure when called by StartupAllAPs. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * s= izeof (*LocalContext->CommonBuffer), 0xFF); + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreCpuNumbers, + FALSE, + 0, + (VOID *)LocalContext + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfProces= sors; ProcessorIndex++) { + UT_ASSERT_TRUE ( + ((ProcessorIndex =3D=3D LocalContext->BspNumber) && (LocalContext->C= ommonBuffer[ProcessorIndex] =3D=3D (UINTN) ~0)) || + ((ProcessorIndex !=3D LocalContext->BspNumber) && (LocalContext->Com= monBuffer[ProcessorIndex] =3D=3D ProcessorIndex)) + ); + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupAllAPs. + When called in single thread, the return status should be EFI_SUCCESS an= d AP executes in ascending order + of processor handle number. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + ZeroMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors * = sizeof (*LocalContext->CommonBuffer)); + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreAPsExecutionOrder, + TRUE, + 0, + (VOID *)LocalContext + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + // + // The layout of CommonBuffer (E.g. BspNumber =3D 2 and NumberOfProcesso= rs =3D 6) + // Index 00 01 02 03 04 05 + // Value 00 01 03 04 05 ApCounter(5) + // + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfProces= sors - 2; ProcessorIndex++) { + UT_ASSERT_TRUE (LocalContext->CommonBuffer[ProcessorIndex] < LocalCont= ext->CommonBuffer[ProcessorIndex + 1]); + } + + UT_ASSERT_EQUAL (LocalContext->CommonBuffer[LocalContext->NumberOfProces= sors - 1], LocalContext->NumberOfProcessors - 1); + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupAllAPs. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceStartupAllAPs= OnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupAllAPs. + When called with all AP timeout, the return status should be EFI_TIMEOUT. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs4 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)InfiniteLoopProcedure, + TRUE, + RUN_PROCEDURE_TIMEOUT_VALUE, + NULL + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); + + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)InfiniteLoopProcedure, + FALSE, + RUN_PROCEDURE_TIMEOUT_VALUE, + NULL + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_TIMEOUT); + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service StartupAllAPs. + When called with the empty Procedure on all disabled APs, the return sta= tus should be EFI_NOT_STARTED. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs5 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + FALSE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)EmptyProcedure, + FALSE, + 0, + NULL + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_STARTED); + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + ApNumber, + TRUE, + NULL + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service SwitchBSP. + When switch current BSP to be BSP, the return status should be EFI_INVAL= ID_PARAMETER. + When switch nonexistent processor to be BSP, the return status should be= EFI_NOT_FOUND. + After switch BSP, all APs(includes new AP) should execute the Procedure = when called by StartupAllAP. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP1 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NewBspNumber; + UINTN ProcessorIndex; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (NewBspNumber =3D 0; NewBspNumber <=3D LocalContext->NumberOfProcess= ors; NewBspNumber++) { + Status =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + NewBspNumber, + TRUE + ); + + if (NewBspNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else if (NewBspNumber =3D=3D LocalContext->NumberOfProcessors) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_NOT_FOUND); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + SetMem (LocalContext->CommonBuffer, LocalContext->NumberOfProcessors= * sizeof (*LocalContext->CommonBuffer), 0xFF); + Status =3D MpServicesUnitTestStartupAllAPs ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)StoreCpuNumbers, + FALSE, + 0, + (VOID *)LocalContext + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + for (ProcessorIndex =3D 0; ProcessorIndex < LocalContext->NumberOfPr= ocessors; ProcessorIndex++) { + UT_ASSERT_TRUE ( + ((ProcessorIndex =3D=3D NewBspNumber) && (LocalContext->CommonBu= ffer[ProcessorIndex] =3D=3D (UINTN) ~0)) || + ((ProcessorIndex !=3D NewBspNumber) && (LocalContext->CommonBuff= er[ProcessorIndex] =3D=3D ProcessorIndex)) + ); + } + + Status =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + LocalContext->BspNumber, + TRUE + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service SwitchBSP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP2 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN ApNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (ApNumber =3D 0; ApNumber < LocalContext->NumberOfProcessors; ApNumb= er++) { + LocalContext->ApNumber =3D ApNumber; + Status =3D MpServicesUnitTestStartupThisAP ( + LocalContext->MpServices, + (EFI_AP_PROCEDURE)RunMpServiceSwitchBSPOnAp, + ApNumber, + 0, + (VOID *)LocalContext + ); + + if (ApNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_STATUS_EQUAL (LocalContext->ApProcedureReturnStatus, EFI_D= EVICE_ERROR); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service SwitchBSP. + When switch a disabled AP to be BSP, the return status should be EFI_INV= ALID_PARAMETER. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP3 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NewBspNumber; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (NewBspNumber =3D 0; NewBspNumber < LocalContext->NumberOfProcessors= ; NewBspNumber++) { + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + NewBspNumber, + FALSE, + NULL + ); + + if (NewBspNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + NewBspNumber, + TRUE + ); + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + NewBspNumber, + TRUE, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Unit test of MP service SwitchBSP. + When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the en= abled state and the old BSP should + be in the enabled state. + When SwitchBSP and EnableOldBSP is False, the new BSP should be in the e= nabled state and the old BSP should + be in the disabled state. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP4 ( + IN UNIT_TEST_CONTEXT Context + ) +{ + EFI_STATUS Status; + UINTN NewBspNumber; + EFI_PROCESSOR_INFORMATION ProcessorInfoBuffer; + MP_SERVICE_UT_CONTEXT *LocalContext; + + LocalContext =3D (MP_SERVICE_UT_CONTEXT *)Context; + + for (NewBspNumber =3D 0; NewBspNumber < LocalContext->NumberOfProcessors= ; NewBspNumber++) { + Status =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + NewBspNumber, + FALSE + ); + + if (NewBspNumber =3D=3D LocalContext->BspNumber) { + UT_ASSERT_STATUS_EQUAL (Status, EFI_INVALID_PARAMETER); + } else { + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + NewBspNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ( + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) + ); + + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + LocalContext->BspNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ( + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) + ); + + Status =3D MpServicesUnitTestEnableDisableAP ( + LocalContext->MpServices, + LocalContext->BspNumber, + TRUE, + NULL + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestSwitchBSP ( + LocalContext->MpServices, + LocalContext->BspNumber, + TRUE + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + LocalContext->BspNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ( + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) + ); + + Status =3D MpServicesUnitTestGetProcessorInfo ( + LocalContext->MpServices, + NewBspNumber, + &ProcessorInfoBuffer + ); + UT_ASSERT_NOT_EFI_ERROR (Status); + UT_ASSERT_TRUE ( + !(ProcessorInfoBuffer.StatusFlag & PROCESSOR_AS_BSP_BIT) && + (ProcessorInfoBuffer.StatusFlag & PROCESSOR_ENABLED_BIT) + ); + } + } + + return UNIT_TEST_PASSED; +} + +/** + Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and Efi= MpServiceProtocol. + + @param[in] Framework A pointer to the framework that is being persi= sted. + @param[in] Context A pointer to the private data buffer. + + @retval EFI_SUCCESS Create test suite and unit tests successfully. + @retval Others Create test suite and unit tests unsuccessfull= y. +**/ +EFI_STATUS +AddCommonTestCase ( + IN UNIT_TEST_FRAMEWORK_HANDLE Framework, + IN MP_SERVICE_UT_CONTEXT *Context + ) +{ + EFI_STATUS Status; + UNIT_TEST_SUITE_HANDLE MpServiceWhoAmITestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceGetNumberOfProcessorsTestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceGetProcessorInfoTestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceEnableDisableAPTestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceStartupThisAPTestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceStartupAllAPsTestSuite; + UNIT_TEST_SUITE_HANDLE MpServiceSwitchBSPTestSuite; + + MpServiceWhoAmITestSuite =3D NULL; + MpServiceGetNumberOfProcessorsTestSuite =3D NULL; + MpServiceGetProcessorInfoTestSuite =3D NULL; + MpServiceEnableDisableAPTestSuite =3D NULL; + MpServiceStartupThisAPTestSuite =3D NULL; + MpServiceStartupAllAPsTestSuite =3D NULL; + MpServiceSwitchBSPTestSuite =3D NULL; + + // + // Test WhoAmI function + // + Status =3D CreateUnitTestSuite (&MpServiceWhoAmITestSuite, Framework, "I= dentify the currently executing processor", "MpServices.WhoAmI", NULL, NULL= ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceWhoAm= I Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceWhoAmITestSuite, "Test WhoAmI 1", "TestWhoAmI1", T= estWhoAmI1, InitUTContext, CheckUTContext, Context); + + // + // Test GetNumberOfProcessors function + // + Status =3D CreateUnitTestSuite (&MpServiceGetNumberOfProcessorsTestSuite= , Framework, "Retrieve the number of logical processor", "MpServices.GetNum= berOfProcessors", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetNu= mberOfProcessors Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfP= rocessors 1", "TestGetNumberOfProcessors1", TestGetNumberOfProcessors1, Ini= tUTContext, CheckUTContext, Context); + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfP= rocessors 2", "TestGetNumberOfProcessors2", TestGetNumberOfProcessors2, Ini= tUTContext, CheckUTContext, Context); + AddTestCase (MpServiceGetNumberOfProcessorsTestSuite, "Test GetNumberOfP= rocessors 3", "TestGetNumberOfProcessors3", TestGetNumberOfProcessors3, Ini= tUTContext, CheckUTContext, Context); + + // + // Test GetProcessorInfo function + // + Status =3D CreateUnitTestSuite (&MpServiceGetProcessorInfoTestSuite, Fra= mework, "Get detailed information on the requested logical processor", "MpS= ervices.GetProcessorInfo", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceGetPr= ocessorInfo Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo = 1", "TestGetProcessorInfo1", TestGetProcessorInfo1, InitUTContext, CheckUTC= ontext, Context); + AddTestCase (MpServiceGetProcessorInfoTestSuite, "Test GetProcessorInfo = 2", "TestGetProcessorInfo2", TestGetProcessorInfo2, InitUTContext, CheckUTC= ontext, Context); + + // + // Test EnableDisableAP function + // + Status =3D CreateUnitTestSuite (&MpServiceEnableDisableAPTestSuite, Fram= ework, "Caller enables or disables an AP from this point onward", "MpServic= es.EnableDisableAP", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceEnabl= eDisableAP Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 1"= , "TestEnableDisableAP1", TestEnableDisableAP1, InitUTContext, CheckUTConte= xt, Context); + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 2"= , "TestEnableDisableAP2", TestEnableDisableAP2, InitUTContext, CheckUTConte= xt, Context); + AddTestCase (MpServiceEnableDisableAPTestSuite, "Test EnableDisableAP 3"= , "TestEnableDisableAP3", TestEnableDisableAP3, InitUTContext, CheckUTConte= xt, Context); + + // + // Test StartupThisAP function + // + Status =3D CreateUnitTestSuite (&MpServiceStartupThisAPTestSuite, Framew= ork, "Get the requested AP to execute a caller-provided function", "MpServi= ces.StartupThisAP", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStart= upThisAP Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 1", "T= estStartupThisAP1", TestStartupThisAP1, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 2", "T= estStartupThisAP2", TestStartupThisAP2, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 3", "T= estStartupThisAP3", TestStartupThisAP3, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupThisAPTestSuite, "Test StartupThisAP 4", "T= estStartupThisAP4", TestStartupThisAP4, InitUTContext, CheckUTContext, Cont= ext); + + // + // Test StartupAllAPs function + // + Status =3D CreateUnitTestSuite (&MpServiceStartupAllAPsTestSuite, Framew= ork, "Execute a caller provided function on all enabled APs", "MpServices.S= tartupAllAPs", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceStart= upAllAPs Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 1", "T= estStartupAllAPs1", TestStartupAllAPs1, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 2", "T= estStartupAllAPs2", TestStartupAllAPs2, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 3", "T= estStartupAllAPs3", TestStartupAllAPs3, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 4", "T= estStartupAllAPs4", TestStartupAllAPs4, InitUTContext, CheckUTContext, Cont= ext); + AddTestCase (MpServiceStartupAllAPsTestSuite, "Test StartupAllAPs 5", "T= estStartupAllAPs5", TestStartupAllAPs5, InitUTContext, CheckUTContext, Cont= ext); + + // + // Test SwitchBSP function + // + Status =3D CreateUnitTestSuite (&MpServiceSwitchBSPTestSuite, Framework,= "Switch the requested AP to be the BSP from that point onward", "MpService= s.SwitchBSP", NULL, NULL); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Failed in CreateUnitTestSuite for MpServiceSwitc= hBSP Test Suite\n")); + return Status; + } + + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 1", "TestSwitc= hBSP1", TestSwitchBSP1, InitUTContext, CheckUTContext, Context); + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 2", "TestSwitc= hBSP2", TestSwitchBSP2, InitUTContext, CheckUTContext, Context); + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 3", "TestSwitc= hBSP3", TestSwitchBSP3, InitUTContext, CheckUTContext, Context); + AddTestCase (MpServiceSwitchBSPTestSuite, "Test SwitchBSP 4", "TestSwitc= hBSP4", TestSwitchBSP4, InitUTContext, FreeUTContext, Context); + + return EFI_SUCCESS; +} diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpSe= rvices2PpiPeiUnitTest.inf b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtoc= ol/EdkiiPeiMpServices2PpiPeiUnitTest.inf new file mode 100644 index 0000000000..0b2ddc5585 --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2= PpiPeiUnitTest.inf @@ -0,0 +1,46 @@ +## @file +# PEIM that unit tests the EdkiiPeiMpServices2Ppi +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D EdkiiPeiMpServices2PpiPeiUnitTest + FILE_GUID =3D A4914810-4D1E-445E-BD6F-F6821B852B5D + 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] + EfiMpServicesUnitTestCommom.c + EfiMpServicesUnitTestCommom.h + EdkiiPeiMpServices2PpiUnitTest.c + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + MemoryAllocationLib + PeimEntryPoint + PeiServicesLib + UnitTestPersistenceLib + UnitTestLib + +[Ppis] + gEdkiiPeiMpServices2PpiGuid ## CONSUMES + +[Depex] + gEdkiiPeiMpServices2PpiGuid diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpService= ProtocolDxeUnitTest.inf b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol= /EfiMpServiceProtocolDxeUnitTest.inf new file mode 100644 index 0000000000..1389092c06 --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtoco= lDxeUnitTest.inf @@ -0,0 +1,46 @@ +## @file +# DXE driver that unit tests the EfiMpServiceProtocol +# +# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D EfiMpServiceProtocolDxeUnitTest + FILE_GUID =3D F1E468E2-A32D-4574-895D-6D82B27B08BC + MODULE_TYPE =3D DXE_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D DxeEntryPoint + +# +# The following information is for reference only and not required by the = build tools. +# +# VALID_ARCHITECTURES =3D IA32 X64 +# + +[Sources] + EfiMpServicesUnitTestCommom.c + EfiMpServicesUnitTestCommom.h + EfiMpServiceProtocolUnitTest.c + +[Packages] + MdePkg/MdePkg.dec + UefiCpuPkg/UefiCpuPkg.dec + +[LibraryClasses] + BaseLib + DebugLib + BaseMemoryLib + MemoryAllocationLib + UefiDriverEntryPoint + UefiBootServicesTableLib + UnitTestPersistenceLib + UnitTestLib + +[Protocols] + gEfiMpServiceProtocolGuid ## CONSUMES + +[Depex] + gEfiMpServiceProtocolGuid diff --git a/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpService= sUnitTestCommom.h b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMp= ServicesUnitTestCommom.h new file mode 100644 index 0000000000..abbbd2faba --- /dev/null +++ b/UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServicesUnitTe= stCommom.h @@ -0,0 +1,627 @@ +/** @file + Common header file for EfiMpServiceProtocolUnitTest DXE driver. + + Copyright (c) 2022, Intel Corporation. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_ +#define EFI_MP_SERVICES_UNIT_TEST_COMMOM_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RUN_PROCEDURE_TIMEOUT_VALUE 100000 // microseconds + +typedef union { + EDKII_PEI_MP_SERVICES2_PPI *Ppi; + EFI_MP_SERVICES_PROTOCOL *Protocol; +} MP_SERVICES; + +typedef struct { + MP_SERVICES MpServices; + UINTN BspNumber; + UINTN ApNumber; + UINTN NumberOfProcessors; + UINTN NumberOfEnabledProcessors; + UINTN *CommonBuffer; + EFI_STATUS ApProcedureReturnStatus; + UINTN *DisabledApNumber; +} MP_SERVICE_UT_CONTEXT; + +/** + 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 +MpServicesUnitTestGetMpServices ( + OUT MP_SERVICES *MpServices + ); + +/** + 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 + ); + +/** + Get detailed information on the requested logical processor. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the processor. + @param[out] ProcessorInfoBuffer Pointer to the buffer where the processo= r information is stored. + + @retval EFI_SUCCESS Get information on the requested logical proce= ssor successfully + @retval Others Get information on the requested logical proce= ssor unsuccessfully +**/ +EFI_STATUS +MpServicesUnitTestGetProcessorInfo ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ); + +/** + 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 + ); + +/** + Switch the requested AP to be the BSP from that point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of AP that is to become th= e new BSP. + @param[in] EnableOldBSP If TRUE, the old BSP will be listed as an enab= led AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS Switch the requested AP to be the BSP successf= ully + @retval Others Switch the requested AP to be the BSP unsucces= sfully +**/ +EFI_STATUS +MpServicesUnitTestSwitchBSP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ); + +/** + Caller enables or disables an AP from this point onward. + + @param[in] MpServices MP_SERVICES structure. + @param[in] ProcessorNumber The handle number of the AP. + @param[in] EnableAP Specifies the new state for the processor for = enabled, FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifi= es the new health status of the AP. + + @retval EFI_SUCCESS Caller enables or disables an AP successfully. + @retval Others Caller enables or disables an AP unsuccessfull= y. +**/ +EFI_STATUS +MpServicesUnitTestEnableDisableAP ( + IN MP_SERVICES MpServices, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag + ); + +/** + 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 + ); + +/** + Empty procedure to be run on specified CPU. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +EmptyProcedure ( + IN OUT VOID *Buffer + ); + +/** + Produce to store ProcessorNumber in CommonBuffer and be run on specified= CPU. + + @param[in,out] Buffer The pointer to private data buffer. +**/ +VOID +StoreCpuNumbers ( + IN OUT VOID *Buffer + ); + +/** + Prep routine for Unit test function. + To save the ProcessorNumber of disabled AP and temporarily enable it. + + @param[in] Context Context pointer for this test. + + @retval UNIT_TEST_PASSED Prep routine runs successful. + @retval UNIT_TEST_ERROR_TEST_FAILED Prep routine runs unsuccessful. +**/ +UNIT_TEST_STATUS +EFIAPI +InitUTContext ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Cleanup routine for Unit test function. + If any processor is disabled unexpectedly then reenable it. + + @param[in] Context Context pointer for this test. +**/ +VOID +EFIAPI +CheckUTContext ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Cleanup routine for Unit test function. + It will be called by the last "AddTestCase" to restore AP state and free= pointer. + + @param[in] Context Context pointer for this test. +**/ +VOID +EFIAPI +FreeUTContext ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service WhoAmI. + The range of ProcessorNumber should be from 0 to NumberOfCPUs minus 1. + The ProcessorNumbers of all CPUs are unique. + + @param[in] Context Context pointer for this test. + + @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 +TestWhoAmI1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service GetNumberOfProcessors. + NumberOfProcessors should be greater that 0 and not less than NumberOfEn= abledProcessors. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service GetNumberOfProcessors. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service GetNumberOfProcessors. + Call EnableDisableAP() to change the number of enabled AP. + + @param[in] Context Context pointer for this test. + + @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 +TestGetNumberOfProcessors3 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service GetProcessorInfo. + When all the parameters are valid, all reserved bits of StatusFlag in Pr= ocessorInfoBuffer should be set to zero. + When all the parameters are valid, the StatusFlag should not have an inv= alid value (The BSP can never be in the disabled state.). + When called with nonexistent processor handle, the return status should = be EFI_NOT_FOUND. + + @param[in] Context Context pointer for this test. + + @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 +TestGetProcessorInfo1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service GetProcessorInfo. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestGetProcessorInfo2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service EnableDisableAP. + When called with BSP number, the return status should be EFI_INVALID_PAR= AMETER. + When called with a nonexistent processor handle, the return status shoul= d be EFI_NOT_FOUND. + The AP should be really Enable/Disabled. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service EnableDisableAP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service EnableDisableAP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestEnableDisableAP3 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupThisAP. + When called to startup a BSP, the return status should be EFI_INVALID_PA= RAMETER. + When called with a nonexistent processor handle, the return status shoul= d be EFI_NOT_FOUND. + The requested AP should execute the Procedure when called by StartupThis= AP. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupThisAP. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupThisAP. + When timeout expired before the requested AP has finished, the return st= atus should be EFI_TIMEOUT. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP3 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupThisAP. + When called with disabled AP, the return status should be EFI_INVALID_PA= RAMETER. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupThisAP4 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupAllAPs. + All APs should execute the Procedure when called by StartupAllAPs. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupAllAPs. + When called in single thread, the return status should be EFI_SUCCESS an= d AP executes in ascending order + of processor handle number. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupAllAPs. + When this service is called from an AP, the return status should be EFI_= DEVICE_ERROR. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs3 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupAllAPs. + When called with all AP timeout, the return status should be EFI_TIMEOUT. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs4 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service StartupAllAPs. + When called with the empty Procedure on all disabled APs, the return sta= tus should be EFI_NOT_STARTED. + + @param[in] Context Context pointer for this test. + + @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 +TestStartupAllAPs5 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service SwitchBSP. + When switch current BSP to be BSP, the return status should be EFI_INVAL= ID_PARAMETER. + When switch nonexistent processor to be BSP, the return status should be= EFI_NOT_FOUND. + After switch BSP, all APs(includes new AP) should execute the Procedure = when called by StartupAllAP. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP1 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service SwitchBSP. + When run this procedure on AP, the return status should be EFI_DEVICE_ER= ROR. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP2 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service SwitchBSP. + When switch a disabled AP to be BSP, the return status should be EFI_INV= ALID_PARAMETER. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP3 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Unit test of MP service SwitchBSP. + When SwitchBSP and EnableOldBSP is TRUE, the new BSP should be in the en= abled state and the old BSP should + be in the enabled state. + When SwitchBSP and EnableOldBSP is False, the new BSP should be in the e= nabled state and the old BSP should + be in the disabled state. + + @param[in] Context Context pointer for this test. + + @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 +TestSwitchBSP4 ( + IN UNIT_TEST_CONTEXT Context + ); + +/** + Create test suite and unit tests for both EdkiiPeiMpServices2Ppi and Efi= MpServiceProtocol. + + @param[in] Framework A pointer to the framework that is being persi= sted. + @param[in] Context A pointer to the private data buffer. + + @retval EFI_SUCCESS Create test suite and unit tests successfully. + @retval Others Create test suite and unit tests unsuccessfull= y. +**/ +EFI_STATUS +AddCommonTestCase ( + IN UNIT_TEST_FRAMEWORK_HANDLE Framework, + IN MP_SERVICE_UT_CONTEXT *Context + ); + +#endif diff --git a/UefiCpuPkg/UefiCpuPkg.dsc b/UefiCpuPkg/UefiCpuPkg.dsc index f694b3a77c..db5fe654b5 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 + UnitTestPersistenceLib|UnitTestFrameworkPkg/Library/UnitTestPersistenceL= ibNull/UnitTestPersistenceLibNull.inf + UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLib.inf + UnitTestResultReportLib|UnitTestFrameworkPkg/Library/UnitTestResultRepor= tLib/UnitTestResultReportLibDebugLib.inf =20 [LibraryClasses.common.SEC] PlatformSecLib|UefiCpuPkg/Library/PlatformSecLibNull/PlatformSecLibNull.= inf @@ -177,6 +180,8 @@ UefiCpuPkg/ResetVector/Vtf0/Bin/ResetVector.inf UefiCpuPkg/Library/SmmCpuRendezvousLib/SmmCpuRendezvousLib.inf UefiCpuPkg/Library/CpuPageTableLib/CpuPageTableLib.inf + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EdkiiPeiMpServices2Ppi= PeiUnitTest.inf + UefiCpuPkg/Test/UnitTest/EfiMpServicesPpiProtocol/EfiMpServiceProtocolDx= eUnitTest.inf =20 [BuildOptions] *_*_*_CC_FLAGS =3D -D DISABLE_NEW_DEPRECATED_INTERFACES --=20 2.28.0.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 (#94940): https://edk2.groups.io/g/devel/message/94940 Mute This Topic: https://groups.io/mt/94236483/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-