diff --git a/Makefile b/Makefile index 16279b603..797b2cfeb 100644 --- a/Makefile +++ b/Makefile @@ -1096,7 +1096,6 @@ $(eval $(call assert_booleans,\ ENABLE_RUNTIME_INSTRUMENTATION \ ENABLE_SME_FOR_NS \ ENABLE_SME_FOR_SWD \ - ENABLE_SPE_FOR_NS \ ENABLE_SVE_FOR_NS \ ENABLE_SVE_FOR_SWD \ ERROR_DEPRECATED \ @@ -1182,6 +1181,7 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_VHE \ ENABLE_MPAM_FOR_LOWER_ELS \ ENABLE_RME \ + ENABLE_SPE_FOR_NS \ ENABLE_TRF_FOR_NS \ FW_ENC_STATUS \ NR_OF_FW_BANKS \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index b639920e5..e000f4f7b 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -87,7 +87,7 @@ BL31_SOURCES += services/std_svc/trng/trng_main.c \ services/std_svc/trng/trng_entropy_pool.c endif -ifeq (${ENABLE_SPE_FOR_NS},1) +ifneq (${ENABLE_SPE_FOR_NS},0) BL31_SOURCES += lib/extensions/spe/spe.c endif diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 9241c3912..9415871df 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -428,10 +428,11 @@ Common build options handle context switching for SME, SVE, and FPU/SIMD registers to ensure that no data is leaked to non-secure world. This is experimental. Default is 0. -- ``ENABLE_SPE_FOR_NS`` : Boolean option to enable Statistical Profiling +- ``ENABLE_SPE_FOR_NS`` : Numeric value to enable Statistical Profiling extensions. This is an optional architectural feature for AArch64. - The default is 1 but is automatically disabled when the target architecture - is AArch32. + This flag can take the values 0 to 2, to align with the ``FEATURE_DETECTION`` + mechanism. The default is 2 but is automatically disabled when the target + architecture is AArch32. - ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension (SVE) for the Non-secure world only. SVE is an optional architectural feature diff --git a/include/arch/aarch32/arch_features.h b/include/arch/aarch32/arch_features.h index a5a5e278b..12df6da4b 100644 --- a/include/arch/aarch32/arch_features.h +++ b/include/arch/aarch32/arch_features.h @@ -43,4 +43,10 @@ static inline bool is_feat_trf_supported(void) return read_feat_trf_id_field() != 0U; } +static inline bool is_feat_spe_supported(void) +{ + /* FEAT_SPE is AArch64 only */ + return false; +} + #endif /* ARCH_FEATURES_H */ diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 582aed12f..58b37521b 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -249,10 +249,22 @@ static inline bool is_armv8_0_feat_csv2_2_present(void) /********************************************************************************** * Function to identify the presence of FEAT_SPE (Statistical Profiling Extension) *********************************************************************************/ -static inline bool is_armv8_2_feat_spe_present(void) +static inline unsigned int read_feat_spe_id_field(void) { - return (((read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT) & - ID_AA64DFR0_PMS_MASK) != ID_AA64DFR0_SPE_NOT_SUPPORTED); + return ISOLATE_FIELD(read_id_aa64dfr0_el1(), ID_AA64DFR0_PMS); +} + +static inline bool is_feat_spe_supported(void) +{ + if (ENABLE_SPE_FOR_NS == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_SPE_FOR_NS == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_spe_id_field() != 0U; } /******************************************************************************* diff --git a/include/lib/extensions/spe.h b/include/lib/extensions/spe.h index d4b925fe4..d443f18fb 100644 --- a/include/lib/extensions/spe.h +++ b/include/lib/extensions/spe.h @@ -9,8 +9,16 @@ #include <stdbool.h> -bool spe_supported(void); +#if ENABLE_SPE_FOR_NS void spe_enable(bool el2_unused); void spe_disable(void); +#else +void spe_enable(bool el2_unused) +{ +} +void spe_disable(void) +{ +} +#endif #endif /* SPE_H */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 50fddc502..c5f20ad35 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -482,9 +482,9 @@ void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) { #if IMAGE_BL31 -#if ENABLE_SPE_FOR_NS - spe_enable(el2_unused); -#endif + if (is_feat_spe_supported()) { + spe_enable(el2_unused); + } #if ENABLE_AMU amu_enable(el2_unused, ctx); diff --git a/lib/extensions/spe/spe.c b/lib/extensions/spe/spe.c index d747efcd7..b1fe39f58 100644 --- a/lib/extensions/spe/spe.c +++ b/lib/extensions/spe/spe.c @@ -7,6 +7,7 @@ #include <stdbool.h> #include <arch.h> +#include <arch_features.h> #include <arch_helpers.h> #include <lib/el3_runtime/pubsub.h> #include <lib/extensions/spe.h> @@ -20,21 +21,10 @@ static inline void psb_csync(void) __asm__ volatile("hint #17"); } -bool spe_supported(void) -{ - uint64_t features; - - features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; - return (features & ID_AA64DFR0_PMS_MASK) > 0ULL; -} - void spe_enable(bool el2_unused) { uint64_t v; - if (!spe_supported()) - return; - if (el2_unused) { /* * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical @@ -69,9 +59,6 @@ void spe_disable(void) { uint64_t v; - if (!spe_supported()) - return; - /* Drain buffered data */ psb_csync(); dsbnsh(); @@ -85,7 +72,7 @@ void spe_disable(void) static void *spe_drain_buffers_hook(const void *arg) { - if (!spe_supported()) + if (!is_feat_spe_supported()) return (void *)-1; /* Drain buffered data */ diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 63ac82e6d..b928fcf98 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -355,7 +355,7 @@ V := 0 WARMBOOT_ENABLE_DCACHE_EARLY := 0 # Build option to enable/disable the Statistical Profiling Extensions -ENABLE_SPE_FOR_NS := 1 +ENABLE_SPE_FOR_NS := 2 # SPE is only supported on AArch64 so disable it on AArch32. ifeq (${ARCH},aarch32) diff --git a/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/plat/arm/board/arm_fpga/fpga_bl31_setup.c index e1b3abb28..5cc1e7645 100644 --- a/plat/arm/board/arm_fpga/fpga_bl31_setup.c +++ b/plat/arm/board/arm_fpga/fpga_bl31_setup.c @@ -364,7 +364,7 @@ static void fpga_prepare_dtb(void) fpga_dtb_update_clock(fdt, system_freq); /* Check whether we support the SPE PMU. Remove the DT node if not. */ - if (!spe_supported()) { + if (!is_feat_spe_supported()) { int node = fdt_node_offset_by_compatible(fdt, 0, "arm,statistical-profiling-extension-v1"); diff --git a/plat/arm/board/fvp/fvp_pm.c b/plat/arm/board/fvp/fvp_pm.c index 9d9386230..3d53388e4 100644 --- a/plat/arm/board/fvp/fvp_pm.c +++ b/plat/arm/board/fvp/fvp_pm.c @@ -6,6 +6,7 @@ #include <assert.h> +#include <arch_features.h> #include <arch_helpers.h> #include <common/debug.h> #include <drivers/arm/gicv3.h> @@ -53,13 +54,13 @@ static void fvp_cluster_pwrdwn_common(void) { uint64_t mpidr = read_mpidr_el1(); -#if ENABLE_SPE_FOR_NS /* * On power down we need to disable statistical profiling extensions * before exiting coherency. */ - spe_disable(); -#endif + if (is_feat_spe_supported()) { + spe_disable(); + } /* Disable coherency if this cluster is to be turned off */ fvp_interconnect_disable();