diff --git a/Makefile b/Makefile index 52d6cf576..20b2aa296 100644 --- a/Makefile +++ b/Makefile @@ -861,6 +861,10 @@ ifeq ($(FEATURE_DETECTION),1) $(info FEATURE_DETECTION is an experimental feature) endif +ifneq ($(ENABLE_SME_FOR_NS), 0) + $(info ENABLE_SME_FOR_NS is an experimental feature) +endif + ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) ifeq (${ALLOW_RO_XLAT_TABLES}, 1) $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2") @@ -877,7 +881,7 @@ endif ifeq (${ARCH},aarch32) # SME/SVE only supported on AArch64 - ifeq (${ENABLE_SME_FOR_NS},1) + ifneq (${ENABLE_SME_FOR_NS},0) $(error "ENABLE_SME_FOR_NS cannot be used with ARCH=aarch32") endif ifeq (${ENABLE_SVE_FOR_NS},1) @@ -898,7 +902,7 @@ endif # Ensure ENABLE_RME is not used with SME ifeq (${ENABLE_RME},1) - ifeq (${ENABLE_SME_FOR_NS},1) + ifneq (${ENABLE_SME_FOR_NS},0) $(error "ENABLE_SME_FOR_NS cannot be used with ENABLE_RME") endif endif @@ -918,7 +922,7 @@ endif # SVE and SME cannot be used with CTX_INCLUDE_FPREGS since secure manager does # its own context management including FPU registers. ifeq (${CTX_INCLUDE_FPREGS},1) - ifeq (${ENABLE_SME_FOR_NS},1) + ifneq (${ENABLE_SME_FOR_NS},0) $(error "ENABLE_SME_FOR_NS cannot be used with CTX_INCLUDE_FPREGS") endif ifeq (${ENABLE_SVE_FOR_NS},1) @@ -1101,7 +1105,6 @@ $(eval $(call assert_booleans,\ ENABLE_PMF \ ENABLE_PSCI_STAT \ ENABLE_RUNTIME_INSTRUMENTATION \ - ENABLE_SME_FOR_NS \ ENABLE_SME_FOR_SWD \ ENABLE_SVE_FOR_NS \ ENABLE_SVE_FOR_SWD \ @@ -1189,6 +1192,7 @@ $(eval $(call assert_numerics,\ ENABLE_RME \ ENABLE_SPE_FOR_NS \ ENABLE_SYS_REG_TRACE_FOR_NS \ + ENABLE_SME_FOR_NS \ ENABLE_TRF_FOR_NS \ FW_ENC_STATUS \ NR_OF_FW_BANKS \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index bf907eaa5..8f3725ad5 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -99,7 +99,7 @@ ifeq (${ENABLE_MPMM},1) BL31_SOURCES += ${MPMM_SOURCES} endif -ifeq (${ENABLE_SME_FOR_NS},1) +ifneq (${ENABLE_SME_FOR_NS},0) BL31_SOURCES += lib/extensions/sme/sme.c BL31_SOURCES += lib/extensions/sve/sve.c else diff --git a/common/feat_detect.c b/common/feat_detect.c index 12cf12638..609a38888 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2022-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -216,6 +216,8 @@ void detect_arch_features(void) "TRBE", 1, 1); /* v9.2 features */ + check_feature(ENABLE_SME_FOR_NS, read_feat_sme_id_field(), + "SME", 1, 2); read_feat_rme(); if (tainted) { diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 20d88071b..4483dd424 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -406,14 +406,15 @@ Common build options instrumented. Enabling this option enables the ``ENABLE_PMF`` build option as well. Default is 0. -- ``ENABLE_SME_FOR_NS``: Boolean option to enable Scalable Matrix Extension +- ``ENABLE_SME_FOR_NS``: Numeric value to enable Scalable Matrix Extension (SME), SVE, and FPU/SIMD for the non-secure world only. These features share registers so are enabled together. Using this option without ENABLE_SME_FOR_SWD=1 will cause SME, SVE, and FPU/SIMD instructions in secure world to trap to EL3. SME is an optional architectural feature for AArch64 and TF-A support is experimental. At this time, this build option cannot be used on systems that have SPD=spmd/SPM_MM or ENABLE_RME, and attempting to - build with these options will fail. Default is 0. + build with these options will fail. This flag can take the values 0 to 2, to + align with the ``FEATURE_DETECTION`` mechanism. Default is 0. - ``ENABLE_SME_FOR_SWD``: Boolean option to enable the Scalable Matrix Extension for secure world use along with SVE and FPU/SIMD, ENABLE_SME_FOR_NS diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 8663ab8e7..2ce1be8f0 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -393,8 +393,10 @@ #define ID_AA64PFR1_MPAM_FRAC_SHIFT ULL(16) #define ID_AA64PFR1_MPAM_FRAC_MASK ULL(0xf) -#define ID_AA64PFR1_EL1_SME_SHIFT U(24) -#define ID_AA64PFR1_EL1_SME_MASK ULL(0xf) +#define ID_AA64PFR1_EL1_SME_SHIFT U(24) +#define ID_AA64PFR1_EL1_SME_MASK ULL(0xf) +#define ID_AA64PFR1_EL1_SME_NOT_SUPPORTED ULL(0x0) +#define ID_AA64PFR1_EL1_SME_SUPPORTED ULL(0x1) /* ID_PFR1_EL1 definitions */ #define ID_PFR1_VIRTEXT_SHIFT U(12) @@ -1004,7 +1006,9 @@ #define SMCR_EL3 S3_6_C1_C2_6 /* ID_AA64SMFR0_EL1 definitions */ -#define ID_AA64SMFR0_EL1_FA64_BIT (UL(1) << 63) +#define ID_AA64SMFR0_EL1_SME_FA64_SHIFT U(63) +#define ID_AA64SMFR0_EL1_SME_FA64_MASK U(0x1) +#define ID_AA64SMFR0_EL1_SME_FA64_SUPPORTED U(0x1) /* SMCR_ELx definitions */ #define SMCR_ELX_LEN_SHIFT U(0) diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index d7116a7cf..a01dfe783 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -516,4 +516,30 @@ static inline bool is_feat_trbe_supported(void) return read_feat_trbe_id_field() != 0U; } +/******************************************************************************* + * Function to identify the presence of FEAT_SMEx (Scalar Matrix Extension) + ******************************************************************************/ +static inline unsigned int read_feat_sme_fa64_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64smfr0_el1(), ID_AA64SMFR0_EL1_SME_FA64); +} + +static inline unsigned int read_feat_sme_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64pfr1_el1(), ID_AA64PFR1_EL1_SME); +} + +static inline bool is_feat_sme_supported(void) +{ + if (ENABLE_SME_FOR_NS == FEAT_STATE_DISABLED) { + return false; + } + + if (ENABLE_SME_FOR_NS == FEAT_STATE_ALWAYS) { + return true; + } + + return read_feat_sme_id_field() >= ID_AA64PFR1_EL1_SME_SUPPORTED; +} + #endif /* ARCH_FEATURES_H */ diff --git a/include/lib/extensions/sme.h b/include/lib/extensions/sme.h index 893f9f2cb..0e9c4b923 100644 --- a/include/lib/extensions/sme.h +++ b/include/lib/extensions/sme.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -8,7 +8,6 @@ #define SME_H #include - #include /* @@ -21,7 +20,16 @@ */ #define SME_SMCR_LEN_MAX U(0x1FF) +#if ENABLE_SME_FOR_NS void sme_enable(cpu_context_t *context); void sme_disable(cpu_context_t *context); +#else +static inline void sme_enable(cpu_context_t *context) +{ +} +static inline void sme_disable(cpu_context_t *context) +{ +} +#endif /* ENABLE_SME_FOR_NS */ #endif /* SME_H */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 12f3e6d03..7fbbd8171 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -489,10 +489,11 @@ static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) amu_enable(el2_unused, ctx); } -#if ENABLE_SME_FOR_NS /* Enable SME, SVE, and FPU/SIMD for non-secure world. */ - sme_enable(ctx); -#elif ENABLE_SVE_FOR_NS + if (is_feat_sme_supported()) { + sme_enable(ctx); + } +#if ENABLE_SVE_FOR_NS /* Enable SVE and FPU/SIMD for non-secure world. */ sve_enable(ctx); #endif diff --git a/lib/extensions/sme/sme.c b/lib/extensions/sme/sme.c index ec8cca82b..1846e003a 100644 --- a/lib/extensions/sme/sme.c +++ b/lib/extensions/sme/sme.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2021-2023, Arm Limited and Contributors. All rights reserved. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,28 +7,13 @@ #include #include +#include #include #include #include #include #include -static bool feat_sme_supported(void) -{ - uint64_t features; - - features = read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SME_SHIFT; - return (features & ID_AA64PFR1_EL1_SME_MASK) != 0U; -} - -static bool feat_sme_fa64_supported(void) -{ - uint64_t features; - - features = read_id_aa64smfr0_el1(); - return (features & ID_AA64SMFR0_EL1_FA64_BIT) != 0U; -} - void sme_enable(cpu_context_t *context) { u_register_t reg; @@ -36,7 +21,7 @@ void sme_enable(cpu_context_t *context) el3_state_t *state; /* Make sure SME is implemented in hardware before continuing. */ - if (!feat_sme_supported()) { + if (!is_feat_sme_supported()) { /* Perhaps the hardware supports SVE only */ sve_enable(context); return; @@ -66,7 +51,7 @@ void sme_enable(cpu_context_t *context) * using SMCR_EL2 and SMCR_EL1. */ reg = SMCR_ELX_LEN_MASK; - if (feat_sme_fa64_supported()) { + if (read_feat_sme_fa64_id_field() != 0U) { VERBOSE("[SME] FA64 enabled\n"); reg |= SMCR_ELX_FA64_BIT; } @@ -86,7 +71,7 @@ void sme_disable(cpu_context_t *context) el3_state_t *state; /* Make sure SME is implemented in hardware before continuing. */ - if (!feat_sme_supported()) { + if (!is_feat_sme_supported()) { /* Perhaps the hardware supports SVE only */ sve_disable(context); return; diff --git a/make_helpers/defaults.mk b/make_helpers/defaults.mk index 80c6174d1..ef917f65b 100644 --- a/make_helpers/defaults.mk +++ b/make_helpers/defaults.mk @@ -388,7 +388,7 @@ ENABLE_SME_FOR_NS := 0 ENABLE_SME_FOR_SWD := 0 # If SME is enabled then force SVE off -ifeq (${ENABLE_SME_FOR_NS},1) +ifneq (${ENABLE_SME_FOR_NS},0) override ENABLE_SVE_FOR_NS := 0 override ENABLE_SVE_FOR_SWD := 0 endif diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 12a4a2712..caac8d48c 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -479,6 +479,17 @@ ENABLE_FEAT_TWED := 2 ENABLE_FEAT_VHE := 2 ENABLE_MPAM_FOR_LOWER_ELS := 2 +# Enable SME access to NS by default +ifeq (${ARCH},aarch64) +ifeq (${SPM_MM}, 0) +ifeq (${ENABLE_RME}, 0) +ifeq (${CTX_INCLUDE_FPREGS}, 0) + ENABLE_SME_FOR_NS := 2 +endif +endif +endif +endif + ifeq (${SPMC_AT_EL3}, 1) PLAT_BL_COMMON_SOURCES += plat/arm/board/fvp/fvp_el3_spmc.c endif diff --git a/services/std_svc/spm/spm_mm/spm_mm.mk b/services/std_svc/spm/spm_mm/spm_mm.mk index f6691c372..b1f045ee6 100644 --- a/services/std_svc/spm/spm_mm/spm_mm.mk +++ b/services/std_svc/spm/spm_mm/spm_mm.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2017-2023, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -13,7 +13,7 @@ endif ifeq (${ENABLE_SVE_FOR_NS},1) $(error "Error: SPM_MM is not compatible with ENABLE_SVE_FOR_NS") endif -ifeq (${ENABLE_SME_FOR_NS},1) +ifneq (${ENABLE_SME_FOR_NS},0) $(error "Error: SPM_MM is not compatible with ENABLE_SME_FOR_NS") endif ifeq (${CTX_INCLUDE_FPREGS},0) diff --git a/services/std_svc/spmd/spmd.mk b/services/std_svc/spmd/spmd.mk index 8efbdc868..6f451c8db 100644 --- a/services/std_svc/spmd/spmd.mk +++ b/services/std_svc/spmd/spmd.mk @@ -1,5 +1,5 @@ # -# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2021-2023, ARM Limited and Contributors. All rights reserved. # # SPDX-License-Identifier: BSD-3-Clause # @@ -8,7 +8,7 @@ ifneq (${ARCH},aarch64) $(error "Error: SPMD is only supported on aarch64.") endif -ifeq (${ENABLE_SME_FOR_NS},1) +ifneq (${ENABLE_SME_FOR_NS},0) $(error "Error: SPMD is not compatible with ENABLE_SME_FOR_NS") endif