<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<p><font face="monospace">No, I expect there to only ever be a
single MP services instance.</font></p>
<p><font face="monospace">I agree that the AP function should do
something, but I'm hoping to get this initial implementation
committed first.</font></p>
<p><font face="monospace"><br>
</font></p>
<p><font face="monospace">-- <br>
Rebecca Cran<br>
</font></p>
<p><font face="monospace"></font><br>
</p>
<div class="moz-cite-prefix">On 12/29/21 20:21, Jeff Fan wrote:<br>
</div>
<blockquote type="cite"
cite="mid:2021123011214518968235@byosoft.com.cn">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<style>body { line-height: 1.5; }blockquote { margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em; }body { font-size: 14px; font-family: "Microsoft YaHei UI"; color: rgb(0, 0, 0); line-height: 1.5; }</style>
<div><span></span>Hi,Rebecca</div>
<div><br>
</div>
<div>I'd like to give two comments on this patch.</div>
<div><br>
</div>
<div>1, <span style="background-color: transparent;">I don't
think there are more than one MP services instances installed
reuirement on one system. X86 platform installed one MP
service instance even on mutiple-sockets system. </span></div>
<div><span style="background-color: transparent;"> For ARM
platform, is there any requirement to handle multple MP
services instance?</span></div>
<div><span style="background-color: transparent;"><br>
</span></div>
<div><span style="background-color: transparent;">2, AP function
is </span><span style="background-color: transparent;">NULL
implementation that could not make sure BSP recongized if APs
run indeed. You could simply update AP function to
use one global variable seamphoere wrapped by lock
protections.</span></div>
<div>
<div><span style="background-color: transparent;"> I think</span><span
style="background-color: transparent;"> this patch is very
good start to add MP test app in open source world. This
comment is only sugestion for your next plan. :-)</span></div>
</div>
<div><span style="background-color: transparent;"><br>
</span></div>
<div><span style="background-color: transparent;">Best Regards,</span></div>
<div><span style="background-color: transparent;">Jeff</span></div>
<blockquote style="margin-Top: 0px; margin-Bottom: 0px;
margin-Left: 0.5em; margin-Right: inherit">
<div> </div>
<div style="border:none;border-top:solid #B5C4DF
1.0pt;padding:3.0pt 0cm 0cm 0cm">
<div style="PADDING-RIGHT: 8px; PADDING-LEFT: 8px; FONT-SIZE:
12px;FONT-FAMILY:tahoma;COLOR:#000000; BACKGROUND: #efefef;
PADDING-BOTTOM: 8px; PADDING-TOP: 8px">
<div><b>From:</b> <a href="mailto:rebecca@nuviainc.com"
moz-do-not-send="true">Rebecca Cran</a></div>
<div><b>Date:</b> 2021-12-13 02:08</div>
<div><b>To:</b> <a href="mailto:devel@edk2.groups.io"
moz-do-not-send="true">devel</a>; <a
href="mailto:ardb+tianocore@kernel.org"
moz-do-not-send="true">Ard Biesheuvel</a>; <a
href="mailto:kraxel@redhat.com" moz-do-not-send="true">Gerd
Hoffmann</a>; <a
href="mailto:samer.el-haj-mahmoud@arm.com"
moz-do-not-send="true">Samer El-Haj-Mahmoud</a>; <a
href="mailto:leif@nuviainc.com" moz-do-not-send="true">Leif
Lindholm</a>; <a href="mailto:jian.j.wang@intel.com"
moz-do-not-send="true">Jian J Wang</a>; <a
href="mailto:gaoliming@byosoft.com.cn"
moz-do-not-send="true">Liming Gao</a>; <a
href="mailto:nd@arm.com" moz-do-not-send="true">nd</a>;
<a href="mailto:sami.mujawar@arm.com"
moz-do-not-send="true">Sami Mujawar</a></div>
<div><b>CC:</b> <a href="mailto:rebecca@nuviainc.com"
moz-do-not-send="true">Rebecca Cran</a></div>
<div><b>Subject:</b> [edk2-devel] [PATCH v4 1/1]
MdeModulePkg: Add MpServicesTest application to exercise
MP Services</div>
</div>
</div>
<div>
<div>Add a new MpServicesTest application under
MdeModulePkg/Application that</div>
<div>exercises the EFI_MP_SERVICES_PROTOCOL.</div>
<div> </div>
<div>Signed-off-by: Rebecca Cran <a class="moz-txt-link-rfc2396E" href="mailto:rebecca@nuviainc.com"><rebecca@nuviainc.com></a></div>
<div>Reviewed-by: Sami Mujawar <a class="moz-txt-link-rfc2396E" href="mailto:sami.mujawar@arm.com"><sami.mujawar@arm.com></a></div>
<div>---</div>
<div>
MdeModulePkg/Application/MpServicesTest/MpServicesTest.c |
422 ++++++++++++++++++++</div>
<div>
MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
| 38 ++</div>
<div>
MdeModulePkg/MdeModulePkg.dsc
| 2 +</div>
<div> 3 files changed, 462 insertions(+)</div>
<div> </div>
<div>diff --git
a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c
b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c</div>
<div>new file mode 100644</div>
<div>index 000000000000..933813e19e05</div>
<div>--- /dev/null</div>
<div>+++
b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.c</div>
<div>@@ -0,0 +1,422 @@</div>
<div>+/** @file</div>
<div>+</div>
<div>+ Copyright (c) 2021, NUVIA Inc. All rights
reserved.<BR></div>
<div>+ SPDX-License-Identifier: BSD-2-Clause-Patent</div>
<div>+**/</div>
<div>+</div>
<div>+#include <Uefi.h></div>
<div>+#include <Library/DebugLib.h></div>
<div>+#include <Library/RngLib.h></div>
<div>+#include <Library/UefiBootServicesTableLib.h></div>
<div>+#include <Library/UefiLib.h></div>
<div>+#include <Pi/PiMultiPhase.h></div>
<div>+#include <Protocol/MpService.h></div>
<div>+</div>
<div>+#define MAX_RANDOM_PROCESSOR_RETRIES 10</div>
<div>+</div>
<div>+#define AP_STARTUP_TEST_TIMEOUT_US 50000</div>
<div>+#define INFINITE_TIMEOUT 0</div>
<div>+</div>
<div>+/** The procedure to run with the MP Services interface.</div>
<div>+</div>
<div>+ @param Buffer The procedure argument.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+VOID</div>
<div>+EFIAPI</div>
<div>+ApFunction (</div>
<div>+ IN OUT VOID *Buffer</div>
<div>+ )</div>
<div>+{</div>
<div>+}</div>
<div><span style="background-color: transparent;">+</span></div>
<div>+/** Displays information returned from MP Services
Protocol.</div>
<div>+</div>
<div>+ @param Mp The MP Services Protocol</div>
<div>+</div>
<div>+ @return The number of CPUs in the system.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+UINTN</div>
<div>+PrintProcessorInformation (</div>
<div>+ IN EFI_MP_SERVICES_PROTOCOL *Mp</div>
<div>+ )</div>
<div>+{</div>
<div>+ EFI_STATUS Status;</div>
<div>+ EFI_PROCESSOR_INFORMATION CpuInfo;</div>
<div>+ UINTN Index;</div>
<div>+ UINTN NumCpu;</div>
<div>+ UINTN NumEnabledCpu;</div>
<div>+</div>
<div>+ Status = Mp->GetNumberOfProcessors (Mp,
&NumCpu, &NumEnabledCpu);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"GetNumberOfProcessors failed: %r\n",
Status);</div>
<div>+ } else {</div>
<div>+ Print (L"Number of CPUs: %ld, Enabled: %d\n",
NumCpu, NumEnabledCpu);</div>
<div>+ }</div>
<div>+</div>
<div>+ for (Index = 0; Index < NumCpu; Index++) {</div>
<div>+ Status = Mp->GetProcessorInfo (Mp,
CPU_V2_EXTENDED_TOPOLOGY | Index, &CpuInfo);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"GetProcessorInfo for Processor %d failed:
%r\n", Index, Status);</div>
<div>+ } else {</div>
<div>+ Print (</div>
<div>+ L"Processor %d:\n"</div>
<div>+ L"\tID: %016lx\n"</div>
<div>+ L"\tStatus: %s | ",</div>
<div>+ Index,</div>
<div>+ CpuInfo.ProcessorId,</div>
<div>+ (CpuInfo.StatusFlag & PROCESSOR_AS_BSP_BIT)
? L"BSP" : L"AP"</div>
<div>+ );</div>
<div>+</div>
<div>+ Print (L"%s | ", (CpuInfo.StatusFlag &
PROCESSOR_ENABLED_BIT) ? L"Enabled" : L"Disabled");</div>
<div>+ Print (L"%s\n", (CpuInfo.StatusFlag &
PROCESSOR_HEALTH_STATUS_BIT) ? L"Healthy" : L"Faulted");</div>
<div>+</div>
<div>+ Print (</div>
<div>+ L"\tLocation: Package %d, Core %d, Thread %d\n"</div>
<div>+ L"\tExtended Information: Package %d, Module %d,
Tile %d, Die %d, Core %d, Thread %d\n\n",</div>
<div>+ CpuInfo.Location.Package,</div>
<div>+ CpuInfo.Location.Core,</div>
<div>+ CpuInfo.Location.Thread,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Package,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Module,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Tile,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Die,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Core,</div>
<div>+ CpuInfo.ExtendedInformation.Location2.Thread</div>
<div>+ );</div>
<div>+ }</div>
<div>+ }</div>
<div>+</div>
<div>+ return NumCpu;</div>
<div>+}</div>
<div>+</div>
<div>+/** Returns the index of an enabled AP selected at
random.</div>
<div>+</div>
<div>+ @param Mp The MP Services Protocol.</div>
<div>+ @param ProcessorIndex The index of a random enabled
AP.</div>
<div>+</div>
<div>+ @retval EFI_SUCCESS An enabled processor was found
and returned.</div>
<div>+ @retval EFI_NOT_FOUND A processor was unable to be
selected.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+EFI_STATUS</div>
<div>+GetRandomEnabledProcessorIndex (</div>
<div>+ IN EFI_MP_SERVICES_PROTOCOL *Mp,</div>
<div>+ OUT UINTN *ProcessorIndex</div>
<div>+ )</div>
<div>+{</div>
<div>+ UINTN Index;</div>
<div>+ UINTN IndexOfEnabledCpu;</div>
<div>+ UINTN NumCpus;</div>
<div>+ UINTN NumEnabledCpus;</div>
<div>+ UINTN IndexOfEnabledCpuToUse;</div>
<div>+ UINT16 RandomNumber;</div>
<div>+ BOOLEAN Success;</div>
<div>+ EFI_STATUS Status;</div>
<div>+ EFI_PROCESSOR_INFORMATION CpuInfo;</div>
<div>+</div>
<div>+ IndexOfEnabledCpu = 0;</div>
<div>+</div>
<div>+ Success = GetRandomNumber16 (&RandomNumber);</div>
<div>+ ASSERT (Success == TRUE);</div>
<div>+</div>
<div>+ Status = Mp->GetNumberOfProcessors (Mp,
&NumCpus, &NumEnabledCpus);</div>
<div>+ ASSERT_EFI_ERROR (Status);</div>
<div>+</div>
<div>+ if (NumEnabledCpus == 1) {</div>
<div>+ Print (L"All APs are disabled\n");</div>
<div>+ return EFI_NOT_FOUND;</div>
<div>+ }</div>
<div>+</div>
<div>+ IndexOfEnabledCpuToUse = RandomNumber %
NumEnabledCpus;</div>
<div>+</div>
<div>+ for (Index = 0; Index < NumCpus; Index++) {</div>
<div>+ Status = Mp->GetProcessorInfo (Mp, Index,
&CpuInfo);</div>
<div>+ ASSERT_EFI_ERROR (Status);</div>
<div>+ if ((CpuInfo.StatusFlag & PROCESSOR_ENABLED_BIT)
&&</div>
<div>+ !(CpuInfo.StatusFlag &
PROCESSOR_AS_BSP_BIT))</div>
<div>+ {</div>
<div>+ if (IndexOfEnabledCpuToUse == IndexOfEnabledCpu) {</div>
<div>+ *ProcessorIndex = Index;</div>
<div>+ Status = EFI_SUCCESS;</div>
<div>+ break;</div>
<div>+ }</div>
<div>+</div>
<div>+ IndexOfEnabledCpu++;</div>
<div>+ }</div>
<div>+ }</div>
<div>+</div>
<div>+ if (Index == NumCpus) {</div>
<div>+ Status = EFI_NOT_FOUND;</div>
<div>+ }</div>
<div>+</div>
<div>+ return Status;</div>
<div>+}</div>
<div>+</div>
<div>+/** Tests for the StartupThisAP function.</div>
<div>+</div>
<div>+ @param Mp The MP Services Protocol.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+VOID</div>
<div>+StartupThisApTests (</div>
<div>+ IN EFI_MP_SERVICES_PROTOCOL *Mp</div>
<div>+ )</div>
<div>+{</div>
<div>+ EFI_STATUS Status;</div>
<div>+ UINTN ProcessorIndex;</div>
<div>+ UINT32 Retries;</div>
<div>+</div>
<div>+ Retries = 0;</div>
<div>+</div>
<div>+ do {</div>
<div>+ Status = GetRandomEnabledProcessorIndex (Mp,
&ProcessorIndex);</div>
<div>+ } while (EFI_ERROR (Status) && Retries++ <
MAX_RANDOM_PROCESSOR_RETRIES);</div>
<div>+</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ return;</div>
<div>+ }</div>
<div>+</div>
<div>+ Print (</div>
<div>+ L"StartupThisAP on Processor %d with 0 (infinite)
timeout...",</div>
<div>+ ProcessorIndex</div>
<div>+ );</div>
<div>+</div>
<div>+ Status = Mp->StartupThisAP (</div>
<div>+ Mp,</div>
<div>+ ApFunction,</div>
<div>+ ProcessorIndex,</div>
<div>+ NULL,</div>
<div>+ INFINITE_TIMEOUT,</div>
<div>+ NULL,</div>
<div>+ NULL</div>
<div>+ );</div>
<div>+</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+</div>
<div>+ Retries = 0;</div>
<div>+</div>
<div>+ do {</div>
<div>+ Status = GetRandomEnabledProcessorIndex (Mp,
&ProcessorIndex);</div>
<div>+ } while (EFI_ERROR (Status) && Retries++ <
MAX_RANDOM_PROCESSOR_RETRIES);</div>
<div>+</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ return;</div>
<div>+ }</div>
<div>+</div>
<div>+ Print (</div>
<div>+ L"StartupThisAP on Processor %d with %dms
timeout...",</div>
<div>+ ProcessorIndex,</div>
<div>+ AP_STARTUP_TEST_TIMEOUT_US / 1000</div>
<div>+ );</div>
<div>+ Status = Mp->StartupThisAP (</div>
<div>+ Mp,</div>
<div>+ ApFunction,</div>
<div>+ ProcessorIndex,</div>
<div>+ NULL,</div>
<div>+ AP_STARTUP_TEST_TIMEOUT_US,</div>
<div>+ NULL,</div>
<div>+ NULL</div>
<div>+ );</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+}</div>
<div>+</div>
<div>+/** Tests for the StartupAllAPs function.</div>
<div>+</div>
<div>+ @param Mp The MP Services Protocol.</div>
<div>+ @param NumCpus The number of CPUs in the system.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+VOID</div>
<div>+StartupAllAPsTests (</div>
<div>+ IN EFI_MP_SERVICES_PROTOCOL *Mp,</div>
<div>+ IN UINTN NumCpus</div>
<div>+ )</div>
<div>+{</div>
<div>+ EFI_STATUS Status;</div>
<div>+ UINTN Timeout;</div>
<div>+</div>
<div>+ Print (L"Running with SingleThread FALSE, 0 (infinite)
timeout...");</div>
<div>+ Status = Mp->StartupAllAPs (Mp, ApFunction, FALSE,
NULL, INFINITE_TIMEOUT, NULL, NULL);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+</div>
<div>+ Timeout = NumCpus * AP_STARTUP_TEST_TIMEOUT_US;</div>
<div>+</div>
<div>+ Print (L"Running with SingleThread TRUE, %dms
timeout...", Timeout / 1000);</div>
<div>+ Status = Mp->StartupAllAPs (</div>
<div>+ Mp,</div>
<div>+ ApFunction,</div>
<div>+ TRUE,</div>
<div>+ NULL,</div>
<div>+ Timeout,</div>
<div>+ NULL,</div>
<div>+ NULL</div>
<div>+ );</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+}</div>
<div>+</div>
<div>+/** Tests for the EnableDisableAP function.</div>
<div>+</div>
<div>+ @param Mp The MP Services Protocol.</div>
<div>+ @param NumCpus The number of CPUs in the system.</div>
<div>+</div>
<div>+**/</div>
<div>+STATIC</div>
<div>+VOID</div>
<div>+EnableDisableAPTests (</div>
<div>+ IN EFI_MP_SERVICES_PROTOCOL *Mp,</div>
<div>+ IN UINTN NumCpus</div>
<div>+ )</div>
<div>+{</div>
<div>+ EFI_STATUS Status;</div>
<div>+ UINTN Index;</div>
<div>+ UINT32 HealthFlag;</div>
<div>+</div>
<div>+ HealthFlag = 0;</div>
<div>+</div>
<div>+ for (Index = 1; Index < NumCpus; Index++) {</div>
<div>+ Print (L"Disabling Processor %d with HealthFlag
faulted...", Index);</div>
<div>+ Status = Mp->EnableDisableAP (Mp, Index, FALSE,
&HealthFlag);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+ }</div>
<div>+</div>
<div>+ HealthFlag = PROCESSOR_HEALTH_STATUS_BIT;</div>
<div>+</div>
<div>+ for (Index = 1; Index < NumCpus; Index++) {</div>
<div>+ Print (L"Enabling Processor %d with HealthFlag
healthy...", Index);</div>
<div>+ Status = Mp->EnableDisableAP (Mp, Index, TRUE,
&HealthFlag);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"failed: %r\n", Status);</div>
<div>+ return;</div>
<div>+ } else {</div>
<div>+ Print (L"done.\n");</div>
<div>+ }</div>
<div>+ }</div>
<div>+}</div>
<div>+</div>
<div>+/**</div>
<div>+ The user Entry Point for Application. The user code
starts with this function</div>
<div>+ as the real entry point for the application.</div>
<div>+</div>
<div>+ @param[in] ImageHandle The firmware allocated
handle for the EFI image.</div>
<div>+ @param[in] SystemTable A pointer to the EFI System
Table.</div>
<div>+</div>
<div>+ @retval EFI_SUCCESS The entry point is executed
successfully.</div>
<div>+ @retval other Some error occurs when
executing this entry point.</div>
<div>+</div>
<div>+**/</div>
<div>+EFI_STATUS</div>
<div>+EFIAPI</div>
<div>+UefiMain (</div>
<div>+ IN EFI_HANDLE ImageHandle,</div>
<div>+ IN EFI_SYSTEM_TABLE *SystemTable</div>
<div>+ )</div>
<div>+{</div>
<div>+ EFI_STATUS Status;</div>
<div>+ EFI_MP_SERVICES_PROTOCOL *Mp;</div>
<div>+ EFI_HANDLE *pHandle;</div>
<div>+ UINTN HandleCount;</div>
<div>+ UINTN BspId;</div>
<div>+ UINTN NumCpus;</div>
<div>+ UINTN Index;</div>
<div>+</div>
<div>+ pHandle = NULL;</div>
<div>+ HandleCount = 0;</div>
<div>+ BspId = 0;</div>
<div>+</div>
<div>+ Status = gBS->LocateHandleBuffer (</div>
<div>+ ByProtocol,</div>
<div>+ &gEfiMpServiceProtocolGuid,</div>
<div>+ NULL,</div>
<div>+ &HandleCount,</div>
<div>+ &pHandle</div>
<div>+ );</div>
<div>+</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"Failed to locate EFI_MP_SERVICES_PROTOCOL
(%r). Not installed on platform?\n", Status);</div>
<div>+ return EFI_NOT_FOUND;</div>
<div>+ }</div>
<div>+</div>
<div>+ for (Index = 0; Index < HandleCount; Index++) {</div>
<div>+ Status = gBS->OpenProtocol (</div>
<div>+ *pHandle,</div>
<div>+ &gEfiMpServiceProtocolGuid,</div>
<div>+ (VOID **)&Mp,</div>
<div>+ NULL,</div>
<div>+ gImageHandle,</div>
<div>+ EFI_OPEN_PROTOCOL_GET_PROTOCOL</div>
<div>+ );</div>
<div>+</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ return Status;</div>
<div>+ }</div>
<div>+</div>
<div>+ pHandle++;</div>
<div>+ }</div>
<div>+</div>
<div><span style="background-color: transparent;">+ Print
(L"Exercising WhoAmI\n\n");</span></div>
<div>+ Status = Mp->WhoAmI (Mp, &BspId);</div>
<div>+ if (EFI_ERROR (Status)) {</div>
<div>+ Print (L"WhoAmI failed: %r\n", Status);</div>
<div>+ return Status;</div>
<div>+ } else {</div>
<div>+ Print (L"WhoAmI: %016lx\n", BspId);</div>
<div>+ }</div>
<div>+</div>
<div>+ Print (L"\n");</div>
<div>+ Print (</div>
<div>+ L"Exercising GetNumberOfProcessors and
GetProcessorInformation with "</div>
<div>+ L"CPU_V2_EXTENDED_TOPOLOGY\n\n"</div>
<div>+ );</div>
<div>+ NumCpus = PrintProcessorInformation (Mp);</div>
<div>+ if (NumCpus < 2) {</div>
<div>+ Print (L"UP system found. Not running further
tests.\n");</div>
<div>+ return EFI_INVALID_PARAMETER;</div>
<div>+ }</div>
<div>+</div>
<div>+ Print (L"\n");</div>
<div>+ Print (L"Exercising StartupThisAP:\n\n");</div>
<div>+ StartupThisApTests (Mp);</div>
<div>+</div>
<div>+ Print (L"\n");</div>
<div>+ Print (L"Exercising StartupAllAPs:\n\n");</div>
<div>+ StartupAllAPsTests (Mp, NumCpus);</div>
<div>+</div>
<div>+ Print (L"\n");</div>
<div>+ Print (L"Exercising EnableDisableAP:\n\n");</div>
<div>+ EnableDisableAPTests (Mp, NumCpus);</div>
<div>+</div>
<div>+ gBS->CloseProtocol (pHandle,
&gEfiMpServiceProtocolGuid, gImageHandle, NULL);</div>
<div>+ return EFI_SUCCESS;</div>
<div>+}</div>
<div>diff --git
a/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf
b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf</div>
<div>new file mode 100644</div>
<div>index 000000000000..8a21ca70d8fa</div>
<div>--- /dev/null</div>
<div>+++
b/MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf</div>
<div>@@ -0,0 +1,38 @@</div>
<div>+## @file</div>
<div>+# UEFI Application to exercise
EFI_MP_SERVICES_PROTOCOL.</div>
<div>+#</div>
<div>+# Copyright (c) 2021, NUVIA Inc. All rights
reserved.<BR></div>
<div>+#</div>
<div>+# SPDX-License-Identifier: BSD-2-Clause-Patent</div>
<div>+#</div>
<div>+##</div>
<div>+</div>
<div>+[Defines]</div>
<div>+ INF_VERSION = 1.29</div>
<div>+ BASE_NAME = MpServicesTest</div>
<div>+ FILE_GUID =
43e9defa-7209-4b0d-b136-cc4ca02cb469</div>
<div>+ MODULE_TYPE = UEFI_APPLICATION</div>
<div>+ VERSION_STRING = 0.1</div>
<div>+ ENTRY_POINT = UefiMain</div>
<div>+</div>
<div>+#</div>
<div>+# The following information is for reference only and
not required by the build tools.</div>
<div>+#</div>
<div>+# VALID_ARCHITECTURES = IA32 X64 AARCH64</div>
<div>+#</div>
<div>+</div>
<div>+[Sources]</div>
<div>+ MpServicesTest.c</div>
<div>+</div>
<div>+[Packages]</div>
<div>+ MdePkg/MdePkg.dec</div>
<div>+</div>
<div>+[LibraryClasses]</div>
<div>+ BaseLib</div>
<div>+ RngLib</div>
<div>+ UefiApplicationEntryPoint</div>
<div>+ UefiLib</div>
<div>+</div>
<div>+[Protocols]</div>
<div>+ gEfiMpServiceProtocolGuid ## CONSUMES</div>
<div>+</div>
<div>diff --git a/MdeModulePkg/MdeModulePkg.dsc
b/MdeModulePkg/MdeModulePkg.dsc</div>
<div>index b1d83461865e..1cf5ccd30d40 100644</div>
<div>--- a/MdeModulePkg/MdeModulePkg.dsc</div>
<div>+++ b/MdeModulePkg/MdeModulePkg.dsc</div>
<div>@@ -164,6 +164,7 @@</div>
<div>
MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf</div>
<div>
DebugLib|MdePkg/Library/UefiDebugLibStdErr/UefiDebugLibStdErr.inf</div>
<div>
FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf</div>
<div>+ RngLib|MdePkg/Library/DxeRngLib/DxeRngLib.inf</div>
<div> </div>
<div> [LibraryClasses.common.MM_STANDALONE]</div>
<div>
HobLib|MdeModulePkg/Library/BaseHobLibNull/BaseHobLibNull.inf</div>
<div>@@ -215,6 +216,7 @@</div>
<div> MdeModulePkg/Application/HelloWorld/HelloWorld.inf</div>
<div> MdeModulePkg/Application/DumpDynPcd/DumpDynPcd.inf</div>
<div>
MdeModulePkg/Application/MemoryProfileInfo/MemoryProfileInfo.inf</div>
<div>+
MdeModulePkg/Application/MpServicesTest/MpServicesTest.inf</div>
<div> </div>
<div> MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf</div>
<div> MdeModulePkg/Logo/Logo.inf</div>
<div>-- </div>
<div>2.31.1</div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
<div> </div>
</div>
</blockquote>
</blockquote>
</body>
</html>
<div width="1" style="color:white;clear:both">_._,_._,_</div> <hr> Groups.io Links:<p> You receive all messages sent to this group. <p> <a target="_blank" href="https://edk2.groups.io/g/devel/message/85234">View/Reply Online (#85234)</a> | | <a target="_blank" href="https://groups.io/mt/87681342/1813853">Mute This Topic</a> | <a href="https://edk2.groups.io/g/devel/post">New Topic</a><br> <a href="https://edk2.groups.io/g/devel/editsub/1813853">Your Subscription</a> | <a href="mailto:devel+owner@edk2.groups.io">Contact Group Owner</a> | <a href="https://edk2.groups.io/g/devel/unsub">Unsubscribe</a> [edk2-devel-archive@redhat.com]<br> <div width="1" style="color:white;clear:both">_._,_._,_</div>