From: "Rebecca Cran" <rebecca@nuviainc.com>
To: Sami Mujawar <sami.mujawar@arm.com>,
devel@edk2.groups.io, Ard Biesheuvel <ardb+tianocore@kernel.org>,
Gerd Hoffmann <kraxel@redhat.com>,
Samer El-Haj-Mahmoud <samer.el-haj-mahmoud@arm.com>,
Leif Lindholm <leif@nuviainc.com>,
Jian J Wang <jian.j.wang@intel.com>,
Liming Gao <gaoliming@byosoft.com.cn>, nd <nd@arm.com>
Subject: Re: [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services
Date: Thu, 9 Dec 2021 15:53:07 -0700 [thread overview]
Message-ID: <89316ba7-29c3-ea7f-5651-fcdeb845b0fd@nuviainc.com> (raw)
In-Reply-To: <bc4d1055-113b-8d13-f872-cdba1e33f97c@arm.com>
Now that the edk2 tree is unfrozen, I'd like to get this committed.
Could anyone else review it please, or if it's ready commit it?
Thanks.
Rebecca Cran
On 11/10/21 11:06 AM, Sami Mujawar wrote:
> Hi Rebecca,
>
> Thank you for the updated patch. These changes look good to me.
>
> The INF file mentions support for IA32 and X64 so it would be got to get
> feedback for other architectures and from the MdeModulePkg maintainers.
>
> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com>
>
> Regards,
>
> Sami Mujawar
>
> On 05/11/2021 08:31 PM, Rebecca Cran wrote:
>> Add a new MpServicesTest application under MdeModulePkg/Application that
>> exercises the EFI_MP_SERVICES_PROTOCOL.
>>
>> Signed-off-by: Rebecca Cran <rebecca@nuviainc.com>
>> ---
>> MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 428
>> ++++++++++++++++++++
>> MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++
>> MdeModulePkg/MdeModulePkg.dsc | 2 +
>> 3 files changed, 468 insertions(+)
>>
>> diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
>> b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
>> new file mode 100644
>> index 000000000000..d066bdd530d5
>> --- /dev/null
>> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
>> @@ -0,0 +1,428 @@
>> +/** @file
>> +
>> + Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
>> + SPDX-License-Identifier: BSD-2-Clause-Patent
>> +**/
>> +
>> +#include <Uefi.h>
>> +#include <Library/DebugLib.h>
>> +#include <Library/RngLib.h>
>> +#include <Library/UefiBootServicesTableLib.h>
>> +#include <Library/UefiLib.h>
>> +#include <Pi/PiMultiPhase.h>
>> +#include <Protocol/MpService.h>
>> +
>> +#define MAX_RANDOM_PROCESSOR_RETRIES 10
>> +
>> +#define AP_STARTUP_TEST_TIMEOUT_US 50000
>> +#define INFINITE_TIMEOUT 0
>> +
>> +
>> +/** The procedure to run with the MP Services interface.
>> +
>> + @param Buffer The procedure argument.
>> +
>> +**/
>> +STATIC
>> +VOID
>> +EFIAPI
>> +ApFunction (
>> + IN OUT VOID *Buffer
>> + )
>> +{
>> +}
>> +
>> +/** Displays information returned from MP Services Protocol.
>> +
>> + @param Mp The MP Services Protocol
>> +
>> + @return The number of CPUs in the system.
>> +
>> +**/
>> +STATIC
>> +UINTN
>> +PrintProcessorInformation (
>> + IN EFI_MP_SERVICES_PROTOCOL *Mp
>> + )
>> +{
>> + EFI_STATUS Status;
>> + EFI_PROCESSOR_INFORMATION CpuInfo;
>> + UINTN Index;
>> + UINTN NumCpu;
>> + UINTN NumEnabledCpu;
>> +
>> + Status = Mp->GetNumberOfProcessors (Mp, &NumCpu, &NumEnabledCpu);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"GetNumberOfProcessors failed: %r\n", Status);
>> + } else {
>> + Print (L"Number of CPUs: %ld, Enabled: %d\n", NumCpu,
>> NumEnabledCpu);
>> + }
>> +
>> + for (Index = 0; Index < NumCpu; Index++) {
>> + Status = Mp->GetProcessorInfo (Mp, CPU_V2_EXTENDED_TOPOLOGY |
>> Index, &CpuInfo);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"GetProcessorInfo for Processor %d failed: %r\n",
>> Index, Status);
>> + } else {
>> + Print (
>> + L"Processor %d:\n"
>> + L"\tID: %016lx\n"
>> + L"\tStatus: %s | ",
>> + Index,
>> + CpuInfo.ProcessorId,
>> + (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT) ? L"BSP" : L"AP"
>> + );
>> +
>> + Print (L"%s | ", (CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT)
>> ? L"Enabled" : L"Disabled");
>> + Print (L"%s\n", (CpuInfo.StatusFlag &
>> PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted");
>> +
>> + Print (
>> + L"\tLocation: Package %d, Core %d, Thread %d\n"
>> + L"\tExtended Information: Package %d, Module %d, Tile %d,
>> Die %d, Core %d, Thread %d\n\n",
>> + CpuInfo.Location.Package,
>> + CpuInfo.Location.Core,
>> + CpuInfo.Location.Thread,
>> + CpuInfo.ExtendedInformation.Location2.Package,
>> + CpuInfo.ExtendedInformation.Location2.Module,
>> + CpuInfo.ExtendedInformation.Location2.Tile,
>> + CpuInfo.ExtendedInformation.Location2.Die,
>> + CpuInfo.ExtendedInformation.Location2.Core,
>> + CpuInfo.ExtendedInformation.Location2.Thread
>> + );
>> + }
>> + }
>> +
>> + return NumCpu;
>> +}
>> +
>> +/** Returns the index of an enabled AP selected at random.
>> +
>> + @param Mp The MP Services Protocol.
>> + @param ProcessorIndex The index of a random enabled AP.
>> +
>> + @retval EFI_SUCCESS An enabled processor was found and returned.
>> + @retval EFI_NOT_FOUND A processor was unable to be selected.
>> +
>> +**/
>> +STATIC
>> +EFI_STATUS
>> +GetRandomEnabledProcessorIndex (
>> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
>> + OUT UINTN *ProcessorIndex
>> + )
>> +{
>> + UINTN Index;
>> + UINTN IndexOfEnabledCpu;
>> + UINTN NumCpus;
>> + UINTN NumEnabledCpus;
>> + UINTN IndexOfEnabledCpuToUse;
>> + UINT16 RandomNumber;
>> + BOOLEAN Success;
>> + EFI_STATUS Status;
>> + EFI_PROCESSOR_INFORMATION CpuInfo;
>> +
>> + IndexOfEnabledCpu = 0;
>> +
>> + Success = GetRandomNumber16 (&RandomNumber);
>> + ASSERT (Success == TRUE);
>> +
>> + Status = Mp->GetNumberOfProcessors (Mp, &NumCpus, &NumEnabledCpus);
>> + ASSERT_EFI_ERROR (Status);
>> +
>> + if (NumEnabledCpus == 1) {
>> + Print (L"All APs are disabled\n");
>> + return EFI_NOT_FOUND;
>> + }
>> +
>> + IndexOfEnabledCpuToUse = RandomNumber % NumEnabledCpus;
>> +
>> + for (Index = 0; Index < NumCpus; Index++) {
>> + Status = Mp->GetProcessorInfo (Mp, Index, &CpuInfo);
>> + ASSERT_EFI_ERROR (Status);
>> + if ((CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT) &&
>> + !(CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT)) {
>> + if (IndexOfEnabledCpuToUse == IndexOfEnabledCpu) {
>> + *ProcessorIndex = Index;
>> + Status = EFI_SUCCESS;
>> + break;
>> + }
>> +
>> + IndexOfEnabledCpu++;
>> + }
>> + }
>> +
>> + if (Index == NumCpus) {
>> + Status = EFI_NOT_FOUND;
>> + }
>> +
>> + return Status;
>> +}
>> +
>> +/** Tests for the StartupThisAP function.
>> +
>> + @param Mp The MP Services Protocol.
>> +
>> +**/
>> +STATIC
>> +VOID
>> +StartupThisApTests (
>> + IN EFI_MP_SERVICES_PROTOCOL *Mp
>> + )
>> +{
>> + EFI_STATUS Status;
>> + UINTN ProcessorIndex;
>> + UINT32 Retries;
>> +
>> + Retries = 0;
>> +
>> + do {
>> + Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
>> + } while (EFI_ERROR (Status) && Retries++ <
>> MAX_RANDOM_PROCESSOR_RETRIES);
>> +
>> + if (EFI_ERROR (Status)) {
>> + return;
>> + }
>> +
>> + Print (
>> + L"StartupThisAP on Processor %d with 0 (infinite) timeout...",
>> + ProcessorIndex
>> + );
>> +
>> + Status = Mp->StartupThisAP (
>> + Mp,
>> + ApFunction,
>> + ProcessorIndex,
>> + NULL,
>> + INFINITE_TIMEOUT,
>> + NULL,
>> + NULL
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> +
>> + Retries = 0;
>> +
>> + do {
>> + Status = GetRandomEnabledProcessorIndex (Mp, &ProcessorIndex);
>> + } while (EFI_ERROR (Status) && Retries++ <
>> MAX_RANDOM_PROCESSOR_RETRIES);
>> +
>> + if (EFI_ERROR (Status)) {
>> + return;
>> + }
>> +
>> + Print (
>> + L"StartupThisAP on Processor %d with %dms timeout...",
>> + ProcessorIndex,
>> + AP_STARTUP_TEST_TIMEOUT_US / 1000
>> + );
>> + Status = Mp->StartupThisAP (
>> + Mp,
>> + ApFunction,
>> + ProcessorIndex,
>> + NULL,
>> + AP_STARTUP_TEST_TIMEOUT_US,
>> + NULL,
>> + NULL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> +}
>> +
>> +/** Tests for the StartupAllAPs function.
>> +
>> + @param Mp The MP Services Protocol.
>> + @param NumCpus The number of CPUs in the system.
>> +
>> +**/
>> +STATIC
>> +VOID
>> +StartupAllAPsTests (
>> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
>> + IN UINTN NumCpus
>> + )
>> +{
>> + EFI_STATUS Status;
>> + UINTN Timeout;
>> +
>> + Print (L"Running with SingleThread FALSE, 0 (infinite) timeout...");
>> + Status = Mp->StartupAllAPs (Mp, ApFunction, FALSE, NULL,
>> INFINITE_TIMEOUT, NULL, NULL);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> +
>> + Timeout = NumCpus * AP_STARTUP_TEST_TIMEOUT_US;
>> +
>> + Print (L"Running with SingleThread TRUE, %dms timeout...", Timeout
>> / 1000);
>> + Status = Mp->StartupAllAPs (
>> + Mp,
>> + ApFunction,
>> + TRUE,
>> + NULL,
>> + Timeout,
>> + NULL,
>> + NULL
>> + );
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> +}
>> +
>> +/** Tests for the EnableDisableAP function.
>> +
>> + @param Mp The MP Services Protocol.
>> + @param NumCpus The number of CPUs in the system.
>> +
>> +**/
>> +STATIC
>> +VOID
>> +EnableDisableAPTests (
>> + IN EFI_MP_SERVICES_PROTOCOL *Mp,
>> + IN UINTN NumCpus
>> + )
>> +{
>> + EFI_STATUS Status;
>> + UINTN Index;
>> + UINT32 HealthFlag;
>> +
>> + HealthFlag = 0;
>> +
>> + for (Index = 1; Index < NumCpus; Index++) {
>> + Print (L"Disabling Processor %d with HealthFlag faulted...",
>> Index);
>> + Status = Mp->EnableDisableAP (Mp, Index, FALSE, &HealthFlag);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> + }
>> +
>> + HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;
>> +
>> + for (Index = 1; Index < NumCpus; Index++) {
>> + Print (L"Enabling Processor %d with HealthFlag healthy...", Index);
>> + Status = Mp->EnableDisableAP (Mp, Index, TRUE, &HealthFlag);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"failed: %r\n", Status);
>> + return;
>> + }
>> + else {
>> + Print (L"done.\n");
>> + }
>> + }
>> +}
>> +
>> +/**
>> + The user Entry Point for Application. The user code starts with
>> this function
>> + as the real entry point for the application.
>> +
>> + @param[in] ImageHandle The firmware allocated handle for the
>> EFI image.
>> + @param[in] SystemTable A pointer to the EFI System Table.
>> +
>> + @retval EFI_SUCCESS The entry point is executed successfully.
>> + @retval other Some error occurs when executing this
>> entry point.
>> +
>> +**/
>> +EFI_STATUS
>> +EFIAPI
>> +UefiMain (
>> + IN EFI_HANDLE ImageHandle,
>> + IN EFI_SYSTEM_TABLE *SystemTable
>> + )
>> +{
>> + EFI_STATUS Status;
>> + EFI_MP_SERVICES_PROTOCOL *Mp;
>> + EFI_HANDLE *pHandle;
>> + UINTN HandleCount;
>> + UINTN BspId;
>> + UINTN NumCpus;
>> + UINTN Index;
>> +
>> + pHandle = NULL;
>> + HandleCount = 0;
>> + BspId = 0;
>> +
>> + Status = gBS->LocateHandleBuffer (
>> + ByProtocol,
>> + &gEfiMpServiceProtocolGuid,
>> + NULL,
>> + &HandleCount,
>> + &pHandle
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL (%r). Not
>> installed on platform?\n", Status);
>> + return EFI_NOT_FOUND;
>> + }
>> +
>> + for (Index = 0; Index < HandleCount; Index++) {
>> + Status = gBS->OpenProtocol (
>> + *pHandle,
>> + &gEfiMpServiceProtocolGuid,
>> + (VOID **)&Mp,
>> + NULL,
>> + gImageHandle,
>> + EFI_OPEN_PROTOCOL_GET_PROTOCOL
>> + );
>> +
>> + if (EFI_ERROR (Status)) {
>> + return Status;
>> + }
>> +
>> + pHandle++;
>> + }
>> +
>> + Print (L"Exercising WhoAmI\n\n");
>> + Status = Mp->WhoAmI (Mp, &BspId);
>> + if (EFI_ERROR (Status)) {
>> + Print (L"WhoAmI failed: %r\n", Status);
>> + return Status;
>> + } else {
>> + Print (L"WhoAmI: %016lx\n", BspId);
>> + }
>> +
>> + Print (L"\n");
>> + Print (
>> + L"Exercising GetNumberOfProcessors and GetProcessorInformation
>> with "
>> + L"CPU_V2_EXTENDED_TOPOLOGY\n\n"
>> + );
>> + NumCpus = PrintProcessorInformation (Mp);
>> + if (NumCpus < 2) {
>> + Print (L"UP system found. Not running further tests.\n");
>> + return EFI_INVALID_PARAMETER;
>> + }
>> +
>> + Print (L"\n");
>> + Print (L"Exercising StartupThisAP:\n\n");
>> + StartupThisApTests (Mp);
>> +
>> + Print (L"\n");
>> + Print (L"Exercising StartupAllAPs:\n\n");
>> + StartupAllAPsTests (Mp, NumCpus);
>> +
>> + Print (L"\n");
>> + Print (L"Exercising EnableDisableAP:\n\n");
>> + EnableDisableAPTests (Mp, NumCpus);
>> +
>> + gBS->CloseProtocol (pHandle, &gEfiMpServiceProtocolGuid,
>> gImageHandle, NULL);
>> + return EFI_SUCCESS;
>> +}
>> diff --git
>> a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
>> b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
>> new file mode 100644
>> index 000000000000..8a21ca70d8fa
>> --- /dev/null
>> +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
>> @@ -0,0 +1,38 @@
>> +## @file
>> +# UEFI Application to exercise EFI_MP_SERVICES_PROTOCOL.
>> +#
>> +# Copyright (c) 2021, NUVIA Inc. All rights reserved.<BR>
>> +#
>> +# SPDX-License-Identifier: BSD-2-Clause-Patent
>> +#
>> +##
>> +
>> +[Defines]
>> + INF_VERSION = 1.29
>> + BASE_NAME = MpServicesTest
>> + FILE_GUID = 43e9defa-7209-4b0d-b136-cc4ca02cb469
>> + MODULE_TYPE = UEFI_APPLICATION
>> + VERSION_STRING = 0.1
>> + ENTRY_POINT = UefiMain
>> +
>> +#
>> +# The following information is for reference only and not required
>> by the build tools.
>> +#
>> +# VALID_ARCHITECTURES = IA32 X64 AARCH64
>> +#
>> +
>> +[Sources]
>> + MpServicesTest.c
>> +
>> +[Packages]
>> + MdePkg/MdePkg.dec
>> +
>> +[LibraryClasses]
>> + BaseLib
>> + RngLib
>> + UefiApplicationEntryPoint
>> + UefiLib
>> +
>> +[Protocols]
>> + gEfiMpServiceProtocolGuid ## CONSUMES
>> +
>> diff --git a/MdeModulePkg/MdeModulePkg.dsc
>> b/MdeModulePkg/MdeModulePkg.dsc
>> index b1d83461865e..1cf5ccd30d40 100644
>> --- a/MdeModulePkg/MdeModulePkg.dsc
>> +++ b/MdeModulePkg/MdeModulePkg.dsc
>> @@ -164,6 +164,7 @@
>> MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
>> DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf
>> FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
>> + RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf
>>
>> [LibraryClasses.common.MM_STANDALONE]
>> HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf
>> @@ -215,6 +216,7 @@
>> MdeModulePkg/Application/HelloWorld/HelloWorld.inf
>> MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf
>> MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf
>> + MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
>>
>> MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
>> MdeModulePkg/Logo/Logo.inf
>
> IMPORTANT NOTICE: The contents of this email and any attachments are
> confidential and may also be privileged. If you are not the intended
> recipient, please notify the sender immediately and do not disclose
> the contents to any other person, use it for any purpose, or store or
> copy the information in any medium. Thank you.
next prev parent reply other threads:[~2021-12-09 22:53 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-05 20:31 [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran
2021-11-10 18:06 ` Sami Mujawar
2021-11-10 18:16 ` Rebecca Cran
2021-12-09 22:53 ` Rebecca Cran [this message]
[not found] ` <16BF3806DE6E3547.21850@groups.io>
2021-12-12 18:09 ` [edk2-devel] " Rebecca Cran
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=89316ba7-29c3-ea7f-5651-fcdeb845b0fd@nuviainc.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox