From: "Rebecca Cran" <rebecca@nuviainc.com>
To: devel@edk2.groups.io, Jian J Wang <jian.j.wang@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>
Cc: Ard Biesheuvel <ardb+tianocore@kernel.org>,
Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>,
Leif Lindholm <leif@nuviainc.com>,
Sami Mujawar <sami.mujawar@arm.com>,
Gerd Hoffmann <kraxel@redhat.com>
Subject: Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services
Date: Sat, 16 Oct 2021 00:32:54 -0600 [thread overview]
Message-ID: <b3dc9311-a30f-be53-9bc8-6b8dbc0e2163@nuviainc.com> (raw)
In-Reply-To: <16A69264F30D2680.28782@groups.io>
(cc Leif, Ard, Sami, Samer, Gerd)
Could someone review this please?
--
Rebecca Cran
On 9/20/21 9:47 AM, Rebecca Cran via groups.io wrote:
> Add a new MpServicesTest application under MdeModulePkg/Application that
> exercises the EFI_MP_SERVICES_PROTOCOL.
>
> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
> ---
> MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 433 ++++++++++++++++++++
> MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
> MdeModulePkg/MdeModulePkg.dsc | 2 +
> 3 files changed, 473 insertions(+)
>
> diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
> new file mode 100644
> index 000000000000..4eb06e6b7cbd
> --- /dev/null
> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
> @@ -0,0 +1,433 @@
> +/** @file
> +
> + Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
> + SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <Uefi.h>
> +#include <Library/DebugLib.h>
> +#include <Library/RngLib.h>
> +#include <Library/UefiBootServicesTableLib.h>
> +#include <Library/UefiLib.h>
> +#include <Pi/PiMultiPhase.h>
> +#include <Protocol/MpService.h>
> +
> +#define MAX_RANDOM_PROCESSOR_RETRIES 10
> +
> +#define AP_STARTUP_TEST_TIMEOUT_US 50000
> +#define INFINITE_TIMEOUT 0
> +
> +#define RETURN_IF_EFI_ERROR(x) \
> + if (EFI_ERROR (x)) { \
> + Print (L"failed: %r\n", x); \
> + return; \
> + } \
> + else { \
> + Print (L"done.\n"); \
> + }
> +
> +/** The procedure to run with the MP Services interface.
> +
> + @param Buffer The procedure argument.
> +
> +**/
> +STATIC
> +VOID
> +EFIAPI
> +ApFunction (
> + IN OUT VOID *Buffer
> + )
> +{
> +}
> +
> +/** Displays information returned from MP Services Protocol.
> +
> + @param Mp The MP Services Protocol
> +
> + @return The number of CPUs in the system.
> +
> +**/
> +STATIC
> +UINTN
> +PrintProcessorInformation (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp
> + )
> +{
> + EFI_STATUS Status;
> + EFI_PROCESSOR_INFORMATION CpuInfo;
> + UINTN Index;
> + UINTN NumCpu;
> + UINTN NumEnabledCpu;
> +
> + Status = Mp->GetNumberOfProcessors (Mp, &NumCpu, &NumEnabledCpu);
> + if (EFI_ERROR (Status)) {
> + Print (L"GetNumberOfProcessors failed: %r\n", Status);
> + } else {
> + Print (L"Number of CPUs: %ld, Enabled: %d\n", NumCpu, NumEnabledCpu);
> + }
> +
> + for (Index = 0; Index < NumCpu; Index++) {
> + Status = Mp->GetProcessorInfo (Mp, CPU_V2_EXTENDED_TOPOLOGY | Index, &CpuInfo);
> + if (EFI_ERROR (Status)) {
> + Print (L"GetProcessorInfo for Processor %d failed: %r\n", Index, Status);
> + } else {
> + Print (
> + L"Processor %d:\n"
> + L"\tID: %016lx\n"
> + L"\tStatus: %s | ",
> + Index,
> + CpuInfo.ProcessorId,
> + (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? L"BSP" : L"AP"
> + );
> +
> + Print (L"%s | ", (CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) ? L"Enabled" : L"Disabled");
> + Print (L"%s\n", (CpuInfo.StatusFlag & PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted");
> +
> + Print (
> + L"\tLocation: Package %d, Core %d, Thread %d\n"
> + L"\tExtended Information: Package %d, Module %d, Tile %d, Die %d, Core %d, Thread %d\n\n",
> + CpuInfo.Location.Package,
> + CpuInfo.Location.Core,
> + CpuInfo.Location.Thread,
> + CpuInfo.ExtendedInformation.Location2.Package,
> + CpuInfo.ExtendedInformation.Location2.Module,
> + CpuInfo.ExtendedInformation.Location2.Tile,
> + CpuInfo.ExtendedInformation.Location2.Die,
> + CpuInfo.ExtendedInformation.Location2.Core,
> + CpuInfo.ExtendedInformation.Location2.Thread
> + );
> + }
> + }
> +
> + return NumCpu;
> +}
> +
> +/** Returns the index of an enabled AP selected at random.
> +
> + @param Mp The MP Services Protocol.
> + @param ProcessorIndex The index of a random enabled AP.
> +
> + @retval EFI_SUCCESS An enabled processor was found and returned.
> + @retval EFI_NOT_FOUND A processor was unable to be selected.
> +
> +**/
> +STATIC
> +EFI_STATUS
> +GetRandomEnabledProcessorIndex (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
> + OUT UINTN *ProcessorIndex
> + )
> +{
> + UINTN Index;
> + UINTN IndexOfEnabledCpu;
> + UINTN NumCpus;
> + UINTN NumEnabledCpus;
> + UINTN IndexOfEnabledCpuToUse;
> + UINT16 RandomNumber;
> + BOOLEAN Success;
> + EFI_STATUS Status;
> + EFI_PROCESSOR_INFORMATION CpuInfo;
> +
> + IndexOfEnabledCpu = 0;
> +
> + Success = GetRandomNumber16 (&RandomNumber);
> + ASSERT (Success == TRUE);
> +
> + Status = Mp->GetNumberOfProcessors (Mp, &NumCpus, &NumEnabledCpus);
> + ASSERT_EFI_ERROR (Status);
> +
> + if (NumEnabledCpus == 1) {
> + Print (L"All APs are disabled\n");
> + return EFI_NOT_FOUND;
> + }
> +
> + IndexOfEnabledCpuToUse = RandomNumber % NumEnabledCpus;
> +
> + for (Index = 0; Index < NumCpus; Index++) {
> + Status = Mp->GetProcessorInfo (Mp, Index, &CpuInfo);
> + ASSERT_EFI_ERROR (Status);
> + if ((CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) &&
> + !(CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT)) {
> + if (IndexOfEnabledCpuToUse == IndexOfEnabledCpu) {
> + *ProcessorIndex = Index;
> + Status = EFI_SUCCESS;
> + break;
> + }
> +
> + IndexOfEnabledCpu++;
> + }
> + }
> +
> + if (Index == NumCpus) {
> + Status = EFI_NOT_FOUND;
> + }
> +
> + return Status;
> +}
> +
> +/** Tests for the StartupThisAP function.
> +
> + @param Mp The MP Services Protocol.
> +
> +**/
> +STATIC
> +VOID
> +StartupThisApTests (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp
> + )
> +{
> + EFI_STATUS Status;
> + UINTN ProcessorIndex;
> + UINT32 Retries;
> +
> + Retries = 0;
> +
> + do {
> + Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
> + } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
> +
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + Print (
> + L"StartupThisAP on Processor %d with 0 (infinite) timeout...",
> + ProcessorIndex
> + );
> +
> + Status = Mp->StartupThisAP (
> + Mp,
> + ApFunction,
> + ProcessorIndex,
> + NULL,
> + INFINITE_TIMEOUT,
> + NULL,
> + NULL
> + );
> +
> + RETURN_IF_EFI_ERROR (Status);
> +
> + Retries = 0;
> +
> + do {
> + Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
> + } while (EFI_ERROR (Status) && Retries++ < MAX_RANDOM_PROCESSOR_RETRIES);
> +
> + if (EFI_ERROR (Status)) {
> + return;
> + }
> +
> + Print (
> + L"StartupThisAP on Processor %d with %dms timeout...",
> + ProcessorIndex,
> + AP_STARTUP_TEST_TIMEOUT_US / 1000
> + );
> + Status = Mp->StartupThisAP (
> + Mp,
> + ApFunction,
> + ProcessorIndex,
> + NULL,
> + AP_STARTUP_TEST_TIMEOUT_US,
> + NULL,
> + NULL
> + );
> + RETURN_IF_EFI_ERROR (Status);
> +}
> +
> +/** Tests for the StartupAllAPs function.
> +
> + @param Mp The MP Services Protocol.
> + @param NumCpus The number of CPUs in the system.
> +
> +**/
> +STATIC
> +VOID
> +StartupAllAPsTests (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
> + IN UINTN NumCpus
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Timeout;
> +
> + Print (L"Running with SingleThread FALSE, 0 (infinite) timeout...");
> + Status = Mp->StartupAllAPs (Mp, ApFunction, FALSE, NULL, INFINITE_TIMEOUT, NULL, NULL);
> + RETURN_IF_EFI_ERROR (Status);
> +
> + Timeout = NumCpus * AP_STARTUP_TEST_TIMEOUT_US;
> +
> + Print (L"Running with SingleThread TRUE, %dms timeout...", Timeout / 1000);
> + Status = Mp->StartupAllAPs (
> + Mp,
> + ApFunction,
> + TRUE,
> + NULL,
> + Timeout,
> + NULL,
> + NULL
> + );
> + RETURN_IF_EFI_ERROR (Status);
> +}
> +
> +/** Tests for the EnableDisableAP function.
> +
> + @param Mp The MP Services Protocol.
> + @param NumCpus The number of CPUs in the system.
> +
> +**/
> +STATIC
> +VOID
> +EnableDisableAPTests (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
> + IN UINTN NumCpus
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Index;
> + UINT32 HealthFlag;
> +
> + HealthFlag = 0;
> +
> + for (Index = 1; Index < NumCpus; Index++) {
> + Print (L"Disabling Processor %d with HealthFlag faulted...", Index);
> + Status = Mp->EnableDisableAP (Mp, Index, FALSE, &HealthFlag);
> + RETURN_IF_EFI_ERROR (Status);
> + }
> +
> + HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
> +
> + for (Index = 1; Index < NumCpus; Index++) {
> + Print (L"Enabling Processor %d with HealthFlag healthy...", Index);
> + Status = Mp->EnableDisableAP (Mp, Index, TRUE, &HealthFlag);
> + RETURN_IF_EFI_ERROR (Status);
> + }
> +}
> +
> +/** Tests for the SwitchBSP function.
> +
> + @param Mp The MP Services Protocol.
> + @param NumCpus The number of CPUs in the system.
> +
> +**/
> +STATIC
> +VOID
> +SwitchBSPTests (
> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
> + IN UINTN NumCpus
> + )
> +{
> + EFI_STATUS Status;
> + UINTN Index;
> +
> + for (Index = 1; Index < NumCpus; Index++) {
> + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index);
> + Status = Mp->SwitchBSP (Mp, Index, FALSE);
> + RETURN_IF_EFI_ERROR (Status);
> + }
> +
> + for (Index = 0; Index < NumCpus; Index++) {
> + Print (L"Switching BSP to Processor %d with EnableOldBSP TRUE...", Index);
> + Status = Mp->SwitchBSP (Mp, Index, TRUE);
> + RETURN_IF_EFI_ERROR (Status);
> + }
> +}
> +
> +/**
> + The user Entry Point for Application. The user code starts with this function
> + as the real entry point for the application.
> +
> + @param[in] ImageHandle The firmware allocated handle for the EFI image.
> + @param[in] SystemTable A pointer to the EFI System Table.
> +
> + @retval EFI_SUCCESS The entry point is executed successfully.
> + @retval other Some error occurs when executing this entry point.
> +
> +**/
> +EFI_STATUS
> +EFIAPI
> +UefiMain (
> + IN EFI_HANDLE ImageHandle,
> + IN EFI_SYSTEM_TABLE *SystemTable
> + )
> +{
> + EFI_STATUS Status;
> + EFI_MP_SERVICES_PROTOCOL *Mp;
> + EFI_HANDLE *pHandle;
> + UINTN HandleCount;
> + UINTN BspId;
> + UINTN NumCpus;
> + UINTN Index;
> +
> + pHandle = NULL;
> + HandleCount = 0;
> + BspId = 0;
> +
> + Status = gBS->LocateHandleBuffer (
> + ByProtocol,
> + &gEfiMpServiceProtocolGuid,
> + NULL,
> + &HandleCount,
> + &pHandle
> + );
> +
> + if (EFI_ERROR (Status)) {
> + Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not installed on platform?\n", Status);
> + return EFI_NOT_FOUND;
> + }
> +
> + for (Index = 0; Index < HandleCount; Index++) {
> + Status = gBS->OpenProtocol (
> + *pHandle,
> + &gEfiMpServiceProtocolGuid,
> + (VOID **)&Mp,
> + NULL,
> + gImageHandle,
> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
> + );
> +
> + if (EFI_ERROR (Status)) {
> + return Status;
> + }
> +
> + pHandle++;
> + }
> +
> + Print (L"Exercising WhoAmI\n\n");
> + Status = Mp->WhoAmI (Mp, &BspId);
> + if (EFI_ERROR (Status)) {
> + Print (L"WhoAmI failed: %r\n", Status);
> + return Status;
> + } else {
> + Print (L"WhoAmI: %016lx\n", BspId);
> + }
> +
> + Print (L"\n");
> + Print (
> + L"Exercising GetNumberOfProcessors and GetProcessorInformation with "
> + L"CPU_V2_EXTENDED_TOPOLOGY\n\n"
> + );
> + NumCpus = PrintProcessorInformation (Mp);
> + if (NumCpus < 2) {
> + Print (L"UP system found. Not running further tests.\n");
> + return EFI_INVALID_PARAMETER;
> + }
> +
> + Print (L"\n");
> + Print (L"Exercising StartupThisAP:\n\n");
> + StartupThisApTests (Mp);
> +
> + Print (L"\n");
> + Print (L"Exercising StartupAllAPs:\n\n");
> + StartupAllAPsTests (Mp, NumCpus);
> +
> + Print (L"\n");
> + Print (L"Exercising EnableDisableAP:\n\n");
> + EnableDisableAPTests (Mp, NumCpus);
> +
> + Print (L"\n");
> + Print (L"Exercising SwitchBSP\n\n");
> + SwitchBSPTests (Mp, NumCpus);
> +
> + gBS->CloseProtocol (pHandle, &gEfiMpServiceProtocolGuid, gImageHandle, NULL);
> + return EFI_SUCCESS;
> +}
> diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> new file mode 100644
> index 000000000000..8a21ca70d8fa
> --- /dev/null
> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> @@ -0,0 +1,38 @@
> +## @file
> +# UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
> +#
> +# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
> +#
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> + INF_VERSION = 1.29
> + BASE_NAME = MpServicesTest
> + FILE_GUID = 43e9defa-7209-4b0d-b136-cc4ca02cb469
> + MODULE_TYPE = UEFI_APPLICATION
> + VERSION_STRING = 0.1
> + ENTRY_POINT = UefiMain
> +
> +#
> +# The following information is for reference only and not required by the build tools.
> +#
> +# VALID_ARCHITECTURES = IA32 X64 AARCH64
> +#
> +
> +[Sources]
> + MpServicesTest.c
> +
> +[Packages]
> + MdePkg/MdePkg.dec
> +
> +[LibraryClasses]
> + BaseLib
> + RngLib
> + UefiApplicationEntryPoint
> + UefiLib
> +
> +[Protocols]
> + gEfiMpServiceProtocolGuid ## CONSUMES
> +
> diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc
> index b1d83461865e..1cf5ccd30d40 100644
> --- a/MdeModulePkg/MdeModulePkg.dsc
> +++ b/MdeModulePkg/MdeModulePkg.dsc
> @@ -164,6 +164,7 @@
> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
> DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
> FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
> + RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf
>
> [LibraryClasses.common.MM_STANDALONE]
> HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
> @@ -215,6 +216,7 @@
> MdeModulePkg/Application/HelloWorld/HelloWorld.inf
> MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
> MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
> + MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
>
> MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
> MdeModulePkg/Logo/Logo.inf
next prev parent reply other threads:[~2021-10-16 6:32 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-20 15:47 [PATCH v2 0/1] MdeModulePkg: Add MpServicesTest.efi to exercise EFI_MP_SERVICES_PROTOCOL Rebecca Cran
2021-09-20 15:47 ` [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran
2021-11-03 10:54 ` [edk2-devel] " Sami Mujawar
2021-11-03 17:22 ` Rebecca Cran
[not found] ` <16A69264F30D2680.28782@groups.io>
2021-10-16 6:32 ` Rebecca Cran [this message]
2021-10-16 6:54 ` Sami Mujawar
2021-11-03 2:31 ` Rebecca Cran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b3dc9311-a30f-be53-9bc8-6b8dbc0e2163@nuviainc.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox