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;
> >> +}
>
>
>
>
next prev parent 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