Aamir Bohra has uploaded this change for review. ( https://review.coreboot.org/c/coreboot/+/49474 )
Change subject: drivers/intel/fsp2_0: Add support for MP PPI services2 APIs ......................................................................
drivers/intel/fsp2_0: Add support for MP PPI services2 APIs
Add support for MP services 2 PPIs, which is slight modification over MP services 1 PPIs. A new API StartupAllCPUs have been added to allow running a task on BSP and all APs. Also the EFI_PEI_SERVICES parameter has been removed from all MP PPI APIs.
Change-Id: Id74baf17fb90147d229c78be90268fdc3ec1badc Signed-off-by: Aamir Bohra aamir.bohra@intel.com --- M src/drivers/intel/fsp2_0/Kconfig M src/drivers/intel/fsp2_0/ppi/Kconfig M src/drivers/intel/fsp2_0/ppi/Makefile.inc A src/drivers/intel/fsp2_0/ppi/mp_service2_ppi.c M src/include/efi/efi_datatype.h A src/vendorcode/intel/edk2/edk2-stable202005/MdePkg/Include/Ppi/MpServices2.h 6 files changed, 480 insertions(+), 6 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/74/49474/1
diff --git a/src/drivers/intel/fsp2_0/Kconfig b/src/drivers/intel/fsp2_0/Kconfig index 96ae282..3651e59 100644 --- a/src/drivers/intel/fsp2_0/Kconfig +++ b/src/drivers/intel/fsp2_0/Kconfig @@ -159,7 +159,6 @@
config FSP_PEIM_TO_PEIM_INTERFACE bool - select FSP_USES_MP_SERVICES_PPI help This option allows SOC user to create specific PPI for Intel FSP usage, coreboot will provide required PPI structure definitions diff --git a/src/drivers/intel/fsp2_0/ppi/Kconfig b/src/drivers/intel/fsp2_0/ppi/Kconfig index 4f77a32..9c16730 100644 --- a/src/drivers/intel/fsp2_0/ppi/Kconfig +++ b/src/drivers/intel/fsp2_0/ppi/Kconfig @@ -2,10 +2,22 @@
config FSP_USES_MP_SERVICES_PPI bool - default n - depends on SOC_INTEL_COMMON_BLOCK_CPU_MPINIT + depends on FSP_PEIM_TO_PEIM_INTERFACE && SOC_INTEL_COMMON_BLOCK_CPU_MPINIT help This option allows SoC user to create MP service PPI for Intel FSP usage, coreboot will provide EFI_PEI_MP_SERVICES_PPI structure definitions along with all APIs as per EDK2 specification. Intel FSP will use this PPI to run CPU feature programming on APs. + +config FSP_USES_MP_SERVICES2_PPI + bool + depends on FSP_PEIM_TO_PEIM_INTERFACE && SOC_INTEL_COMMON_BLOCK_CPU_MPINIT + help + This option allows SoC user to create MP service PPI for Intel + FSP usage, coreboot will provide EFI_PEI_MP_SERVICES_PPI structure + definitions along with all APIs as per EDK2 specification. Intel FSP + will use this PPI to run CPU feature programming on APs. Allows using + MP services 2 PPIs, which is slight modification on MP services 1 PPIs. + A new API StartupAllCPUs have been added to allow running a task on BSP + and all APs. Also the EFI_PEI_SERVICES parameter has been removed from + all MP PPI APIs. diff --git a/src/drivers/intel/fsp2_0/ppi/Makefile.inc b/src/drivers/intel/fsp2_0/ppi/Makefile.inc index 8d8d990..e30c503 100644 --- a/src/drivers/intel/fsp2_0/ppi/Makefile.inc +++ b/src/drivers/intel/fsp2_0/ppi/Makefile.inc @@ -1,3 +1,4 @@ # SPDX-License-Identifier: GPL-2.0-only
ramstage-$(CONFIG_FSP_USES_MP_SERVICES_PPI) += mp_service_ppi.c +ramstage-$(CONFIG_FSP_USES_MP_SERVICES2_PPI) += mp_service2_ppi.c diff --git a/src/drivers/intel/fsp2_0/ppi/mp_service2_ppi.c b/src/drivers/intel/fsp2_0/ppi/mp_service2_ppi.c new file mode 100644 index 0000000..64cba2e --- /dev/null +++ b/src/drivers/intel/fsp2_0/ppi/mp_service2_ppi.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <cpu/x86/mp.h> +#include <cpu/x86/lapic.h> +#include <cpu/intel/microcode.h> +#include <fsp/api.h> +#include <fsp/ppi/mp_service_ppi.h> +#include <intelblocks/cpulib.h> +#include <intelblocks/mp_init.h> + +#define BSP_CPU_SLOT 0 +#define SINGLE_CHIP_PACKAGE 0 + +static efi_return_status_t mp_get_number_of_processors( + efi_pei_mp_services_ppi *ignored1, + efi_uintn_t *number_of_processors, + efi_uintn_t *number_of_enabled_processors) +{ + if (number_of_processors == NULL || number_of_enabled_processors == + NULL) + return FSP_INVALID_PARAMETER; + + *number_of_processors = get_cpu_count(); + *number_of_enabled_processors = get_cpu_count(); + + return FSP_SUCCESS; +} + +static efi_return_status_t mp_get_processor_info( + efi_pei_mp_services_ppi *ignored1, + efi_uintn_t processor_number, + efi_processor_information *processor_info_buffer) +{ + unsigned int num_virt_cores, num_phys_cores; + + if (cpu_index() < 0) + return FSP_DEVICE_ERROR; + + if (processor_info_buffer == NULL) + return FSP_INVALID_PARAMETER; + + if (processor_number >= get_cpu_count()) + return FSP_NOT_FOUND; + + processor_info_buffer->ProcessorId = lapicid(); + + processor_info_buffer->StatusFlag = PROCESSOR_HEALTH_STATUS_BIT + | PROCESSOR_ENABLED_BIT; + + if (processor_number == BSP_CPU_SLOT) + processor_info_buffer->StatusFlag |= PROCESSOR_AS_BSP_BIT; + + /* Fill EFI_CPU_PHYSICAL_LOCATION structure information */ + cpu_read_topology(&num_phys_cores, &num_virt_cores); + + /* FSP will add one to the value in this Package field */ + processor_info_buffer->Location.Package = SINGLE_CHIP_PACKAGE; + processor_info_buffer->Location.Core = num_phys_cores; + processor_info_buffer->Location.Thread = num_virt_cores; + + return FSP_SUCCESS; +} + +static efi_return_status_t mp_startup_all_aps( + efi_pei_mp_services_ppi *ignored1, + efi_ap_procedure procedure, efi_boolean_t ignored2, + efi_uintn_t timeout_usec, void *argument) +{ + if (cpu_index() < 0) + return FSP_DEVICE_ERROR; + + if (procedure == NULL) + return FSP_INVALID_PARAMETER; + + if (mp_run_on_aps((void *)procedure, argument, + MP_RUN_ON_ALL_CPUS, timeout_usec)) { + return FSP_NOT_STARTED; + } + + return FSP_SUCCESS; +} + +static efi_return_status_t mp_startup_all_cpus( + efi_pei_mp_services_ppi *ignored1, + efi_ap_procedure procedure, + efi_uintn_t ignored2, void *argument) +{ + if (cpu_index() < 0) + return FSP_DEVICE_ERROR; + + if (procedure == NULL) + return FSP_INVALID_PARAMETER; + + if (mp_run_on_all_cpus((void *)procedure, argument)) { + return FSP_NOT_STARTED; + } + + return FSP_SUCCESS; +} + +static efi_return_status_t mp_startup_this_ap( + efi_pei_mp_services_ppi *ignored1, + efi_ap_procedure procedure, efi_uintn_t processor_number, + efi_uintn_t timeout_usec, void *argument) +{ + if (cpu_index() < 0) + return FSP_DEVICE_ERROR; + + if (processor_number > get_cpu_count()) + return FSP_NOT_FOUND; + + if (processor_number == BSP_CPU_SLOT) + return FSP_INVALID_PARAMETER; + + if (procedure == NULL) + return FSP_INVALID_PARAMETER; + + if (mp_run_on_aps((void *)procedure, argument, + processor_number, timeout_usec)) { + return FSP_NOT_STARTED; + } + + return FSP_SUCCESS; +} + +static efi_return_status_t mp_switch_bsp( + efi_pei_mp_services_ppi *ignored1, efi_uintn_t ignored2, + efi_boolean_t ignored3) +{ + /* FSP don't need this API hence return unsupported */ + return FSP_UNSUPPORTED; +} + +static efi_return_status_t mp_enable_disable_ap( + efi_pei_mp_services_ppi *ignored1, + efi_uintn_t ignored2, efi_boolean_t ignored3, efi_uint32_t *ignored4) +{ + /* FSP don't need this API hence return unsupported */ + return FSP_UNSUPPORTED; +} + +static efi_return_status_t mp_identify_processor( + efi_pei_mp_services_ppi *ignored1, + efi_uintn_t *processor_number) +{ + int index; + + if (processor_number == NULL) + return FSP_INVALID_PARAMETER; + + index = cpu_index(); + + if (index < 0) + return FSP_DEVICE_ERROR; + + *processor_number = index; + + return FSP_SUCCESS; +} + +/* + * EDK2 UEFIPKG Open Source MP Service PPI to be installed + */ + +static efi_pei_mp_services_ppi mp_service_ppi = { + mp_get_number_of_processors, + mp_get_processor_info, + mp_startup_all_aps, + mp_startup_this_ap, + mp_switch_bsp, + mp_enable_disable_ap, + mp_identify_processor, + mp_startup_all_cpus, +}; + +efi_pei_mp_services_ppi *mp_fill_ppi_services_data(void) +{ + return &mp_service_ppi; +} diff --git a/src/include/efi/efi_datatype.h b/src/include/efi/efi_datatype.h index f6a20a7..1bf65f5 100644 --- a/src/include/efi/efi_datatype.h +++ b/src/include/efi/efi_datatype.h @@ -7,6 +7,7 @@ #include <Base.h> #include <PiPei.h> #include <Ppi/MpServices.h> +#include <Ppi/MpServices2.h>
/* Basic Data types */
@@ -54,11 +55,13 @@
/* Data structure */
-/* Data structure for EFI_PEI_SERVICE. */ -typedef EFI_PEI_SERVICES efi_pei_services; - /* Data structure for UEFI PI Multi-processor PPI */ +#if CONFIG(FSP_USES_MP_SERVICES2_PPI) +typedef EDKII_PEI_MP_SERVICES2_PPI efi_pei_mp_services_ppi; +#else typedef EFI_PEI_MP_SERVICES_PPI efi_pei_mp_services_ppi; +typedef EFI_PEI_SERVICES efi_pei_services; +#endif
/* Structure that describes information about a logical CPU. */ typedef EFI_PROCESSOR_INFORMATION efi_processor_information; diff --git a/src/vendorcode/intel/edk2/edk2-stable202005/MdePkg/Include/Ppi/MpServices2.h b/src/vendorcode/intel/edk2/edk2-stable202005/MdePkg/Include/Ppi/MpServices2.h new file mode 100644 index 0000000..1e368ab --- /dev/null +++ b/src/vendorcode/intel/edk2/edk2-stable202005/MdePkg/Include/Ppi/MpServices2.h @@ -0,0 +1,279 @@ +/** @file + This file declares EDKII Multi-processor service PPI. + + Copyright (c) 2019, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ +#ifndef __EDKII_PEI_MP_SERVICES2_PPI_H__ +#define __EDKII_PEI_MP_SERVICES2_PPI_H__ + +#include <Ppi/MpServices.h> + +#define EDKII_PEI_MP_SERVICES2_PPI_GUID \ + { \ + 0x5cb9cb3d, 0x31a4, 0x480c, { 0x94, 0x98, 0x29, 0xd2, 0x69, 0xba, 0xcf, 0xba} \ + } + +typedef struct _EDKII_PEI_MP_SERVICES2_PPI EDKII_PEI_MP_SERVICES2_PPI; + +/** + Get the number of CPU's. + + @param[in] This Pointer to this instance of the PPI. + @param[out] NumberOfProcessors Pointer to the total number of logical processors in + the system, including the BSP and disabled APs. + @param[out] NumberOfEnabledProcessors + Number of processors in the system that are enabled. + + @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. + NumberOfEnabledProcessors is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + OUT UINTN *NumberOfProcessors, + OUT UINTN *NumberOfEnabledProcessors + ); + +/** + Get information on a specific CPU. + + @param[in] This Pointer to this instance of the PPI. + @param[in] ProcessorNumber Pointer to the total number of logical processors in + the system, including the BSP and disabled APs. + @param[out] ProcessorInfoBuffer Number of processors in the system that are enabled. + + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_GET_PROCESSOR_INFO) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN UINTN ProcessorNumber, + OUT EFI_PROCESSOR_INFORMATION *ProcessorInfoBuffer + ); + +/** + Activate all of the application proessors. + + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] Procedure A pointer to the function to be run on enabled APs of + the system. + @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] TimeoutInMicroSeconds + Indicates the time limit in microseconds for APs to + return from Procedure, for blocking mode only. 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_PEI_MP_SERVICES_PPI.StartupAllAPs() + or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the + timeout expires in blocking mode, BSP returns + EFI_TIMEOUT. + @param[in] ProcedureArgument The parameter passed into Procedure for all APs. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before the + timeout expired. + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_STARTUP_ALL_APS) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN BOOLEAN SingleThread, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument OPTIONAL + ); + +/** + Activate a specific application processor. + + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[in] Procedure A pointer to the function to be run on enabled APs of + the system. + @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_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + @param[in] TimeoutInMicroSeconds + Indicates the time limit in microseconds for APs to + return from Procedure, for blocking mode only. 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_PEI_MP_SERVICES_PPI.StartupAllAPs() + or EFI_PEI_MP_SERVICES_PPI.StartupThisAP(). If the + timeout expires in blocking mode, BSP returns + EFI_TIMEOUT. + @param[in] ProcedureArgument The parameter passed into Procedure for all APs. + + @retval EFI_SUCCESS In blocking mode, specified AP finished before the + timeout expires. + @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_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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_STARTUP_THIS_AP) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN ProcessorNumber, + IN UINTN TimeoutInMicroseconds, + IN VOID *ProcedureArgument OPTIONAL + ); + +/** + Switch the boot strap processor. + + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @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_PEI_MP_SERVICES_PPI.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_DEVICE_ERROR 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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_SWITCH_BSP) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableOldBSP + ); + +/** + Enable or disable an application processor. + + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @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_PEI_MP_SERVICES_PPI.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_PEI_MP_SERVICES_PPI.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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_ENABLEDISABLEAP) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN UINTN ProcessorNumber, + IN BOOLEAN EnableAP, + IN UINT32 *HealthFlag OPTIONAL + ); + +/** + Identify the currently executing processor. + + @param[in] This A pointer to the EFI_PEI_MP_SERVICES_PPI instance. + @param[out] 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_PEI_MP_SERVICES_PPI.GetNumberOfProcessors(). + + @retval EFI_SUCCESS The current processor handle number was returned in + ProcessorNumber. + @retval EFI_INVALID_PARAMETER ProcessorNumber is NULL. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_WHOAMI) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + OUT UINTN *ProcessorNumber + ); + + +/** + Activate all of the application proessors. + + @param[in] This A pointer to the EDKII_PEI_MP_SERVICES2_PPI instance. + @param[in] Procedure A pointer to the function to be run on enabled APs of + the system. + @param[in] TimeoutInMicroSeconds + Indicates the time limit in microseconds for APs to + return from Procedure, for blocking mode only. Zero + means infinity. If the timeout expires in blocking + mode, BSP returns EFI_TIMEOUT. + @param[in] ProcedureArgument The parameter passed into Procedure for all CPUs. + + @retval EFI_SUCCESS In blocking mode, all APs have finished before the + timeout expired. + @retval EFI_DEVICE_ERROR Caller processor is AP. + @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. +**/ +typedef +EFI_STATUS +(EFIAPI *EDKII_PEI_MP_SERVICES_STARTUP_ALL_CPUS) ( + IN EDKII_PEI_MP_SERVICES2_PPI *This, + IN EFI_AP_PROCEDURE Procedure, + IN UINTN TimeoutInMicroSeconds, + IN VOID *ProcedureArgument OPTIONAL + ); + +struct _EDKII_PEI_MP_SERVICES2_PPI { + EDKII_PEI_MP_SERVICES_GET_NUMBER_OF_PROCESSORS GetNumberOfProcessors; + EDKII_PEI_MP_SERVICES_GET_PROCESSOR_INFO GetProcessorInfo; + EDKII_PEI_MP_SERVICES_STARTUP_ALL_APS StartupAllAPs; + EDKII_PEI_MP_SERVICES_STARTUP_THIS_AP StartupThisAP; + EDKII_PEI_MP_SERVICES_SWITCH_BSP SwitchBSP; + EDKII_PEI_MP_SERVICES_ENABLEDISABLEAP EnableDisableAP; + EDKII_PEI_MP_SERVICES_WHOAMI WhoAmI; + EDKII_PEI_MP_SERVICES_STARTUP_ALL_CPUS StartupAllCPUs; +}; + +extern EFI_GUID gEdkiiPeiMpServices2PpiGuid; + +#endif +