public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Ni, Ray" <ray.ni@intel.com>
To: "devel@edk2.groups.io" <devel@edk2.groups.io>,
	"quic_rcran@quicinc.com" <quic_rcran@quicinc.com>,
	Kun Qin <kuqin12@gmail.com>, Sami Mujawar <sami.mujawar@arm.com>,
	Ard Biesheuvel <ardb+tianocore@kernel.org>,
	"Leif Lindholm" <quic_llindhol@quicinc.com>,
	"Wang, Jian J" <jian.j.wang@intel.com>,
	"Gao, Liming" <gaoliming@byosoft.com.cn>,
	Tiger Liu <TigerLiu@zhaoxin.com>
Subject: Re: [edk2-devel] [PATCH v4 3/3] MdeModulePkg: Add new Application/MpServicesTest application
Date: Mon, 9 Jan 2023 01:32:54 +0000	[thread overview]
Message-ID: <MN6PR11MB8244FEB616B6E8EB65C6052A8CFE9@MN6PR11MB8244.namprd11.prod.outlook.com> (raw)
In-Reply-To: <b6d102e5-bc29-bf80-0175-eceb87b8a3d0@quicinc.com>

Rebecca,
Have you reviewed UefiCpuPkg\Test\UnitTest\EfiMpServicesPpiProtocol? It's based on UnitTestFrameworkPkg for unit testing on MP PPI and MP protocol.
Do you think if the MpServicesTest app and the EfiMpServicesPpiProtocol have some overlapped functionalities?



Thanks,
Ray

> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Rebecca Cran
> Sent: Sunday, January 8, 2023 12:56 PM
> To: Kun Qin <kuqin12@gmail.com>; devel@edk2.groups.io; Sami Mujawar <sami.mujawar@arm.com>; Ard Biesheuvel
> <ardb+tianocore@kernel.org>; Leif Lindholm <quic_llindhol@quicinc.com>; Wang, Jian J <jian.j.wang@intel.com>; Gao,
> Liming <gaoliming@byosoft.com.cn>; Tiger Liu <TigerLiu@zhaoxin.com>
> Subject: Re: [edk2-devel] [PATCH v4 3/3] MdeModulePkg: Add new Application/MpServicesTest application
> 
> Thanks! I've fixed all the issues you noted and will send out a v5 patch
> in the next couple of days.
> 
> --
> Rebecca Cran
> 
> On 1/6/23 15:33, Kun Qin wrote:
> > Hi Rebecca,
> >
> > Thanks for sharing this patch. I found a few minor issues when running
> > this test app. Please see comments with [KQ] below.
> >
> > Regards,
> > Kun
> >
> > On 1/4/2023 7:37 AM, Rebecca Cran wrote:
> >> The MpServicesTest application exercises the EFI_MP_SERVICES_PROTOCOL.
> >>
> >> usage:
> >>    MpServicesTest -A [-O]
> >>    MpServicesTest -T <Timeout>
> >>    MpServicesTest -S <Processor #>
> >>    MpServicesTest -P
> >>    MpServicesTest -U
> >>    MpServicesTest -W
> >>    MpServicesTest -E <Processor #>
> >>    MpServicesTest -D <Processor #>
> >>    MpServicesTest -h
> >>
> >> Parameter:
> >>    -A:  Run all APs.
> >>    -O:  Run APs sequentially (use with -A).
> >>    -T:  Specify timeout in milliseconds. Default is to wait forever.
> >>    -S:  Specify the single AP to run.
> >>    -P:  Print processor information.
> >>    -U:  Set the specified AP to the Unhealthy status (use with -E/-D).
> >>    -W:  Run WhoAmI and print index of BSP.
> >>    -E:  Enable the specified AP.
> >>    -D:  Disable the specified AP.
> >>    -h:  Print this help page.
> >>
> >> Signed-off-by: Rebecca Cran <rebecca@quicinc.com>
> >> ---
> >>   MdeModulePkg/MdeModulePkg.dsc                              |   2 +
> >>   MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf |  40 ++
> >>   MdeModulePkg/Application/MpServicesTest/Options.h          |  39 ++
> >>   MdeModulePkg/Application/MpServicesTest/MpServicesTest.c   | 560
> >> ++++++++++++++++++++
> >>   MdeModulePkg/Application/MpServicesTest/Options.c          | 164 ++++++
> >>   5 files changed, 805 insertions(+)
> >>
> >> diff --git a/MdeModulePkg/MdeModulePkg.dsc
> >> b/MdeModulePkg/MdeModulePkg.dsc
> >> index 659482ab737f..6992b3ae8db6 100644
> >> --- a/MdeModulePkg/MdeModulePkg.dsc
> >> +++ b/MdeModulePkg/MdeModulePkg.dsc
> >> @@ -166,6 +166,7 @@ [LibraryClasses.common.UEFI_APPLICATION]
> >>
> >> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
> >>     DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
> >>     FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
> >> +  ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
> >>   [LibraryClasses.common.MM_STANDALONE]
> >>     HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
> >> @@ -445,6 +446,7 @@ [Components]
> >>
> >> MdeModulePkg/Library/BaseVariableFlashInfoLib/BaseVariableFlashInfoLib.inf
> >>   [Components.IA32, Components.X64, Components.AARCH64]
> >> +  MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> >>     MdeModulePkg/Universal/EbcDxe/EbcDxe.inf
> >>     MdeModulePkg/Universal/EbcDxe/EbcDebugger.inf
> >>     MdeModulePkg/Universal/EbcDxe/EbcDebuggerConfig.inf
> >> diff --git
> >> a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> >> b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> >> new file mode 100644
> >> index 000000000000..07ee4afec845
> >> --- /dev/null
> >> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
> >> @@ -0,0 +1,40 @@
> >> +## @file
> >> +#  UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
> >> +#
> >> +#  Copyright (c) 2022, Qualcomm Innovation Center, 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
> >> +  Options.c
> >> +  Options.h
> >> +
> >> +[Packages]
> >> +  MdePkg/MdePkg.dec
> >> +
> >> +[LibraryClasses]
> >> +  BaseLib
> >> +  ShellLib
> >> +  UefiApplicationEntryPoint
> >> +  UefiLib
> >> +
> >> +[Protocols]
> >> +  gEfiMpServiceProtocolGuid    ## CONSUMES
> >> +
> >> diff --git a/MdeModulePkg/Application/MpServicesTest/Options.h
> >> b/MdeModulePkg/Application/MpServicesTest/Options.h
> >> new file mode 100644
> >> index 000000000000..cb28230ab095
> >> --- /dev/null
> >> +++ b/MdeModulePkg/Application/MpServicesTest/Options.h
> >> @@ -0,0 +1,39 @@
> >> +/** @file
> >> +  Options handling code.
> >> +
> >> +  Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights
> >> reserved.<BR>
> >> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >> +**/
> >> +
> >> +#ifndef MPSERVICESTEST_OPTIONS_H_
> >> +#define MPSERVICESTEST_OPTIONS_H_
> >> +
> >> +#define INFINITE_TIMEOUT  0
> >> +
> >> +typedef struct {
> >> +  UINTN      Timeout;
> >> +  UINTN      ProcessorIndex;
> >> +  BOOLEAN    RunAllAPs;
> >> +  BOOLEAN    RunSingleAP;
> >> +  BOOLEAN    DisableProcessor;
> >> +  BOOLEAN    EnableProcessor;
> >> +  BOOLEAN    SetProcessorHealthy;
> >> +  BOOLEAN    SetProcessorUnhealthy;
> >> +  BOOLEAN    PrintProcessorInformation;
> >> +  BOOLEAN    PrintBspProcessorIndex;
> >> +  BOOLEAN    RunAPsSequentially;
> >> +} MP_SERVICES_TEST_OPTIONS;
> >> +
> >> +/**
> >> +  Parses any arguments provided on the command line.
> >> +
> >> +  @param Options  The arguments structure.
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +**/
> >> +EFI_STATUS
> >> +ParseArguments (
> >> +  MP_SERVICES_TEST_OPTIONS  *Options
> >> +  );
> >> +
> >> +#endif /* MPSERVICESTEST_OPTIONS_H_ */
> >> diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
> >> b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
> >> new file mode 100644
> >> index 000000000000..3f3d9752d500
> >> --- /dev/null
> >> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
> >> @@ -0,0 +1,560 @@
> >> +/** @file
> >> +  UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
> >> +
> >> +  Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights
> >> reserved.<BR>
> >> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >> +**/
> >> +
> >> +#include <Uefi.h>
> >> +#include <Library/BaseMemoryLib.h>
> >> +#include <Library/DebugLib.h>
> >> +#include <Library/MemoryAllocationLib.h>
> >> +#include <Library/PrintLib.h>
> >> +#include <Library/UefiBootServicesTableLib.h>
> >> +#include <Library/UefiLib.h>
> >> +#include <Pi/PiMultiPhase.h>
> >> +#include <Protocol/MpService.h>
> >> +
> >> +#include "Options.h"
> >> +
> >> +#define APFUNC_BUFFER_LEN  256
> >> +
> >> +typedef struct {
> >> +  EFI_MP_SERVICES_PROTOCOL    *Mp;
> >> +  CHAR16                      **Buffer;
> >> +} APFUNC_ARG;
> >> +
> >> +/** The procedure to run with the MP Services interface.
> >> +
> >> +  @param Arg The procedure argument.
> >> +
> >> +**/
> >> +STATIC
> >> +VOID
> >> +EFIAPI
> >> +ApFunction (
> >> +  IN OUT VOID  *Arg
> >> +  )
> >> +{
> >> +  APFUNC_ARG  *Param;
> >> +  UINTN       ProcessorId;
> >> +
> >> +  if (Arg != NULL) {
> >> +    Param = Arg;
> >> +
> >> +    Param->Mp->WhoAmI (Param->Mp, &ProcessorId);
> >> +    UnicodeSPrint (Param->Buffer[ProcessorId], APFUNC_BUFFER_LEN,
> >> L"Hello from CPU %ld\n", ProcessorId);
> >> +  }
> >> +}
> >> +
> >> +/**
> >> +  Fetches the number of processors and which processor is the BSP.
> >> +
> >> +  @param Mp  MP Services Protocol.
> >> +  @param NumProcessors Number of processors.
> >> +  @param BspIndex      The index of the BSP.
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +GetProcessorInformation (
> >> +  IN  EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  OUT UINTN                     *NumProcessors,
> >> +  OUT UINTN                     *BspIndex
> >> +  )
> >> +{
> >> +  EFI_STATUS  Status;
> >> +  UINTN       NumEnabledProcessors;
> >> +
> >> +  Status = Mp->GetNumberOfProcessors (Mp, NumProcessors,
> >> &NumEnabledProcessors);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> >> +  Status = Mp->WhoAmI (Mp, BspIndex);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/** Displays information returned from MP Services Protocol.
> >> +
> >> +  @param Mp       The MP Services Protocol
> >> +  @param BspIndex On return, contains the index of the BSP.
> >> +
> >> +  @return The number of CPUs in the system.
> >> +
> >> +**/
> >> +STATIC
> >> +UINTN
> >> +PrintProcessorInformation (
> >> +  IN   EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  OUT  UINTN                     *BspIndex
> >> +  )
> >> +{
> >> +  EFI_STATUS                 Status;
> >> +  EFI_PROCESSOR_INFORMATION  CpuInfo;
> >> +  UINTN                      Index;
> >> +  UINTN                      NumCpu;
> >> +  UINTN                      NumEnabledCpu;
> > [KQ] The NumCpu and NumEnabledCpu probably should be initialized to 0s?
> > Otherwise if the
> > GetNumberOfProcessors function somehow fails, the rest of the call will
> > essentially be no-op,
> > instead of running into undefined number of CPUs.
> >> +
> >> +  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"
> >> +        );
> >> +
> >> +      if ((CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) && (BspIndex !=
> >> NULL)) {
> >> +        *BspIndex = Index;
> >> +      }
> >> +
> >> +      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;
> >> +}
> >> +
> >> +/** Allocates memory in ApArg for the single AP specified.
> >> +
> >> +  @param ApArg          Pointer to the AP argument structure.
> >> +  @param Mp             The MP Services Protocol.
> >> +  @param ProcessorIndex The index of the AP.
> >> +
> >> +  @retval EFI_SUCCESS          Memory was successfully allocated.
> >> +  @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> >> +
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +AllocateApFuncBufferSingleAP (
> >> +  IN APFUNC_ARG                *ApArg,
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  IN UINTN                     ProcessorIndex
> >> +  )
> >> +{
> >> +  ApArg->Mp = Mp;
> >> +
> >> +  ApArg->Buffer = AllocateZeroPool ((ProcessorIndex + 1) * sizeof
> >> (VOID *));
> >> +  if (ApArg->Buffer == NULL) {
> >> +    Print (L"Failed to allocate buffer for AP buffer\n");
> >> +    return EFI_OUT_OF_RESOURCES;
> >> +  }
> >> +
> >> +  ApArg->Buffer[ProcessorIndex] = AllocateZeroPool (APFUNC_BUFFER_LEN);
> >> +  if (ApArg->Buffer[ProcessorIndex] == NULL) {
> >> +    Print (L"Failed to allocate buffer for AP buffer\n");
> >> +    FreePool (ApArg->Buffer);
> >> +    return EFI_OUT_OF_RESOURCES;
> >> +  }
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/** Allocates memory in ApArg for all APs.
> >> +
> >> +  @param ApArg   Pointer to the AP argument structure.
> >> +  @param Mp      The MP Services Protocol.
> >> +  @param NumCpus The number of CPUs.
> >> +
> >> +  @retval EFI_SUCCESS          Memory was successfully allocated.
> >> +  @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.
> >> +
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +AllocateApFuncBufferAllAPs (
> >> +  IN APFUNC_ARG                *ApArg,
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  IN UINTN                     NumCpus
> >> +  )
> >> +{
> >> +  UINT32  Index;
> > [KQ] The Index of UINT32 compared to NumCpus of UINTN could make some
> > compilers unhappy.
> >> +
> >> +  ApArg->Mp = Mp;
> >> +
> >> +  ApArg->Buffer = AllocateZeroPool (NumCpus * sizeof (VOID *));
> >> +  if (ApArg->Buffer == NULL) {
> >> +    Print (L"Failed to allocate buffer for AP message\n");
> >> +    return EFI_OUT_OF_RESOURCES;
> >> +  }
> >> +
> >> +  for (Index = 0; Index < NumCpus; Index++) {
> >> +    ApArg->Buffer[Index] = AllocateZeroPool (APFUNC_BUFFER_LEN);
> >> +    if (ApArg->Buffer[Index] == NULL) {
> >> +      Print (L"Failed to allocate buffer for AP message\n");
> >> +      for (--Index; Index >= 0; Index++) {
> > [KQ] This Index increment could cause the loop not ending as expected.
> >> +        FreePool (ApArg->Buffer[Index]);
> >> +      }
> >> +
> >> +      FreePool (ApArg->Buffer);
> >> +      return EFI_OUT_OF_RESOURCES;
> >> +    }
> >> +  }
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/** Frees memory in ApArg for all APs.
> >> +
> >> +  @param ApArg   Pointer to the AP argument structure.
> >> +  @param NumCpus The number of CPUs.
> >> +
> >> +**/
> >> +STATIC
> >> +VOID
> >> +FreeApFuncBuffer (
> >> +  APFUNC_ARG  *ApArg,
> >> +  UINTN       NumCpus
> >> +  )
> >> +{
> >> +  UINTN  Index;
> >> +
> >> +  for (Index = 0; Index < NumCpus; Index++) {
> >> +    if (ApArg->Buffer[Index] != NULL) {
> >> +      FreePool (ApArg->Buffer[Index]);
> >> +    }
> >> +  }
> >> +
> >> +  FreePool (ApArg->Buffer);
> >> +}
> >> +
> >> +/** Runs a specified AP.
> >> +
> >> +  @param Mp             The MP Services Protocol.
> >> +  @param ProcessorIndex The processor index.
> >> +  @param Timeout        Timeout in milliseconds.
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +StartupThisAP (
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  IN UINTN                     ProcessorIndex,
> >> +  IN UINTN                     Timeout
> >> +  )
> >> +{
> >> +  EFI_STATUS  Status;
> >> +  APFUNC_ARG  ApArg;
> >> +
> >> +  Status = AllocateApFuncBufferSingleAP (&ApArg, Mp, ProcessorIndex);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> >> +  Status = AllocateApFuncBufferSingleAP (&ApArg, Mp, ProcessorIndex);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> > [KQ] I guess the above double calls are not intended?
> >> +  Print (
> >> +    L"StartupThisAP on Processor %d with %d%s timeout...",
> >> +    ProcessorIndex,
> >> +    Timeout,
> >> +    (Timeout == INFINITE_TIMEOUT) ? L" (infinite)" : L"ms"
> >> +    );
> >> +  Status = Mp->StartupThisAP (
> >> +                 Mp,
> >> +                 ApFunction,
> >> +                 ProcessorIndex,
> >> +                 NULL,
> >> +                 Timeout * 1000,
> >> +                 &ApArg,
> >> +                 NULL
> >> +                 );
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"failed: %r\n", Status);
> >> +    return Status;
> >> +  } else {
> >> +    Print (L"done.\n");
> >> +    Print (ApArg.Buffer[ProcessorIndex]);
> >> +  }
> >> +
> >> +  FreeApFuncBuffer (&ApArg, ProcessorIndex + 1);
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/** Runs all APs.
> >> +
> >> +  @param Mp                 The MP Services Protocol.
> >> +  @param NumCpus            The number of CPUs in the system.
> >> +  @param Timeout            Timeout in milliseconds.
> >> +  @param RunAPsSequentially Run APs sequentially (FALSE: run
> >> simultaneously)
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +StartupAllAPs (
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  IN UINTN                     NumCpus,
> >> +  IN UINTN                     Timeout,
> >> +  IN BOOLEAN                   RunAPsSequentially
> >> +  )
> >> +{
> >> +  EFI_STATUS  Status;
> >> +  UINTN       Index;
> >> +  APFUNC_ARG  ApArg;
> >> +
> >> +  Status = AllocateApFuncBufferAllAPs (&ApArg, Mp, NumCpus);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> >> +  Print (
> >> +    L"Running with SingleThread %s, %u%s timeout...",
> >> +    (RunAPsSequentially) ? L"TRUE" : L"FALSE",
> >> +    Timeout,
> >> +    (Timeout == INFINITE_TIMEOUT) ? L" (infinite)" : L"ms"
> >> +    );
> >> +
> >> +  Status = Mp->StartupAllAPs (
> >> +                 Mp,
> >> +                 ApFunction,
> >> +                 RunAPsSequentially,
> >> +                 NULL,
> >> +                 Timeout * 1000,
> >> +                 &ApArg,
> >> +                 NULL
> >> +                 );
> >> +
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"failed: %r\n", Status);
> >> +
> >> +    return Status;
> >> +  } else {
> >> +    Print (L"done.\n");
> >> +
> >> +    for (Index = 0; Index < NumCpus; Index++) {
> >> +      Print (ApArg.Buffer[Index]);
> >> +    }
> >> +  }
> >> +
> >> +  FreeApFuncBuffer (&ApArg, NumCpus);
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/**
> >> +  Enables the specified AP.
> >> +
> >> +  @param Mp               The MP Services Protocol.
> >> +  @param ProcessorIndex   The processor to enable.
> >> +  @param ProcessorHealthy The health status of the processor.
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +EnableAP (
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  UINTN                        ProcessorIndex,
> >> +  BOOLEAN                      ProcessorHealthy
> > [KQ] These parameters should have the "IN" attributes?
> >> +  )
> >> +{
> >> +  EFI_STATUS  Status;
> >> +  UINT32      HealthFlag;
> >> +
> >> +  if (ProcessorHealthy) {
> >> +    Print (L"Enabling Processor %d with HealthFlag healthy...",
> >> ProcessorIndex);
> >> +    HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
> >> +  } else {
> >> +    Print (L"Enabling Processor %d with HealthFlag faulted...",
> >> ProcessorIndex);
> >> +    HealthFlag = 0;
> >> +  }
> >> +
> >> +  Status = Mp->EnableDisableAP (Mp, ProcessorIndex, TRUE, &HealthFlag);
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"failed: %r\n", Status);
> >> +    return Status;
> >> +  } else {
> >> +    Print (L"done.\n");
> >> +  }
> >> +
> >> +  return Status;
> >> +}
> >> +
> >> +/**
> >> +  Disables the specified AP.
> >> +
> >> +  @param Mp               The MP Services Protocol.
> >> +  @param ProcessorIndex   The processor to disable.
> >> +  @param ProcessorHealthy The health status of the processor.
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +**/
> >> +STATIC
> >> +EFI_STATUS
> >> +DisableAP (
> >> +  IN EFI_MP_SERVICES_PROTOCOL  *Mp,
> >> +  UINTN                        ProcessorIndex,
> >> +  BOOLEAN                      ProcessorHealthy
> > [KQ] These parameters should have the "IN" attributes?
> >> +  )
> >> +{
> >> +  EFI_STATUS  Status;
> >> +  UINT32      HealthFlag;
> >> +
> >> +  if (ProcessorHealthy) {
> >> +    Print (L"Disabling Processor %d with HealthFlag healthy...",
> >> ProcessorIndex);
> >> +    HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
> >> +  } else {
> >> +    Print (L"Disabling Processor %d with HealthFlag faulted...",
> >> ProcessorIndex);
> >> +    HealthFlag = 0;
> >> +  }
> >> +
> >> +  Status = Mp->EnableDisableAP (Mp, ProcessorIndex, FALSE, &HealthFlag);
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"failed: %r\n", Status);
> >> +    return Status;
> >> +  } else {
> >> +    Print (L"done.\n");
> >> +  }
> >> +
> >> +  return 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;
> >> +  UINTN                     BspIndex;
> >> +  UINTN                     CpuIndex;
> >> +  UINTN                     NumCpus;
> >> +  BOOLEAN                   ProcessorHealthy;
> >> +  MP_SERVICES_TEST_OPTIONS  Options;
> >> +
> >> +  BspIndex = 0;
> >> +
> >> +  Status = gBS->LocateProtocol (
> >> +                  &gEfiMpServiceProtocolGuid,
> >> +                  NULL,
> >> +                  (VOID **)&Mp
> >> +                  );
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not
> >> installed on platform?\n", Status);
> >> +    return EFI_NOT_FOUND;
> >> +  }
> >> +
> >> +  Status = ParseArguments (&Options);
> >> +  if (EFI_ERROR (Status)) {
> >> +    return EFI_INVALID_PARAMETER;
> >> +  }
> >> +
> >> +  Status = GetProcessorInformation (Mp, &NumCpus, &BspIndex);
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"Error: Failed to fetch processor information.\n");
> >> +    return Status;
> >> +  }
> >> +
> >> +  if (Options.PrintBspProcessorIndex) {
> >> +    Status = Mp->WhoAmI (Mp, &CpuIndex);
> >> +    if (EFI_ERROR (Status)) {
> >> +      Print (L"WhoAmI failed: %r\n", Status);
> >> +      return Status;
> >> +    } else {
> >> +      Print (L"BSP: %016lx\n", CpuIndex);
> >> +    }
> >> +  }
> >> +
> >> +  if (Options.PrintProcessorInformation) {
> >> +    NumCpus = PrintProcessorInformation (Mp, &BspIndex);
> >> +    if (NumCpus < 2) {
> >> +      Print (L"Error: Uniprocessor system found.\n");
> >> +      return EFI_INVALID_PARAMETER;
> >> +    }
> >> +  }
> >> +
> >> +  if (Options.RunSingleAP) {
> >> +    Status = StartupThisAP (
> >> +               Mp,
> >> +               Options.ProcessorIndex,
> >> +               Options.Timeout
> >> +               );
> >> +    if (EFI_ERROR (Status)) {
> >> +      return Status;
> >> +    }
> >> +  }
> >> +
> >> +  if (Options.RunAllAPs) {
> >> +    Status = StartupAllAPs (Mp, NumCpus, Options.Timeout,
> >> Options.RunAPsSequentially);
> >> +    if (EFI_ERROR (Status)) {
> >> +      return Status;
> >> +    }
> >> +  }
> >> +
> >> +  if (Options.EnableProcessor) {
> >> +    ProcessorHealthy = TRUE;
> >> +    if (Options.SetProcessorUnhealthy) {
> >> +      ProcessorHealthy = FALSE;
> >> +    }
> >> +
> >> +    Status = EnableAP (Mp, Options.ProcessorIndex, ProcessorHealthy);
> >> +    if (EFI_ERROR (Status)) {
> >> +      return Status;
> >> +    }
> >> +  }
> >> +
> >> +  if (Options.DisableProcessor) {
> >> +    ProcessorHealthy = TRUE;
> >> +    if (Options.SetProcessorUnhealthy) {
> >> +      ProcessorHealthy = FALSE;
> >> +    }
> >> +
> >> +    Status = DisableAP (Mp, Options.ProcessorIndex, ProcessorHealthy);
> >> +    if (EFI_ERROR (Status)) {
> >> +      return Status;
> >> +    }
> >> +  }
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> >> diff --git a/MdeModulePkg/Application/MpServicesTest/Options.c
> >> b/MdeModulePkg/Application/MpServicesTest/Options.c
> >> new file mode 100644
> >> index 000000000000..e820c061e1ec
> >> --- /dev/null
> >> +++ b/MdeModulePkg/Application/MpServicesTest/Options.c
> >> @@ -0,0 +1,164 @@
> >> +/** @file
> >> +  Options handling code.
> >> +
> >> +  Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights
> >> reserved.<BR>
> >> +  Copyright (c) 2010-2019  Finnbarr P. Murphy.   All rights
> >> reserved.<BR>
> >> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> >> +**/
> >> +
> >> +#include <Uefi.h>
> >> +#include <Library/BaseMemoryLib.h>
> >> +#include <Protocol/ShellParameters.h>
> >> +#include <Library/BaseLib.h>
> >> +#include <Library/UefiLib.h>
> >> +#include <Library/UefiBootServicesTableLib.h>
> >> +
> >> +#include "Options.h"
> >> +
> >> +STATIC UINTN   Argc;
> >> +STATIC CHAR16  **Argv;
> >> +
> >> +/**
> >> +
> >> +  This function provides argc and argv.
> >> +
> >> +  @return Status
> >> +**/
> >> +EFI_STATUS
> >> +GetArg (
> >> +  VOID
> >> +  )
> >> +{
> >> +  EFI_STATUS                     Status;
> >> +  EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters;
> >> +
> >> +  Status = gBS->HandleProtocol (
> >> +                  gImageHandle,
> >> +                  &gEfiShellParametersProtocolGuid,
> >> +                  (VOID **)&ShellParameters
> >> +                  );
> >> +  if (EFI_ERROR (Status)) {
> >> +    return Status;
> >> +  }
> >> +
> >> +  Argc = ShellParameters->Argc;
> >> +  Argv = ShellParameters->Argv;
> >> +  return EFI_SUCCESS;
> >> +}
> >> +
> >> +/**
> >> +  Print app usage.
> >> +**/
> >> +STATIC
> >> +VOID
> >> +PrintUsage (
> >> +  VOID
> >> +  )
> >> +{
> >> +  Print (L"MpServicesTest:  usage\n");
> >> +  Print (L"  MpServicesTest -A [-O]\n");
> >> +  Print (L"  MpServicesTest -T <Timeout>\n");
> >> +  Print (L"  MpServicesTest -S <Processor #>\n");
> >> +  Print (L"  MpServicesTest -P\n");
> >> +  Print (L"  MpServicesTest -U\n");
> >> +  Print (L"  MpServicesTest -W\n");
> >> +  Print (L"  MpServicesTest -E <Processor #>\n");
> >> +  Print (L"  MpServicesTest -D <Processor #>\n");
> >> +  Print (L"  MpServicesTest -h\n");
> >> +  Print (L"Parameter:\n");
> >> +  Print (L"  -A:  Run all APs.\n");
> >> +  Print (L"  -O:  Run APs sequentially (use with -A).\n");
> >> +  Print (L"  -T:  Specify timeout in milliseconds. Default is to wait
> >> forever.\n");
> >> +  Print (L"  -S:  Specify the single AP to run.\n");
> >> +  Print (L"  -P:  Print processor information.\n");
> >> +  Print (L"  -U:  Set the specified AP to the Unhealthy status (use
> >> with -E/-D).\n");
> >> +  Print (L"  -W:  Run WhoAmI and print index of BSP.\n");
> >> +  Print (L"  -E:  Enable the specified AP.\n");
> >> +  Print (L"  -D:  Disable the specified AP.\n");
> >> +  Print (L"  -h:  Print this help page.\n");
> >> +}
> >> +
> >> +/**
> >> +  Parses any arguments provided on the command line.
> >> +
> >> +  @param Options  The arguments structure.
> >> +
> >> +  @return EFI_SUCCESS on success, or an error code.
> >> +**/
> >> +EFI_STATUS
> >> +ParseArguments (
> >> +  MP_SERVICES_TEST_OPTIONS  *Options
> >> +  )
> >> +{
> >> +  EFI_STATUS    Status;
> >> +  UINT32        ArgIndex;
> > [KQ] Similar to the other comment, ArgIndex is of UINT32 is compared to
> > Argc of UINTN could make some compilers unhappy.
> >> +  CONST CHAR16  *Argument;
> >> +  BOOLEAN       NeedsValue;
> >> +  UINTN         *Value;
> >> +
> >> +  Status = GetArg ();
> >> +  if (EFI_ERROR (Status)) {
> >> +    Print (L"Please use the UEFI Shell to run this application!\n",
> >> Status);
> >> +    return Status;
> >> +  }
> >> +
> >> +  if (Argc == 1) {
> >> +    PrintUsage ();
> >> +  }
> >> +
> >> +  ZeroMem (Options, sizeof (MP_SERVICES_TEST_OPTIONS));
> >> +
> >> +  for (ArgIndex = 1; ArgIndex < Argc; ArgIndex++) {
> >> +    Argument   = Argv[ArgIndex];
> >> +    NeedsValue = FALSE;
> >> +
> >> +    if (StrCmp (Argument, L"-A") == 0) {
> >> +      Options->RunAllAPs = TRUE;
> >> +    } else if (StrCmp (Argument, L"-O") == 0) {
> >> +      Options->RunAPsSequentially = TRUE;
> >> +    } else if (StrCmp (Argument, L"-T") == 0) {
> >> +      NeedsValue = TRUE;
> >> +      Value      = &Options->Timeout;
> >> +    } else if (StrCmp (Argument, L"-S") == 0) {
> >> +      Options->RunSingleAP = TRUE;
> >> +      NeedsValue           = TRUE;
> >> +      Value                = &Options->ProcessorIndex;
> >> +    } else if (StrCmp (Argument, L"-P") == 0) {
> >> +      Options->PrintProcessorInformation = TRUE;
> >> +    } else if (StrCmp (Argument, L"-U") == 0) {
> >> +      Options->SetProcessorUnhealthy = TRUE;
> >> +    } else if (StrCmp (Argument, L"-W") == 0) {
> >> +      Options->PrintBspProcessorIndex = TRUE;
> >> +    } else if (StrCmp (Argument, L"-E") == 0) {
> >> +      Options->EnableProcessor = TRUE;
> >> +      NeedsValue               = TRUE;
> >> +      Value                    = &Options->ProcessorIndex;
> >> +    } else if (StrCmp (Argument, L"-D") == 0) {
> >> +      Options->DisableProcessor = TRUE;
> >> +      NeedsValue                = TRUE;
> >> +      Value                     = &Options->ProcessorIndex;
> >> +    } else {
> >> +      PrintUsage ();
> >> +      ZeroMem (Options, sizeof (MP_SERVICES_TEST_OPTIONS));
> >> +      return EFI_SUCCESS;
> >> +    }
> >> +
> >> +    if (NeedsValue) {
> >> +      if ((ArgIndex + 1) < Argc) {
> >> +        Status = StrDecimalToUintnS (Argv[ArgIndex + 1], NULL, Value);
> >> +        if (EFI_ERROR (Status)) {
> >> +          Print (L"Error: option value must be a positive integer.\n");
> >> +          PrintUsage ();
> >> +          return EFI_INVALID_PARAMETER;
> >> +        }
> >> +
> >> +        ArgIndex++;
> >> +      } else {
> >> +        PrintUsage ();
> >> +        return EFI_INVALID_PARAMETER;
> >> +      }
> >> +    }
> >> +  }
> >> +
> >> +  return EFI_SUCCESS;
> >> +}
> 
> 
> 
> 


  reply	other threads:[~2023-01-09  1:33 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-04 15:37 [PATCH v4 0/3] ArmPkg,MdeModulePkg: Implement EFI_MP_SERVICES_PROTOCOL for AArch64 and add an MpServicesTest application to exercise it Rebecca Cran
2023-01-04 15:37 ` [PATCH v4 1/3] ArmPkg: Add GET_MPIDR_AFFINITY_BITS and MPIDR_MT_BIT to ArmLib.h Rebecca Cran
2023-01-04 15:37 ` [PATCH v4 2/3] ArmPkg: implement EFI_MP_SERVICES_PROTOCOL based on PSCI calls Rebecca Cran
2023-01-06 22:11   ` [edk2-devel] " Kun Qin
2023-01-16 18:41     ` Rebecca Cran
     [not found]   ` <1737D7D0377487BE.3916@groups.io>
2023-01-06 22:16     ` Kun Qin
2023-01-13  2:01       ` Kun Qin
2023-01-16 19:06         ` Rebecca Cran
2023-01-16 18:45       ` Rebecca Cran
2023-01-04 15:37 ` [PATCH v4 3/3] MdeModulePkg: Add new Application/MpServicesTest application Rebecca Cran
2023-01-06  9:40   ` Ard Biesheuvel
2023-01-06 11:02     ` [edk2-devel] " Laszlo Ersek
2023-01-06 18:40       ` Rebecca Cran
2023-01-06 22:33   ` Kun Qin
2023-01-08  4:56     ` Rebecca Cran
2023-01-09  1:32       ` Ni, Ray [this message]
2023-01-09 14:25         ` Rebecca Cran
2023-01-09 17:12           ` Ard Biesheuvel
2023-01-10  1:08             ` Ni, Ray
2023-01-15  1:02               ` Rebecca Cran
2023-01-07 22:19   ` Laszlo Ersek
2023-01-05 17:39 ` [PATCH v4 0/3] ArmPkg,MdeModulePkg: Implement EFI_MP_SERVICES_PROTOCOL for AArch64 and add an MpServicesTest application to exercise it Ard Biesheuvel
2023-01-05 17:59   ` Ard Biesheuvel
2023-01-06  5:11     ` [edk2-devel] " Kun Qin
2023-01-06 18:42       ` Rebecca Cran
2023-01-06 19:56         ` Kun Qin
2023-01-08  3:55   ` Rebecca Cran
2023-01-11 16:41 ` [edk2-devel] " Patrik Berglund
2023-01-11 22:54   ` 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=MN6PR11MB8244FEB616B6E8EB65C6052A8CFE9@MN6PR11MB8244.namprd11.prod.outlook.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