From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pf1-f173.google.com (mail-pf1-f173.google.com [209.85.210.173]) by mx.groups.io with SMTP id smtpd.web09.5726.1639626408153024651 for ; Wed, 15 Dec 2021 19:46:48 -0800 Authentication-Results: mx.groups.io; dkim=pass header.i=@nuviainc-com.20210112.gappssmtp.com header.s=20210112 header.b=esXQGMIC; spf=pass (domain: nuviainc.com, ip: 209.85.210.173, mailfrom: rebecca@nuviainc.com) Received: by mail-pf1-f173.google.com with SMTP id 8so22470616pfo.4 for ; Wed, 15 Dec 2021 19:46:48 -0800 (PST) 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=097Qt5N7NrfS3IzrN/FOeax2x9W5q+yQTOmVovqmcAE=; b=esXQGMICwH/DIBUHw6NHs9HHxBIRDbh0JU3Pm3O+z5Oc3dZXr757fbhk93HesMcfZH pXJVoHnBkEv7hTAvfRslp3spTs/qlbfEGXkb86Au0Dj2R2JtwAHkRPs/X4vT0R7rwPNV mzAFZgBrScdJjbeR/m+n6oUvRJXQLOLOObG1QzJOLX3QG/uDET7SFqBggEALB0WAJmlk Ma1GDzIOoM5zkRQTGR3GDuPTAFsdm+TmTaVeqxk+uGOW5l5ASCJ1apBh/MSoD2+vRqdP F5YOuynczjKeYLU59t2VjYHP2QTAgL0zK8tfEc94hDcd8VKsfY11MNoXVRp/4RfUon9i w/nw== 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=097Qt5N7NrfS3IzrN/FOeax2x9W5q+yQTOmVovqmcAE=; b=XIAYXKm6EiC848ASgwMnYrNfZFjaLNcfXFIwqsCQp9toNO2tFoOgLD2VKPyRsRXctD QB0brN1ZYsIp1l3iz2Nqn4tTdXWObsHoEbZBw5J3dGsAEJSW2sx4nJ9Kv/Uuy+J69v1S 9nF/Q4HjCYYnynYjHJwQgdaMRIoc7q6EjdVJ7Mpy7V7quNZ9Gv1pISNFHj4CqEW2mZUf xsfmTqb+whxAfbTDbahuvnGlB4hkpXXnr3WlUZMfxoKKGc7TlnMPzznODx01s+9JBfhD tnQvHJNJg/pyBent+1ESr8wXFhk+krS1IQi33zTbKHrw8xXWuz2iiRaQaMJJnnLmqGJH Zglw== X-Gm-Message-State: AOAM533us5HO583H6Rw1xnAGq2p70NnsE3vhBgkDtX17XEuzTXIpV/Am mBfMvyAvB+rRr4o1Z4fomKKA7EEiWjAJUULWuDd4Yq//PRw0BMRQVsKPH2y6iamk09D951L8eha GXzM7tuRYaut0MV1bkfkv2Vk9nmU1DepoiXfLpACxwQ5C4JiT30nGKKFbw/hJVN5zrnDwAg== X-Google-Smtp-Source: ABdhPJyPbwGIQG0szFr/K0jVZKdtSsYi57euG8omni9tXBRG39VpIPVRl4KXhf1hotV60NXPHRTwIw== X-Received: by 2002:a63:d054:: with SMTP id s20mr10357455pgi.565.1639626406931; Wed, 15 Dec 2021 19:46:46 -0800 (PST) Return-Path: Received: from linbox.ba.nuviainc.com ([2601:681:4300:69e:9e7b:efff:fe2b:884c]) by smtp.gmail.com with ESMTPSA id c21sm4124054pfl.138.2021.12.15.19.46.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 15 Dec 2021 19:46:46 -0800 (PST) From: "Rebecca Cran" To: devel@edk2.groups.io, Ard Biesheuvel , Gerd Hoffmann , Samer El-Haj-Mahmoud , Leif Lindholm , Sami Mujawar Cc: Rebecca Cran Subject: [PATCH v3 4/4] ArmPkg: Update Drivers/CpuDxe to initialize MpInitLib Date: Wed, 15 Dec 2021 20:46:34 -0700 Message-Id: <20211216034634.15468-5-rebecca@nuviainc.com> X-Mailer: git-send-email 2.31.1 In-Reply-To: <20211216034634.15468-1-rebecca@nuviainc.com> References: <20211216034634.15468-1-rebecca@nuviainc.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Update Drivers/CpuDxe to initialize MpInitLib, which enables EFI_MP_SERVICES_PROTOCOL support on AARCH64. Signed-off-by: Rebecca Cran --- ArmPkg/Drivers/CpuDxe/AArch64/Arch.c | 21 + ArmPkg/Drivers/CpuDxe/Arm/Arch.c | 21 + ArmPkg/Drivers/CpuDxe/CpuDxe.c | 2 + ArmPkg/Drivers/CpuDxe/CpuDxe.h | 10 + ArmPkg/Drivers/CpuDxe/CpuDxe.inf | 6 + ArmPkg/Drivers/CpuDxe/CpuMpInit.c | 608 ++++++++++++++++++++ 6 files changed, 668 insertions(+) diff --git a/ArmPkg/Drivers/CpuDxe/AArch64/Arch.c b/ArmPkg/Drivers/CpuDxe/AArch64/Arch.c new file mode 100644 index 000000000000..cb7cb747bc15 --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/AArch64/Arch.c @@ -0,0 +1,21 @@ +/** @file + Architecture specific functions. + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** Initializes multi-processor support. + * +**/ +VOID +ArchInitializeMpSupport ( + VOID + ) +{ + InitializeMpSupport (); +} diff --git a/ArmPkg/Drivers/CpuDxe/Arm/Arch.c b/ArmPkg/Drivers/CpuDxe/Arm/Arch.c new file mode 100644 index 000000000000..f8d57b41225a --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/Arm/Arch.c @@ -0,0 +1,21 @@ +/** @file + Architecture specific functions. + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include + +/** Initializes multi-processor support. + * +**/ +VOID +ArchInitializeMpSupport ( + VOID + ) +{ + /* Nothing to do - ARM doesn't support EFI_MP_SERVICES_PROTOCOL */ +} diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.c b/ArmPkg/Drivers/CpuDxe/CpuDxe.c index 62a6e2d620a6..6c076982a1bd 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.c +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.c @@ -275,5 +275,7 @@ CpuDxeInitialize ( ); ASSERT_EFI_ERROR (Status); + ArchInitializeMpSupport (); + return Status; } diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.h b/ArmPkg/Drivers/CpuDxe/CpuDxe.h index 58ee1444c1b3..3f04b89d7ad0 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.h +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.h @@ -141,4 +141,14 @@ SetGcdMemorySpaceAttributes ( IN UINT64 Attributes ); +VOID +InitializeMpSupport ( + VOID + ); + +VOID +ArchInitializeMpSupport ( + VOID + ); + #endif // CPU_DXE_H_ diff --git a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf index e5549fc71df7..f4cdb8ab5613 100644 --- a/ArmPkg/Drivers/CpuDxe/CpuDxe.inf +++ b/ArmPkg/Drivers/CpuDxe/CpuDxe.inf @@ -26,10 +26,13 @@ Exception.c [Sources.ARM] + Arm/Arch.c Arm/Mmu.c [Sources.AARCH64] + AArch64/Arch.c AArch64/Mmu.c + CpuMpInit.c [Packages] ArmPkg/ArmPkg.dec @@ -37,6 +40,9 @@ MdePkg/MdePkg.dec MdeModulePkg/MdeModulePkg.dec +[LibraryClasses.AARCH64] + MpInitLib + [LibraryClasses] ArmLib ArmMmuLib diff --git a/ArmPkg/Drivers/CpuDxe/CpuMpInit.c b/ArmPkg/Drivers/CpuDxe/CpuMpInit.c new file mode 100644 index 000000000000..876a29e09b1b --- /dev/null +++ b/ArmPkg/Drivers/CpuDxe/CpuMpInit.c @@ -0,0 +1,608 @@ +/** @file + Construct MP Services Protocol. + + The MP Services Protocol provides a generalized way of performing following tasks: + - Retrieving information of multi-processor environment and MP-related status of + specific processors. + - Dispatching user-provided function to APs. + - Maintain MP-related processor status. + + The MP Services Protocol must be produced on any system with more than one logical + processor. + + The Protocol is available only during boot time. + + MP Services Protocol is hardware-independent. Most of the logic of this protocol + is architecturally neutral. It abstracts the multi-processor environment and + status of processors, and provides interfaces to retrieve information, maintain, + and dispatch. + + MP Services Protocol may be consumed by ACPI module. The ACPI module may use this + protocol to retrieve data that are needed for an MP platform and report them to OS. + MP Services Protocol may also be used to program and configure processors, such + as MTRR synchronization for memory space attributes setting in DXE Services. + MP Services Protocol may be used by non-CPU DXE drivers to speed up platform boot + by taking advantage of the processing capabilities of the APs, for example, using + APs to help test system memory in parallel with other device initialization. + Diagnostics applications may also use this protocol for multi-processor. + + Copyright (c) 2021, NUVIA Inc. All rights reserved.
+ SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include + +/** + This service retrieves the number of logical processor in the platform + and the number of those logical processors that are enabled on this boot. + This service may only be called from the BSP. + + This function is used to retrieve the following information: + - The number of logical processors that are present in the system. + - The number of enabled logical processors in the system at the instant + this call is made. + + Because MP Service Protocol provides services to enable and disable processors + dynamically, the number of enabled logical processors may vary during the + course of a boot session. + + If this service is called from an AP, then EFI_DEVICE_ERROR is returned. + If NumberOfProcessors or NumberOfEnabledProcessors is NULL, then + EFI_INVALID_PARAMETER is returned. Otherwise, the total number of processors + is returned in NumberOfProcessors, the number of currently enabled processor + is returned in NumberOfEnabledProcessors, and EFI_SUCCESS is returned. + + @param[in] This A pointer to the + EFI_MP_SERVICES_PROTOCOL instance. + @param[out] NumberOfProcessors Pointer to the total number of logical + processors in the system, including + the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors Pointer to the number of enabled + logical processors that exist in the + system, including the BSP. + + @retval EFI_SUCCESS The number of logical processors and enabled + logical processors was retrieved. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER NumberOfProcessors is NULL. + @retval EFI_INVALID_PARAMETER NumberOfEnabledProcessors is NULL. + +**/ +STATIC +EFI_STATUS +EFIAPI +GetNumberOfProcessors ( + IN EFI_MP_SERVICES_PROTOCOL *This, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ) +{ + return MpInitLibGetNumberOfProcessors ( + This, + NumberOfProcessors, + NumberOfEnabledProcessors + ); +} + +/** + Gets detailed MP-related information on the requested processor at the + instant this call is made. This service may only be called from the BSP. + + This service retrieves detailed MP-related information about any processor + on the platform. Note the following: + - The processor information may change during the course of a boot session. + - The information presented here is entirely MP related. + + Information regarding the number of caches and their sizes, frequency of + operation, slot numbers is all considered platform-related information and is + not provided by this service. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] ProcessorNumber The index of the processor. + @param[out] ProcessorInfoBuffer A pointer to the buffer where information + for the requested processor is deposited. + + @retval EFI_SUCCESS Processor information was returned. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_INVALID_PARAMETER ProcessorInfoBuffer is NULL. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist in the platform. + +**/ +STATIC +EFI_STATUS +EFIAPI +GetProcessorInfo ( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ) +{ + return MpInitLibGetProcessorInfo ( + This, + ProcessorNumber, + ProcessorInfoBuffer + ); +} + +/** + This service executes a caller provided function on all enabled APs. APs can + run either simultaneously or one at a time in sequence. This service supports + both blocking and non-blocking requests. The non-blocking requests use EFI + events so the BSP can detect when the APs have finished. This service may only + be called from the BSP. + + This function is used to dispatch all the enabled APs to the function + specified by Procedure. If any enabled AP is busy, then EFI_NOT_READY is + returned immediately and Procedure is not started on any AP. + + If SingleThread is TRUE, all the enabled APs execute the function specified by + Procedure one by one, in ascending order of processor handle number. + Otherwise, all the enabled APs execute the function specified by Procedure + simultaneously. + + If WaitEvent is NULL, execution is in blocking mode. The BSP waits until all + APs finish or TimeoutInMicroseconds expires. Otherwise, execution is in + non-blocking mode, and the BSP returns from this service without waiting for + APs. If a non-blocking mode is requested after the UEFI Event + EFI_EVENT_GROUP_READY_TO_BOOT is signaled, then EFI_UNSUPPORTED must be + returned. + + If the timeout specified by TimeoutInMicroseconds expires before all APs + return from Procedure, then Procedure on the failed APs is terminated. + All enabled APs are always available for further calls to + EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and + EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). If FailedCpuList is not NULL, its + content points to the list of processor handle numbers in which Procedure was + terminated. + + Note: It is the responsibility of the consumer of the + EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() to make sure that the nature of the + code that is executed on the BSP and the dispatched APs is well controlled. + The MP Services Protocol does not guarantee that the Procedure function is + MP-safe. Hence, the tasks that can be run in parallel are limited to certain + independent tasks and well-controlled exclusive code. EFI services and + protocols may not be called by APs unless otherwise specified. + + In blocking execution mode, BSP waits until all APs finish or + TimeoutInMicroseconds expires. + + In non-blocking execution mode, BSP is freed to return to the caller and then + proceed to the next task without having to wait for APs. The following + sequence needs to occur in a non-blocking execution mode: + + -# The caller that intends to use this MP Services Protocol in non-blocking + mode creates WaitEvent by calling the EFI CreateEvent() service. The + caller invokes EFI_MP_SERVICES_PROTOCOL.StartupAllAPs(). If the parameter + WaitEvent is not NULL, then StartupAllAPs() executes in non-blocking + mode. It requests the function specified by Procedure to be started on + all the enabled APs, and releases the BSP to continue with other tasks. + -# The caller can use the CheckEvent() and WaitForEvent() services to check + the state of the WaitEvent created in step 1. + -# When the APs complete their task or TimeoutInMicroSecondss expires, the + MP Service signals WaitEvent by calling the EFI SignalEvent() function. + If FailedCpuList is not NULL, its content is available when WaitEvent is + signaled. If all APs returned from Procedure prior to the timeout, then + FailedCpuList is set to NULL. If not all APs return from Procedure before + the timeout, then FailedCpuList is filled in with the list of the failed + APs. The buffer is allocated by MP Service Protocol using AllocatePool(). + It is the caller's responsibility to free the buffer with FreePool() + service. + -# This invocation of SignalEvent() function informs the caller that invoked + EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() that either all the APs + completed the specified task or a timeout occurred. The contents of + FailedCpuList can be examined to determine which APs did not complete the + specified task prior to the timeout. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] Procedure A pointer to the function to be run on + enabled APs of the system. See type + EFI_AP_PROCEDURE. + @param[in] SingleThread If TRUE, then all the enabled APs execute + the function specified by Procedure one by + one, in ascending order of processor + handle number. If FALSE, then all the + enabled APs execute the function specified + by Procedure simultaneously. + @param[in] WaitEvent The event created by the caller with + CreateEvent() service. If it is NULL, + then execute in blocking mode. BSP waits + until all APs finish or + TimeoutInMicroseconds expires. If it's + not NULL, then execute in non-blocking + mode. BSP requests the function specified + by Procedure to be started on all the + enabled APs, and go on executing + immediately. If all return from Procedure, + or TimeoutInMicroseconds expires, this + event is signaled. The BSP can use the + CheckEvent() or WaitForEvent() + services to check the state of event. Type + EFI_EVENT is defined in CreateEvent() in + the Unified Extensible Firmware Interface + Specification. + @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds + for APs to return from Procedure, either + for blocking or non-blocking mode. Zero + means infinity. If the timeout expires + before all APs return from Procedure, then + Procedure on the failed APs is terminated. + All enabled APs are available for next + function assigned by + EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + or EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + If the timeout expires in blocking mode, + BSP returns EFI_TIMEOUT. If the timeout + expires in non-blocking mode, WaitEvent + is signaled with SignalEvent(). + @param[in] ProcedureArgument The parameter passed into Procedure for + all APs. + @param[out] FailedCpuList If NULL, this parameter is ignored. + Otherwise, if all APs finish successfully, + then its content is set to NULL. If not + all APs finish before timeout expires, + then its content is set to address of the + buffer holding handle numbers of the + failed APs. + The buffer is allocated by MP Service + Protocol, and it's the caller's + responsibility to free the buffer with + FreePool() service. + In blocking mode, it is ready for + consumption when the call returns. In + non-blocking mode, it is ready when + WaitEvent is signaled. The list of failed + CPU is terminated by END_OF_CPU_LIST. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before + the timeout expired. + @retval EFI_SUCCESS In non-blocking mode, function has been + dispatched to all enabled APs. + @retval EFI_UNSUPPORTED A non-blocking mode request was made after the + UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was + signaled. + @retval EFI_DEVICE_ERROR Caller processor is AP. + @retval EFI_NOT_STARTED No enabled APs exist in the system. + @retval EFI_NOT_READY Any enabled APs are busy. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + all enabled APs have finished. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +STATIC +EFI_STATUS +EFIAPI +StartupAllAPs ( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT UINTN **FailedCpuList OPTIONAL + ) +{ + return MpInitLibStartupAllAPs ( + This, + Procedure, + SingleThread, + WaitEvent, + TimeoutInMicroseconds, + ProcedureArgument, + FailedCpuList + ); +} + +/** + This service lets the caller get one enabled AP to execute a caller-provided + function. The caller can request the BSP to either wait for the completion + of the AP or just proceed with the next task by using the EFI event mechanism. + See EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() for more details on non-blocking + execution support. This service may only be called from the BSP. + + This function is used to dispatch one enabled AP to the function specified by + Procedure passing in the argument specified by ProcedureArgument. If WaitEvent + is NULL, execution is in blocking mode. The BSP waits until the AP finishes or + TimeoutInMicroSecondss expires. Otherwise, execution is in non-blocking mode. + BSP proceeds to the next task without waiting for the AP. If a non-blocking mode + is requested after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled, + then EFI_UNSUPPORTED must be returned. + + If the timeout specified by TimeoutInMicroseconds expires before the AP returns + from Procedure, then execution of Procedure by the AP is terminated. The AP is + available for subsequent calls to EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() and + EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL + instance. + @param[in] Procedure A pointer to the function to be run on + enabled APs of the system. See type + EFI_AP_PROCEDURE. + @param[in] ProcessorNumber The handle number of the AP. The range is + from 0 to the total number of logical + processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] WaitEvent The event created by the caller with CreateEvent() + service. If it is NULL, then execute in + blocking mode. BSP waits until all APs finish + or TimeoutInMicroseconds expires. If it's + not NULL, then execute in non-blocking mode. + BSP requests the function specified by + Procedure to be started on all the enabled + APs, and go on executing immediately. If + all return from Procedure or TimeoutInMicroseconds + expires, this event is signaled. The BSP + can use the CheckEvent() or WaitForEvent() + services to check the state of event. Type + EFI_EVENT is defined in CreateEvent() in + the Unified Extensible Firmware Interface + Specification. + @param[in] TimeoutInMicroseconds Indicates the time limit in microseconds for + APs to return from Procedure, either for + blocking or non-blocking mode. Zero means + infinity. If the timeout expires before + all APs return from Procedure, then Procedure + on the failed APs is terminated. All enabled + APs are available for next function assigned + by EFI_MP_SERVICES_PROTOCOL.StartupAllAPs() + or EFI_MP_SERVICES_PROTOCOL.StartupThisAP(). + If the timeout expires in blocking mode, + BSP returns EFI_TIMEOUT. If the timeout + expires in non-blocking mode, WaitEvent + is signaled with SignalEvent(). + @param[in] ProcedureArgument The parameter passed into Procedure for + all APs. + @param[out] Finished If NULL, this parameter is ignored. In + blocking mode, this parameter is ignored. + In non-blocking mode, if AP returns from + Procedure before the timeout expires, its + content is set to TRUE. Otherwise, the + value is set to FALSE. The caller can + determine if the AP returned from Procedure + by evaluating this value. + + @retval EFI_SUCCESS In blocking mode, specified AP finished before + the timeout expires. + @retval EFI_SUCCESS In non-blocking mode, the function has been + dispatched to specified AP. + @retval EFI_UNSUPPORTED A non-blocking mode request was made after the + UEFI event EFI_EVENT_GROUP_READY_TO_BOOT was + signaled. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_TIMEOUT In blocking mode, the timeout expired before + the specified AP has finished. + @retval EFI_NOT_READY The specified AP is busy. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP or disabled AP. + @retval EFI_INVALID_PARAMETER Procedure is NULL. + +**/ +STATIC +EFI_STATUS +EFIAPI +StartupThisAP ( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN EFI_EVENT WaitEvent OPTIONAL, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL, + OUT BOOLEAN *Finished OPTIONAL + ) +{ + return MpInitLibStartupThisAP ( + This, + Procedure, + ProcessorNumber, + WaitEvent, + TimeoutInMicroseconds, + ProcedureArgument, + Finished + ); +} + +/** + This service switches the requested AP to be the BSP from that point onward. + This service changes the BSP for all purposes. This call can only be + performed by the current BSP. + + This service switches the requested AP to be the BSP from that point onward. + This service changes the BSP for all purposes. The new BSP can take over the + execution of the old BSP and continue seamlessly from where the old one left + off. This service may not be supported after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT + is signaled. + + If the BSP cannot be switched prior to the return from this service, then + EFI_UNSUPPORTED must be returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[in] ProcessorNumber The handle number of AP that is to become the new + BSP. The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] EnableOldBSP If TRUE, then the old BSP will be listed as an + enabled AP. Otherwise, it will be disabled. + + @retval EFI_SUCCESS BSP successfully switched. + @retval EFI_UNSUPPORTED Switching the BSP cannot be completed prior to + this service returning. + @retval EFI_UNSUPPORTED Switching the BSP is not supported. + @retval EFI_SUCCESS The calling processor is an AP. + @retval EFI_NOT_FOUND The processor with the handle specified by + ProcessorNumber does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the current BSP or + a disabled AP. + @retval EFI_NOT_READY The specified AP is busy. + +**/ +STATIC +EFI_STATUS +EFIAPI +SwitchBSP ( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ) +{ + return MpInitLibSwitchBSP (This, ProcessorNumber, EnableOldBSP); +} + +/** + This service lets the caller enable or disable an AP from this point onward. + This service may only be called from the BSP. + + This service allows the caller enable or disable an AP from this point onward. + The caller can optionally specify the health status of the AP by Health. If + an AP is being disabled, then the state of the disabled AP is implementation + dependent. If an AP is enabled, then the implementation must guarantee that a + complete initialization sequence is performed on the AP, so the AP is in a state + that is compatible with an MP operating system. This service may not be supported + after the UEFI Event EFI_EVENT_GROUP_READY_TO_BOOT is signaled. + + If the enable or disable AP operation cannot be completed prior to the return + from this service, then EFI_UNSUPPORTED must be returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[in] ProcessorNumber The handle number of AP that is to become the new + BSP. The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + @param[in] EnableAP Specifies the new state for the processor for + enabled, FALSE for disabled. + @param[in] HealthFlag If not NULL, a pointer to a value that specifies + the new health status of the AP. This flag + corresponds to StatusFlag defined in + EFI_MP_SERVICES_PROTOCOL.GetProcessorInfo(). Only + the PROCESSOR_HEALTH_STATUS_BIT is used. All other + bits are ignored. If it is NULL, this parameter + is ignored. + + @retval EFI_SUCCESS The specified AP was enabled or disabled successfully. + @retval EFI_UNSUPPORTED Enabling or disabling an AP cannot be completed + prior to this service returning. + @retval EFI_UNSUPPORTED Enabling or disabling an AP is not supported. + @retval EFI_DEVICE_ERROR The calling processor is an AP. + @retval EFI_NOT_FOUND Processor with the handle specified by ProcessorNumber + does not exist. + @retval EFI_INVALID_PARAMETER ProcessorNumber specifies the BSP. + +**/ +STATIC +EFI_STATUS +EFIAPI +EnableDisableAP ( + IN EFI_MP_SERVICES_PROTOCOL *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag OPTIONAL + ) +{ + return MpInitLibEnableDisableAP (This, ProcessorNumber, EnableAP, HealthFlag); +} + +/** + This return the handle number for the calling processor. This service may be + called from the BSP and APs. + + This service returns the processor handle number for the calling processor. + The returned value is in the range from 0 to the total number of logical + processors minus 1. The total number of logical processors can be retrieved + with EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). This service may be + called from the BSP and APs. If ProcessorNumber is NULL, then EFI_INVALID_PARAMETER + is returned. Otherwise, the current processors handle number is returned in + ProcessorNumber, and EFI_SUCCESS is returned. + + @param[in] This A pointer to the EFI_MP_SERVICES_PROTOCOL instance. + @param[out] ProcessorNumber The handle number of AP that is to become the new + BSP. The range is from 0 to the total number of + logical processors minus 1. The total number of + logical processors can be retrieved by + EFI_MP_SERVICES_PROTOCOL.GetNumberOfProcessors(). + + @retval EFI_SUCCESS The current processor handle number was returned + in ProcessorNumber. + @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. + +**/ +STATIC +EFI_STATUS +EFIAPI +WhoAmI ( + IN EFI_MP_SERVICES_PROTOCOL *This, + OUT UINTN *ProcessorNumber + ) +{ + return MpInitLibWhoAmI (This, ProcessorNumber); +} + +EFI_MP_SERVICES_PROTOCOL mMpServicesTemplate = { + GetNumberOfProcessors, + GetProcessorInfo, + StartupAllAPs, + StartupThisAP, + SwitchBSP, + EnableDisableAP, + WhoAmI +}; + +/** Initialize multi-processor support. + +**/ +VOID +InitializeMpSupport ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HANDLE Handle; + UINTN MaxCpus; + EFI_HOB_GENERIC_HEADER *Hob; + VOID *HobData; + UINTN HobDataSize; + ARM_PROCESSOR_TABLE CpuInfo; + + MaxCpus = 1; + ZeroMem (&CpuInfo, sizeof (ARM_PROCESSOR_TABLE)); + + DEBUG ((DEBUG_INFO, "Starting MP services")); + + Hob = GetFirstGuidHob (&gArmMpCoreInfoGuid); + if (Hob != NULL) { + HobData = GET_GUID_HOB_DATA (Hob); + HobDataSize = GET_GUID_HOB_DATA_SIZE (Hob); + CpuInfo.ArmCpus = (ARM_CORE_INFO *)HobData; + CpuInfo.NumberOfEntries = HobDataSize / sizeof (ARM_CORE_INFO); + MaxCpus = CpuInfo.NumberOfEntries; + } + + if (MaxCpus == 1) { + DEBUG ((DEBUG_WARN, "Trying to use EFI_MP_SERVICES_PROTOCOL on a UP system")); + // We are not MP so nothing to do + return; + } + + MpInitLibInitialize (MaxCpus, &CpuInfo); + + // + // Now install the MP services protocol. + // + Handle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces ( + &Handle, + &gEfiMpServiceProtocolGuid, + &mMpServicesTemplate, + NULL + ); + ASSERT_EFI_ERROR (Status); +} -- 2.31.1