From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pl1-f177.google.com (mail-pl1-f177.google.com [209.85.214.177]) by mx.groups.io with SMTP id smtpd.web10.11182.1636144284642132247 for ; Fri, 05 Nov 2021 13:31:24 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=e0cd967o; spf=pass (domain: nuviainc.com, ip: 209.85.214.177, mailfrom: rebecca@nuviainc.com) Received: by mail-pl1-f177.google.com with SMTP id t21so11772447plr.6 for ; Fri, 05 Nov 2021 13:31:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nuviainc-com.20210112.gappssmtp.com; s=20210112; h=from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=fyonuxH5FlwJF1SgFD/F7vY/R132TSLXfrfZfCvosOs=; b=e0cd967oSR8JdSo3rNgxRhIi8t4AocuXUV6gKHoWa2B053yHNRwpKw7WeMOFQIN7Gg li/WIZvrWpopAGJouLWz/k3E6fLturSYH2+KTyflCXo/hgqaFwWzMDVRcXHESh+VLpYQ wvmEoL/zsaFF+jdRSOPTf4nNG33VqdkqMLeamwJoz/6u8CHeZWTHV4pMlPiPK8XOXLgA 9ueul6FIGsu1XuGi3GEz1WBTHX6saWIv+BC3JcAIkE4jJKPVgvcRUm325VAWKuzEOL0c P63M4GqJB2Qz6vsCPi39a6YtHuT8piW8j9KzaKOrpRy16Ckw4NGgJP12WHWbX0pivxFe j9mQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=fyonuxH5FlwJF1SgFD/F7vY/R132TSLXfrfZfCvosOs=; b=bBqCQVPdFZq7YXHXvMTKm/sB3jgndbt96S1jYz5JskCYWB94qLcN2rU0rzxXa7qw46 DY3Ij2PYv1rfZh8Wdjvfo4lpvaHkmsCtJDO9qpsViVM3gVAlt+MEHAzWP2mosmRY6UPX tgeFWJ/W06qisEusSXjOKIAZ/K/g2IHlknVpomyorFAICkgBCSMfmpjt03rcOmL1C0Qb 353oF84QiIyqbBEwlxduklitS5PB7wEZRpHGfy3WL1qA0QryNJN8A0Ly9UcAR4EFYlf0 3qwlW32X8qkw86daYK706tZqgz73Vekae0wFBBr1rYg4nCoXcF2n4YfmBDySyfROJ148 VSiw== X-Gm-Message-State: AOAM530O9hX45KtiR3vJ4jbECAPMV7tZDC8utVvdOaWO2j0JywKV+O1N oluI9o7G31FwNye+o9ektQptIIIgBL4NNBJVEcgDKuXP/fgX3fMsPX8RO1c7ZyRkj/JpOKMp+dK xd0M92fEjrMovDOObpLRbD/0J2uYRcAlL74MoLAV4XMZxf3mspztSB8Wtw08EEzYN0WH+zjHq X-Google-Smtp-Source: ABdhPJw1tp1oMIRBrZx8Y9WjEkiIQ7Yyedgc+sUx9d3z8YtgMZVna9IdN/9jenRP8fUSh82XlXkw6w== X-Received: by 2002:a17:902:c3cc:b0:141:be17:405e with SMTP id j12-20020a170902c3cc00b00141be17405emr43177179plj.76.1636144283417; Fri, 05 Nov 2021 13:31:23 -0700 (PDT) Return-Path: Received: from linbox.ba.nuviainc.com (c-174-52-16-57.hsd1.ut.comcast.net. [174.52.16.57]) by smtp.gmail.com with ESMTPSA id f16sm8838041pfe.172.2021.11.05.13.31.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Nov 2021 13:31:22 -0700 (PDT) From: "Rebecca Cran" To: devel@edk2.groups.io, Sami Mujawar , Ard Biesheuvel , Gerd Hoffmann , Samer El-Haj-Mahmoud , Leif Lindholm , Jian J Wang , Liming Gao , nd Cc: Rebecca Cran Subject: [PATCH v3 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Date: Fri, 5 Nov 2021 14:31:12 -0600 Message-Id: <20211105203112.24313-1-rebecca@nuviainc.com> X-Mailer: git-send-email 2.31.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Add a new MpServicesTest application under MdeModulePkg/Application that exercises the EFI_MP_SERVICES_PROTOCOL. Signed-off-by: Rebecca Cran --- 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.
+ SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include +#include +#include +#include +#include +#include +#include + +#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.
+# +# 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