public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* Re: [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application
@ 2023-01-09  8:38 Tiger Liu(BJ-RD)
  0 siblings, 0 replies; 3+ messages in thread
From: Tiger Liu(BJ-RD) @ 2023-01-09  8:38 UTC (permalink / raw)
  To: Rebecca Cran, devel@edk2.groups.io, Rebecca Cran

[-- Attachment #1: Type: text/plain, Size: 30710 bytes --]

Hi, Rebecca:
Got it!

I think shell MP test tool is convenient than unit test infrastructure.

Thanks
发件人: Rebecca Cran <rebecca@bsdio.com>
发送时间: 2022年12月29日 8:01
收件人: devel@edk2.groups.io; Tiger Liu(BJ-RD) <TigerLiu@zhaoxin.com>; Rebecca Cran <rebecca@quicinc.com>
主题: Re: [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application


No, it hasn't been merged yet. I did some work to finish off bug fixes and improvements last week, so I'll send out a new patch series: I was going to wait until people are back after Christmas and the New Year, but I may as well send it out now.



--
Rebecca Cran


On 12/26/22 23:19, Tiger Liu(BJ-RD) wrote:

Hello:

Does this MpServicesTest app have been merged into master branch?

I could not find it in current GitHub code base.



Thanks

-----邮件原件-----

发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Rebecca Cran

发送时间: 2022年9月7日 12:03

收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; ardb@kernel.org<mailto:ardb@kernel.org>; quic_llindhol@quicinc.com<mailto:quic_llindhol@quicinc.com>; Sami Mujawar <sami.mujawar@arm.com<mailto:sami.mujawar@arm.com>>; Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Liming Gao <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>

抄送: Rebecca Cran <rebecca@quicinc.com<mailto:rebecca@quicinc.com>>

主题: [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application



The MpServicesTest application exercises the EFI_MP_SERVICES_PROTOCOL.



usage:

  MpServicesTest -A [-O]

  MpServicesTest -T <Timeout>

  MpServicesTest -S <Processor #>

  MpServicesTest -P

  MpServicesTest -U <Processor #>

  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<mailto:rebecca@quicinc.com>>

Reviewed-by: Ard Biesheuvel <ardb@kernel.org<mailto:ardb@kernel.org>>

---

MdeModulePkg/MdeModulePkg.dsc                              |   2 +

MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf |  40 ++

MdeModulePkg/Application/MpServicesTest/Options.h          |  39 ++

MdeModulePkg/Application/MpServicesTest/MpServicesTest.c   | 555 ++++++++++++++++++++

MdeModulePkg/Application/MpServicesTest/Options.c          | 215 ++++++++

5 files changed, 851 insertions(+)



diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 45a8ec84ad69..295ff4ddfcd8 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..1cea8f52f25d

--- /dev/null

+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c

@@ -0,0 +1,555 @@

+/** @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;

+

+  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

+  )

+{

+  INT32  Index;

+

+  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++) {

+        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;

+  }

+

+  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 TRUE, %d%s timeout...",

+    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

+  )

+{

+  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

+  )

+{

+  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..2ea2c94b7c74

--- /dev/null

+++ b/MdeModulePkg/Application/MpServicesTest/Options.c

@@ -0,0 +1,215 @@

+/** @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;

+}

+

+/**

+  Checks if the character is a decimal digit.

+

+  @param Char The character to check.

+

+  @return TRUE if the character is a decimal digit.

+**/

+BOOLEAN

+IsUnicodeDecimalDigit (

+  CHAR16  Char

+  )

+{

+  return ((BOOLEAN)(Char >= L'0' && Char <= L'9')); }

+

+/**

+  Converts the string to an integer.

+

+  @param String The input string.

+  @param Value  The converted number.

+

+  @return EFI_SUCCESS on success, or an error code.

+**/

+EFI_STATUS

+UnicodeStringToInteger (

+  CHAR16  *String,

+  UINTN   *Value

+  )

+{

+  UINTN  Result;

+

+  Result = 0;

+

+  if ((String == NULL) || (StrSize (String) == 0) || (Value == NULL)) {

+    return (EFI_INVALID_PARAMETER);

+  }

+

+  while (IsUnicodeDecimalDigit (*String)) {

+    if (!(Result <= (DivU64x32 ((((UINT64) ~0) - (*String - L'0')), 10)))) {

+      return (EFI_DEVICE_ERROR);

+    }

+

+    Result = MultU64x32 (Result, 10) + (*String - L'0');

+    String++;

+  }

+

+  *Value = Result;

+

+  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;

+  INT32         ArgIndex;

+  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 = UnicodeStringToInteger (Argv[ArgIndex + 1], 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;

+}

--

2.30.2











保密声明:
本邮件含有保密或专有信息,仅供指定收件人使用。严禁对本邮件或其内容做任何未经授权的查阅、使用、复制或转发。
CONFIDENTIAL NOTE:
This email contains confidential or legally privileged information and is for the sole use of its intended recipient. Any unauthorized review, use, copying or forwarding of this email or the content of this email is strictly prohibited.



保密声明:
本邮件含有保密或专有信息,仅供指定收件人使用。严禁对本邮件或其内容做任何未经授权的查阅、使用、复制或转发。
CONFIDENTIAL NOTE:
This email contains confidential or legally privileged information and is for the sole use of its intended recipient. Any unauthorized review, use, copying or forwarding of this email or the content of this email is strictly prohibited.

[-- Attachment #2: Type: text/html, Size: 116795 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread
* Re: [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application
@ 2022-12-27  6:19 Tiger Liu(BJ-RD)
  2022-12-29  0:00 ` Rebecca Cran
  0 siblings, 1 reply; 3+ messages in thread
From: Tiger Liu(BJ-RD) @ 2022-12-27  6:19 UTC (permalink / raw)
  To: edk2-devel-groups-io, Rebecca Cran

[-- Attachment #1: Type: text/plain, Size: 29464 bytes --]

Hello:

Does this MpServicesTest app have been merged into master branch?

I could not find it in current GitHub code base.



Thanks

-----邮件原件-----

发件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io> <devel@edk2.groups.io<mailto:devel@edk2.groups.io>> 代表 Rebecca Cran

发送时间: 2022年9月7日 12:03

收件人: devel@edk2.groups.io<mailto:devel@edk2.groups.io>; ardb@kernel.org<mailto:ardb@kernel.org>; quic_llindhol@quicinc.com<mailto:quic_llindhol@quicinc.com>; Sami Mujawar <sami.mujawar@arm.com<mailto:sami.mujawar@arm.com>>; Jian J Wang <jian.j.wang@intel.com<mailto:jian.j.wang@intel.com>>; Liming Gao <gaoliming@byosoft.com.cn<mailto:gaoliming@byosoft.com.cn>>

抄送: Rebecca Cran <rebecca@quicinc.com<mailto:rebecca@quicinc.com>>

主题: [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application



The MpServicesTest application exercises the EFI_MP_SERVICES_PROTOCOL.



usage:

  MpServicesTest -A [-O]

  MpServicesTest -T <Timeout>

  MpServicesTest -S <Processor #>

  MpServicesTest -P

  MpServicesTest -U <Processor #>

  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<mailto:rebecca@quicinc.com>>

Reviewed-by: Ard Biesheuvel <ardb@kernel.org<mailto:ardb@kernel.org>>

---

MdeModulePkg/MdeModulePkg.dsc                              |   2 +

MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf |  40 ++

MdeModulePkg/Application/MpServicesTest/Options.h          |  39 ++

MdeModulePkg/Application/MpServicesTest/MpServicesTest.c   | 555 ++++++++++++++++++++

MdeModulePkg/Application/MpServicesTest/Options.c          | 215 ++++++++

5 files changed, 851 insertions(+)



diff --git a/MdeModulePkg/MdeModulePkg.dsc b/MdeModulePkg/MdeModulePkg.dsc index 45a8ec84ad69..295ff4ddfcd8 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..1cea8f52f25d

--- /dev/null

+++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c

@@ -0,0 +1,555 @@

+/** @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;

+

+  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

+  )

+{

+  INT32  Index;

+

+  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++) {

+        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;

+  }

+

+  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 TRUE, %d%s timeout...",

+    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

+  )

+{

+  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

+  )

+{

+  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..2ea2c94b7c74

--- /dev/null

+++ b/MdeModulePkg/Application/MpServicesTest/Options.c

@@ -0,0 +1,215 @@

+/** @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;

+}

+

+/**

+  Checks if the character is a decimal digit.

+

+  @param Char The character to check.

+

+  @return TRUE if the character is a decimal digit.

+**/

+BOOLEAN

+IsUnicodeDecimalDigit (

+  CHAR16  Char

+  )

+{

+  return ((BOOLEAN)(Char >= L'0' && Char <= L'9')); }

+

+/**

+  Converts the string to an integer.

+

+  @param String The input string.

+  @param Value  The converted number.

+

+  @return EFI_SUCCESS on success, or an error code.

+**/

+EFI_STATUS

+UnicodeStringToInteger (

+  CHAR16  *String,

+  UINTN   *Value

+  )

+{

+  UINTN  Result;

+

+  Result = 0;

+

+  if ((String == NULL) || (StrSize (String) == 0) || (Value == NULL)) {

+    return (EFI_INVALID_PARAMETER);

+  }

+

+  while (IsUnicodeDecimalDigit (*String)) {

+    if (!(Result <= (DivU64x32 ((((UINT64) ~0) - (*String - L'0')), 10)))) {

+      return (EFI_DEVICE_ERROR);

+    }

+

+    Result = MultU64x32 (Result, 10) + (*String - L'0');

+    String++;

+  }

+

+  *Value = Result;

+

+  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;

+  INT32         ArgIndex;

+  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 = UnicodeStringToInteger (Argv[ArgIndex + 1], 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;

+}

--

2.30.2














保密声明:
本邮件含有保密或专有信息,仅供指定收件人使用。严禁对本邮件或其内容做任何未经授权的查阅、使用、复制或转发。
CONFIDENTIAL NOTE:
This email contains confidential or legally privileged information and is for the sole use of its intended recipient. Any unauthorized review, use, copying or forwarding of this email or the content of this email is strictly prohibited.

[-- Attachment #2: Type: text/html, Size: 111898 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-01-09  8:38 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-01-09  8:38 [edk2-devel] [PATCH v2 2/2] MdeModulePkg: Add new Application/MpServicesTest application Tiger Liu(BJ-RD)
  -- strict thread matches above, loose matches on Subject: below --
2022-12-27  6:19 Tiger Liu(BJ-RD)
2022-12-29  0:00 ` Rebecca Cran

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox