From: "Kun Qin" <kuqin12@gmail.com>
To: devel@edk2.groups.io, rebecca@quicinc.com,
Sami Mujawar <sami.mujawar@arm.com>,
Ard Biesheuvel <ardb+tianocore@kernel.org>,
Leif Lindholm <quic_llindhol@quicinc.com>,
Jian J Wang <jian.j.wang@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>,
Tiger Liu <TigerLiu@zhaoxin.com>
Subject: Re: [edk2-devel] [PATCH v4 3/3] MdeModulePkg: Add new Application/MpServicesTest application
Date: Fri, 6 Jan 2023 14:33:46 -0800 [thread overview]
Message-ID: <cc32bdc7-26fb-7375-0b9a-006fd53ab3d4@gmail.com> (raw)
In-Reply-To: <20230104153727.345236-4-rebecca@quicinc.com>
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-06 22: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 [this message]
2023-01-08 4:56 ` Rebecca Cran
2023-01-09 1:32 ` Ni, Ray
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=cc32bdc7-26fb-7375-0b9a-006fd53ab3d4@gmail.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