diff --git a/Makefile b/Makefile index 384c1e43e..2b6857b5b 100644 --- a/Makefile +++ b/Makefile @@ -951,8 +951,21 @@ ifeq (${ARCH},aarch32) ifeq (${ENABLE_FEAT_RNG_TRAP},1) $(error "ENABLE_FEAT_RNG_TRAP cannot be used with ARCH=aarch32") endif + + ifneq (${ENABLE_FEAT_FPMR},0) + $(error "ENABLE_FEAT_FPMR cannot be used with ARCH=aarch32") + endif endif #(ARCH=aarch32) +ifneq (${ENABLE_FEAT_FPMR},0) + ifeq (${ENABLE_FEAT_FGT},0) + $(error "ENABLE_FEAT_FPMR requires ENABLE_FEAT_FGT") + endif + ifeq (${ENABLE_FEAT_HCX},0) + $(error "ENABLE_FEAT_FPMR requires ENABLE_FEAT_HCX") + endif +endif #(ENABLE_FEAT_FPMR) + ifneq (${ENABLE_SME_FOR_NS},0) ifeq (${ENABLE_SVE_FOR_NS},0) $(error "ENABLE_SME_FOR_NS requires ENABLE_SVE_FOR_NS") @@ -1264,6 +1277,7 @@ $(eval $(call assert_numerics,\ ENABLE_FEAT_ECV \ ENABLE_FEAT_FGT \ ENABLE_FEAT_FGT2 \ + ENABLE_FEAT_FPMR \ ENABLE_FEAT_HCX \ ENABLE_FEAT_LS64_ACCDATA \ ENABLE_FEAT_MTE2 \ @@ -1425,6 +1439,7 @@ $(eval $(call add_defines,\ ENABLE_MPMM_FCONF \ ENABLE_FEAT_FGT \ ENABLE_FEAT_FGT2 \ + ENABLE_FEAT_FPMR \ ENABLE_FEAT_ECV \ ENABLE_FEAT_AMUv1p1 \ ENABLE_FEAT_SEL2 \ diff --git a/bl31/bl31.mk b/bl31/bl31.mk index 336ad2bef..2f9dc6501 100644 --- a/bl31/bl31.mk +++ b/bl31/bl31.mk @@ -150,6 +150,10 @@ ifneq (${ENABLE_TRF_FOR_NS},0) BL31_SOURCES += lib/extensions/trf/aarch64/trf.c endif +ifneq (${ENABLE_FEAT_FPMR},0) +BL31_SOURCES += lib/extensions/fpmr/fpmr.c +endif + ifeq (${WORKAROUND_CVE_2017_5715},1) BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ lib/cpus/aarch64/wa_cve_2017_5715_mmu.S diff --git a/common/feat_detect.c b/common/feat_detect.c index 8c03ab829..0f6be9f00 100644 --- a/common/feat_detect.c +++ b/common/feat_detect.c @@ -280,6 +280,12 @@ static unsigned int read_feat_d128_id_field(void) ID_AA64MMFR3_EL1_D128_MASK); } +static unsigned int read_feat_fpmr_id_field(void) +{ + return ISOLATE_FIELD(read_id_aa64pfr2_el1(), ID_AA64PFR2_EL1_FPMR_SHIFT, + ID_AA64PFR2_EL1_FPMR_MASK); +} + /*********************************************************************************** * TF-A supports many Arm architectural features starting from arch version * (8.0 till 8.7+). These features are mostly enabled through build flags. This @@ -405,6 +411,8 @@ void detect_arch_features(void) "SME", 1, 2); check_feature(ENABLE_SME2_FOR_NS, read_feat_sme_id_field(), "SME2", 2, 2); + check_feature(ENABLE_FEAT_FPMR, read_feat_fpmr_id_field(), + "FPMR", 1, 1); /* v9.3 features */ check_feature(ENABLE_FEAT_D128, read_feat_d128_id_field(), diff --git a/docs/getting_started/build-options.rst b/docs/getting_started/build-options.rst index 7d067c6c5..bd11d6880 100644 --- a/docs/getting_started/build-options.rst +++ b/docs/getting_started/build-options.rst @@ -351,6 +351,12 @@ Common build options This flag can take the values 0 to 2, to align with the ``ENABLE_FEAT`` mechanism. Default value is ``0``. +- ``ENABLE_FEAT_FPMR``: Numerical value to enable support for Floating Point + Mode Register feature, allowing access to the FPMR register. FPMR register + controls the behaviors of FP8 instructions. It is an optional architectural + feature from v9.2 and upwards. This flag can take value of 0 to 2, to align + with the ``FEATURE_DETECTION`` mechanism. Default value is ``0``. + - ``ENABLE_FEAT_FGT``: Numeric value to enable support for FGT (Fine Grain Traps) feature allowing for access to the HDFGRTR_EL2 (Hypervisor Debug Fine-Grained Read Trap Register) during EL2 to EL3 context save/restore operations. diff --git a/include/arch/aarch64/arch.h b/include/arch/aarch64/arch.h index 737d07ad9..3a7e2ebd9 100644 --- a/include/arch/aarch64/arch.h +++ b/include/arch/aarch64/arch.h @@ -465,6 +465,11 @@ #define ID_AA64PFR2_EL1_MTEFAR_SHIFT U(8) #define ID_AA64PFR2_EL1_MTEFAR_MASK ULL(0xf) +#define ID_AA64PFR2_EL1_FPMR_SHIFT U(32) +#define ID_AA64PFR2_EL1_FPMR_MASK ULL(0xf) + +#define FPMR_IMPLEMENTED ULL(0x1) + #define VDISR_EL2 S3_4_C12_C1_1 #define VSESR_EL2 S3_4_C5_C2_3 @@ -605,6 +610,7 @@ #define SCR_NSE_SHIFT U(62) #define SCR_FGTEN2_BIT (UL(1) << 59) #define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT) +#define SCR_EnFPM_BIT (ULL(1) << 50) #define SCR_GPF_BIT (UL(1) << 48) #define SCR_D128En_BIT (UL(1) << 47) #define SCR_TWEDEL_SHIFT U(30) @@ -1522,6 +1528,11 @@ ******************************************************************************/ #define CLUSTERPWRDN_EL1 S3_0_c15_c3_6 +/******************************************************************************* + * FEAT_FPMR - Floating point Mode Register + ******************************************************************************/ +#define FPMR S3_3_C4_C4_2 + /* CLUSTERPWRDN_EL1 register definitions */ #define DSU_CLUSTER_PWR_OFF 0 #define DSU_CLUSTER_PWR_ON 1 diff --git a/include/arch/aarch64/arch_features.h b/include/arch/aarch64/arch_features.h index 59188da38..8bdc13c34 100644 --- a/include/arch/aarch64/arch_features.h +++ b/include/arch/aarch64/arch_features.h @@ -142,6 +142,8 @@ CREATE_FEATURE_SUPPORTED(name, is_ ## name ## _present, guard) * +----------------------------+ * | FEAT_LS64_ACCDATA | * +----------------------------+ + * | FEAT_FPMR | + * +----------------------------+ */ __attribute__((always_inline)) @@ -284,6 +286,12 @@ CREATE_FEATURE_FUNCS(feat_d128, id_aa64mmfr3_el1, ID_AA64MMFR3_EL1_D128_SHIFT, ID_AA64MMFR3_EL1_D128_MASK, D128_IMPLEMENTED, ENABLE_FEAT_D128) +/* FEAT_FPMR */ +CREATE_FEATURE_FUNCS(feat_fpmr, id_aa64pfr2_el1, ID_AA64PFR2_EL1_FPMR_SHIFT, + ID_AA64PFR2_EL1_FPMR_MASK, FPMR_IMPLEMENTED, + ENABLE_FEAT_FPMR) + + __attribute__((always_inline)) static inline bool is_feat_sxpie_supported(void) { diff --git a/include/arch/aarch64/arch_helpers.h b/include/arch/aarch64/arch_helpers.h index 119c42899..3f3f14dca 100644 --- a/include/arch/aarch64/arch_helpers.h +++ b/include/arch/aarch64/arch_helpers.h @@ -718,6 +718,8 @@ DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3) DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3) DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(fpmr, FPMR) + #define IS_IN_EL(x) \ (GET_EL(read_CurrentEl()) == MODE_EL##x) diff --git a/include/lib/extensions/fpmr.h b/include/lib/extensions/fpmr.h new file mode 100644 index 000000000..bc3ee9e79 --- /dev/null +++ b/include/lib/extensions/fpmr.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FPMR_H +#define FPMR_H + +#include + +#if ENABLE_FEAT_FPMR +void fpmr_enable_per_world(per_world_context_t *per_world_ctx); +#else +static inline void fpmr_enable_per_world(per_world_context_t *per_world_ctx) +{ +} +#endif /* ENABLE_FEAT_FPMR */ + +#endif /* FPMR_H */ diff --git a/lib/el3_runtime/aarch64/context_mgmt.c b/lib/el3_runtime/aarch64/context_mgmt.c index 4ae13061f..f963ed19c 100644 --- a/lib/el3_runtime/aarch64/context_mgmt.c +++ b/lib/el3_runtime/aarch64/context_mgmt.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -291,6 +292,13 @@ static void setup_ns_context(cpu_context_t *ctx, const struct entry_point_info * scr_el3 |= SCR_D128En_BIT; } + if (is_feat_fpmr_supported()) { + /* Set the EnFPM bit in SCR_EL3 to enable access to FPMR + * register. + */ + scr_el3 |= SCR_EnFPM_BIT; + } + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); /* Initialize EL2 context registers */ @@ -714,6 +722,10 @@ void manage_extensions_nonsecure_per_world(void) if (is_feat_mpam_supported()) { mpam_enable_per_world(&per_world_context[CPU_CONTEXT_NS]); } + + if (is_feat_fpmr_supported()) { + fpmr_enable_per_world(&per_world_context[CPU_CONTEXT_NS]); + } } #endif /* IMAGE_BL31 */ diff --git a/lib/extensions/fpmr/fpmr.c b/lib/extensions/fpmr/fpmr.c new file mode 100644 index 000000000..8e37e7a91 --- /dev/null +++ b/lib/extensions/fpmr/fpmr.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2024, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +void fpmr_enable_per_world(per_world_context_t *per_world_ctx) +{ + u_register_t reg; + + /* Disable Floating point Trap in CPTR_EL3. */ + reg = per_world_ctx->ctx_cptr_el3; + reg &= ~TFP_BIT; + per_world_ctx->ctx_cptr_el3 = reg; +} diff --git a/make_helpers/arch_features.mk b/make_helpers/arch_features.mk index 57609d51c..a1db0b8f2 100644 --- a/make_helpers/arch_features.mk +++ b/make_helpers/arch_features.mk @@ -408,6 +408,9 @@ ENABLE_SME_FOR_SWD ?= 0 # if FEAT_BRBE is implemented. ENABLE_BRBE_FOR_NS ?= 0 +# Flag to enable Floating point exception Mode Register Feature (FEAT_FPMR) +ENABLE_FEAT_FPMR ?= 0 + #---- # 9.3 #---- diff --git a/plat/arm/board/fvp/platform.mk b/plat/arm/board/fvp/platform.mk index 1340a6561..3b638e414 100644 --- a/plat/arm/board/fvp/platform.mk +++ b/plat/arm/board/fvp/platform.mk @@ -57,6 +57,7 @@ endif ENABLE_BRBE_FOR_NS := 2 ENABLE_TRBE_FOR_NS := 2 ENABLE_FEAT_D128 := 2 + ENABLE_FEAT_FPMR := 2 endif ENABLE_SYS_REG_TRACE_FOR_NS := 2