public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Rebecca Cran" <rebecca@nuviainc.com>
To: Sami Mujawar <sami.mujawar@arm.com>,
	devel@edk2.groups.io, Ard Biesheuvel <ardb+tianocore@kernel.org>,
	Gerd Hoffmann <kraxel@redhat.com>,
	Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>,
	Leif Lindholm <leif@nuviainc.com>,
	Jian J Wang <jian.j.wang@intel.com>,
	Liming Gao <gaoliming@byosoft.com.cn>, nd <nd@arm.com>
Subject: Re: [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services
Date: Thu, 9 Dec 2021 15:53:07 -0700	[thread overview]
Message-ID: <89316ba7-29c3-ea7f-5651-fcdeb845b0fd@nuviainc.com> (raw)
In-Reply-To: <bc4d1055-113b-8d13-f872-cdba1e33f97c@arm.com>

Now that the edk2 tree is unfrozen, I'd like to get this committed.

Could anyone else review it please, or if it's ready commit it?


Thanks.

Rebecca Cran


On 11/10/21 11:06 AM, Sami Mujawar wrote:
> Hi Rebecca,
>
> Thank you for the updated patch. These changes look good to me.
>
> The INF file mentions support for IA32 and X64 so it would be got to get
> feedback for other architectures and from the MdeModulePkg maintainers.
>
> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
>
> Regards,
>
> Sami Mujawar
>
> On 05/11/2021 08:31 PM, Rebecca Cran 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   | 428 
>> ++++++++++++++++++++
>>   MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
>>   MdeModulePkg/MdeModulePkg.dsc                              | 2 +
>>   3 files changed, 468 insertions(+)
>>
>> diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c 
>> b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
>> new file mode 100644
>> index 000000000000..d066bdd530d5
>> --- /dev/null
>> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
>> @@ -0,0 +1,428 @@
>> +/** @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
>> +
>> +
>> +/** 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
>> +                 );
>> +
>> +  if (EFI_ERROR (Status)) {
>> +    Print (L"failed: %r\n", Status);
>> +    return;
>> +  }
>> +  else {
>> +    Print (L"done.\n");
>> +  }
>> +
>> +  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
>> +                 );
>> +  if (EFI_ERROR (Status)) {
>> +    Print (L"failed: %r\n", Status);
>> +    return;
>> +  }
>> +  else {
>> +    Print (L"done.\n");
>> +  }
>> +}
>> +
>> +/** 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);
>> +  if (EFI_ERROR (Status)) {
>> +    Print (L"failed: %r\n", Status);
>> +    return;
>> +  }
>> +  else {
>> +    Print (L"done.\n");
>> +  }
>> +
>> +  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
>> +                 );
>> +  if (EFI_ERROR (Status)) {
>> +    Print (L"failed: %r\n", Status);
>> +    return;
>> +  }
>> +  else {
>> +    Print (L"done.\n");
>> +  }
>> +}
>> +
>> +/** 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);
>> +    if (EFI_ERROR (Status)) {
>> +      Print (L"failed: %r\n", Status);
>> +      return;
>> +    }
>> +    else {
>> +      Print (L"done.\n");
>> +    }
>> +  }
>> +
>> +  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);
>> +    if (EFI_ERROR (Status)) {
>> +      Print (L"failed: %r\n", Status);
>> +      return;
>> +    }
>> +    else {
>> +      Print (L"done.\n");
>> +    }
>> +  }
>> +}
>> +
>> +/**
>> +  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);
>> +
>> +  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
>
> IMPORTANT NOTICE: The contents of this email and any attachments are 
> confidential and may also be privileged. If you are not the intended 
> recipient, please notify the sender immediately and do not disclose 
> the contents to any other person, use it for any purpose, or store or 
> copy the information in any medium. Thank you.

  parent reply	other threads:[~2021-12-09 22:53 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-11-05 20:31 [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran
2021-11-10 18:06 ` Sami Mujawar
2021-11-10 18:16   ` Rebecca Cran
2021-12-09 22:53   ` Rebecca Cran [this message]
     [not found]   ` <16BF3806DE6E3547.21850@groups.io>
2021-12-12 18:09     ` [edk2-devel] " 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=89316ba7-29c3-ea7f-5651-fcdeb845b0fd@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