* [PATCH v2 0/1] MdeModulePkg: Add MpServicesTest.efi to exercise EFI_MP_SERVICES_PROTOCOL @ 2021-09-20 15:47 Rebecca Cran 2021-09-20 15:47 ` [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran [not found] ` <16A69264F30D2680.28782@groups.io> 0 siblings, 2 replies; 7+ messages in thread From: Rebecca Cran @ 2021-09-20 15:47 UTC (permalink / raw) To: devel, Jian J Wang, Liming Gao; +Cc: Rebecca Cran Add a new application to MdeModulePkg to exercise EFI_MP_SERVICES_PROTOCOL. Changes from v1 to v2: Added Doxygen comments to the functions. Rebecca Cran (1): MdeModulePkg: Add MpServicesTest application to exercise MP Services MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 433 ++++++++++++++++++++ MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ MdeModulePkg/MdeModulePkg.dsc | 2 + 3 files changed, 473 insertions(+) create mode 100644 MdeModulePkg/Application/MpServicesTest/MpServicesTest.c create mode 100644 MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf -- 2.31.1 ^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services 2021-09-20 15:47 [PATCH v2 0/1] MdeModulePkg: Add MpServicesTest.efi to exercise EFI_MP_SERVICES_PROTOCOL Rebecca Cran @ 2021-09-20 15:47 ` Rebecca Cran 2021-11-03 10:54 ` [edk2-devel] " Sami Mujawar [not found] ` <16A69264F30D2680.28782@groups.io> 1 sibling, 1 reply; 7+ messages in thread From: Rebecca Cran @ 2021-09-20 15:47 UTC (permalink / raw) To: devel, Jian J Wang, Liming Gao; +Cc: Rebecca Cran 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 | 433 ++++++++++++++++++++ MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ MdeModulePkg/MdeModulePkg.dsc | 2 + 3 files changed, 473 insertions(+) diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c new file mode 100644 index 000000000000..4eb06e6b7cbd --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c @@ -0,0 +1,433 @@ +/** @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 + +#define RETURN_IF_EFI_ERROR(x) \ + if (EFI_ERROR (x)) { \ + Print (L"failed: %r\n", x); \ + return; \ + } \ + else { \ + Print (L"done.\n"); \ + } + +/** 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 + ); + + RETURN_IF_EFI_ERROR (Status); + + 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 + ); + RETURN_IF_EFI_ERROR (Status); +} + +/** 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); + RETURN_IF_EFI_ERROR (Status); + + 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 + ); + RETURN_IF_EFI_ERROR (Status); +} + +/** 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); + RETURN_IF_EFI_ERROR (Status); + } + + 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); + RETURN_IF_EFI_ERROR (Status); + } +} + +/** Tests for the SwitchBSP function. + + @param Mp The MP Services Protocol. + @param NumCpus The number of CPUs in the system. + +**/ +STATIC +VOID +SwitchBSPTests ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN NumCpus + ) +{ + EFI_STATUS Status; + UINTN Index; + + for (Index = 1; Index < NumCpus; Index++) { + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index); + Status = Mp->SwitchBSP (Mp, Index, FALSE); + RETURN_IF_EFI_ERROR (Status); + } + + for (Index = 0; Index < NumCpus; Index++) { + Print (L"Switching BSP to Processor %d with EnableOldBSP TRUE...", Index); + Status = Mp->SwitchBSP (Mp, Index, TRUE); + RETURN_IF_EFI_ERROR (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; + 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); + + Print (L"\n"); + Print (L"Exercising SwitchBSP\n\n"); + SwitchBSPTests (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 -- 2.31.1 ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services 2021-09-20 15:47 ` [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran @ 2021-11-03 10:54 ` Sami Mujawar 2021-11-03 17:22 ` Rebecca Cran 0 siblings, 1 reply; 7+ messages in thread From: Sami Mujawar @ 2021-11-03 10:54 UTC (permalink / raw) To: devel, rebecca, Jian J Wang, Liming Gao, nd [-- Attachment #1: Type: text/plain, Size: 15750 bytes --] Hi Rebecca, Apologies, I missed reviewing this patch. Please find my feedback inline marked [SAMI]. Regards, Sami Mujawar On 20/09/2021 04:47 PM, Rebecca Cran via groups.io wrote: Add a new MpServicesTest application under MdeModulePkg/Application that exercises the EFI_MP_SERVICES_PROTOCOL. Signed-off-by: Rebecca Cran <rebecca@nuviainc.com><mailto:rebecca@nuviainc.com> --- MdeModulePkg/Application/MpServicesTest/MpServicesTest.c | 433 ++++++++++++++++++++ MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ MdeModulePkg/MdeModulePkg.dsc | 2 + 3 files changed, 473 insertions(+) diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c new file mode 100644 index 000000000000..4eb06e6b7cbd --- /dev/null +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c @@ -0,0 +1,433 @@ +/** @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 + +#define RETURN_IF_EFI_ERROR(x) \ + if (EFI_ERROR (x)) { \ + Print (L"failed: %r\n", x); \ + return; \ + } \ + else { \ + Print (L"done.\n"); \ + } + +/** 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; [SAMI] Minor. I think it should be possible to return from here. In that case the check below if (Index == NumCpus) is not needed and EFI_NOT_FOUND can be returned at the end of the function. + } + + 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 + ); [SAMI] Please align the above code. + + RETURN_IF_EFI_ERROR (Status); [SAMI] I can see that the RETURN_IF_EFI_ERROR() macro is avoiding repetitive code. But I am concerned that the return statement in the macro is hiding the program flow. + + 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 + ); + RETURN_IF_EFI_ERROR (Status); +} + +/** 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); + RETURN_IF_EFI_ERROR (Status); + + 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 + ); + RETURN_IF_EFI_ERROR (Status); +} + +/** 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); + RETURN_IF_EFI_ERROR (Status); + } + + 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); + RETURN_IF_EFI_ERROR (Status); + } +} + +/** Tests for the SwitchBSP function. + + @param Mp The MP Services Protocol. + @param NumCpus The number of CPUs in the system. + +**/ +STATIC +VOID +SwitchBSPTests ( + IN EFI_MP_SERVICES_PROTOCOL *Mp, + IN UINTN NumCpus + ) +{ + EFI_STATUS Status; + UINTN Index; + + for (Index = 1; Index < NumCpus; Index++) { + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index); + Status = Mp->SwitchBSP (Mp, Index, FALSE); [SAMI] The SwitchBsp call can only be performed by the current BSP. So, I am not sure if this would work in a for loop. + RETURN_IF_EFI_ERROR (Status); + } + + for (Index = 0; Index < NumCpus; Index++) { + Print (L"Switching BSP to Processor %d with EnableOldBSP TRUE...", Index); + Status = Mp->SwitchBSP (Mp, Index, TRUE); + RETURN_IF_EFI_ERROR (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; + 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); + + Print (L"\n"); + Print (L"Exercising SwitchBSP\n\n"); + SwitchBSPTests (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. [-- Attachment #2: Type: text/html, Size: 17322 bytes --] ^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services 2021-11-03 10:54 ` [edk2-devel] " Sami Mujawar @ 2021-11-03 17:22 ` Rebecca Cran 0 siblings, 0 replies; 7+ messages in thread From: Rebecca Cran @ 2021-11-03 17:22 UTC (permalink / raw) To: Sami Mujawar, devel, Jian J Wang, Liming Gao, nd [-- Attachment #1: Type: text/plain, Size: 1335 bytes --] Thanks. I have a couple of comments, but will otherwise send out a v2 patch later today. On 11/3/21 4:54 AM, Sami Mujawar wrote: > On 20/09/2021 04:47 PM, Rebecca Cran via groups.io wrote: >> + >> + 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; > [SAMI] Minor. I think it should be possible to return from here. In > that case the check below if (Index == NumCpus) is not needed and > EFI_NOT_FOUND can be returned at the end of the function. That's true, but I prefer to avoid returning from within loops like this. >> + >> + for (Index = 1; Index < NumCpus; Index++) { >> + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index); >> + Status = Mp->SwitchBSP (Mp, Index, FALSE); > [SAMI] The SwitchBsp call can only be performed by the current BSP. > So, I am not sure if this would work in a for loop. That makes sense. I don't think there's a good way to test this then, so I'll remove the SwitchBsp tests. -- Rebecca Cran [-- Attachment #2: Type: text/html, Size: 2295 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
[parent not found: <16A69264F30D2680.28782@groups.io>]
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services [not found] ` <16A69264F30D2680.28782@groups.io> @ 2021-10-16 6:32 ` Rebecca Cran 2021-10-16 6:54 ` Sami Mujawar 0 siblings, 1 reply; 7+ messages in thread From: Rebecca Cran @ 2021-10-16 6:32 UTC (permalink / raw) To: devel, Jian J Wang, Liming Gao Cc: Ard Biesheuvel, Samer El-Haj-Mahmoud, Leif Lindholm, Sami Mujawar, Gerd Hoffmann (cc Leif, Ard, Sami, Samer, Gerd) Could someone review this please? -- Rebecca Cran On 9/20/21 9:47 AM, Rebecca Cran via groups.io 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 | 433 ++++++++++++++++++++ > MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ > MdeModulePkg/MdeModulePkg.dsc | 2 + > 3 files changed, 473 insertions(+) > > diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > new file mode 100644 > index 000000000000..4eb06e6b7cbd > --- /dev/null > +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > @@ -0,0 +1,433 @@ > +/** @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 > + > +#define RETURN_IF_EFI_ERROR(x) \ > + if (EFI_ERROR (x)) { \ > + Print (L"failed: %r\n", x); \ > + return; \ > + } \ > + else { \ > + Print (L"done.\n"); \ > + } > + > +/** 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 > + ); > + > + RETURN_IF_EFI_ERROR (Status); > + > + 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 > + ); > + RETURN_IF_EFI_ERROR (Status); > +} > + > +/** 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); > + RETURN_IF_EFI_ERROR (Status); > + > + 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 > + ); > + RETURN_IF_EFI_ERROR (Status); > +} > + > +/** 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); > + RETURN_IF_EFI_ERROR (Status); > + } > + > + 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); > + RETURN_IF_EFI_ERROR (Status); > + } > +} > + > +/** Tests for the SwitchBSP function. > + > + @param Mp The MP Services Protocol. > + @param NumCpus The number of CPUs in the system. > + > +**/ > +STATIC > +VOID > +SwitchBSPTests ( > + IN EFI_MP_SERVICES_PROTOCOL *Mp, > + IN UINTN NumCpus > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + > + for (Index = 1; Index < NumCpus; Index++) { > + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index); > + Status = Mp->SwitchBSP (Mp, Index, FALSE); > + RETURN_IF_EFI_ERROR (Status); > + } > + > + for (Index = 0; Index < NumCpus; Index++) { > + Print (L"Switching BSP to Processor %d with EnableOldBSP TRUE...", Index); > + Status = Mp->SwitchBSP (Mp, Index, TRUE); > + RETURN_IF_EFI_ERROR (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; > + 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); > + > + Print (L"\n"); > + Print (L"Exercising SwitchBSP\n\n"); > + SwitchBSPTests (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 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services 2021-10-16 6:32 ` Rebecca Cran @ 2021-10-16 6:54 ` Sami Mujawar 2021-11-03 2:31 ` Rebecca Cran 0 siblings, 1 reply; 7+ messages in thread From: Sami Mujawar @ 2021-10-16 6:54 UTC (permalink / raw) To: Rebecca Cran, devel@edk2.groups.io, Jian J Wang, Liming Gao Cc: Ard Biesheuvel, Samer El-Haj-Mahmoud, Leif Lindholm, Gerd Hoffmann, nd [-- Attachment #1: Type: text/plain, Size: 16286 bytes --] Hi Rebecca, I will review this next week. Regard Sami Mujawar ________________________________ From: Rebecca Cran <rebecca@nuviainc.com> Sent: Saturday, 16 October 2021, 7:33 am To: devel@edk2.groups.io; Jian J Wang; Liming Gao Cc: Ard Biesheuvel; Samer El-Haj-Mahmoud; Leif Lindholm; Sami Mujawar; Gerd Hoffmann Subject: Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services (cc Leif, Ard, Sami, Samer, Gerd) Could someone review this please? -- Rebecca Cran On 9/20/21 9:47 AM, Rebecca Cran via groups.io 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 | 433 ++++++++++++++++++++ > MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ > MdeModulePkg/MdeModulePkg.dsc | 2 + > 3 files changed, 473 insertions(+) > > diff --git a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > new file mode 100644 > index 000000000000..4eb06e6b7cbd > --- /dev/null > +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > @@ -0,0 +1,433 @@ > +/** @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 > + > +#define RETURN_IF_EFI_ERROR(x) \ > + if (EFI_ERROR (x)) { \ > + Print (L"failed: %r\n", x); \ > + return; \ > + } \ > + else { \ > + Print (L"done.\n"); \ > + } > + > +/** 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 > + ); > + > + RETURN_IF_EFI_ERROR (Status); > + > + 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 > + ); > + RETURN_IF_EFI_ERROR (Status); > +} > + > +/** 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); > + RETURN_IF_EFI_ERROR (Status); > + > + 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 > + ); > + RETURN_IF_EFI_ERROR (Status); > +} > + > +/** 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); > + RETURN_IF_EFI_ERROR (Status); > + } > + > + 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); > + RETURN_IF_EFI_ERROR (Status); > + } > +} > + > +/** Tests for the SwitchBSP function. > + > + @param Mp The MP Services Protocol. > + @param NumCpus The number of CPUs in the system. > + > +**/ > +STATIC > +VOID > +SwitchBSPTests ( > + IN EFI_MP_SERVICES_PROTOCOL *Mp, > + IN UINTN NumCpus > + ) > +{ > + EFI_STATUS Status; > + UINTN Index; > + > + for (Index = 1; Index < NumCpus; Index++) { > + Print (L"Switching BSP to Processor %d with EnableOldBSP FALSE...", Index); > + Status = Mp->SwitchBSP (Mp, Index, FALSE); > + RETURN_IF_EFI_ERROR (Status); > + } > + > + for (Index = 0; Index < NumCpus; Index++) { > + Print (L"Switching BSP to Processor %d with EnableOldBSP TRUE...", Index); > + Status = Mp->SwitchBSP (Mp, Index, TRUE); > + RETURN_IF_EFI_ERROR (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; > + 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); > + > + Print (L"\n"); > + Print (L"Exercising SwitchBSP\n\n"); > + SwitchBSPTests (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 [-- Attachment #2: Type: text/html, Size: 31441 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services 2021-10-16 6:54 ` Sami Mujawar @ 2021-11-03 2:31 ` Rebecca Cran 0 siblings, 0 replies; 7+ messages in thread From: Rebecca Cran @ 2021-11-03 2:31 UTC (permalink / raw) To: Sami Mujawar, devel@edk2.groups.io, Jian J Wang, Liming Gao Cc: Ard Biesheuvel, Samer El-Haj-Mahmoud, Leif Lindholm, Gerd Hoffmann, nd [-- Attachment #1: Type: text/plain, Size: 17062 bytes --] Sami, I don't see your review. Did you review this, or just the separate patch to add EFI_MP_SERVICES_PROTOCOL for AArch64? -- Rebecca Cran On 10/16/21 12:54 AM, Sami Mujawar wrote: > Hi Rebecca, > > I will review this next week. > > Regard > > Sami Mujawar > > ------------------------------------------------------------------------ > *From:* Rebecca Cran <rebecca@nuviainc.com> > *Sent:* Saturday, 16 October 2021, 7:33 am > *To:* devel@edk2.groups.io; Jian J Wang; Liming Gao > *Cc:* Ard Biesheuvel; Samer El-Haj-Mahmoud; Leif Lindholm; Sami > Mujawar; Gerd Hoffmann > *Subject:* Re: [edk2-devel] [PATCH v2 1/1] MdeModulePkg: Add > MpServicesTest application to exercise MP Services > > (cc Leif, Ard, Sami, Samer, Gerd) > > > Could someone review this please? > > > -- > Rebecca Cran > > > On 9/20/21 9:47 AM, Rebecca Cran via groups.io 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 | 433 > ++++++++++++++++++++ > > MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf | 38 ++ > > MdeModulePkg/MdeModulePkg.dsc | 2 + > > 3 files changed, 473 insertions(+) > > > > diff --git > a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > > new file mode 100644 > > index 000000000000..4eb06e6b7cbd > > --- /dev/null > > +++ b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c > > @@ -0,0 +1,433 @@ > > +/** @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 > > + > > +#define RETURN_IF_EFI_ERROR(x) \ > > + if (EFI_ERROR (x)) { \ > > + Print (L"failed: %r\n", x); \ > > + return; \ > > + } \ > > + else { \ > > + Print (L"done.\n"); \ > > + } > > + > > +/** 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 > > + ); > > + > > + RETURN_IF_EFI_ERROR (Status); > > + > > + 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 > > + ); > > + RETURN_IF_EFI_ERROR (Status); > > +} > > + > > +/** 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); > > + RETURN_IF_EFI_ERROR (Status); > > + > > + 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 > > + ); > > + RETURN_IF_EFI_ERROR (Status); > > +} > > + > > +/** 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); > > + RETURN_IF_EFI_ERROR (Status); > > + } > > + > > + 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); > > + RETURN_IF_EFI_ERROR (Status); > > + } > > +} > > + > > +/** Tests for the SwitchBSP function. > > + > > + @param Mp The MP Services Protocol. > > + @param NumCpus The number of CPUs in the system. > > + > > +**/ > > +STATIC > > +VOID > > +SwitchBSPTests ( > > + IN EFI_MP_SERVICES_PROTOCOL *Mp, > > + IN UINTN NumCpus > > + ) > > +{ > > + EFI_STATUS Status; > > + UINTN Index; > > + > > + for (Index = 1; Index < NumCpus; Index++) { > > + Print (L"Switching BSP to Processor %d with EnableOldBSP > FALSE...", Index); > > + Status = Mp->SwitchBSP (Mp, Index, FALSE); > > + RETURN_IF_EFI_ERROR (Status); > > + } > > + > > + for (Index = 0; Index < NumCpus; Index++) { > > + Print (L"Switching BSP to Processor %d with EnableOldBSP > TRUE...", Index); > > + Status = Mp->SwitchBSP (Mp, Index, TRUE); > > + RETURN_IF_EFI_ERROR (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; > > + 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); > > + > > + Print (L"\n"); > > + Print (L"Exercising SwitchBSP\n\n"); > > + SwitchBSPTests (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 > [-- Attachment #2: Type: text/html, Size: 30828 bytes --] ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2021-11-03 17:22 UTC | newest] Thread overview: 7+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-09-20 15:47 [PATCH v2 0/1] MdeModulePkg: Add MpServicesTest.efi to exercise EFI_MP_SERVICES_PROTOCOL Rebecca Cran 2021-09-20 15:47 ` [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Rebecca Cran 2021-11-03 10:54 ` [edk2-devel] " Sami Mujawar 2021-11-03 17:22 ` Rebecca Cran [not found] ` <16A69264F30D2680.28782@groups.io> 2021-10-16 6:32 ` Rebecca Cran 2021-10-16 6:54 ` Sami Mujawar 2021-11-03 2:31 ` Rebecca Cran
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox