From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f179.google.com (mail-pf1-f179.google.com [209.85.210.179]) by mx.groups.io with SMTP id smtpd.web09.542.1632152876737105359 for ; Mon, 20 Sep 2021 08:47:56 -0700 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=KwgYU2vy; spf=pass (domain: nuviainc.com, ip: 209.85.210.179, mailfrom: rebecca@nuviainc.com) Received: by mail-pf1-f179.google.com with SMTP id q23so14537344pfs.9 for ; Mon, 20 Sep 2021 08:47:56 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=7SPj/zIB0L7EL5+NmHbWMRZ+yT9Za9x+RD7Z784FCpc=; b=KwgYU2vy/ERmVlRUh8hZDyjbOnxr382px2o27CbUl0NeJ9jK9waXvX3jVJKBFZCXsA RzESQ2xMAxo6+nfHqKonnqGcXA5HSezcRko3ALs/iMoz5cpE2BqvwDptVgQjh1rv73DB QFlon9u1p33APdRFsnLFKjSG2JyBXqtG0XIT/Zl4g4eEq9cItRLIQj9ddeYy5YnNn0A1 xTofOMtRcz97cv/GxRVkcj15I7Eezp4hbXKcjRBrXT2umcxeZdPOXAaZLD/QEIbI7/io sjbpUMH1MHecAI2IegvTde95/rtlWu3UYbP7UG0tO3wN/3leUKnTeHpC4UDG3dAFWMfz PrnA== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=7SPj/zIB0L7EL5+NmHbWMRZ+yT9Za9x+RD7Z784FCpc=; b=H99/MlguLj3rcCbLLWkGdDBFmyQj/AM6cCvUmXIthdAD7+1TS+6i+Y7Hj5QqnKuX6M C0/gIKZ7TffSWDw7I324pmLjSxLdJtB1dVDorraSMdhToEWXtkMcKsOGhrz5O23YjJD2 bCdayBMlIteZe026BUBzBY4QYDWaSeJslM5n0A4/YPNszv/D0ZznX8Tybc7bb7A7nbfW /hNnLr7Xe71+EGpu+lsIdzl1M8rakgJvqIX4rO63jfhHFTO44tG16rU9T3Qv/lBodxoA WfU735swDMe/RH5Rql4Z5hLMGKGyrNk3V6v+U4hSx8XRpaP7LJYANjbk19t9lhghLxod wvNA== X-Gm-Message-State: AOAM531XMGCgud0nUSz93G0Ivp59eFVMIzSctXQqdn6WirxYeFk0iB0Y csxPiMwGRfXS3OAL8/9w+GyohCZPq8ADTStBuJnyMRAKVZUWxn90uDObdfiAWuR/s99b046OKOT EPPH5WFzXZEDbGiuqnmNHT/dSidos8X9i1VnqsLGaKLWlOKi7qb07cN0xMbbcVtzsePQJbkEb X-Google-Smtp-Source: ABdhPJx5XNVNpgheDsh96so2s7NgirxXMa+o32tzEfPUMNfc6N85RLdtMSj90pUijOH+A8b5lHhPVg== X-Received: by 2002:a62:ee12:0:b0:412:444e:f5ff with SMTP id e18-20020a62ee12000000b00412444ef5ffmr26355092pfi.82.1632152875651; Mon, 20 Sep 2021 08:47:55 -0700 (PDT) Return-Path: Received: from linbox.int.bluestop.org.com (c-174-52-16-57.hsd1.ut.comcast.net. [174.52.16.57]) by smtp.gmail.com with ESMTPSA id x16sm15656182pgc.49.2021.09.20.08.47.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 20 Sep 2021 08:47:55 -0700 (PDT) From: "Rebecca Cran" To: devel@edk2.groups.io, Jian J Wang , Liming Gao Cc: Rebecca Cran Subject: [PATCH v2 1/1] MdeModulePkg: Add MpServicesTest application to exercise MP Services Date: Mon, 20 Sep 2021 09:47:32 -0600 Message-Id: <20210920154732.10181-2-rebecca@nuviainc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20210920154732.10181-1-rebecca@nuviainc.com> References: <20210920154732.10181-1-rebecca@nuviainc.com> 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 | 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.
+ 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 + +#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.
+# +# 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