mirror of
https://github.com/acidanthera/audk.git
synced 2025-07-30 09:04:07 +02:00
ArmPkg: implement EFI_MP_SERVICES_PROTOCOL based on PSCI calls
Add support for EFI_MP_SERVICES_PROTOCOL during the DXE phase under AArch64. PSCI_CPU_ON is called to power on the core, the supplied procedure is executed and PSCI_CPU_OFF is called to power off the core. Fixes contributed by Ard Biesheuvel. Signed-off-by: Rebecca Cran <rebecca@quicinc.com> Reviewed-by: Ard Biesheuvel <ardb@kernel.org> Tested-by: Kun Qin <kun.qin@microsoft.com>
This commit is contained in:
parent
d1855afc6e
commit
e7aac7fc13
@ -164,6 +164,7 @@
|
|||||||
ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
|
ArmPkg/Universal/Smbios/OemMiscLibNull/OemMiscLibNull.inf
|
||||||
|
|
||||||
[Components.AARCH64]
|
[Components.AARCH64]
|
||||||
|
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
|
||||||
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
ArmPkg/Drivers/MmCommunicationDxe/MmCommunication.inf
|
||||||
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
ArmPkg/Library/ArmMmuLib/ArmMmuPeiLib.inf
|
||||||
|
|
||||||
|
1859
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.c
Normal file
1859
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.c
Normal file
File diff suppressed because it is too large
Load Diff
56
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
Normal file
56
ArmPkg/Drivers/ArmPsciMpServicesDxe/ArmPsciMpServicesDxe.inf
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
## @file
|
||||||
|
# ARM MP services protocol driver
|
||||||
|
#
|
||||||
|
# Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.<BR>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#
|
||||||
|
##
|
||||||
|
|
||||||
|
[Defines]
|
||||||
|
INF_VERSION = 1.27
|
||||||
|
BASE_NAME = ArmPsciMpServicesDxe
|
||||||
|
FILE_GUID = 007ab472-dc4a-4df8-a5c2-abb4a327278c
|
||||||
|
MODULE_TYPE = DXE_DRIVER
|
||||||
|
VERSION_STRING = 1.0
|
||||||
|
|
||||||
|
ENTRY_POINT = ArmPsciMpServicesDxeInitialize
|
||||||
|
|
||||||
|
[Sources.Common]
|
||||||
|
ArmPsciMpServicesDxe.c
|
||||||
|
MpFuncs.S
|
||||||
|
MpServicesInternal.h
|
||||||
|
|
||||||
|
[Packages]
|
||||||
|
ArmPkg/ArmPkg.dec
|
||||||
|
ArmPlatformPkg/ArmPlatformPkg.dec
|
||||||
|
EmbeddedPkg/EmbeddedPkg.dec
|
||||||
|
MdePkg/MdePkg.dec
|
||||||
|
MdeModulePkg/MdeModulePkg.dec
|
||||||
|
|
||||||
|
[LibraryClasses]
|
||||||
|
ArmLib
|
||||||
|
ArmMmuLib
|
||||||
|
ArmSmcLib
|
||||||
|
BaseMemoryLib
|
||||||
|
CacheMaintenanceLib
|
||||||
|
CpuExceptionHandlerLib
|
||||||
|
DebugLib
|
||||||
|
HobLib
|
||||||
|
MemoryAllocationLib
|
||||||
|
UefiBootServicesTableLib
|
||||||
|
UefiDriverEntryPoint
|
||||||
|
UefiLib
|
||||||
|
|
||||||
|
[Protocols]
|
||||||
|
gEfiMpServiceProtocolGuid ## PRODUCES
|
||||||
|
gEfiLoadedImageProtocolGuid ## CONSUMES
|
||||||
|
|
||||||
|
[Guids]
|
||||||
|
gArmMpCoreInfoGuid
|
||||||
|
|
||||||
|
[Depex]
|
||||||
|
TRUE
|
||||||
|
|
||||||
|
[BuildOptions]
|
||||||
|
GCC:*_*_*_CC_FLAGS = -mstrict-align
|
74
ArmPkg/Drivers/ArmPsciMpServicesDxe/MpFuncs.S
Normal file
74
ArmPkg/Drivers/ArmPsciMpServicesDxe/MpFuncs.S
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#===============================================================================
|
||||||
|
# Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
#===============================================================================
|
||||||
|
|
||||||
|
.text
|
||||||
|
.align 3
|
||||||
|
|
||||||
|
#include <AsmMacroIoLibV8.h>
|
||||||
|
#include <IndustryStandard/ArmStdSmc.h>
|
||||||
|
#include <Library/ArmLib.h>
|
||||||
|
|
||||||
|
#include "MpServicesInternal.h"
|
||||||
|
|
||||||
|
GCC_ASM_IMPORT (gApStacksBase)
|
||||||
|
GCC_ASM_IMPORT (gProcessorIDs)
|
||||||
|
GCC_ASM_IMPORT (ApProcedure)
|
||||||
|
GCC_ASM_IMPORT (gApStackSize)
|
||||||
|
GCC_ASM_IMPORT (gTcr)
|
||||||
|
GCC_ASM_IMPORT (gTtbr0)
|
||||||
|
GCC_ASM_IMPORT (gMair)
|
||||||
|
|
||||||
|
GCC_ASM_EXPORT (ApEntryPoint)
|
||||||
|
|
||||||
|
// Entry-point for the AP
|
||||||
|
// VOID
|
||||||
|
// ApEntryPoint (
|
||||||
|
// VOID
|
||||||
|
// );
|
||||||
|
ASM_PFX(ApEntryPoint):
|
||||||
|
// Configure the MMU and caches
|
||||||
|
ldr x0, gTcr
|
||||||
|
bl ArmSetTCR
|
||||||
|
ldr x0, gTtbr0
|
||||||
|
bl ArmSetTTBR0
|
||||||
|
ldr x0, gMair
|
||||||
|
bl ArmSetMAIR
|
||||||
|
bl ArmDisableAlignmentCheck
|
||||||
|
bl ArmEnableStackAlignmentCheck
|
||||||
|
bl ArmEnableInstructionCache
|
||||||
|
bl ArmEnableDataCache
|
||||||
|
bl ArmEnableMmu
|
||||||
|
|
||||||
|
mrs x0, mpidr_el1
|
||||||
|
// Mask the non-affinity bits
|
||||||
|
bic x0, x0, 0x00ff000000
|
||||||
|
and x0, x0, 0xffffffffff
|
||||||
|
ldr x1, gProcessorIDs
|
||||||
|
mov x2, 0 // x2 = processor index
|
||||||
|
|
||||||
|
// Find index in gProcessorIDs for current processor
|
||||||
|
1:
|
||||||
|
ldr x3, [x1, x2, lsl #3] // x4 = gProcessorIDs + x2 * 8
|
||||||
|
cmp x3, #-1 // check if we've reached the end of gProcessorIDs
|
||||||
|
beq ProcessorNotFound
|
||||||
|
add x2, x2, 1 // x2++
|
||||||
|
cmp x0, x3 // if mpidr_el1 != gProcessorIDs[x] then loop
|
||||||
|
bne 1b
|
||||||
|
|
||||||
|
// Calculate stack address
|
||||||
|
// x2 contains the index for the current processor plus 1
|
||||||
|
ldr x0, gApStacksBase
|
||||||
|
ldr x1, gApStackSize
|
||||||
|
mul x3, x2, x1 // x3 = (ProcessorIndex + 1) * gApStackSize
|
||||||
|
add sp, x0, x3 // sp = gApStacksBase + x3
|
||||||
|
mov x29, xzr
|
||||||
|
bl ApProcedure // doesn't return
|
||||||
|
|
||||||
|
ProcessorNotFound:
|
||||||
|
// Turn off the processor
|
||||||
|
MOV32 (w0, ARM_SMC_ID_PSCI_CPU_OFF)
|
||||||
|
smc #0
|
||||||
|
b .
|
345
ArmPkg/Drivers/ArmPsciMpServicesDxe/MpServicesInternal.h
Normal file
345
ArmPkg/Drivers/ArmPsciMpServicesDxe/MpServicesInternal.h
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
/** @file
|
||||||
|
|
||||||
|
Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.<BR>
|
||||||
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||||
|
Portions copyright (c) 2011, Apple Inc. All rights reserved.
|
||||||
|
|
||||||
|
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
#ifndef MP_SERVICES_INTERNAL_H_
|
||||||
|
#define MP_SERVICES_INTERNAL_H_
|
||||||
|
|
||||||
|
#include <Protocol/Cpu.h>
|
||||||
|
#include <Protocol/MpService.h>
|
||||||
|
|
||||||
|
#include <Library/BaseLib.h>
|
||||||
|
#include <Library/UefiLib.h>
|
||||||
|
|
||||||
|
#define AP_STACK_SIZE 0x1000
|
||||||
|
|
||||||
|
//
|
||||||
|
// Internal Data Structures
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// AP state
|
||||||
|
//
|
||||||
|
// The state transitions for an AP when it processes a procedure are:
|
||||||
|
// Idle ----> Ready ----> Busy ----> Finished ----> Idle
|
||||||
|
// [BSP] [BSP] [AP] [BSP]
|
||||||
|
//
|
||||||
|
typedef enum {
|
||||||
|
CpuStateIdle,
|
||||||
|
CpuStateReady,
|
||||||
|
CpuStateBlocked,
|
||||||
|
CpuStateBusy,
|
||||||
|
CpuStateFinished,
|
||||||
|
CpuStateDisabled
|
||||||
|
} CPU_STATE;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define Individual Processor Data block.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
EFI_PROCESSOR_INFORMATION Info;
|
||||||
|
EFI_AP_PROCEDURE Procedure;
|
||||||
|
VOID *Parameter;
|
||||||
|
CPU_STATE State;
|
||||||
|
EFI_EVENT CheckThisAPEvent;
|
||||||
|
EFI_EVENT WaitEvent;
|
||||||
|
UINTN Timeout;
|
||||||
|
UINTN TimeTaken;
|
||||||
|
BOOLEAN TimeoutActive;
|
||||||
|
BOOLEAN *SingleApFinished;
|
||||||
|
} CPU_AP_DATA;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Define MP data block which consumes individual processor block.
|
||||||
|
//
|
||||||
|
typedef struct {
|
||||||
|
UINTN NumberOfProcessors;
|
||||||
|
UINTN NumberOfEnabledProcessors;
|
||||||
|
EFI_EVENT CheckAllAPsEvent;
|
||||||
|
EFI_EVENT AllWaitEvent;
|
||||||
|
UINTN FinishCount;
|
||||||
|
UINTN StartCount;
|
||||||
|
EFI_AP_PROCEDURE Procedure;
|
||||||
|
VOID *ProcedureArgument;
|
||||||
|
BOOLEAN SingleThread;
|
||||||
|
UINTN StartedNumber;
|
||||||
|
CPU_AP_DATA *CpuData;
|
||||||
|
UINTN *FailedList;
|
||||||
|
UINTN FailedListIndex;
|
||||||
|
UINTN AllTimeout;
|
||||||
|
UINTN AllTimeTaken;
|
||||||
|
BOOLEAN AllTimeoutActive;
|
||||||
|
} CPU_MP_DATA;
|
||||||
|
|
||||||
|
/** Secondary core entry point.
|
||||||
|
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ApEntryPoint (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/** C entry-point for the AP.
|
||||||
|
This function gets called from the assembly function ApEntryPoint.
|
||||||
|
**/
|
||||||
|
VOID
|
||||||
|
ApProcedure (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Turns on the specified core using PSCI and executes the user-supplied
|
||||||
|
function that's been configured via a previous call to SetApProcedure.
|
||||||
|
|
||||||
|
@param ProcessorIndex The index of the core to turn on.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS The processor was successfully turned on.
|
||||||
|
@retval EFI_DEVICE_ERROR An error occurred turning the processor on.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
EFIAPI
|
||||||
|
DispatchCpu (
|
||||||
|
IN UINTN ProcessorIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns whether the specified processor is the BSP.
|
||||||
|
|
||||||
|
@param[in] ProcessorIndex The index the processor to check.
|
||||||
|
|
||||||
|
@return TRUE if the processor is the BSP, FALSE otherwise.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
IsProcessorBSP (
|
||||||
|
UINTN ProcessorIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns whether the processor executing this function is the BSP.
|
||||||
|
|
||||||
|
@return Whether the current processor is the BSP.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
IsCurrentProcessorBSP (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns whether the specified processor is enabled.
|
||||||
|
|
||||||
|
@param[in] ProcessorIndex The index of the processor to check.
|
||||||
|
|
||||||
|
@return TRUE if the processor is enabled, FALSE otherwise.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
BOOLEAN
|
||||||
|
IsProcessorEnabled (
|
||||||
|
UINTN ProcessorIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Configures the processor context with the user-supplied procedure and
|
||||||
|
argument.
|
||||||
|
|
||||||
|
@param CpuData The processor context.
|
||||||
|
@param Procedure The user-supplied procedure.
|
||||||
|
@param ProcedureArgument The user-supplied procedure argument.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
SetApProcedure (
|
||||||
|
IN CPU_AP_DATA *CpuData,
|
||||||
|
IN EFI_AP_PROCEDURE Procedure,
|
||||||
|
IN VOID *ProcedureArgument
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Get the Application Processors state.
|
||||||
|
|
||||||
|
@param[in] CpuData The pointer to CPU_AP_DATA of specified AP
|
||||||
|
|
||||||
|
@return The AP status
|
||||||
|
**/
|
||||||
|
CPU_STATE
|
||||||
|
GetApState (
|
||||||
|
IN CPU_AP_DATA *CpuData
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Returns the index of the next processor that is blocked.
|
||||||
|
|
||||||
|
@param[out] NextNumber The index of the next blocked processor.
|
||||||
|
|
||||||
|
@retval EFI_SUCCESS Successfully found the next blocked processor.
|
||||||
|
@retval EFI_NOT_FOUND There are no blocked processors.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
GetNextBlockedNumber (
|
||||||
|
OUT UINTN *NextNumber
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Stalls the BSP for the minimum of gPollInterval and Timeout.
|
||||||
|
|
||||||
|
@param[in] Timeout The time limit in microseconds remaining for
|
||||||
|
APs to return from Procedure.
|
||||||
|
|
||||||
|
@retval StallTime Time of execution stall.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
UINTN
|
||||||
|
CalculateAndStallInterval (
|
||||||
|
IN UINTN Timeout
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Sets up the state for the StartupAllAPs function.
|
||||||
|
|
||||||
|
@param SingleThread Whether the APs will execute sequentially.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
StartupAllAPsPrepareState (
|
||||||
|
IN BOOLEAN SingleThread
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Handles execution of StartupAllAPs when a WaitEvent has been specified.
|
||||||
|
|
||||||
|
@param Procedure The user-supplied procedure.
|
||||||
|
@param ProcedureArgument The user-supplied procedure argument.
|
||||||
|
@param WaitEvent The wait event to be signaled when the work is
|
||||||
|
complete or a timeout has occurred.
|
||||||
|
@param TimeoutInMicroseconds The timeout for the work to be completed. Zero
|
||||||
|
indicates an infinite timeout.
|
||||||
|
@param SingleThread Whether the APs will execute sequentially.
|
||||||
|
@param FailedCpuList User-supplied pointer for list of failed CPUs.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS on success.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
StartupAllAPsWithWaitEvent (
|
||||||
|
IN EFI_AP_PROCEDURE Procedure,
|
||||||
|
IN VOID *ProcedureArgument,
|
||||||
|
IN EFI_EVENT WaitEvent,
|
||||||
|
IN UINTN TimeoutInMicroseconds,
|
||||||
|
IN BOOLEAN SingleThread,
|
||||||
|
IN UINTN **FailedCpuList
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Handles execution of StartupAllAPs when no wait event has been specified.
|
||||||
|
|
||||||
|
@param Procedure The user-supplied procedure.
|
||||||
|
@param ProcedureArgument The user-supplied procedure argument.
|
||||||
|
@param TimeoutInMicroseconds The timeout for the work to be completed. Zero
|
||||||
|
indicates an infinite timeout.
|
||||||
|
@param SingleThread Whether the APs will execute sequentially.
|
||||||
|
@param FailedCpuList User-supplied pointer for list of failed CPUs.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS on success.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
StartupAllAPsNoWaitEvent (
|
||||||
|
IN EFI_AP_PROCEDURE Procedure,
|
||||||
|
IN VOID *ProcedureArgument,
|
||||||
|
IN UINTN TimeoutInMicroseconds,
|
||||||
|
IN BOOLEAN SingleThread,
|
||||||
|
IN UINTN **FailedCpuList
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Adds the specified processor the list of failed processors.
|
||||||
|
|
||||||
|
@param ProcessorIndex The processor index to add.
|
||||||
|
@param ApState Processor state.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
AddProcessorToFailedList (
|
||||||
|
UINTN ProcessorIndex,
|
||||||
|
CPU_STATE ApState
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Handles the StartupAllAPs case where the timeout has occurred.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
ProcessStartupAllAPsTimeout (
|
||||||
|
VOID
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
If a timeout is specified in StartupAllAps(), a timer is set, which invokes
|
||||||
|
this procedure periodically to check whether all APs have finished.
|
||||||
|
|
||||||
|
@param[in] Event The WaitEvent the user supplied.
|
||||||
|
@param[in] Context The event context.
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
CheckAllAPsStatus (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/** Invoked periodically via a timer to check the state of the processor.
|
||||||
|
|
||||||
|
@param Event The event supplied by the timer expiration.
|
||||||
|
@param Context The processor context.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
CheckThisAPStatus (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
This function is called by all processors (both BSP and AP) once and collects
|
||||||
|
MP related data.
|
||||||
|
|
||||||
|
@param BSP TRUE if the processor is the BSP.
|
||||||
|
@param Mpidr The MPIDR for the specified processor. This should be
|
||||||
|
the full MPIDR and not only the affinity bits.
|
||||||
|
@param ProcessorIndex The index of the processor.
|
||||||
|
|
||||||
|
@return EFI_SUCCESS if the data for the processor collected and filled in.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
EFI_STATUS
|
||||||
|
FillInProcessorInformation (
|
||||||
|
IN BOOLEAN BSP,
|
||||||
|
IN UINTN Mpidr,
|
||||||
|
IN UINTN ProcessorIndex
|
||||||
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Event notification function called when the EFI_EVENT_GROUP_READY_TO_BOOT is
|
||||||
|
signaled. After this point, non-blocking mode is no longer allowed.
|
||||||
|
|
||||||
|
@param Event Event whose notification function is being invoked.
|
||||||
|
@param Context The pointer to the notification function's context,
|
||||||
|
which is implementation-dependent.
|
||||||
|
|
||||||
|
**/
|
||||||
|
STATIC
|
||||||
|
VOID
|
||||||
|
EFIAPI
|
||||||
|
ReadyToBootSignaled (
|
||||||
|
IN EFI_EVENT Event,
|
||||||
|
IN VOID *Context
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif /* MP_SERVICES_INTERNAL_H_ */
|
Loading…
x
Reference in New Issue
Block a user